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