1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21#include "qemu/osdep.h"
22#include "qemu/qemu-print.h"
23#include "tcg/tcg.h"
24#include "cpu.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"
30#include "exec/log.h"
31#include "exec/translator.h"
32#include "exec/gen-icount.h"
33
34
35
36
37
38
39
40
41#undef BREAKPOINT_ON_BREAK
42
43static TCGv cpu_pc;
44
45static TCGv cpu_Cf;
46static TCGv cpu_Zf;
47static TCGv cpu_Nf;
48static TCGv cpu_Vf;
49static TCGv cpu_Sf;
50static TCGv cpu_Hf;
51static TCGv cpu_Tf;
52static TCGv cpu_If;
53
54static TCGv cpu_rampD;
55static TCGv cpu_rampX;
56static TCGv cpu_rampY;
57static TCGv cpu_rampZ;
58
59static TCGv cpu_r[NUMBER_OF_CPU_REGISTERS];
60static TCGv cpu_eind;
61static TCGv cpu_sp;
62
63static TCGv cpu_skip;
64
65static 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",
70};
71#define REG(x) (cpu_r[x])
72
73enum {
74 DISAS_EXIT = DISAS_TARGET_0,
75 DISAS_LOOKUP = DISAS_TARGET_1,
76 DISAS_CHAIN = DISAS_TARGET_2,
77};
78
79typedef struct DisasContext DisasContext;
80
81
82struct DisasContext {
83 DisasContextBase base;
84
85 CPUAVRState *env;
86 CPUState *cs;
87
88 target_long npc;
89 uint32_t opcode;
90
91
92 int memidx;
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123 TCGv skip_var0;
124 TCGv skip_var1;
125 TCGCond skip_cond;
126 bool free_skip_var0;
127};
128
129void avr_cpu_tcg_init(void)
130{
131 int i;
132
133#define AVR_REG_OFFS(x) offsetof(CPUAVRState, x)
134 cpu_pc = tcg_global_mem_new_i32(cpu_env, AVR_REG_OFFS(pc_w), "pc");
135 cpu_Cf = tcg_global_mem_new_i32(cpu_env, AVR_REG_OFFS(sregC), "Cf");
136 cpu_Zf = tcg_global_mem_new_i32(cpu_env, AVR_REG_OFFS(sregZ), "Zf");
137 cpu_Nf = tcg_global_mem_new_i32(cpu_env, AVR_REG_OFFS(sregN), "Nf");
138 cpu_Vf = tcg_global_mem_new_i32(cpu_env, AVR_REG_OFFS(sregV), "Vf");
139 cpu_Sf = tcg_global_mem_new_i32(cpu_env, AVR_REG_OFFS(sregS), "Sf");
140 cpu_Hf = tcg_global_mem_new_i32(cpu_env, AVR_REG_OFFS(sregH), "Hf");
141 cpu_Tf = tcg_global_mem_new_i32(cpu_env, AVR_REG_OFFS(sregT), "Tf");
142 cpu_If = tcg_global_mem_new_i32(cpu_env, AVR_REG_OFFS(sregI), "If");
143 cpu_rampD = tcg_global_mem_new_i32(cpu_env, AVR_REG_OFFS(rampD), "rampD");
144 cpu_rampX = tcg_global_mem_new_i32(cpu_env, AVR_REG_OFFS(rampX), "rampX");
145 cpu_rampY = tcg_global_mem_new_i32(cpu_env, AVR_REG_OFFS(rampY), "rampY");
146 cpu_rampZ = tcg_global_mem_new_i32(cpu_env, AVR_REG_OFFS(rampZ), "rampZ");
147 cpu_eind = tcg_global_mem_new_i32(cpu_env, AVR_REG_OFFS(eind), "eind");
148 cpu_sp = tcg_global_mem_new_i32(cpu_env, AVR_REG_OFFS(sp), "sp");
149 cpu_skip = tcg_global_mem_new_i32(cpu_env, AVR_REG_OFFS(skip), "skip");
150
151 for (i = 0; i < NUMBER_OF_CPU_REGISTERS; i++) {
152 cpu_r[i] = tcg_global_mem_new_i32(cpu_env, AVR_REG_OFFS(r[i]),
153 reg_names[i]);
154 }
155#undef AVR_REG_OFFS
156}
157
158static int to_regs_16_31_by_one(DisasContext *ctx, int indx)
159{
160 return 16 + (indx % 16);
161}
162
163static int to_regs_16_23_by_one(DisasContext *ctx, int indx)
164{
165 return 16 + (indx % 8);
166}
167
168static int to_regs_24_30_by_two(DisasContext *ctx, int indx)
169{
170 return 24 + (indx % 4) * 2;
171}
172
173static int to_regs_00_30_by_two(DisasContext *ctx, int indx)
174{
175 return (indx % 16) * 2;
176}
177
178static uint16_t next_word(DisasContext *ctx)
179{
180 return cpu_lduw_code(ctx->env, ctx->npc++ * 2);
181}
182
183static int append_16(DisasContext *ctx, int x)
184{
185 return x << 16 | next_word(ctx);
186}
187
188static bool avr_have_feature(DisasContext *ctx, int feature)
189{
190 if (!avr_feature(ctx->env, feature)) {
191 gen_helper_unsupported(cpu_env);
192 ctx->base.is_jmp = DISAS_NORETURN;
193 return false;
194 }
195 return true;
196}
197
198static bool decode_insn(DisasContext *ctx, uint16_t insn);
199#include "decode-insn.c.inc"
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217static void gen_add_CHf(TCGv R, TCGv Rd, TCGv Rr)
218{
219 TCGv t1 = tcg_temp_new_i32();
220 TCGv t2 = tcg_temp_new_i32();
221 TCGv t3 = tcg_temp_new_i32();
222
223 tcg_gen_and_tl(t1, Rd, Rr);
224 tcg_gen_andc_tl(t2, Rd, R);
225 tcg_gen_andc_tl(t3, Rr, R);
226 tcg_gen_or_tl(t1, t1, t2);
227 tcg_gen_or_tl(t1, t1, t3);
228
229 tcg_gen_shri_tl(cpu_Cf, t1, 7);
230 tcg_gen_shri_tl(cpu_Hf, t1, 3);
231 tcg_gen_andi_tl(cpu_Hf, cpu_Hf, 1);
232
233 tcg_temp_free_i32(t3);
234 tcg_temp_free_i32(t2);
235 tcg_temp_free_i32(t1);
236}
237
238static void gen_add_Vf(TCGv R, TCGv Rd, TCGv Rr)
239{
240 TCGv t1 = tcg_temp_new_i32();
241 TCGv t2 = tcg_temp_new_i32();
242
243
244
245 tcg_gen_xor_tl(t1, Rd, R);
246 tcg_gen_xor_tl(t2, Rd, Rr);
247 tcg_gen_andc_tl(t1, t1, t2);
248
249 tcg_gen_shri_tl(cpu_Vf, t1, 7);
250
251 tcg_temp_free_i32(t2);
252 tcg_temp_free_i32(t1);
253}
254
255static void gen_sub_CHf(TCGv R, TCGv Rd, TCGv Rr)
256{
257 TCGv t1 = tcg_temp_new_i32();
258 TCGv t2 = tcg_temp_new_i32();
259 TCGv t3 = tcg_temp_new_i32();
260
261 tcg_gen_not_tl(t1, Rd);
262 tcg_gen_and_tl(t2, t1, Rr);
263 tcg_gen_or_tl(t3, t1, Rr);
264 tcg_gen_and_tl(t3, t3, R);
265 tcg_gen_or_tl(t2, t2, t3);
266
267 tcg_gen_shri_tl(cpu_Cf, t2, 7);
268 tcg_gen_shri_tl(cpu_Hf, t2, 3);
269 tcg_gen_andi_tl(cpu_Hf, cpu_Hf, 1);
270
271 tcg_temp_free_i32(t3);
272 tcg_temp_free_i32(t2);
273 tcg_temp_free_i32(t1);
274}
275
276static void gen_sub_Vf(TCGv R, TCGv Rd, TCGv Rr)
277{
278 TCGv t1 = tcg_temp_new_i32();
279 TCGv t2 = tcg_temp_new_i32();
280
281
282
283 tcg_gen_xor_tl(t1, Rd, R);
284 tcg_gen_xor_tl(t2, Rd, Rr);
285 tcg_gen_and_tl(t1, t1, t2);
286
287 tcg_gen_shri_tl(cpu_Vf, t1, 7);
288
289 tcg_temp_free_i32(t2);
290 tcg_temp_free_i32(t1);
291}
292
293static void gen_NSf(TCGv R)
294{
295 tcg_gen_shri_tl(cpu_Nf, R, 7);
296 tcg_gen_xor_tl(cpu_Sf, cpu_Nf, cpu_Vf);
297}
298
299static void gen_ZNSf(TCGv R)
300{
301 tcg_gen_setcondi_tl(TCG_COND_EQ, cpu_Zf, R, 0);
302
303
304 tcg_gen_shri_tl(cpu_Nf, R, 7);
305 tcg_gen_xor_tl(cpu_Sf, cpu_Nf, cpu_Vf);
306}
307
308
309
310
311
312static bool trans_ADD(DisasContext *ctx, arg_ADD *a)
313{
314 TCGv Rd = cpu_r[a->rd];
315 TCGv Rr = cpu_r[a->rr];
316 TCGv R = tcg_temp_new_i32();
317
318 tcg_gen_add_tl(R, Rd, Rr);
319 tcg_gen_andi_tl(R, R, 0xff);
320
321
322 gen_add_CHf(R, Rd, Rr);
323 gen_add_Vf(R, Rd, Rr);
324 gen_ZNSf(R);
325
326
327 tcg_gen_mov_tl(Rd, R);
328
329 tcg_temp_free_i32(R);
330
331 return true;
332}
333
334
335
336
337
338static bool trans_ADC(DisasContext *ctx, arg_ADC *a)
339{
340 TCGv Rd = cpu_r[a->rd];
341 TCGv Rr = cpu_r[a->rr];
342 TCGv R = tcg_temp_new_i32();
343
344 tcg_gen_add_tl(R, Rd, Rr);
345 tcg_gen_add_tl(R, R, cpu_Cf);
346 tcg_gen_andi_tl(R, R, 0xff);
347
348
349 gen_add_CHf(R, Rd, Rr);
350 gen_add_Vf(R, Rd, Rr);
351 gen_ZNSf(R);
352
353
354 tcg_gen_mov_tl(Rd, R);
355
356 tcg_temp_free_i32(R);
357
358 return true;
359}
360
361
362
363
364
365
366
367
368static bool trans_ADIW(DisasContext *ctx, arg_ADIW *a)
369{
370 if (!avr_have_feature(ctx, AVR_FEATURE_ADIW_SBIW)) {
371 return true;
372 }
373
374 TCGv RdL = cpu_r[a->rd];
375 TCGv RdH = cpu_r[a->rd + 1];
376 int Imm = (a->imm);
377 TCGv R = tcg_temp_new_i32();
378 TCGv Rd = tcg_temp_new_i32();
379
380 tcg_gen_deposit_tl(Rd, RdL, RdH, 8, 8);
381 tcg_gen_addi_tl(R, Rd, Imm);
382 tcg_gen_andi_tl(R, R, 0xffff);
383
384
385 tcg_gen_andc_tl(cpu_Cf, Rd, R);
386 tcg_gen_shri_tl(cpu_Cf, cpu_Cf, 15);
387 tcg_gen_andc_tl(cpu_Vf, R, Rd);
388 tcg_gen_shri_tl(cpu_Vf, cpu_Vf, 15);
389 tcg_gen_setcondi_tl(TCG_COND_EQ, cpu_Zf, R, 0);
390 tcg_gen_shri_tl(cpu_Nf, R, 15);
391 tcg_gen_xor_tl(cpu_Sf, cpu_Nf, cpu_Vf);
392
393
394 tcg_gen_andi_tl(RdL, R, 0xff);
395 tcg_gen_shri_tl(RdH, R, 8);
396
397 tcg_temp_free_i32(Rd);
398 tcg_temp_free_i32(R);
399
400 return true;
401}
402
403
404
405
406
407static bool trans_SUB(DisasContext *ctx, arg_SUB *a)
408{
409 TCGv Rd = cpu_r[a->rd];
410 TCGv Rr = cpu_r[a->rr];
411 TCGv R = tcg_temp_new_i32();
412
413 tcg_gen_sub_tl(R, Rd, Rr);
414 tcg_gen_andi_tl(R, R, 0xff);
415
416
417 tcg_gen_andc_tl(cpu_Cf, Rd, R);
418 gen_sub_CHf(R, Rd, Rr);
419 gen_sub_Vf(R, Rd, Rr);
420 gen_ZNSf(R);
421
422
423 tcg_gen_mov_tl(Rd, R);
424
425 tcg_temp_free_i32(R);
426
427 return true;
428}
429
430
431
432
433
434
435static bool trans_SUBI(DisasContext *ctx, arg_SUBI *a)
436{
437 TCGv Rd = cpu_r[a->rd];
438 TCGv Rr = tcg_const_i32(a->imm);
439 TCGv R = tcg_temp_new_i32();
440
441 tcg_gen_sub_tl(R, Rd, Rr);
442 tcg_gen_andi_tl(R, R, 0xff);
443
444
445 gen_sub_CHf(R, Rd, Rr);
446 gen_sub_Vf(R, Rd, Rr);
447 gen_ZNSf(R);
448
449
450 tcg_gen_mov_tl(Rd, R);
451
452 tcg_temp_free_i32(R);
453 tcg_temp_free_i32(Rr);
454
455 return true;
456}
457
458
459
460
461
462static bool trans_SBC(DisasContext *ctx, arg_SBC *a)
463{
464 TCGv Rd = cpu_r[a->rd];
465 TCGv Rr = cpu_r[a->rr];
466 TCGv R = tcg_temp_new_i32();
467 TCGv zero = tcg_const_i32(0);
468
469 tcg_gen_sub_tl(R, Rd, Rr);
470 tcg_gen_sub_tl(R, R, cpu_Cf);
471 tcg_gen_andi_tl(R, R, 0xff);
472
473
474 gen_sub_CHf(R, Rd, Rr);
475 gen_sub_Vf(R, Rd, Rr);
476 gen_NSf(R);
477
478
479
480
481
482 tcg_gen_movcond_tl(TCG_COND_EQ, cpu_Zf, R, zero, cpu_Zf, zero);
483
484
485 tcg_gen_mov_tl(Rd, R);
486
487 tcg_temp_free_i32(zero);
488 tcg_temp_free_i32(R);
489
490 return true;
491}
492
493
494
495
496static bool trans_SBCI(DisasContext *ctx, arg_SBCI *a)
497{
498 TCGv Rd = cpu_r[a->rd];
499 TCGv Rr = tcg_const_i32(a->imm);
500 TCGv R = tcg_temp_new_i32();
501 TCGv zero = tcg_const_i32(0);
502
503 tcg_gen_sub_tl(R, Rd, Rr);
504 tcg_gen_sub_tl(R, R, cpu_Cf);
505 tcg_gen_andi_tl(R, R, 0xff);
506
507
508 gen_sub_CHf(R, Rd, Rr);
509 gen_sub_Vf(R, Rd, Rr);
510 gen_NSf(R);
511
512
513
514
515
516 tcg_gen_movcond_tl(TCG_COND_EQ, cpu_Zf, R, zero, cpu_Zf, zero);
517
518
519 tcg_gen_mov_tl(Rd, R);
520
521 tcg_temp_free_i32(zero);
522 tcg_temp_free_i32(R);
523 tcg_temp_free_i32(Rr);
524
525 return true;
526}
527
528
529
530
531
532
533
534
535static bool trans_SBIW(DisasContext *ctx, arg_SBIW *a)
536{
537 if (!avr_have_feature(ctx, AVR_FEATURE_ADIW_SBIW)) {
538 return true;
539 }
540
541 TCGv RdL = cpu_r[a->rd];
542 TCGv RdH = cpu_r[a->rd + 1];
543 int Imm = (a->imm);
544 TCGv R = tcg_temp_new_i32();
545 TCGv Rd = tcg_temp_new_i32();
546
547 tcg_gen_deposit_tl(Rd, RdL, RdH, 8, 8);
548 tcg_gen_subi_tl(R, Rd, Imm);
549 tcg_gen_andi_tl(R, R, 0xffff);
550
551
552 tcg_gen_andc_tl(cpu_Cf, R, Rd);
553 tcg_gen_shri_tl(cpu_Cf, cpu_Cf, 15);
554 tcg_gen_andc_tl(cpu_Vf, Rd, R);
555 tcg_gen_shri_tl(cpu_Vf, cpu_Vf, 15);
556 tcg_gen_setcondi_tl(TCG_COND_EQ, cpu_Zf, R, 0);
557 tcg_gen_shri_tl(cpu_Nf, R, 15);
558 tcg_gen_xor_tl(cpu_Sf, cpu_Nf, cpu_Vf);
559
560
561 tcg_gen_andi_tl(RdL, R, 0xff);
562 tcg_gen_shri_tl(RdH, R, 8);
563
564 tcg_temp_free_i32(Rd);
565 tcg_temp_free_i32(R);
566
567 return true;
568}
569
570
571
572
573
574static bool trans_AND(DisasContext *ctx, arg_AND *a)
575{
576 TCGv Rd = cpu_r[a->rd];
577 TCGv Rr = cpu_r[a->rr];
578 TCGv R = tcg_temp_new_i32();
579
580 tcg_gen_and_tl(R, Rd, Rr);
581
582
583 tcg_gen_movi_tl(cpu_Vf, 0);
584 tcg_gen_setcondi_tl(TCG_COND_EQ, cpu_Zf, R, 0);
585 gen_ZNSf(R);
586
587
588 tcg_gen_mov_tl(Rd, R);
589
590 tcg_temp_free_i32(R);
591
592 return true;
593}
594
595
596
597
598
599static bool trans_ANDI(DisasContext *ctx, arg_ANDI *a)
600{
601 TCGv Rd = cpu_r[a->rd];
602 int Imm = (a->imm);
603
604 tcg_gen_andi_tl(Rd, Rd, Imm);
605
606
607 tcg_gen_movi_tl(cpu_Vf, 0x00);
608 gen_ZNSf(Rd);
609
610 return true;
611}
612
613
614
615
616
617static bool trans_OR(DisasContext *ctx, arg_OR *a)
618{
619 TCGv Rd = cpu_r[a->rd];
620 TCGv Rr = cpu_r[a->rr];
621 TCGv R = tcg_temp_new_i32();
622
623 tcg_gen_or_tl(R, Rd, Rr);
624
625
626 tcg_gen_movi_tl(cpu_Vf, 0);
627 gen_ZNSf(R);
628
629
630 tcg_gen_mov_tl(Rd, R);
631
632 tcg_temp_free_i32(R);
633
634 return true;
635}
636
637
638
639
640
641static bool trans_ORI(DisasContext *ctx, arg_ORI *a)
642{
643 TCGv Rd = cpu_r[a->rd];
644 int Imm = (a->imm);
645
646 tcg_gen_ori_tl(Rd, Rd, Imm);
647
648
649 tcg_gen_movi_tl(cpu_Vf, 0x00);
650 gen_ZNSf(Rd);
651
652 return true;
653}
654
655
656
657
658
659static bool trans_EOR(DisasContext *ctx, arg_EOR *a)
660{
661 TCGv Rd = cpu_r[a->rd];
662 TCGv Rr = cpu_r[a->rr];
663
664 tcg_gen_xor_tl(Rd, Rd, Rr);
665
666
667 tcg_gen_movi_tl(cpu_Vf, 0);
668 gen_ZNSf(Rd);
669
670 return true;
671}
672
673
674
675
676
677
678static bool trans_COM(DisasContext *ctx, arg_COM *a)
679{
680 TCGv Rd = cpu_r[a->rd];
681 TCGv R = tcg_temp_new_i32();
682
683 tcg_gen_xori_tl(Rd, Rd, 0xff);
684
685
686 tcg_gen_movi_tl(cpu_Cf, 1);
687 tcg_gen_movi_tl(cpu_Vf, 0);
688 gen_ZNSf(Rd);
689
690 tcg_temp_free_i32(R);
691
692 return true;
693}
694
695
696
697
698
699static bool trans_NEG(DisasContext *ctx, arg_NEG *a)
700{
701 TCGv Rd = cpu_r[a->rd];
702 TCGv t0 = tcg_const_i32(0);
703 TCGv R = tcg_temp_new_i32();
704
705 tcg_gen_sub_tl(R, t0, Rd);
706 tcg_gen_andi_tl(R, R, 0xff);
707
708
709 gen_sub_CHf(R, t0, Rd);
710 gen_sub_Vf(R, t0, Rd);
711 gen_ZNSf(R);
712
713
714 tcg_gen_mov_tl(Rd, R);
715
716 tcg_temp_free_i32(t0);
717 tcg_temp_free_i32(R);
718
719 return true;
720}
721
722
723
724
725
726
727
728
729
730static bool trans_INC(DisasContext *ctx, arg_INC *a)
731{
732 TCGv Rd = cpu_r[a->rd];
733
734 tcg_gen_addi_tl(Rd, Rd, 1);
735 tcg_gen_andi_tl(Rd, Rd, 0xff);
736
737
738 tcg_gen_setcondi_tl(TCG_COND_EQ, cpu_Vf, Rd, 0x80);
739 gen_ZNSf(Rd);
740
741 return true;
742}
743
744
745
746
747
748
749
750
751
752static bool trans_DEC(DisasContext *ctx, arg_DEC *a)
753{
754 TCGv Rd = cpu_r[a->rd];
755
756 tcg_gen_subi_tl(Rd, Rd, 1);
757 tcg_gen_andi_tl(Rd, Rd, 0xff);
758
759
760 tcg_gen_setcondi_tl(TCG_COND_EQ, cpu_Vf, Rd, 0x7f);
761 gen_ZNSf(Rd);
762
763 return true;
764}
765
766
767
768
769static bool trans_MUL(DisasContext *ctx, arg_MUL *a)
770{
771 if (!avr_have_feature(ctx, AVR_FEATURE_MUL)) {
772 return true;
773 }
774
775 TCGv R0 = cpu_r[0];
776 TCGv R1 = cpu_r[1];
777 TCGv Rd = cpu_r[a->rd];
778 TCGv Rr = cpu_r[a->rr];
779 TCGv R = tcg_temp_new_i32();
780
781 tcg_gen_mul_tl(R, Rd, Rr);
782 tcg_gen_andi_tl(R0, R, 0xff);
783 tcg_gen_shri_tl(R1, R, 8);
784
785
786 tcg_gen_shri_tl(cpu_Cf, R, 15);
787 tcg_gen_setcondi_tl(TCG_COND_EQ, cpu_Zf, R, 0);
788
789 tcg_temp_free_i32(R);
790
791 return true;
792}
793
794
795
796
797static bool trans_MULS(DisasContext *ctx, arg_MULS *a)
798{
799 if (!avr_have_feature(ctx, AVR_FEATURE_MUL)) {
800 return true;
801 }
802
803 TCGv R0 = cpu_r[0];
804 TCGv R1 = cpu_r[1];
805 TCGv Rd = cpu_r[a->rd];
806 TCGv Rr = cpu_r[a->rr];
807 TCGv R = tcg_temp_new_i32();
808 TCGv t0 = tcg_temp_new_i32();
809 TCGv t1 = tcg_temp_new_i32();
810
811 tcg_gen_ext8s_tl(t0, Rd);
812 tcg_gen_ext8s_tl(t1, Rr);
813 tcg_gen_mul_tl(R, t0, t1);
814 tcg_gen_andi_tl(R, R, 0xffff);
815 tcg_gen_andi_tl(R0, R, 0xff);
816 tcg_gen_shri_tl(R1, R, 8);
817
818
819 tcg_gen_shri_tl(cpu_Cf, R, 15);
820 tcg_gen_setcondi_tl(TCG_COND_EQ, cpu_Zf, R, 0);
821
822 tcg_temp_free_i32(t1);
823 tcg_temp_free_i32(t0);
824 tcg_temp_free_i32(R);
825
826 return true;
827}
828
829
830
831
832
833static bool trans_MULSU(DisasContext *ctx, arg_MULSU *a)
834{
835 if (!avr_have_feature(ctx, AVR_FEATURE_MUL)) {
836 return true;
837 }
838
839 TCGv R0 = cpu_r[0];
840 TCGv R1 = cpu_r[1];
841 TCGv Rd = cpu_r[a->rd];
842 TCGv Rr = cpu_r[a->rr];
843 TCGv R = tcg_temp_new_i32();
844 TCGv t0 = tcg_temp_new_i32();
845
846 tcg_gen_ext8s_tl(t0, Rd);
847 tcg_gen_mul_tl(R, t0, Rr);
848 tcg_gen_andi_tl(R, R, 0xffff);
849 tcg_gen_andi_tl(R0, R, 0xff);
850 tcg_gen_shri_tl(R1, R, 8);
851
852
853 tcg_gen_shri_tl(cpu_Cf, R, 15);
854 tcg_gen_setcondi_tl(TCG_COND_EQ, cpu_Zf, R, 0);
855
856 tcg_temp_free_i32(t0);
857 tcg_temp_free_i32(R);
858
859 return true;
860}
861
862
863
864
865
866static bool trans_FMUL(DisasContext *ctx, arg_FMUL *a)
867{
868 if (!avr_have_feature(ctx, AVR_FEATURE_MUL)) {
869 return true;
870 }
871
872 TCGv R0 = cpu_r[0];
873 TCGv R1 = cpu_r[1];
874 TCGv Rd = cpu_r[a->rd];
875 TCGv Rr = cpu_r[a->rr];
876 TCGv R = tcg_temp_new_i32();
877
878 tcg_gen_mul_tl(R, Rd, Rr);
879
880
881 tcg_gen_shri_tl(cpu_Cf, R, 15);
882 tcg_gen_setcondi_tl(TCG_COND_EQ, cpu_Zf, R, 0);
883
884
885 tcg_gen_shli_tl(R, R, 1);
886 tcg_gen_andi_tl(R0, R, 0xff);
887 tcg_gen_shri_tl(R1, R, 8);
888 tcg_gen_andi_tl(R1, R1, 0xff);
889
890
891 tcg_temp_free_i32(R);
892
893 return true;
894}
895
896
897
898
899
900static bool trans_FMULS(DisasContext *ctx, arg_FMULS *a)
901{
902 if (!avr_have_feature(ctx, AVR_FEATURE_MUL)) {
903 return true;
904 }
905
906 TCGv R0 = cpu_r[0];
907 TCGv R1 = cpu_r[1];
908 TCGv Rd = cpu_r[a->rd];
909 TCGv Rr = cpu_r[a->rr];
910 TCGv R = tcg_temp_new_i32();
911 TCGv t0 = tcg_temp_new_i32();
912 TCGv t1 = tcg_temp_new_i32();
913
914 tcg_gen_ext8s_tl(t0, Rd);
915 tcg_gen_ext8s_tl(t1, Rr);
916 tcg_gen_mul_tl(R, t0, t1);
917 tcg_gen_andi_tl(R, R, 0xffff);
918
919
920 tcg_gen_shri_tl(cpu_Cf, R, 15);
921 tcg_gen_setcondi_tl(TCG_COND_EQ, cpu_Zf, R, 0);
922
923
924 tcg_gen_shli_tl(R, R, 1);
925 tcg_gen_andi_tl(R0, R, 0xff);
926 tcg_gen_shri_tl(R1, R, 8);
927 tcg_gen_andi_tl(R1, R1, 0xff);
928
929 tcg_temp_free_i32(t1);
930 tcg_temp_free_i32(t0);
931 tcg_temp_free_i32(R);
932
933 return true;
934}
935
936
937
938
939
940static bool trans_FMULSU(DisasContext *ctx, arg_FMULSU *a)
941{
942 if (!avr_have_feature(ctx, AVR_FEATURE_MUL)) {
943 return true;
944 }
945
946 TCGv R0 = cpu_r[0];
947 TCGv R1 = cpu_r[1];
948 TCGv Rd = cpu_r[a->rd];
949 TCGv Rr = cpu_r[a->rr];
950 TCGv R = tcg_temp_new_i32();
951 TCGv t0 = tcg_temp_new_i32();
952
953 tcg_gen_ext8s_tl(t0, Rd);
954 tcg_gen_mul_tl(R, t0, Rr);
955 tcg_gen_andi_tl(R, R, 0xffff);
956
957
958 tcg_gen_shri_tl(cpu_Cf, R, 15);
959 tcg_gen_setcondi_tl(TCG_COND_EQ, cpu_Zf, R, 0);
960
961
962 tcg_gen_shli_tl(R, R, 1);
963 tcg_gen_andi_tl(R0, R, 0xff);
964 tcg_gen_shri_tl(R1, R, 8);
965 tcg_gen_andi_tl(R1, R1, 0xff);
966
967 tcg_temp_free_i32(t0);
968 tcg_temp_free_i32(R);
969
970 return true;
971}
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993static bool trans_DES(DisasContext *ctx, arg_DES *a)
994{
995
996 if (!avr_have_feature(ctx, AVR_FEATURE_DES)) {
997 return true;
998 }
999
1000 qemu_log_mask(LOG_UNIMP, "%s: not implemented\n", __func__);
1001
1002 return true;
1003}
1004
1005
1006
1007
1008static void gen_jmp_ez(DisasContext *ctx)
1009{
1010 tcg_gen_deposit_tl(cpu_pc, cpu_r[30], cpu_r[31], 8, 8);
1011 tcg_gen_or_tl(cpu_pc, cpu_pc, cpu_eind);
1012 ctx->base.is_jmp = DISAS_LOOKUP;
1013}
1014
1015static void gen_jmp_z(DisasContext *ctx)
1016{
1017 tcg_gen_deposit_tl(cpu_pc, cpu_r[30], cpu_r[31], 8, 8);
1018 ctx->base.is_jmp = DISAS_LOOKUP;
1019}
1020
1021static void gen_push_ret(DisasContext *ctx, int ret)
1022{
1023 if (avr_feature(ctx->env, AVR_FEATURE_1_BYTE_PC)) {
1024
1025 TCGv t0 = tcg_const_i32((ret & 0x0000ff));
1026
1027 tcg_gen_qemu_st_tl(t0, cpu_sp, MMU_DATA_IDX, MO_UB);
1028 tcg_gen_subi_tl(cpu_sp, cpu_sp, 1);
1029
1030 tcg_temp_free_i32(t0);
1031 } else if (avr_feature(ctx->env, AVR_FEATURE_2_BYTE_PC)) {
1032
1033 TCGv t0 = tcg_const_i32((ret & 0x00ffff));
1034
1035 tcg_gen_subi_tl(cpu_sp, cpu_sp, 1);
1036 tcg_gen_qemu_st_tl(t0, cpu_sp, MMU_DATA_IDX, MO_BEUW);
1037 tcg_gen_subi_tl(cpu_sp, cpu_sp, 1);
1038
1039 tcg_temp_free_i32(t0);
1040
1041 } else if (avr_feature(ctx->env, AVR_FEATURE_3_BYTE_PC)) {
1042
1043 TCGv lo = tcg_const_i32((ret & 0x0000ff));
1044 TCGv hi = tcg_const_i32((ret & 0xffff00) >> 8);
1045
1046 tcg_gen_qemu_st_tl(lo, cpu_sp, MMU_DATA_IDX, MO_UB);
1047 tcg_gen_subi_tl(cpu_sp, cpu_sp, 2);
1048 tcg_gen_qemu_st_tl(hi, cpu_sp, MMU_DATA_IDX, MO_BEUW);
1049 tcg_gen_subi_tl(cpu_sp, cpu_sp, 1);
1050
1051 tcg_temp_free_i32(lo);
1052 tcg_temp_free_i32(hi);
1053 }
1054}
1055
1056static void gen_pop_ret(DisasContext *ctx, TCGv ret)
1057{
1058 if (avr_feature(ctx->env, AVR_FEATURE_1_BYTE_PC)) {
1059 tcg_gen_addi_tl(cpu_sp, cpu_sp, 1);
1060 tcg_gen_qemu_ld_tl(ret, cpu_sp, MMU_DATA_IDX, MO_UB);
1061 } else if (avr_feature(ctx->env, AVR_FEATURE_2_BYTE_PC)) {
1062 tcg_gen_addi_tl(cpu_sp, cpu_sp, 1);
1063 tcg_gen_qemu_ld_tl(ret, cpu_sp, MMU_DATA_IDX, MO_BEUW);
1064 tcg_gen_addi_tl(cpu_sp, cpu_sp, 1);
1065 } else if (avr_feature(ctx->env, AVR_FEATURE_3_BYTE_PC)) {
1066 TCGv lo = tcg_temp_new_i32();
1067 TCGv hi = tcg_temp_new_i32();
1068
1069 tcg_gen_addi_tl(cpu_sp, cpu_sp, 1);
1070 tcg_gen_qemu_ld_tl(hi, cpu_sp, MMU_DATA_IDX, MO_BEUW);
1071
1072 tcg_gen_addi_tl(cpu_sp, cpu_sp, 2);
1073 tcg_gen_qemu_ld_tl(lo, cpu_sp, MMU_DATA_IDX, MO_UB);
1074
1075 tcg_gen_deposit_tl(ret, lo, hi, 8, 16);
1076
1077 tcg_temp_free_i32(lo);
1078 tcg_temp_free_i32(hi);
1079 }
1080}
1081
1082static void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest)
1083{
1084 const TranslationBlock *tb = ctx->base.tb;
1085
1086 if (translator_use_goto_tb(&ctx->base, dest)) {
1087 tcg_gen_goto_tb(n);
1088 tcg_gen_movi_i32(cpu_pc, dest);
1089 tcg_gen_exit_tb(tb, n);
1090 } else {
1091 tcg_gen_movi_i32(cpu_pc, dest);
1092 if (ctx->base.singlestep_enabled) {
1093 gen_helper_debug(cpu_env);
1094 } else {
1095 tcg_gen_lookup_and_goto_ptr();
1096 }
1097 }
1098 ctx->base.is_jmp = DISAS_NORETURN;
1099}
1100
1101
1102
1103
1104
1105
1106
1107static bool trans_RJMP(DisasContext *ctx, arg_RJMP *a)
1108{
1109 int dst = ctx->npc + a->imm;
1110
1111 gen_goto_tb(ctx, 0, dst);
1112
1113 return true;
1114}
1115
1116
1117
1118
1119
1120
1121
1122
1123static bool trans_IJMP(DisasContext *ctx, arg_IJMP *a)
1124{
1125 if (!avr_have_feature(ctx, AVR_FEATURE_IJMP_ICALL)) {
1126 return true;
1127 }
1128
1129 gen_jmp_z(ctx);
1130
1131 return true;
1132}
1133
1134
1135
1136
1137
1138
1139
1140
1141static bool trans_EIJMP(DisasContext *ctx, arg_EIJMP *a)
1142{
1143 if (!avr_have_feature(ctx, AVR_FEATURE_EIJMP_EICALL)) {
1144 return true;
1145 }
1146
1147 gen_jmp_ez(ctx);
1148 return true;
1149}
1150
1151
1152
1153
1154
1155
1156static bool trans_JMP(DisasContext *ctx, arg_JMP *a)
1157{
1158 if (!avr_have_feature(ctx, AVR_FEATURE_JMP_CALL)) {
1159 return true;
1160 }
1161
1162 gen_goto_tb(ctx, 0, a->imm);
1163
1164 return true;
1165}
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175static bool trans_RCALL(DisasContext *ctx, arg_RCALL *a)
1176{
1177 int ret = ctx->npc;
1178 int dst = ctx->npc + a->imm;
1179
1180 gen_push_ret(ctx, ret);
1181 gen_goto_tb(ctx, 0, dst);
1182
1183 return true;
1184}
1185
1186
1187
1188
1189
1190
1191
1192
1193static bool trans_ICALL(DisasContext *ctx, arg_ICALL *a)
1194{
1195 if (!avr_have_feature(ctx, AVR_FEATURE_IJMP_ICALL)) {
1196 return true;
1197 }
1198
1199 int ret = ctx->npc;
1200
1201 gen_push_ret(ctx, ret);
1202 gen_jmp_z(ctx);
1203
1204 return true;
1205}
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215static bool trans_EICALL(DisasContext *ctx, arg_EICALL *a)
1216{
1217 if (!avr_have_feature(ctx, AVR_FEATURE_EIJMP_EICALL)) {
1218 return true;
1219 }
1220
1221 int ret = ctx->npc;
1222
1223 gen_push_ret(ctx, ret);
1224 gen_jmp_ez(ctx);
1225 return true;
1226}
1227
1228
1229
1230
1231
1232
1233
1234
1235static bool trans_CALL(DisasContext *ctx, arg_CALL *a)
1236{
1237 if (!avr_have_feature(ctx, AVR_FEATURE_JMP_CALL)) {
1238 return true;
1239 }
1240
1241 int Imm = a->imm;
1242 int ret = ctx->npc;
1243
1244 gen_push_ret(ctx, ret);
1245 gen_goto_tb(ctx, 0, Imm);
1246
1247 return true;
1248}
1249
1250
1251
1252
1253
1254static bool trans_RET(DisasContext *ctx, arg_RET *a)
1255{
1256 gen_pop_ret(ctx, cpu_pc);
1257
1258 ctx->base.is_jmp = DISAS_LOOKUP;
1259 return true;
1260}
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270static bool trans_RETI(DisasContext *ctx, arg_RETI *a)
1271{
1272 gen_pop_ret(ctx, cpu_pc);
1273 tcg_gen_movi_tl(cpu_If, 1);
1274
1275
1276 ctx->base.is_jmp = DISAS_EXIT;
1277 return true;
1278}
1279
1280
1281
1282
1283
1284static bool trans_CPSE(DisasContext *ctx, arg_CPSE *a)
1285{
1286 ctx->skip_cond = TCG_COND_EQ;
1287 ctx->skip_var0 = cpu_r[a->rd];
1288 ctx->skip_var1 = cpu_r[a->rr];
1289 return true;
1290}
1291
1292
1293
1294
1295
1296
1297static bool trans_CP(DisasContext *ctx, arg_CP *a)
1298{
1299 TCGv Rd = cpu_r[a->rd];
1300 TCGv Rr = cpu_r[a->rr];
1301 TCGv R = tcg_temp_new_i32();
1302
1303 tcg_gen_sub_tl(R, Rd, Rr);
1304 tcg_gen_andi_tl(R, R, 0xff);
1305
1306
1307 gen_sub_CHf(R, Rd, Rr);
1308 gen_sub_Vf(R, Rd, Rr);
1309 gen_ZNSf(R);
1310
1311 tcg_temp_free_i32(R);
1312
1313 return true;
1314}
1315
1316
1317
1318
1319
1320
1321static bool trans_CPC(DisasContext *ctx, arg_CPC *a)
1322{
1323 TCGv Rd = cpu_r[a->rd];
1324 TCGv Rr = cpu_r[a->rr];
1325 TCGv R = tcg_temp_new_i32();
1326 TCGv zero = tcg_const_i32(0);
1327
1328 tcg_gen_sub_tl(R, Rd, Rr);
1329 tcg_gen_sub_tl(R, R, cpu_Cf);
1330 tcg_gen_andi_tl(R, R, 0xff);
1331
1332 gen_sub_CHf(R, Rd, Rr);
1333 gen_sub_Vf(R, Rd, Rr);
1334 gen_NSf(R);
1335
1336
1337
1338
1339
1340 tcg_gen_movcond_tl(TCG_COND_EQ, cpu_Zf, R, zero, cpu_Zf, zero);
1341
1342 tcg_temp_free_i32(zero);
1343 tcg_temp_free_i32(R);
1344
1345 return true;
1346}
1347
1348
1349
1350
1351
1352
1353static bool trans_CPI(DisasContext *ctx, arg_CPI *a)
1354{
1355 TCGv Rd = cpu_r[a->rd];
1356 int Imm = a->imm;
1357 TCGv Rr = tcg_const_i32(Imm);
1358 TCGv R = tcg_temp_new_i32();
1359
1360 tcg_gen_sub_tl(R, Rd, Rr);
1361 tcg_gen_andi_tl(R, R, 0xff);
1362
1363
1364 gen_sub_CHf(R, Rd, Rr);
1365 gen_sub_Vf(R, Rd, Rr);
1366 gen_ZNSf(R);
1367
1368 tcg_temp_free_i32(R);
1369 tcg_temp_free_i32(Rr);
1370
1371 return true;
1372}
1373
1374
1375
1376
1377
1378static bool trans_SBRC(DisasContext *ctx, arg_SBRC *a)
1379{
1380 TCGv Rr = cpu_r[a->rr];
1381
1382 ctx->skip_cond = TCG_COND_EQ;
1383 ctx->skip_var0 = tcg_temp_new();
1384 ctx->free_skip_var0 = true;
1385
1386 tcg_gen_andi_tl(ctx->skip_var0, Rr, 1 << a->bit);
1387 return true;
1388}
1389
1390
1391
1392
1393
1394static bool trans_SBRS(DisasContext *ctx, arg_SBRS *a)
1395{
1396 TCGv Rr = cpu_r[a->rr];
1397
1398 ctx->skip_cond = TCG_COND_NE;
1399 ctx->skip_var0 = tcg_temp_new();
1400 ctx->free_skip_var0 = true;
1401
1402 tcg_gen_andi_tl(ctx->skip_var0, Rr, 1 << a->bit);
1403 return true;
1404}
1405
1406
1407
1408
1409
1410
1411static bool trans_SBIC(DisasContext *ctx, arg_SBIC *a)
1412{
1413 TCGv temp = tcg_const_i32(a->reg);
1414
1415 gen_helper_inb(temp, cpu_env, temp);
1416 tcg_gen_andi_tl(temp, temp, 1 << a->bit);
1417 ctx->skip_cond = TCG_COND_EQ;
1418 ctx->skip_var0 = temp;
1419 ctx->free_skip_var0 = true;
1420
1421 return true;
1422}
1423
1424
1425
1426
1427
1428
1429static bool trans_SBIS(DisasContext *ctx, arg_SBIS *a)
1430{
1431 TCGv temp = tcg_const_i32(a->reg);
1432
1433 gen_helper_inb(temp, cpu_env, temp);
1434 tcg_gen_andi_tl(temp, temp, 1 << a->bit);
1435 ctx->skip_cond = TCG_COND_NE;
1436 ctx->skip_var0 = temp;
1437 ctx->free_skip_var0 = true;
1438
1439 return true;
1440}
1441
1442
1443
1444
1445
1446
1447
1448
1449static bool trans_BRBC(DisasContext *ctx, arg_BRBC *a)
1450{
1451 TCGLabel *not_taken = gen_new_label();
1452
1453 TCGv var;
1454
1455 switch (a->bit) {
1456 case 0x00:
1457 var = cpu_Cf;
1458 break;
1459 case 0x01:
1460 var = cpu_Zf;
1461 break;
1462 case 0x02:
1463 var = cpu_Nf;
1464 break;
1465 case 0x03:
1466 var = cpu_Vf;
1467 break;
1468 case 0x04:
1469 var = cpu_Sf;
1470 break;
1471 case 0x05:
1472 var = cpu_Hf;
1473 break;
1474 case 0x06:
1475 var = cpu_Tf;
1476 break;
1477 case 0x07:
1478 var = cpu_If;
1479 break;
1480 default:
1481 g_assert_not_reached();
1482 }
1483
1484 tcg_gen_brcondi_i32(TCG_COND_NE, var, 0, not_taken);
1485 gen_goto_tb(ctx, 0, ctx->npc + a->imm);
1486 gen_set_label(not_taken);
1487
1488 ctx->base.is_jmp = DISAS_CHAIN;
1489 return true;
1490}
1491
1492
1493
1494
1495
1496
1497
1498static bool trans_BRBS(DisasContext *ctx, arg_BRBS *a)
1499{
1500 TCGLabel *not_taken = gen_new_label();
1501
1502 TCGv var;
1503
1504 switch (a->bit) {
1505 case 0x00:
1506 var = cpu_Cf;
1507 break;
1508 case 0x01:
1509 var = cpu_Zf;
1510 break;
1511 case 0x02:
1512 var = cpu_Nf;
1513 break;
1514 case 0x03:
1515 var = cpu_Vf;
1516 break;
1517 case 0x04:
1518 var = cpu_Sf;
1519 break;
1520 case 0x05:
1521 var = cpu_Hf;
1522 break;
1523 case 0x06:
1524 var = cpu_Tf;
1525 break;
1526 case 0x07:
1527 var = cpu_If;
1528 break;
1529 default:
1530 g_assert_not_reached();
1531 }
1532
1533 tcg_gen_brcondi_i32(TCG_COND_EQ, var, 0, not_taken);
1534 gen_goto_tb(ctx, 0, ctx->npc + a->imm);
1535 gen_set_label(not_taken);
1536
1537 ctx->base.is_jmp = DISAS_CHAIN;
1538 return true;
1539}
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551static void gen_set_addr(TCGv addr, TCGv H, TCGv M, TCGv L)
1552{
1553
1554 tcg_gen_andi_tl(L, addr, 0x000000ff);
1555
1556 tcg_gen_andi_tl(M, addr, 0x0000ff00);
1557 tcg_gen_shri_tl(M, M, 8);
1558
1559 tcg_gen_andi_tl(H, addr, 0x00ff0000);
1560}
1561
1562static void gen_set_xaddr(TCGv addr)
1563{
1564 gen_set_addr(addr, cpu_rampX, cpu_r[27], cpu_r[26]);
1565}
1566
1567static void gen_set_yaddr(TCGv addr)
1568{
1569 gen_set_addr(addr, cpu_rampY, cpu_r[29], cpu_r[28]);
1570}
1571
1572static void gen_set_zaddr(TCGv addr)
1573{
1574 gen_set_addr(addr, cpu_rampZ, cpu_r[31], cpu_r[30]);
1575}
1576
1577static TCGv gen_get_addr(TCGv H, TCGv M, TCGv L)
1578{
1579 TCGv addr = tcg_temp_new_i32();
1580
1581 tcg_gen_deposit_tl(addr, M, H, 8, 8);
1582 tcg_gen_deposit_tl(addr, L, addr, 8, 16);
1583
1584 return addr;
1585}
1586
1587static TCGv gen_get_xaddr(void)
1588{
1589 return gen_get_addr(cpu_rampX, cpu_r[27], cpu_r[26]);
1590}
1591
1592static TCGv gen_get_yaddr(void)
1593{
1594 return gen_get_addr(cpu_rampY, cpu_r[29], cpu_r[28]);
1595}
1596
1597static TCGv gen_get_zaddr(void)
1598{
1599 return gen_get_addr(cpu_rampZ, cpu_r[31], cpu_r[30]);
1600}
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612static void gen_data_store(DisasContext *ctx, TCGv data, TCGv addr)
1613{
1614 if (ctx->base.tb->flags & TB_FLAGS_FULL_ACCESS) {
1615 gen_helper_fullwr(cpu_env, data, addr);
1616 } else {
1617 tcg_gen_qemu_st8(data, addr, MMU_DATA_IDX);
1618 }
1619}
1620
1621static void gen_data_load(DisasContext *ctx, TCGv data, TCGv addr)
1622{
1623 if (ctx->base.tb->flags & TB_FLAGS_FULL_ACCESS) {
1624 gen_helper_fullrd(data, cpu_env, addr);
1625 } else {
1626 tcg_gen_qemu_ld8u(data, addr, MMU_DATA_IDX);
1627 }
1628}
1629
1630
1631
1632
1633
1634
1635static bool trans_MOV(DisasContext *ctx, arg_MOV *a)
1636{
1637 TCGv Rd = cpu_r[a->rd];
1638 TCGv Rr = cpu_r[a->rr];
1639
1640 tcg_gen_mov_tl(Rd, Rr);
1641
1642 return true;
1643}
1644
1645
1646
1647
1648
1649
1650
1651
1652static bool trans_MOVW(DisasContext *ctx, arg_MOVW *a)
1653{
1654 if (!avr_have_feature(ctx, AVR_FEATURE_MOVW)) {
1655 return true;
1656 }
1657
1658 TCGv RdL = cpu_r[a->rd];
1659 TCGv RdH = cpu_r[a->rd + 1];
1660 TCGv RrL = cpu_r[a->rr];
1661 TCGv RrH = cpu_r[a->rr + 1];
1662
1663 tcg_gen_mov_tl(RdH, RrH);
1664 tcg_gen_mov_tl(RdL, RrL);
1665
1666 return true;
1667}
1668
1669
1670
1671
1672static bool trans_LDI(DisasContext *ctx, arg_LDI *a)
1673{
1674 TCGv Rd = cpu_r[a->rd];
1675 int imm = a->imm;
1676
1677 tcg_gen_movi_tl(Rd, imm);
1678
1679 return true;
1680}
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694static bool trans_LDS(DisasContext *ctx, arg_LDS *a)
1695{
1696 TCGv Rd = cpu_r[a->rd];
1697 TCGv addr = tcg_temp_new_i32();
1698 TCGv H = cpu_rampD;
1699 a->imm = next_word(ctx);
1700
1701 tcg_gen_mov_tl(addr, H);
1702 tcg_gen_shli_tl(addr, addr, 16);
1703 tcg_gen_ori_tl(addr, addr, a->imm);
1704
1705 gen_data_load(ctx, Rd, addr);
1706
1707 tcg_temp_free_i32(addr);
1708
1709 return true;
1710}
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737static bool trans_LDX1(DisasContext *ctx, arg_LDX1 *a)
1738{
1739 TCGv Rd = cpu_r[a->rd];
1740 TCGv addr = gen_get_xaddr();
1741
1742 gen_data_load(ctx, Rd, addr);
1743
1744 tcg_temp_free_i32(addr);
1745
1746 return true;
1747}
1748
1749static bool trans_LDX2(DisasContext *ctx, arg_LDX2 *a)
1750{
1751 TCGv Rd = cpu_r[a->rd];
1752 TCGv addr = gen_get_xaddr();
1753
1754 gen_data_load(ctx, Rd, addr);
1755 tcg_gen_addi_tl(addr, addr, 1);
1756
1757 gen_set_xaddr(addr);
1758
1759 tcg_temp_free_i32(addr);
1760
1761 return true;
1762}
1763
1764static bool trans_LDX3(DisasContext *ctx, arg_LDX3 *a)
1765{
1766 TCGv Rd = cpu_r[a->rd];
1767 TCGv addr = gen_get_xaddr();
1768
1769 tcg_gen_subi_tl(addr, addr, 1);
1770 gen_data_load(ctx, Rd, addr);
1771 gen_set_xaddr(addr);
1772
1773 tcg_temp_free_i32(addr);
1774
1775 return true;
1776}
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803static bool trans_LDY2(DisasContext *ctx, arg_LDY2 *a)
1804{
1805 TCGv Rd = cpu_r[a->rd];
1806 TCGv addr = gen_get_yaddr();
1807
1808 gen_data_load(ctx, Rd, addr);
1809 tcg_gen_addi_tl(addr, addr, 1);
1810
1811 gen_set_yaddr(addr);
1812
1813 tcg_temp_free_i32(addr);
1814
1815 return true;
1816}
1817
1818static bool trans_LDY3(DisasContext *ctx, arg_LDY3 *a)
1819{
1820 TCGv Rd = cpu_r[a->rd];
1821 TCGv addr = gen_get_yaddr();
1822
1823 tcg_gen_subi_tl(addr, addr, 1);
1824 gen_data_load(ctx, Rd, addr);
1825 gen_set_yaddr(addr);
1826
1827 tcg_temp_free_i32(addr);
1828
1829 return true;
1830}
1831
1832static bool trans_LDDY(DisasContext *ctx, arg_LDDY *a)
1833{
1834 TCGv Rd = cpu_r[a->rd];
1835 TCGv addr = gen_get_yaddr();
1836
1837 tcg_gen_addi_tl(addr, addr, a->imm);
1838 gen_data_load(ctx, Rd, addr);
1839
1840 tcg_temp_free_i32(addr);
1841
1842 return true;
1843}
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874static bool trans_LDZ2(DisasContext *ctx, arg_LDZ2 *a)
1875{
1876 TCGv Rd = cpu_r[a->rd];
1877 TCGv addr = gen_get_zaddr();
1878
1879 gen_data_load(ctx, Rd, addr);
1880 tcg_gen_addi_tl(addr, addr, 1);
1881
1882 gen_set_zaddr(addr);
1883
1884 tcg_temp_free_i32(addr);
1885
1886 return true;
1887}
1888
1889static bool trans_LDZ3(DisasContext *ctx, arg_LDZ3 *a)
1890{
1891 TCGv Rd = cpu_r[a->rd];
1892 TCGv addr = gen_get_zaddr();
1893
1894 tcg_gen_subi_tl(addr, addr, 1);
1895 gen_data_load(ctx, Rd, addr);
1896
1897 gen_set_zaddr(addr);
1898
1899 tcg_temp_free_i32(addr);
1900
1901 return true;
1902}
1903
1904static bool trans_LDDZ(DisasContext *ctx, arg_LDDZ *a)
1905{
1906 TCGv Rd = cpu_r[a->rd];
1907 TCGv addr = gen_get_zaddr();
1908
1909 tcg_gen_addi_tl(addr, addr, a->imm);
1910 gen_data_load(ctx, Rd, addr);
1911
1912 tcg_temp_free_i32(addr);
1913
1914 return true;
1915}
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929static bool trans_STS(DisasContext *ctx, arg_STS *a)
1930{
1931 TCGv Rd = cpu_r[a->rd];
1932 TCGv addr = tcg_temp_new_i32();
1933 TCGv H = cpu_rampD;
1934 a->imm = next_word(ctx);
1935
1936 tcg_gen_mov_tl(addr, H);
1937 tcg_gen_shli_tl(addr, addr, 16);
1938 tcg_gen_ori_tl(addr, addr, a->imm);
1939 gen_data_store(ctx, Rd, addr);
1940
1941 tcg_temp_free_i32(addr);
1942
1943 return true;
1944}
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967static bool trans_STX1(DisasContext *ctx, arg_STX1 *a)
1968{
1969 TCGv Rd = cpu_r[a->rr];
1970 TCGv addr = gen_get_xaddr();
1971
1972 gen_data_store(ctx, Rd, addr);
1973
1974 tcg_temp_free_i32(addr);
1975
1976 return true;
1977}
1978
1979static bool trans_STX2(DisasContext *ctx, arg_STX2 *a)
1980{
1981 TCGv Rd = cpu_r[a->rr];
1982 TCGv addr = gen_get_xaddr();
1983
1984 gen_data_store(ctx, Rd, addr);
1985 tcg_gen_addi_tl(addr, addr, 1);
1986 gen_set_xaddr(addr);
1987
1988 tcg_temp_free_i32(addr);
1989
1990 return true;
1991}
1992
1993static bool trans_STX3(DisasContext *ctx, arg_STX3 *a)
1994{
1995 TCGv Rd = cpu_r[a->rr];
1996 TCGv addr = gen_get_xaddr();
1997
1998 tcg_gen_subi_tl(addr, addr, 1);
1999 gen_data_store(ctx, Rd, addr);
2000 gen_set_xaddr(addr);
2001
2002 tcg_temp_free_i32(addr);
2003
2004 return true;
2005}
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030static bool trans_STY2(DisasContext *ctx, arg_STY2 *a)
2031{
2032 TCGv Rd = cpu_r[a->rd];
2033 TCGv addr = gen_get_yaddr();
2034
2035 gen_data_store(ctx, Rd, addr);
2036 tcg_gen_addi_tl(addr, addr, 1);
2037 gen_set_yaddr(addr);
2038
2039 tcg_temp_free_i32(addr);
2040
2041 return true;
2042}
2043
2044static bool trans_STY3(DisasContext *ctx, arg_STY3 *a)
2045{
2046 TCGv Rd = cpu_r[a->rd];
2047 TCGv addr = gen_get_yaddr();
2048
2049 tcg_gen_subi_tl(addr, addr, 1);
2050 gen_data_store(ctx, Rd, addr);
2051 gen_set_yaddr(addr);
2052
2053 tcg_temp_free_i32(addr);
2054
2055 return true;
2056}
2057
2058static bool trans_STDY(DisasContext *ctx, arg_STDY *a)
2059{
2060 TCGv Rd = cpu_r[a->rd];
2061 TCGv addr = gen_get_yaddr();
2062
2063 tcg_gen_addi_tl(addr, addr, a->imm);
2064 gen_data_store(ctx, Rd, addr);
2065
2066 tcg_temp_free_i32(addr);
2067
2068 return true;
2069}
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094static bool trans_STZ2(DisasContext *ctx, arg_STZ2 *a)
2095{
2096 TCGv Rd = cpu_r[a->rd];
2097 TCGv addr = gen_get_zaddr();
2098
2099 gen_data_store(ctx, Rd, addr);
2100 tcg_gen_addi_tl(addr, addr, 1);
2101
2102 gen_set_zaddr(addr);
2103
2104 tcg_temp_free_i32(addr);
2105
2106 return true;
2107}
2108
2109static bool trans_STZ3(DisasContext *ctx, arg_STZ3 *a)
2110{
2111 TCGv Rd = cpu_r[a->rd];
2112 TCGv addr = gen_get_zaddr();
2113
2114 tcg_gen_subi_tl(addr, addr, 1);
2115 gen_data_store(ctx, Rd, addr);
2116
2117 gen_set_zaddr(addr);
2118
2119 tcg_temp_free_i32(addr);
2120
2121 return true;
2122}
2123
2124static bool trans_STDZ(DisasContext *ctx, arg_STDZ *a)
2125{
2126 TCGv Rd = cpu_r[a->rd];
2127 TCGv addr = gen_get_zaddr();
2128
2129 tcg_gen_addi_tl(addr, addr, a->imm);
2130 gen_data_store(ctx, Rd, addr);
2131
2132 tcg_temp_free_i32(addr);
2133
2134 return true;
2135}
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151static bool trans_LPM1(DisasContext *ctx, arg_LPM1 *a)
2152{
2153 if (!avr_have_feature(ctx, AVR_FEATURE_LPM)) {
2154 return true;
2155 }
2156
2157 TCGv Rd = cpu_r[0];
2158 TCGv addr = tcg_temp_new_i32();
2159 TCGv H = cpu_r[31];
2160 TCGv L = cpu_r[30];
2161
2162 tcg_gen_shli_tl(addr, H, 8);
2163 tcg_gen_or_tl(addr, addr, L);
2164 tcg_gen_qemu_ld8u(Rd, addr, MMU_CODE_IDX);
2165
2166 tcg_temp_free_i32(addr);
2167
2168 return true;
2169}
2170
2171static bool trans_LPM2(DisasContext *ctx, arg_LPM2 *a)
2172{
2173 if (!avr_have_feature(ctx, AVR_FEATURE_LPM)) {
2174 return true;
2175 }
2176
2177 TCGv Rd = cpu_r[a->rd];
2178 TCGv addr = tcg_temp_new_i32();
2179 TCGv H = cpu_r[31];
2180 TCGv L = cpu_r[30];
2181
2182 tcg_gen_shli_tl(addr, H, 8);
2183 tcg_gen_or_tl(addr, addr, L);
2184 tcg_gen_qemu_ld8u(Rd, addr, MMU_CODE_IDX);
2185
2186 tcg_temp_free_i32(addr);
2187
2188 return true;
2189}
2190
2191static bool trans_LPMX(DisasContext *ctx, arg_LPMX *a)
2192{
2193 if (!avr_have_feature(ctx, AVR_FEATURE_LPMX)) {
2194 return true;
2195 }
2196
2197 TCGv Rd = cpu_r[a->rd];
2198 TCGv addr = tcg_temp_new_i32();
2199 TCGv H = cpu_r[31];
2200 TCGv L = cpu_r[30];
2201
2202 tcg_gen_shli_tl(addr, H, 8);
2203 tcg_gen_or_tl(addr, addr, L);
2204 tcg_gen_qemu_ld8u(Rd, addr, MMU_CODE_IDX);
2205 tcg_gen_addi_tl(addr, addr, 1);
2206 tcg_gen_andi_tl(L, addr, 0xff);
2207 tcg_gen_shri_tl(addr, addr, 8);
2208 tcg_gen_andi_tl(H, addr, 0xff);
2209
2210 tcg_temp_free_i32(addr);
2211
2212 return true;
2213}
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230static bool trans_ELPM1(DisasContext *ctx, arg_ELPM1 *a)
2231{
2232 if (!avr_have_feature(ctx, AVR_FEATURE_ELPM)) {
2233 return true;
2234 }
2235
2236 TCGv Rd = cpu_r[0];
2237 TCGv addr = gen_get_zaddr();
2238
2239 tcg_gen_qemu_ld8u(Rd, addr, MMU_CODE_IDX);
2240
2241 tcg_temp_free_i32(addr);
2242
2243 return true;
2244}
2245
2246static bool trans_ELPM2(DisasContext *ctx, arg_ELPM2 *a)
2247{
2248 if (!avr_have_feature(ctx, AVR_FEATURE_ELPM)) {
2249 return true;
2250 }
2251
2252 TCGv Rd = cpu_r[a->rd];
2253 TCGv addr = gen_get_zaddr();
2254
2255 tcg_gen_qemu_ld8u(Rd, addr, MMU_CODE_IDX);
2256
2257 tcg_temp_free_i32(addr);
2258
2259 return true;
2260}
2261
2262static bool trans_ELPMX(DisasContext *ctx, arg_ELPMX *a)
2263{
2264 if (!avr_have_feature(ctx, AVR_FEATURE_ELPMX)) {
2265 return true;
2266 }
2267
2268 TCGv Rd = cpu_r[a->rd];
2269 TCGv addr = gen_get_zaddr();
2270
2271 tcg_gen_qemu_ld8u(Rd, addr, MMU_CODE_IDX);
2272 tcg_gen_addi_tl(addr, addr, 1);
2273 gen_set_zaddr(addr);
2274
2275 tcg_temp_free_i32(addr);
2276
2277 return true;
2278}
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300static bool trans_SPM(DisasContext *ctx, arg_SPM *a)
2301{
2302
2303 if (!avr_have_feature(ctx, AVR_FEATURE_SPM)) {
2304 return true;
2305 }
2306
2307 return true;
2308}
2309
2310static bool trans_SPMX(DisasContext *ctx, arg_SPMX *a)
2311{
2312
2313 if (!avr_have_feature(ctx, AVR_FEATURE_SPMX)) {
2314 return true;
2315 }
2316
2317 return true;
2318}
2319
2320
2321
2322
2323
2324static bool trans_IN(DisasContext *ctx, arg_IN *a)
2325{
2326 TCGv Rd = cpu_r[a->rd];
2327 TCGv port = tcg_const_i32(a->imm);
2328
2329 gen_helper_inb(Rd, cpu_env, port);
2330
2331 tcg_temp_free_i32(port);
2332
2333 return true;
2334}
2335
2336
2337
2338
2339
2340static bool trans_OUT(DisasContext *ctx, arg_OUT *a)
2341{
2342 TCGv Rd = cpu_r[a->rd];
2343 TCGv port = tcg_const_i32(a->imm);
2344
2345 gen_helper_outb(cpu_env, port, Rd);
2346
2347 tcg_temp_free_i32(port);
2348
2349 return true;
2350}
2351
2352
2353
2354
2355
2356
2357
2358static bool trans_PUSH(DisasContext *ctx, arg_PUSH *a)
2359{
2360 TCGv Rd = cpu_r[a->rd];
2361
2362 gen_data_store(ctx, Rd, cpu_sp);
2363 tcg_gen_subi_tl(cpu_sp, cpu_sp, 1);
2364
2365 return true;
2366}
2367
2368
2369
2370
2371
2372
2373
2374static bool trans_POP(DisasContext *ctx, arg_POP *a)
2375{
2376
2377
2378
2379
2380
2381
2382
2383 TCGv t1 = tcg_temp_new_i32();
2384 TCGv Rd = cpu_r[a->rd];
2385
2386 tcg_gen_addi_tl(t1, cpu_sp, 1);
2387 gen_data_load(ctx, Rd, t1);
2388 tcg_gen_mov_tl(cpu_sp, t1);
2389
2390 return true;
2391}
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403static bool trans_XCH(DisasContext *ctx, arg_XCH *a)
2404{
2405 if (!avr_have_feature(ctx, AVR_FEATURE_RMW)) {
2406 return true;
2407 }
2408
2409 TCGv Rd = cpu_r[a->rd];
2410 TCGv t0 = tcg_temp_new_i32();
2411 TCGv addr = gen_get_zaddr();
2412
2413 gen_data_load(ctx, t0, addr);
2414 gen_data_store(ctx, Rd, addr);
2415 tcg_gen_mov_tl(Rd, t0);
2416
2417 tcg_temp_free_i32(t0);
2418 tcg_temp_free_i32(addr);
2419
2420 return true;
2421}
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434static bool trans_LAS(DisasContext *ctx, arg_LAS *a)
2435{
2436 if (!avr_have_feature(ctx, AVR_FEATURE_RMW)) {
2437 return true;
2438 }
2439
2440 TCGv Rr = cpu_r[a->rd];
2441 TCGv addr = gen_get_zaddr();
2442 TCGv t0 = tcg_temp_new_i32();
2443 TCGv t1 = tcg_temp_new_i32();
2444
2445 gen_data_load(ctx, t0, addr);
2446 tcg_gen_or_tl(t1, t0, Rr);
2447 tcg_gen_mov_tl(Rr, t0);
2448 gen_data_store(ctx, t1, addr);
2449
2450 tcg_temp_free_i32(t1);
2451 tcg_temp_free_i32(t0);
2452 tcg_temp_free_i32(addr);
2453
2454 return true;
2455}
2456
2457
2458
2459
2460
2461
2462
2463
2464
2465
2466
2467
2468
2469static bool trans_LAC(DisasContext *ctx, arg_LAC *a)
2470{
2471 if (!avr_have_feature(ctx, AVR_FEATURE_RMW)) {
2472 return true;
2473 }
2474
2475 TCGv Rr = cpu_r[a->rd];
2476 TCGv addr = gen_get_zaddr();
2477 TCGv t0 = tcg_temp_new_i32();
2478 TCGv t1 = tcg_temp_new_i32();
2479
2480 gen_data_load(ctx, t0, addr);
2481 tcg_gen_andc_tl(t1, t0, Rr);
2482 tcg_gen_mov_tl(Rr, t0);
2483 gen_data_store(ctx, t1, addr);
2484
2485 tcg_temp_free_i32(t1);
2486 tcg_temp_free_i32(t0);
2487 tcg_temp_free_i32(addr);
2488
2489 return true;
2490}
2491
2492
2493
2494
2495
2496
2497
2498
2499
2500
2501
2502
2503
2504static bool trans_LAT(DisasContext *ctx, arg_LAT *a)
2505{
2506 if (!avr_have_feature(ctx, AVR_FEATURE_RMW)) {
2507 return true;
2508 }
2509
2510 TCGv Rd = cpu_r[a->rd];
2511 TCGv addr = gen_get_zaddr();
2512 TCGv t0 = tcg_temp_new_i32();
2513 TCGv t1 = tcg_temp_new_i32();
2514
2515 gen_data_load(ctx, t0, addr);
2516 tcg_gen_xor_tl(t1, t0, Rd);
2517 tcg_gen_mov_tl(Rd, t0);
2518 gen_data_store(ctx, t1, addr);
2519
2520 tcg_temp_free_i32(t1);
2521 tcg_temp_free_i32(t0);
2522 tcg_temp_free_i32(addr);
2523
2524 return true;
2525}
2526
2527
2528
2529
2530static void gen_rshift_ZNVSf(TCGv R)
2531{
2532 tcg_gen_setcondi_tl(TCG_COND_EQ, cpu_Zf, R, 0);
2533 tcg_gen_shri_tl(cpu_Nf, R, 7);
2534 tcg_gen_xor_tl(cpu_Vf, cpu_Nf, cpu_Cf);
2535 tcg_gen_xor_tl(cpu_Sf, cpu_Nf, cpu_Vf);
2536}
2537
2538
2539
2540
2541
2542
2543static bool trans_LSR(DisasContext *ctx, arg_LSR *a)
2544{
2545 TCGv Rd = cpu_r[a->rd];
2546
2547 tcg_gen_andi_tl(cpu_Cf, Rd, 1);
2548 tcg_gen_shri_tl(Rd, Rd, 1);
2549
2550
2551 tcg_gen_setcondi_tl(TCG_COND_EQ, cpu_Zf, Rd, 0);
2552 tcg_gen_movi_tl(cpu_Nf, 0);
2553 tcg_gen_mov_tl(cpu_Vf, cpu_Cf);
2554 tcg_gen_mov_tl(cpu_Sf, cpu_Vf);
2555
2556 return true;
2557}
2558
2559
2560
2561
2562
2563
2564
2565
2566static bool trans_ROR(DisasContext *ctx, arg_ROR *a)
2567{
2568 TCGv Rd = cpu_r[a->rd];
2569 TCGv t0 = tcg_temp_new_i32();
2570
2571 tcg_gen_shli_tl(t0, cpu_Cf, 7);
2572
2573
2574 tcg_gen_andi_tl(cpu_Cf, Rd, 1);
2575
2576
2577 tcg_gen_shri_tl(Rd, Rd, 1);
2578 tcg_gen_or_tl(Rd, Rd, t0);
2579
2580
2581 gen_rshift_ZNVSf(Rd);
2582
2583 tcg_temp_free_i32(t0);
2584
2585 return true;
2586}
2587
2588
2589
2590
2591
2592
2593
2594static bool trans_ASR(DisasContext *ctx, arg_ASR *a)
2595{
2596 TCGv Rd = cpu_r[a->rd];
2597 TCGv t0 = tcg_temp_new_i32();
2598
2599
2600 tcg_gen_andi_tl(cpu_Cf, Rd, 1);
2601
2602
2603 tcg_gen_andi_tl(t0, Rd, 0x80);
2604 tcg_gen_shri_tl(Rd, Rd, 1);
2605 tcg_gen_or_tl(Rd, Rd, t0);
2606
2607
2608 gen_rshift_ZNVSf(Rd);
2609
2610 tcg_temp_free_i32(t0);
2611
2612 return true;
2613}
2614
2615
2616
2617
2618static bool trans_SWAP(DisasContext *ctx, arg_SWAP *a)
2619{
2620 TCGv Rd = cpu_r[a->rd];
2621 TCGv t0 = tcg_temp_new_i32();
2622 TCGv t1 = tcg_temp_new_i32();
2623
2624 tcg_gen_andi_tl(t0, Rd, 0x0f);
2625 tcg_gen_shli_tl(t0, t0, 4);
2626 tcg_gen_andi_tl(t1, Rd, 0xf0);
2627 tcg_gen_shri_tl(t1, t1, 4);
2628 tcg_gen_or_tl(Rd, t0, t1);
2629
2630 tcg_temp_free_i32(t1);
2631 tcg_temp_free_i32(t0);
2632
2633 return true;
2634}
2635
2636
2637
2638
2639
2640static bool trans_SBI(DisasContext *ctx, arg_SBI *a)
2641{
2642 TCGv data = tcg_temp_new_i32();
2643 TCGv port = tcg_const_i32(a->reg);
2644
2645 gen_helper_inb(data, cpu_env, port);
2646 tcg_gen_ori_tl(data, data, 1 << a->bit);
2647 gen_helper_outb(cpu_env, port, data);
2648
2649 tcg_temp_free_i32(port);
2650 tcg_temp_free_i32(data);
2651
2652 return true;
2653}
2654
2655
2656
2657
2658
2659static bool trans_CBI(DisasContext *ctx, arg_CBI *a)
2660{
2661 TCGv data = tcg_temp_new_i32();
2662 TCGv port = tcg_const_i32(a->reg);
2663
2664 gen_helper_inb(data, cpu_env, port);
2665 tcg_gen_andi_tl(data, data, ~(1 << a->bit));
2666 gen_helper_outb(cpu_env, port, data);
2667
2668 tcg_temp_free_i32(data);
2669 tcg_temp_free_i32(port);
2670
2671 return true;
2672}
2673
2674
2675
2676
2677static bool trans_BST(DisasContext *ctx, arg_BST *a)
2678{
2679 TCGv Rd = cpu_r[a->rd];
2680
2681 tcg_gen_andi_tl(cpu_Tf, Rd, 1 << a->bit);
2682 tcg_gen_shri_tl(cpu_Tf, cpu_Tf, a->bit);
2683
2684 return true;
2685}
2686
2687
2688
2689
2690static bool trans_BLD(DisasContext *ctx, arg_BLD *a)
2691{
2692 TCGv Rd = cpu_r[a->rd];
2693 TCGv t1 = tcg_temp_new_i32();
2694
2695 tcg_gen_andi_tl(Rd, Rd, ~(1u << a->bit));
2696 tcg_gen_shli_tl(t1, cpu_Tf, a->bit);
2697 tcg_gen_or_tl(Rd, Rd, t1);
2698
2699 tcg_temp_free_i32(t1);
2700
2701 return true;
2702}
2703
2704
2705
2706
2707static bool trans_BSET(DisasContext *ctx, arg_BSET *a)
2708{
2709 switch (a->bit) {
2710 case 0x00:
2711 tcg_gen_movi_tl(cpu_Cf, 0x01);
2712 break;
2713 case 0x01:
2714 tcg_gen_movi_tl(cpu_Zf, 0x01);
2715 break;
2716 case 0x02:
2717 tcg_gen_movi_tl(cpu_Nf, 0x01);
2718 break;
2719 case 0x03:
2720 tcg_gen_movi_tl(cpu_Vf, 0x01);
2721 break;
2722 case 0x04:
2723 tcg_gen_movi_tl(cpu_Sf, 0x01);
2724 break;
2725 case 0x05:
2726 tcg_gen_movi_tl(cpu_Hf, 0x01);
2727 break;
2728 case 0x06:
2729 tcg_gen_movi_tl(cpu_Tf, 0x01);
2730 break;
2731 case 0x07:
2732 tcg_gen_movi_tl(cpu_If, 0x01);
2733 break;
2734 }
2735
2736 return true;
2737}
2738
2739
2740
2741
2742static bool trans_BCLR(DisasContext *ctx, arg_BCLR *a)
2743{
2744 switch (a->bit) {
2745 case 0x00:
2746 tcg_gen_movi_tl(cpu_Cf, 0x00);
2747 break;
2748 case 0x01:
2749 tcg_gen_movi_tl(cpu_Zf, 0x00);
2750 break;
2751 case 0x02:
2752 tcg_gen_movi_tl(cpu_Nf, 0x00);
2753 break;
2754 case 0x03:
2755 tcg_gen_movi_tl(cpu_Vf, 0x00);
2756 break;
2757 case 0x04:
2758 tcg_gen_movi_tl(cpu_Sf, 0x00);
2759 break;
2760 case 0x05:
2761 tcg_gen_movi_tl(cpu_Hf, 0x00);
2762 break;
2763 case 0x06:
2764 tcg_gen_movi_tl(cpu_Tf, 0x00);
2765 break;
2766 case 0x07:
2767 tcg_gen_movi_tl(cpu_If, 0x00);
2768 break;
2769 }
2770
2771 return true;
2772}
2773
2774
2775
2776
2777
2778
2779
2780
2781
2782
2783
2784
2785
2786
2787
2788static bool trans_BREAK(DisasContext *ctx, arg_BREAK *a)
2789{
2790 if (!avr_have_feature(ctx, AVR_FEATURE_BREAK)) {
2791 return true;
2792 }
2793
2794#ifdef BREAKPOINT_ON_BREAK
2795 tcg_gen_movi_tl(cpu_pc, ctx->npc - 1);
2796 gen_helper_debug(cpu_env);
2797 ctx->base.is_jmp = DISAS_EXIT;
2798#else
2799
2800#endif
2801
2802 return true;
2803}
2804
2805
2806
2807
2808static bool trans_NOP(DisasContext *ctx, arg_NOP *a)
2809{
2810
2811
2812
2813 return true;
2814}
2815
2816
2817
2818
2819
2820static bool trans_SLEEP(DisasContext *ctx, arg_SLEEP *a)
2821{
2822 gen_helper_sleep(cpu_env);
2823 ctx->base.is_jmp = DISAS_NORETURN;
2824 return true;
2825}
2826
2827
2828
2829
2830
2831
2832static bool trans_WDR(DisasContext *ctx, arg_WDR *a)
2833{
2834 gen_helper_wdr(cpu_env);
2835
2836 return true;
2837}
2838
2839
2840
2841
2842
2843
2844
2845
2846
2847
2848static void translate(DisasContext *ctx)
2849{
2850 uint32_t opcode = next_word(ctx);
2851
2852 if (!decode_insn(ctx, opcode)) {
2853 gen_helper_unsupported(cpu_env);
2854 ctx->base.is_jmp = DISAS_NORETURN;
2855 }
2856}
2857
2858
2859static bool canonicalize_skip(DisasContext *ctx)
2860{
2861 switch (ctx->skip_cond) {
2862 case TCG_COND_NEVER:
2863
2864 return false;
2865
2866 case TCG_COND_ALWAYS:
2867
2868
2869
2870
2871
2872 return false;
2873
2874 case TCG_COND_NE:
2875 if (ctx->skip_var1 == NULL) {
2876 tcg_gen_mov_tl(cpu_skip, ctx->skip_var0);
2877 } else {
2878 tcg_gen_xor_tl(cpu_skip, ctx->skip_var0, ctx->skip_var1);
2879 ctx->skip_var1 = NULL;
2880 }
2881 break;
2882
2883 default:
2884
2885 if (ctx->skip_var1 == NULL) {
2886 tcg_gen_setcondi_tl(ctx->skip_cond, cpu_skip, ctx->skip_var0, 0);
2887 } else {
2888 tcg_gen_setcond_tl(ctx->skip_cond, cpu_skip,
2889 ctx->skip_var0, ctx->skip_var1);
2890 ctx->skip_var1 = NULL;
2891 }
2892 ctx->skip_cond = TCG_COND_NE;
2893 break;
2894 }
2895 if (ctx->free_skip_var0) {
2896 tcg_temp_free(ctx->skip_var0);
2897 ctx->free_skip_var0 = false;
2898 }
2899 ctx->skip_var0 = cpu_skip;
2900 return true;
2901}
2902
2903static void avr_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
2904{
2905 DisasContext *ctx = container_of(dcbase, DisasContext, base);
2906 CPUAVRState *env = cs->env_ptr;
2907 uint32_t tb_flags = ctx->base.tb->flags;
2908
2909 ctx->cs = cs;
2910 ctx->env = env;
2911 ctx->npc = ctx->base.pc_first / 2;
2912
2913 ctx->skip_cond = TCG_COND_NEVER;
2914 if (tb_flags & TB_FLAGS_SKIP) {
2915 ctx->skip_cond = TCG_COND_ALWAYS;
2916 ctx->skip_var0 = cpu_skip;
2917 }
2918
2919 if (tb_flags & TB_FLAGS_FULL_ACCESS) {
2920
2921
2922
2923
2924 ctx->base.max_insns = 1;
2925 }
2926}
2927
2928static void avr_tr_tb_start(DisasContextBase *db, CPUState *cs)
2929{
2930}
2931
2932static void avr_tr_insn_start(DisasContextBase *dcbase, CPUState *cs)
2933{
2934 DisasContext *ctx = container_of(dcbase, DisasContext, base);
2935
2936 tcg_gen_insn_start(ctx->npc);
2937}
2938
2939static void avr_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
2940{
2941 DisasContext *ctx = container_of(dcbase, DisasContext, base);
2942 TCGLabel *skip_label = NULL;
2943
2944
2945 if (ctx->skip_cond != TCG_COND_NEVER) {
2946 skip_label = gen_new_label();
2947 if (ctx->skip_var0 == cpu_skip) {
2948
2949
2950
2951
2952
2953 ctx->free_skip_var0 = true;
2954 ctx->skip_var0 = tcg_temp_new();
2955 tcg_gen_mov_tl(ctx->skip_var0, cpu_skip);
2956 tcg_gen_movi_tl(cpu_skip, 0);
2957 }
2958 if (ctx->skip_var1 == NULL) {
2959 tcg_gen_brcondi_tl(ctx->skip_cond, ctx->skip_var0, 0, skip_label);
2960 } else {
2961 tcg_gen_brcond_tl(ctx->skip_cond, ctx->skip_var0,
2962 ctx->skip_var1, skip_label);
2963 ctx->skip_var1 = NULL;
2964 }
2965 if (ctx->free_skip_var0) {
2966 tcg_temp_free(ctx->skip_var0);
2967 ctx->free_skip_var0 = false;
2968 }
2969 ctx->skip_cond = TCG_COND_NEVER;
2970 ctx->skip_var0 = NULL;
2971 }
2972
2973 translate(ctx);
2974
2975 ctx->base.pc_next = ctx->npc * 2;
2976
2977 if (skip_label) {
2978 canonicalize_skip(ctx);
2979 gen_set_label(skip_label);
2980 if (ctx->base.is_jmp == DISAS_NORETURN) {
2981 ctx->base.is_jmp = DISAS_CHAIN;
2982 }
2983 }
2984
2985 if (ctx->base.is_jmp == DISAS_NEXT) {
2986 target_ulong page_first = ctx->base.pc_first & TARGET_PAGE_MASK;
2987
2988 if ((ctx->base.pc_next - page_first) >= TARGET_PAGE_SIZE - 4) {
2989 ctx->base.is_jmp = DISAS_TOO_MANY;
2990 }
2991 }
2992}
2993
2994static void avr_tr_tb_stop(DisasContextBase *dcbase, CPUState *cs)
2995{
2996 DisasContext *ctx = container_of(dcbase, DisasContext, base);
2997 bool nonconst_skip = canonicalize_skip(ctx);
2998
2999 switch (ctx->base.is_jmp) {
3000 case DISAS_NORETURN:
3001 assert(!nonconst_skip);
3002 break;
3003 case DISAS_NEXT:
3004 case DISAS_TOO_MANY:
3005 case DISAS_CHAIN:
3006 if (!nonconst_skip) {
3007
3008 gen_goto_tb(ctx, 1, ctx->npc);
3009 break;
3010 }
3011 tcg_gen_movi_tl(cpu_pc, ctx->npc);
3012
3013 case DISAS_LOOKUP:
3014 if (!ctx->base.singlestep_enabled) {
3015 tcg_gen_lookup_and_goto_ptr();
3016 break;
3017 }
3018
3019 case DISAS_EXIT:
3020 if (ctx->base.singlestep_enabled) {
3021 gen_helper_debug(cpu_env);
3022 } else {
3023 tcg_gen_exit_tb(NULL, 0);
3024 }
3025 break;
3026 default:
3027 g_assert_not_reached();
3028 }
3029}
3030
3031static void avr_tr_disas_log(const DisasContextBase *dcbase, CPUState *cs)
3032{
3033 qemu_log("IN: %s\n", lookup_symbol(dcbase->pc_first));
3034 log_target_disas(cs, dcbase->pc_first, dcbase->tb->size);
3035}
3036
3037static const TranslatorOps avr_tr_ops = {
3038 .init_disas_context = avr_tr_init_disas_context,
3039 .tb_start = avr_tr_tb_start,
3040 .insn_start = avr_tr_insn_start,
3041 .translate_insn = avr_tr_translate_insn,
3042 .tb_stop = avr_tr_tb_stop,
3043 .disas_log = avr_tr_disas_log,
3044};
3045
3046void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int max_insns)
3047{
3048 DisasContext dc = { };
3049 translator_loop(&avr_tr_ops, &dc.base, cs, tb, max_insns);
3050}
3051
3052void restore_state_to_opc(CPUAVRState *env, TranslationBlock *tb,
3053 target_ulong *data)
3054{
3055 env->pc_w = data[0];
3056}
3057