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