4 * Copyright (c) 2019-2020 Michael Rolnik
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, see
18 * <http://www.gnu.org/licenses/lgpl-2.1.html>
21 #include "qemu/osdep.h"
22 #include "qemu/qemu-print.h"
25 #include "exec/exec-all.h"
26 #include "tcg/tcg-op.h"
27 #include "exec/cpu_ldst.h"
28 #include "exec/helper-proto.h"
29 #include "exec/helper-gen.h"
31 #include "exec/translator.h"
32 #include "exec/gen-icount.h"
35 * Define if you want a BREAK instruction translated to a breakpoint
36 * Active debugging connection is assumed
38 * https://github.com/seharris/qemu-avr-tests/tree/master/instruction-tests
41 #undef BREAKPOINT_ON_BREAK
54 static TCGv cpu_rampD
;
55 static TCGv cpu_rampX
;
56 static TCGv cpu_rampY
;
57 static TCGv cpu_rampZ
;
59 static TCGv cpu_r
[NUMBER_OF_CPU_REGISTERS
];
65 static const char reg_names
[NUMBER_OF_CPU_REGISTERS
][8] = {
66 "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
67 "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
68 "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
69 "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
71 #define REG(x) (cpu_r[x])
74 DISAS_EXIT
= DISAS_TARGET_0
, /* We want return to the cpu main loop. */
75 DISAS_LOOKUP
= DISAS_TARGET_1
, /* We have a variable condition exit. */
76 DISAS_CHAIN
= DISAS_TARGET_2
, /* We have a single condition exit. */
79 typedef struct DisasContext DisasContext
;
81 /* This is the state at translation time. */
91 /* Routine used to access memory */
97 * some AVR instructions can make the following instruction to be skipped
98 * Let's name those instructions
99 * A - instruction that can skip the next one
100 * B - instruction that can be skipped. this depends on execution of A
101 * there are two scenarios
102 * 1. A and B belong to the same translation block
103 * 2. A is the last instruction in the translation block and B is the last
105 * following variables are used to simplify the skipping logic, they are
106 * used in the following manner (sketch)
108 * TCGLabel *skip_label = NULL;
109 * if (ctx.skip_cond != TCG_COND_NEVER) {
110 * skip_label = gen_new_label();
111 * tcg_gen_brcond_tl(skip_cond, skip_var0, skip_var1, skip_label);
114 * if (free_skip_var0) {
115 * tcg_temp_free(skip_var0);
116 * free_skip_var0 = false;
122 * gen_set_label(skip_label);
131 static int to_regs_16_31_by_one(DisasContext
*ctx
, int indx
)
133 return 16 + (indx
% 16);
136 static int to_regs_16_23_by_one(DisasContext
*ctx
, int indx
)
138 return 16 + (indx
% 8);
141 static int to_regs_24_30_by_two(DisasContext
*ctx
, int indx
)
143 return 24 + (indx
% 4) * 2;
147 static bool avr_have_feature(DisasContext
*ctx
, int feature
)
149 if (!avr_feature(ctx
->env
, feature
)) {
150 gen_helper_unsupported(cpu_env
);
151 ctx
->bstate
= DISAS_NORETURN
;
157 static bool decode_insn(DisasContext
*ctx
, uint16_t insn
);
158 #include "decode_insn.inc.c"
161 * Arithmetic Instructions
165 * Utility functions for updating status registers:
176 static void gen_add_CHf(TCGv R
, TCGv Rd
, TCGv Rr
)
178 TCGv t1
= tcg_temp_new_i32();
179 TCGv t2
= tcg_temp_new_i32();
180 TCGv t3
= tcg_temp_new_i32();
182 tcg_gen_and_tl(t1
, Rd
, Rr
); /* t1 = Rd & Rr */
183 tcg_gen_andc_tl(t2
, Rd
, R
); /* t2 = Rd & ~R */
184 tcg_gen_andc_tl(t3
, Rr
, R
); /* t3 = Rr & ~R */
185 tcg_gen_or_tl(t1
, t1
, t2
); /* t1 = t1 | t2 | t3 */
186 tcg_gen_or_tl(t1
, t1
, t3
);
188 tcg_gen_shri_tl(cpu_Cf
, t1
, 7); /* Cf = t1(7) */
189 tcg_gen_shri_tl(cpu_Hf
, t1
, 3); /* Hf = t1(3) */
190 tcg_gen_andi_tl(cpu_Hf
, cpu_Hf
, 1);
192 tcg_temp_free_i32(t3
);
193 tcg_temp_free_i32(t2
);
194 tcg_temp_free_i32(t1
);
197 static void gen_add_Vf(TCGv R
, TCGv Rd
, TCGv Rr
)
199 TCGv t1
= tcg_temp_new_i32();
200 TCGv t2
= tcg_temp_new_i32();
202 /* t1 = Rd & Rr & ~R | ~Rd & ~Rr & R */
203 /* = (Rd ^ R) & ~(Rd ^ Rr) */
204 tcg_gen_xor_tl(t1
, Rd
, R
);
205 tcg_gen_xor_tl(t2
, Rd
, Rr
);
206 tcg_gen_andc_tl(t1
, t1
, t2
);
208 tcg_gen_shri_tl(cpu_Vf
, t1
, 7); /* Vf = t1(7) */
210 tcg_temp_free_i32(t2
);
211 tcg_temp_free_i32(t1
);
214 static void gen_sub_CHf(TCGv R
, TCGv Rd
, TCGv Rr
)
216 TCGv t1
= tcg_temp_new_i32();
217 TCGv t2
= tcg_temp_new_i32();
218 TCGv t3
= tcg_temp_new_i32();
220 tcg_gen_not_tl(t1
, Rd
); /* t1 = ~Rd */
221 tcg_gen_and_tl(t2
, t1
, Rr
); /* t2 = ~Rd & Rr */
222 tcg_gen_or_tl(t3
, t1
, Rr
); /* t3 = (~Rd | Rr) & R */
223 tcg_gen_and_tl(t3
, t3
, R
);
224 tcg_gen_or_tl(t2
, t2
, t3
); /* t2 = ~Rd & Rr | ~Rd & R | R & Rr */
226 tcg_gen_shri_tl(cpu_Cf
, t2
, 7); /* Cf = t2(7) */
227 tcg_gen_shri_tl(cpu_Hf
, t2
, 3); /* Hf = t2(3) */
228 tcg_gen_andi_tl(cpu_Hf
, cpu_Hf
, 1);
230 tcg_temp_free_i32(t3
);
231 tcg_temp_free_i32(t2
);
232 tcg_temp_free_i32(t1
);
235 static void gen_sub_Vf(TCGv R
, TCGv Rd
, TCGv Rr
)
237 TCGv t1
= tcg_temp_new_i32();
238 TCGv t2
= tcg_temp_new_i32();
240 /* t1 = Rd & ~Rr & ~R | ~Rd & Rr & R */
241 /* = (Rd ^ R) & (Rd ^ R) */
242 tcg_gen_xor_tl(t1
, Rd
, R
);
243 tcg_gen_xor_tl(t2
, Rd
, Rr
);
244 tcg_gen_and_tl(t1
, t1
, t2
);
246 tcg_gen_shri_tl(cpu_Vf
, t1
, 7); /* Vf = t1(7) */
248 tcg_temp_free_i32(t2
);
249 tcg_temp_free_i32(t1
);
252 static void gen_NSf(TCGv R
)
254 tcg_gen_shri_tl(cpu_Nf
, R
, 7); /* Nf = R(7) */
255 tcg_gen_xor_tl(cpu_Sf
, cpu_Nf
, cpu_Vf
); /* Sf = Nf ^ Vf */
258 static void gen_ZNSf(TCGv R
)
260 tcg_gen_setcondi_tl(TCG_COND_EQ
, cpu_Zf
, R
, 0); /* Zf = R == 0 */
262 /* update status register */
263 tcg_gen_shri_tl(cpu_Nf
, R
, 7); /* Nf = R(7) */
264 tcg_gen_xor_tl(cpu_Sf
, cpu_Nf
, cpu_Vf
); /* Sf = Nf ^ Vf */
268 * Adds two registers without the C Flag and places the result in the
269 * destination register Rd.
271 static bool trans_ADD(DisasContext
*ctx
, arg_ADD
*a
)
273 TCGv Rd
= cpu_r
[a
->rd
];
274 TCGv Rr
= cpu_r
[a
->rr
];
275 TCGv R
= tcg_temp_new_i32();
277 tcg_gen_add_tl(R
, Rd
, Rr
); /* Rd = Rd + Rr */
278 tcg_gen_andi_tl(R
, R
, 0xff); /* make it 8 bits */
280 /* update status register */
281 gen_add_CHf(R
, Rd
, Rr
);
282 gen_add_Vf(R
, Rd
, Rr
);
285 /* update output registers */
286 tcg_gen_mov_tl(Rd
, R
);
288 tcg_temp_free_i32(R
);
294 * Adds two registers and the contents of the C Flag and places the result in
295 * the destination register Rd.
297 static bool trans_ADC(DisasContext
*ctx
, arg_ADC
*a
)
299 TCGv Rd
= cpu_r
[a
->rd
];
300 TCGv Rr
= cpu_r
[a
->rr
];
301 TCGv R
= tcg_temp_new_i32();
303 tcg_gen_add_tl(R
, Rd
, Rr
); /* R = Rd + Rr + Cf */
304 tcg_gen_add_tl(R
, R
, cpu_Cf
);
305 tcg_gen_andi_tl(R
, R
, 0xff); /* make it 8 bits */
307 /* update status register */
308 gen_add_CHf(R
, Rd
, Rr
);
309 gen_add_Vf(R
, Rd
, Rr
);
312 /* update output registers */
313 tcg_gen_mov_tl(Rd
, R
);
315 tcg_temp_free_i32(R
);
321 * Adds an immediate value (0 - 63) to a register pair and places the result
322 * in the register pair. This instruction operates on the upper four register
323 * pairs, and is well suited for operations on the pointer registers. This
324 * instruction is not available in all devices. Refer to the device specific
325 * instruction set summary.
327 static bool trans_ADIW(DisasContext
*ctx
, arg_ADIW
*a
)
329 if (!avr_have_feature(ctx
, AVR_FEATURE_ADIW_SBIW
)) {
333 TCGv RdL
= cpu_r
[a
->rd
];
334 TCGv RdH
= cpu_r
[a
->rd
+ 1];
336 TCGv R
= tcg_temp_new_i32();
337 TCGv Rd
= tcg_temp_new_i32();
339 tcg_gen_deposit_tl(Rd
, RdL
, RdH
, 8, 8); /* Rd = RdH:RdL */
340 tcg_gen_addi_tl(R
, Rd
, Imm
); /* R = Rd + Imm */
341 tcg_gen_andi_tl(R
, R
, 0xffff); /* make it 16 bits */
343 /* update status register */
344 tcg_gen_andc_tl(cpu_Cf
, Rd
, R
); /* Cf = Rd & ~R */
345 tcg_gen_shri_tl(cpu_Cf
, cpu_Cf
, 15);
346 tcg_gen_andc_tl(cpu_Vf
, R
, Rd
); /* Vf = R & ~Rd */
347 tcg_gen_shri_tl(cpu_Vf
, cpu_Vf
, 15);
348 tcg_gen_setcondi_tl(TCG_COND_EQ
, cpu_Zf
, R
, 0); /* Zf = R == 0 */
349 tcg_gen_shri_tl(cpu_Nf
, R
, 15); /* Nf = R(15) */
350 tcg_gen_xor_tl(cpu_Sf
, cpu_Nf
, cpu_Vf
);/* Sf = Nf ^ Vf */
352 /* update output registers */
353 tcg_gen_andi_tl(RdL
, R
, 0xff);
354 tcg_gen_shri_tl(RdH
, R
, 8);
356 tcg_temp_free_i32(Rd
);
357 tcg_temp_free_i32(R
);
363 * Subtracts two registers and places the result in the destination
366 static bool trans_SUB(DisasContext
*ctx
, arg_SUB
*a
)
368 TCGv Rd
= cpu_r
[a
->rd
];
369 TCGv Rr
= cpu_r
[a
->rr
];
370 TCGv R
= tcg_temp_new_i32();
372 tcg_gen_sub_tl(R
, Rd
, Rr
); /* R = Rd - Rr */
373 tcg_gen_andi_tl(R
, R
, 0xff); /* make it 8 bits */
375 /* update status register */
376 tcg_gen_andc_tl(cpu_Cf
, Rd
, R
); /* Cf = Rd & ~R */
377 gen_sub_CHf(R
, Rd
, Rr
);
378 gen_sub_Vf(R
, Rd
, Rr
);
381 /* update output registers */
382 tcg_gen_mov_tl(Rd
, R
);
384 tcg_temp_free_i32(R
);
390 * Subtracts a register and a constant and places the result in the
391 * destination register Rd. This instruction is working on Register R16 to R31
392 * and is very well suited for operations on the X, Y, and Z-pointers.
394 static bool trans_SUBI(DisasContext
*ctx
, arg_SUBI
*a
)
396 TCGv Rd
= cpu_r
[a
->rd
];
397 TCGv Rr
= tcg_const_i32(a
->imm
);
398 TCGv R
= tcg_temp_new_i32();
400 tcg_gen_sub_tl(R
, Rd
, Rr
); /* R = Rd - Imm */
401 tcg_gen_andi_tl(R
, R
, 0xff); /* make it 8 bits */
403 /* update status register */
404 gen_sub_CHf(R
, Rd
, Rr
);
405 gen_sub_Vf(R
, Rd
, Rr
);
408 /* update output registers */
409 tcg_gen_mov_tl(Rd
, R
);
411 tcg_temp_free_i32(R
);
412 tcg_temp_free_i32(Rr
);
418 * Subtracts two registers and subtracts with the C Flag and places the
419 * result in the destination register Rd.
421 static bool trans_SBC(DisasContext
*ctx
, arg_SBC
*a
)
423 TCGv Rd
= cpu_r
[a
->rd
];
424 TCGv Rr
= cpu_r
[a
->rr
];
425 TCGv R
= tcg_temp_new_i32();
426 TCGv zero
= tcg_const_i32(0);
428 tcg_gen_sub_tl(R
, Rd
, Rr
); /* R = Rd - Rr - Cf */
429 tcg_gen_sub_tl(R
, R
, cpu_Cf
);
430 tcg_gen_andi_tl(R
, R
, 0xff); /* make it 8 bits */
432 /* update status register */
433 gen_sub_CHf(R
, Rd
, Rr
);
434 gen_sub_Vf(R
, Rd
, Rr
);
438 * Previous value remains unchanged when the result is zero;
441 tcg_gen_movcond_tl(TCG_COND_EQ
, cpu_Zf
, R
, zero
, cpu_Zf
, zero
);
443 /* update output registers */
444 tcg_gen_mov_tl(Rd
, R
);
446 tcg_temp_free_i32(zero
);
447 tcg_temp_free_i32(R
);
453 * SBCI -- Subtract Immediate with Carry
455 static bool trans_SBCI(DisasContext
*ctx
, arg_SBCI
*a
)
457 TCGv Rd
= cpu_r
[a
->rd
];
458 TCGv Rr
= tcg_const_i32(a
->imm
);
459 TCGv R
= tcg_temp_new_i32();
460 TCGv zero
= tcg_const_i32(0);
462 tcg_gen_sub_tl(R
, Rd
, Rr
); /* R = Rd - Rr - Cf */
463 tcg_gen_sub_tl(R
, R
, cpu_Cf
);
464 tcg_gen_andi_tl(R
, R
, 0xff); /* make it 8 bits */
466 /* update status register */
467 gen_sub_CHf(R
, Rd
, Rr
);
468 gen_sub_Vf(R
, Rd
, Rr
);
472 * Previous value remains unchanged when the result is zero;
475 tcg_gen_movcond_tl(TCG_COND_EQ
, cpu_Zf
, R
, zero
, cpu_Zf
, zero
);
477 /* update output registers */
478 tcg_gen_mov_tl(Rd
, R
);
480 tcg_temp_free_i32(zero
);
481 tcg_temp_free_i32(R
);
482 tcg_temp_free_i32(Rr
);
488 * Subtracts an immediate value (0-63) from a register pair and places the
489 * result in the register pair. This instruction operates on the upper four
490 * register pairs, and is well suited for operations on the Pointer Registers.
491 * This instruction is not available in all devices. Refer to the device
492 * specific instruction set summary.
494 static bool trans_SBIW(DisasContext
*ctx
, arg_SBIW
*a
)
496 if (!avr_have_feature(ctx
, AVR_FEATURE_ADIW_SBIW
)) {
500 TCGv RdL
= cpu_r
[a
->rd
];
501 TCGv RdH
= cpu_r
[a
->rd
+ 1];
503 TCGv R
= tcg_temp_new_i32();
504 TCGv Rd
= tcg_temp_new_i32();
506 tcg_gen_deposit_tl(Rd
, RdL
, RdH
, 8, 8); /* Rd = RdH:RdL */
507 tcg_gen_subi_tl(R
, Rd
, Imm
); /* R = Rd - Imm */
508 tcg_gen_andi_tl(R
, R
, 0xffff); /* make it 16 bits */
510 /* update status register */
511 tcg_gen_andc_tl(cpu_Cf
, R
, Rd
);
512 tcg_gen_shri_tl(cpu_Cf
, cpu_Cf
, 15); /* Cf = R & ~Rd */
513 tcg_gen_andc_tl(cpu_Vf
, Rd
, R
);
514 tcg_gen_shri_tl(cpu_Vf
, cpu_Vf
, 15); /* Vf = Rd & ~R */
515 tcg_gen_setcondi_tl(TCG_COND_EQ
, cpu_Zf
, R
, 0); /* Zf = R == 0 */
516 tcg_gen_shri_tl(cpu_Nf
, R
, 15); /* Nf = R(15) */
517 tcg_gen_xor_tl(cpu_Sf
, cpu_Nf
, cpu_Vf
); /* Sf = Nf ^ Vf */
519 /* update output registers */
520 tcg_gen_andi_tl(RdL
, R
, 0xff);
521 tcg_gen_shri_tl(RdH
, R
, 8);
523 tcg_temp_free_i32(Rd
);
524 tcg_temp_free_i32(R
);
530 * Performs the logical AND between the contents of register Rd and register
531 * Rr and places the result in the destination register Rd.
533 static bool trans_AND(DisasContext
*ctx
, arg_AND
*a
)
535 TCGv Rd
= cpu_r
[a
->rd
];
536 TCGv Rr
= cpu_r
[a
->rr
];
537 TCGv R
= tcg_temp_new_i32();
539 tcg_gen_and_tl(R
, Rd
, Rr
); /* Rd = Rd and Rr */
541 /* update status register */
542 tcg_gen_movi_tl(cpu_Vf
, 0); /* Vf = 0 */
543 tcg_gen_setcondi_tl(TCG_COND_EQ
, cpu_Zf
, R
, 0); /* Zf = R == 0 */
546 /* update output registers */
547 tcg_gen_mov_tl(Rd
, R
);
549 tcg_temp_free_i32(R
);
555 * Performs the logical AND between the contents of register Rd and a constant
556 * and places the result in the destination register Rd.
558 static bool trans_ANDI(DisasContext
*ctx
, arg_ANDI
*a
)
560 TCGv Rd
= cpu_r
[a
->rd
];
563 tcg_gen_andi_tl(Rd
, Rd
, Imm
); /* Rd = Rd & Imm */
565 /* update status register */
566 tcg_gen_movi_tl(cpu_Vf
, 0x00); /* Vf = 0 */
573 * Performs the logical OR between the contents of register Rd and register
574 * Rr and places the result in the destination register Rd.
576 static bool trans_OR(DisasContext
*ctx
, arg_OR
*a
)
578 TCGv Rd
= cpu_r
[a
->rd
];
579 TCGv Rr
= cpu_r
[a
->rr
];
580 TCGv R
= tcg_temp_new_i32();
582 tcg_gen_or_tl(R
, Rd
, Rr
);
584 /* update status register */
585 tcg_gen_movi_tl(cpu_Vf
, 0);
588 /* update output registers */
589 tcg_gen_mov_tl(Rd
, R
);
591 tcg_temp_free_i32(R
);
597 * Performs the logical OR between the contents of register Rd and a
598 * constant and places the result in the destination register Rd.
600 static bool trans_ORI(DisasContext
*ctx
, arg_ORI
*a
)
602 TCGv Rd
= cpu_r
[a
->rd
];
605 tcg_gen_ori_tl(Rd
, Rd
, Imm
); /* Rd = Rd | Imm */
607 /* update status register */
608 tcg_gen_movi_tl(cpu_Vf
, 0x00); /* Vf = 0 */
615 * Performs the logical EOR between the contents of register Rd and
616 * register Rr and places the result in the destination register Rd.
618 static bool trans_EOR(DisasContext
*ctx
, arg_EOR
*a
)
620 TCGv Rd
= cpu_r
[a
->rd
];
621 TCGv Rr
= cpu_r
[a
->rr
];
623 tcg_gen_xor_tl(Rd
, Rd
, Rr
);
625 /* update status register */
626 tcg_gen_movi_tl(cpu_Vf
, 0);
633 * Clears the specified bits in register Rd. Performs the logical AND
634 * between the contents of register Rd and the complement of the constant mask
635 * K. The result will be placed in register Rd.
637 static bool trans_COM(DisasContext
*ctx
, arg_COM
*a
)
639 TCGv Rd
= cpu_r
[a
->rd
];
640 TCGv R
= tcg_temp_new_i32();
642 tcg_gen_xori_tl(Rd
, Rd
, 0xff);
644 /* update status register */
645 tcg_gen_movi_tl(cpu_Cf
, 1); /* Cf = 1 */
646 tcg_gen_movi_tl(cpu_Vf
, 0); /* Vf = 0 */
649 tcg_temp_free_i32(R
);
655 * Replaces the contents of register Rd with its two's complement; the
656 * value $80 is left unchanged.
658 static bool trans_NEG(DisasContext
*ctx
, arg_NEG
*a
)
660 TCGv Rd
= cpu_r
[a
->rd
];
661 TCGv t0
= tcg_const_i32(0);
662 TCGv R
= tcg_temp_new_i32();
664 tcg_gen_sub_tl(R
, t0
, Rd
); /* R = 0 - Rd */
665 tcg_gen_andi_tl(R
, R
, 0xff); /* make it 8 bits */
667 /* update status register */
668 gen_sub_CHf(R
, t0
, Rd
);
669 gen_sub_Vf(R
, t0
, Rd
);
672 /* update output registers */
673 tcg_gen_mov_tl(Rd
, R
);
675 tcg_temp_free_i32(t0
);
676 tcg_temp_free_i32(R
);
682 * Adds one -1- to the contents of register Rd and places the result in the
683 * destination register Rd. The C Flag in SREG is not affected by the
684 * operation, thus allowing the INC instruction to be used on a loop counter in
685 * multiple-precision computations. When operating on unsigned numbers, only
686 * BREQ and BRNE branches can be expected to perform consistently. When
687 * operating on two's complement values, all signed branches are available.
689 static bool trans_INC(DisasContext
*ctx
, arg_INC
*a
)
691 TCGv Rd
= cpu_r
[a
->rd
];
693 tcg_gen_addi_tl(Rd
, Rd
, 1);
694 tcg_gen_andi_tl(Rd
, Rd
, 0xff);
696 /* update status register */
697 tcg_gen_setcondi_tl(TCG_COND_EQ
, cpu_Vf
, Rd
, 0x80); /* Vf = Rd == 0x80 */
704 * Subtracts one -1- from the contents of register Rd and places the result
705 * in the destination register Rd. The C Flag in SREG is not affected by the
706 * operation, thus allowing the DEC instruction to be used on a loop counter in
707 * multiple-precision computations. When operating on unsigned values, only
708 * BREQ and BRNE branches can be expected to perform consistently. When
709 * operating on two's complement values, all signed branches are available.
711 static bool trans_DEC(DisasContext
*ctx
, arg_DEC
*a
)
713 TCGv Rd
= cpu_r
[a
->rd
];
715 tcg_gen_subi_tl(Rd
, Rd
, 1); /* Rd = Rd - 1 */
716 tcg_gen_andi_tl(Rd
, Rd
, 0xff); /* make it 8 bits */
718 /* update status register */
719 tcg_gen_setcondi_tl(TCG_COND_EQ
, cpu_Vf
, Rd
, 0x7f); /* Vf = Rd == 0x7f */
726 * This instruction performs 8-bit x 8-bit -> 16-bit unsigned multiplication.
728 static bool trans_MUL(DisasContext
*ctx
, arg_MUL
*a
)
730 if (!avr_have_feature(ctx
, AVR_FEATURE_MUL
)) {
736 TCGv Rd
= cpu_r
[a
->rd
];
737 TCGv Rr
= cpu_r
[a
->rr
];
738 TCGv R
= tcg_temp_new_i32();
740 tcg_gen_mul_tl(R
, Rd
, Rr
); /* R = Rd * Rr */
741 tcg_gen_andi_tl(R0
, R
, 0xff);
742 tcg_gen_shri_tl(R1
, R
, 8);
744 /* update status register */
745 tcg_gen_shri_tl(cpu_Cf
, R
, 15); /* Cf = R(15) */
746 tcg_gen_setcondi_tl(TCG_COND_EQ
, cpu_Zf
, R
, 0); /* Zf = R == 0 */
748 tcg_temp_free_i32(R
);
754 * This instruction performs 8-bit x 8-bit -> 16-bit signed multiplication.
756 static bool trans_MULS(DisasContext
*ctx
, arg_MULS
*a
)
758 if (!avr_have_feature(ctx
, AVR_FEATURE_MUL
)) {
764 TCGv Rd
= cpu_r
[a
->rd
];
765 TCGv Rr
= cpu_r
[a
->rr
];
766 TCGv R
= tcg_temp_new_i32();
767 TCGv t0
= tcg_temp_new_i32();
768 TCGv t1
= tcg_temp_new_i32();
770 tcg_gen_ext8s_tl(t0
, Rd
); /* make Rd full 32 bit signed */
771 tcg_gen_ext8s_tl(t1
, Rr
); /* make Rr full 32 bit signed */
772 tcg_gen_mul_tl(R
, t0
, t1
); /* R = Rd * Rr */
773 tcg_gen_andi_tl(R
, R
, 0xffff); /* make it 16 bits */
774 tcg_gen_andi_tl(R0
, R
, 0xff);
775 tcg_gen_shri_tl(R1
, R
, 8);
777 /* update status register */
778 tcg_gen_shri_tl(cpu_Cf
, R
, 15); /* Cf = R(15) */
779 tcg_gen_setcondi_tl(TCG_COND_EQ
, cpu_Zf
, R
, 0); /* Zf = R == 0 */
781 tcg_temp_free_i32(t1
);
782 tcg_temp_free_i32(t0
);
783 tcg_temp_free_i32(R
);
789 * This instruction performs 8-bit x 8-bit -> 16-bit multiplication of a
790 * signed and an unsigned number.
792 static bool trans_MULSU(DisasContext
*ctx
, arg_MULSU
*a
)
794 if (!avr_have_feature(ctx
, AVR_FEATURE_MUL
)) {
800 TCGv Rd
= cpu_r
[a
->rd
];
801 TCGv Rr
= cpu_r
[a
->rr
];
802 TCGv R
= tcg_temp_new_i32();
803 TCGv t0
= tcg_temp_new_i32();
805 tcg_gen_ext8s_tl(t0
, Rd
); /* make Rd full 32 bit signed */
806 tcg_gen_mul_tl(R
, t0
, Rr
); /* R = Rd * Rr */
807 tcg_gen_andi_tl(R
, R
, 0xffff); /* make R 16 bits */
808 tcg_gen_andi_tl(R0
, R
, 0xff);
809 tcg_gen_shri_tl(R1
, R
, 8);
811 /* update status register */
812 tcg_gen_shri_tl(cpu_Cf
, R
, 15); /* Cf = R(15) */
813 tcg_gen_setcondi_tl(TCG_COND_EQ
, cpu_Zf
, R
, 0); /* Zf = R == 0 */
815 tcg_temp_free_i32(t0
);
816 tcg_temp_free_i32(R
);
822 * This instruction performs 8-bit x 8-bit -> 16-bit unsigned
823 * multiplication and shifts the result one bit left.
825 static bool trans_FMUL(DisasContext
*ctx
, arg_FMUL
*a
)
827 if (!avr_have_feature(ctx
, AVR_FEATURE_MUL
)) {
833 TCGv Rd
= cpu_r
[a
->rd
];
834 TCGv Rr
= cpu_r
[a
->rr
];
835 TCGv R
= tcg_temp_new_i32();
837 tcg_gen_mul_tl(R
, Rd
, Rr
); /* R = Rd * Rr */
839 /* update status register */
840 tcg_gen_shri_tl(cpu_Cf
, R
, 15); /* Cf = R(15) */
841 tcg_gen_setcondi_tl(TCG_COND_EQ
, cpu_Zf
, R
, 0); /* Zf = R == 0 */
843 /* update output registers */
844 tcg_gen_shli_tl(R
, R
, 1);
845 tcg_gen_andi_tl(R0
, R
, 0xff);
846 tcg_gen_shri_tl(R1
, R
, 8);
847 tcg_gen_andi_tl(R1
, R1
, 0xff);
850 tcg_temp_free_i32(R
);
856 * This instruction performs 8-bit x 8-bit -> 16-bit signed multiplication
857 * and shifts the result one bit left.
859 static bool trans_FMULS(DisasContext
*ctx
, arg_FMULS
*a
)
861 if (!avr_have_feature(ctx
, AVR_FEATURE_MUL
)) {
867 TCGv Rd
= cpu_r
[a
->rd
];
868 TCGv Rr
= cpu_r
[a
->rr
];
869 TCGv R
= tcg_temp_new_i32();
870 TCGv t0
= tcg_temp_new_i32();
871 TCGv t1
= tcg_temp_new_i32();
873 tcg_gen_ext8s_tl(t0
, Rd
); /* make Rd full 32 bit signed */
874 tcg_gen_ext8s_tl(t1
, Rr
); /* make Rr full 32 bit signed */
875 tcg_gen_mul_tl(R
, t0
, t1
); /* R = Rd * Rr */
876 tcg_gen_andi_tl(R
, R
, 0xffff); /* make it 16 bits */
878 /* update status register */
879 tcg_gen_shri_tl(cpu_Cf
, R
, 15); /* Cf = R(15) */
880 tcg_gen_setcondi_tl(TCG_COND_EQ
, cpu_Zf
, R
, 0); /* Zf = R == 0 */
882 /* update output registers */
883 tcg_gen_shli_tl(R
, R
, 1);
884 tcg_gen_andi_tl(R0
, R
, 0xff);
885 tcg_gen_shri_tl(R1
, R
, 8);
886 tcg_gen_andi_tl(R1
, R1
, 0xff);
888 tcg_temp_free_i32(t1
);
889 tcg_temp_free_i32(t0
);
890 tcg_temp_free_i32(R
);
896 * This instruction performs 8-bit x 8-bit -> 16-bit signed multiplication
897 * and shifts the result one bit left.
899 static bool trans_FMULSU(DisasContext
*ctx
, arg_FMULSU
*a
)
901 if (!avr_have_feature(ctx
, AVR_FEATURE_MUL
)) {
907 TCGv Rd
= cpu_r
[a
->rd
];
908 TCGv Rr
= cpu_r
[a
->rr
];
909 TCGv R
= tcg_temp_new_i32();
910 TCGv t0
= tcg_temp_new_i32();
912 tcg_gen_ext8s_tl(t0
, Rd
); /* make Rd full 32 bit signed */
913 tcg_gen_mul_tl(R
, t0
, Rr
); /* R = Rd * Rr */
914 tcg_gen_andi_tl(R
, R
, 0xffff); /* make it 16 bits */
916 /* update status register */
917 tcg_gen_shri_tl(cpu_Cf
, R
, 15); /* Cf = R(15) */
918 tcg_gen_setcondi_tl(TCG_COND_EQ
, cpu_Zf
, R
, 0); /* Zf = R == 0 */
920 /* update output registers */
921 tcg_gen_shli_tl(R
, R
, 1);
922 tcg_gen_andi_tl(R0
, R
, 0xff);
923 tcg_gen_shri_tl(R1
, R
, 8);
924 tcg_gen_andi_tl(R1
, R1
, 0xff);
926 tcg_temp_free_i32(t0
);
927 tcg_temp_free_i32(R
);
933 * The module is an instruction set extension to the AVR CPU, performing
934 * DES iterations. The 64-bit data block (plaintext or ciphertext) is placed in
935 * the CPU register file, registers R0-R7, where LSB of data is placed in LSB
936 * of R0 and MSB of data is placed in MSB of R7. The full 64-bit key (including
937 * parity bits) is placed in registers R8- R15, organized in the register file
938 * with LSB of key in LSB of R8 and MSB of key in MSB of R15. Executing one DES
939 * instruction performs one round in the DES algorithm. Sixteen rounds must be
940 * executed in increasing order to form the correct DES ciphertext or
941 * plaintext. Intermediate results are stored in the register file (R0-R15)
942 * after each DES instruction. The instruction's operand (K) determines which
943 * round is executed, and the half carry flag (H) determines whether encryption
944 * or decryption is performed. The DES algorithm is described in
945 * "Specifications for the Data Encryption Standard" (Federal Information
946 * Processing Standards Publication 46). Intermediate results in this
947 * implementation differ from the standard because the initial permutation and
948 * the inverse initial permutation are performed each iteration. This does not
949 * affect the result in the final ciphertext or plaintext, but reduces
952 static bool trans_DES(DisasContext
*ctx
, arg_DES
*a
)
955 if (!avr_have_feature(ctx
, AVR_FEATURE_DES
)) {
959 qemu_log_mask(LOG_UNIMP
, "%s: not implemented\n", __func__
);