xref: /openbmc/qemu/target/rx/translate.c (revision 136cb9cc)
1 /*
2  *  RX translation
3  *
4  *  Copyright (c) 2019 Yoshinori Sato
5  *
6  * This program is free software; you can redistribute it and/or modify it
7  * under the terms and conditions of the GNU General Public License,
8  * version 2 or later, as published by the Free Software Foundation.
9  *
10  * This program is distributed in the hope it will be useful, but WITHOUT
11  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
13  * more details.
14  *
15  * You should have received a copy of the GNU General Public License along with
16  * this program.  If not, see <http://www.gnu.org/licenses/>.
17  */
18 
19 #include "qemu/osdep.h"
20 #include "qemu/bswap.h"
21 #include "qemu/qemu-print.h"
22 #include "cpu.h"
23 #include "exec/exec-all.h"
24 #include "tcg/tcg-op.h"
25 #include "exec/cpu_ldst.h"
26 #include "exec/helper-proto.h"
27 #include "exec/helper-gen.h"
28 #include "exec/translator.h"
29 #include "exec/log.h"
30 
31 #define HELPER_H "helper.h"
32 #include "exec/helper-info.c.inc"
33 #undef  HELPER_H
34 
35 
36 typedef struct DisasContext {
37     DisasContextBase base;
38     CPURXState *env;
39     uint32_t pc;
40     uint32_t tb_flags;
41 } DisasContext;
42 
43 typedef struct DisasCompare {
44     TCGv value;
45     TCGv temp;
46     TCGCond cond;
47 } DisasCompare;
48 
49 const char *rx_crname(uint8_t cr)
50 {
51     static const char *cr_names[] = {
52         "psw", "pc", "usp", "fpsw", "", "", "", "",
53         "bpsw", "bpc", "isp", "fintv", "intb", "", "", ""
54     };
55     if (cr >= ARRAY_SIZE(cr_names)) {
56         return "illegal";
57     }
58     return cr_names[cr];
59 }
60 
61 /* Target-specific values for dc->base.is_jmp.  */
62 #define DISAS_JUMP    DISAS_TARGET_0
63 #define DISAS_UPDATE  DISAS_TARGET_1
64 #define DISAS_EXIT    DISAS_TARGET_2
65 
66 /* global register indexes */
67 static TCGv cpu_regs[16];
68 static TCGv cpu_psw_o, cpu_psw_s, cpu_psw_z, cpu_psw_c;
69 static TCGv cpu_psw_i, cpu_psw_pm, cpu_psw_u, cpu_psw_ipl;
70 static TCGv cpu_usp, cpu_fpsw, cpu_bpsw, cpu_bpc, cpu_isp;
71 static TCGv cpu_fintv, cpu_intb, cpu_pc;
72 static TCGv_i64 cpu_acc;
73 
74 #define cpu_sp cpu_regs[0]
75 
76 /* decoder helper */
77 static uint32_t decode_load_bytes(DisasContext *ctx, uint32_t insn,
78                            int i, int n)
79 {
80     while (++i <= n) {
81         uint8_t b = cpu_ldub_code(ctx->env, ctx->base.pc_next++);
82         insn |= b << (32 - i * 8);
83     }
84     return insn;
85 }
86 
87 static uint32_t li(DisasContext *ctx, int sz)
88 {
89     int32_t tmp, addr;
90     CPURXState *env = ctx->env;
91     addr = ctx->base.pc_next;
92 
93     tcg_debug_assert(sz < 4);
94     switch (sz) {
95     case 1:
96         ctx->base.pc_next += 1;
97         return cpu_ldsb_code(env, addr);
98     case 2:
99         ctx->base.pc_next += 2;
100         return cpu_ldsw_code(env, addr);
101     case 3:
102         ctx->base.pc_next += 3;
103         tmp = cpu_ldsb_code(env, addr + 2) << 16;
104         tmp |= cpu_lduw_code(env, addr) & 0xffff;
105         return tmp;
106     case 0:
107         ctx->base.pc_next += 4;
108         return cpu_ldl_code(env, addr);
109     }
110     return 0;
111 }
112 
113 static int bdsp_s(DisasContext *ctx, int d)
114 {
115     /*
116      * 0 -> 8
117      * 1 -> 9
118      * 2 -> 10
119      * 3 -> 3
120      * :
121      * 7 -> 7
122      */
123     if (d < 3) {
124         d += 8;
125     }
126     return d;
127 }
128 
129 /* Include the auto-generated decoder. */
130 #include "decode-insns.c.inc"
131 
132 void rx_cpu_dump_state(CPUState *cs, FILE *f, int flags)
133 {
134     RXCPU *cpu = RX_CPU(cs);
135     CPURXState *env = &cpu->env;
136     int i;
137     uint32_t psw;
138 
139     psw = rx_cpu_pack_psw(env);
140     qemu_fprintf(f, "pc=0x%08x psw=0x%08x\n",
141                  env->pc, psw);
142     for (i = 0; i < 16; i += 4) {
143         qemu_fprintf(f, "r%d=0x%08x r%d=0x%08x r%d=0x%08x r%d=0x%08x\n",
144                      i, env->regs[i], i + 1, env->regs[i + 1],
145                      i + 2, env->regs[i + 2], i + 3, env->regs[i + 3]);
146     }
147 }
148 
149 static void gen_goto_tb(DisasContext *dc, int n, target_ulong dest)
150 {
151     if (translator_use_goto_tb(&dc->base, dest)) {
152         tcg_gen_goto_tb(n);
153         tcg_gen_movi_i32(cpu_pc, dest);
154         tcg_gen_exit_tb(dc->base.tb, n);
155     } else {
156         tcg_gen_movi_i32(cpu_pc, dest);
157         tcg_gen_lookup_and_goto_ptr();
158     }
159     dc->base.is_jmp = DISAS_NORETURN;
160 }
161 
162 /* generic load wrapper */
163 static inline void rx_gen_ld(unsigned int size, TCGv reg, TCGv mem)
164 {
165     tcg_gen_qemu_ld_i32(reg, mem, 0, size | MO_SIGN | MO_TE);
166 }
167 
168 /* unsigned load wrapper */
169 static inline void rx_gen_ldu(unsigned int size, TCGv reg, TCGv mem)
170 {
171     tcg_gen_qemu_ld_i32(reg, mem, 0, size | MO_TE);
172 }
173 
174 /* generic store wrapper */
175 static inline void rx_gen_st(unsigned int size, TCGv reg, TCGv mem)
176 {
177     tcg_gen_qemu_st_i32(reg, mem, 0, size | MO_TE);
178 }
179 
180 /* [ri, rb] */
181 static inline void rx_gen_regindex(DisasContext *ctx, TCGv mem,
182                                    int size, int ri, int rb)
183 {
184     tcg_gen_shli_i32(mem, cpu_regs[ri], size);
185     tcg_gen_add_i32(mem, mem, cpu_regs[rb]);
186 }
187 
188 /* dsp[reg] */
189 static inline TCGv rx_index_addr(DisasContext *ctx, TCGv mem,
190                                  int ld, int size, int reg)
191 {
192     uint32_t dsp;
193 
194     tcg_debug_assert(ld < 3);
195     switch (ld) {
196     case 0:
197         return cpu_regs[reg];
198     case 1:
199         dsp = cpu_ldub_code(ctx->env, ctx->base.pc_next) << size;
200         tcg_gen_addi_i32(mem, cpu_regs[reg], dsp);
201         ctx->base.pc_next += 1;
202         return mem;
203     case 2:
204         dsp = cpu_lduw_code(ctx->env, ctx->base.pc_next) << size;
205         tcg_gen_addi_i32(mem, cpu_regs[reg], dsp);
206         ctx->base.pc_next += 2;
207         return mem;
208     }
209     return NULL;
210 }
211 
212 static inline MemOp mi_to_mop(unsigned mi)
213 {
214     static const MemOp mop[5] = { MO_SB, MO_SW, MO_UL, MO_UW, MO_UB };
215     tcg_debug_assert(mi < 5);
216     return mop[mi];
217 }
218 
219 /* load source operand */
220 static inline TCGv rx_load_source(DisasContext *ctx, TCGv mem,
221                                   int ld, int mi, int rs)
222 {
223     TCGv addr;
224     MemOp mop;
225     if (ld < 3) {
226         mop = mi_to_mop(mi);
227         addr = rx_index_addr(ctx, mem, ld, mop & MO_SIZE, rs);
228         tcg_gen_qemu_ld_i32(mem, addr, 0, mop | MO_TE);
229         return mem;
230     } else {
231         return cpu_regs[rs];
232     }
233 }
234 
235 /* Processor mode check */
236 static int is_privileged(DisasContext *ctx, int is_exception)
237 {
238     if (FIELD_EX32(ctx->tb_flags, PSW, PM)) {
239         if (is_exception) {
240             gen_helper_raise_privilege_violation(cpu_env);
241         }
242         return 0;
243     } else {
244         return 1;
245     }
246 }
247 
248 /* generate QEMU condition */
249 static void psw_cond(DisasCompare *dc, uint32_t cond)
250 {
251     tcg_debug_assert(cond < 16);
252     switch (cond) {
253     case 0: /* z */
254         dc->cond = TCG_COND_EQ;
255         dc->value = cpu_psw_z;
256         break;
257     case 1: /* nz */
258         dc->cond = TCG_COND_NE;
259         dc->value = cpu_psw_z;
260         break;
261     case 2: /* c */
262         dc->cond = TCG_COND_NE;
263         dc->value = cpu_psw_c;
264         break;
265     case 3: /* nc */
266         dc->cond = TCG_COND_EQ;
267         dc->value = cpu_psw_c;
268         break;
269     case 4: /* gtu (C& ~Z) == 1 */
270     case 5: /* leu (C& ~Z) == 0 */
271         tcg_gen_setcondi_i32(TCG_COND_NE, dc->temp, cpu_psw_z, 0);
272         tcg_gen_and_i32(dc->temp, dc->temp, cpu_psw_c);
273         dc->cond = (cond == 4) ? TCG_COND_NE : TCG_COND_EQ;
274         dc->value = dc->temp;
275         break;
276     case 6: /* pz (S == 0) */
277         dc->cond = TCG_COND_GE;
278         dc->value = cpu_psw_s;
279         break;
280     case 7: /* n (S == 1) */
281         dc->cond = TCG_COND_LT;
282         dc->value = cpu_psw_s;
283         break;
284     case 8: /* ge (S^O)==0 */
285     case 9: /* lt (S^O)==1 */
286         tcg_gen_xor_i32(dc->temp, cpu_psw_o, cpu_psw_s);
287         dc->cond = (cond == 8) ? TCG_COND_GE : TCG_COND_LT;
288         dc->value = dc->temp;
289         break;
290     case 10: /* gt ((S^O)|Z)==0 */
291     case 11: /* le ((S^O)|Z)==1 */
292         tcg_gen_xor_i32(dc->temp, cpu_psw_o, cpu_psw_s);
293         tcg_gen_sari_i32(dc->temp, dc->temp, 31);
294         tcg_gen_andc_i32(dc->temp, cpu_psw_z, dc->temp);
295         dc->cond = (cond == 10) ? TCG_COND_NE : TCG_COND_EQ;
296         dc->value = dc->temp;
297         break;
298     case 12: /* o */
299         dc->cond = TCG_COND_LT;
300         dc->value = cpu_psw_o;
301         break;
302     case 13: /* no */
303         dc->cond = TCG_COND_GE;
304         dc->value = cpu_psw_o;
305         break;
306     case 14: /* always true */
307         dc->cond = TCG_COND_ALWAYS;
308         dc->value = dc->temp;
309         break;
310     case 15: /* always false */
311         dc->cond = TCG_COND_NEVER;
312         dc->value = dc->temp;
313         break;
314     }
315 }
316 
317 static void move_from_cr(DisasContext *ctx, TCGv ret, int cr, uint32_t pc)
318 {
319     switch (cr) {
320     case 0:     /* PSW */
321         gen_helper_pack_psw(ret, cpu_env);
322         break;
323     case 1:     /* PC */
324         tcg_gen_movi_i32(ret, pc);
325         break;
326     case 2:     /* USP */
327         if (FIELD_EX32(ctx->tb_flags, PSW, U)) {
328             tcg_gen_mov_i32(ret, cpu_sp);
329         } else {
330             tcg_gen_mov_i32(ret, cpu_usp);
331         }
332         break;
333     case 3:     /* FPSW */
334         tcg_gen_mov_i32(ret, cpu_fpsw);
335         break;
336     case 8:     /* BPSW */
337         tcg_gen_mov_i32(ret, cpu_bpsw);
338         break;
339     case 9:     /* BPC */
340         tcg_gen_mov_i32(ret, cpu_bpc);
341         break;
342     case 10:    /* ISP */
343         if (FIELD_EX32(ctx->tb_flags, PSW, U)) {
344             tcg_gen_mov_i32(ret, cpu_isp);
345         } else {
346             tcg_gen_mov_i32(ret, cpu_sp);
347         }
348         break;
349     case 11:    /* FINTV */
350         tcg_gen_mov_i32(ret, cpu_fintv);
351         break;
352     case 12:    /* INTB */
353         tcg_gen_mov_i32(ret, cpu_intb);
354         break;
355     default:
356         qemu_log_mask(LOG_GUEST_ERROR, "Unimplement control register %d", cr);
357         /* Unimplement registers return 0 */
358         tcg_gen_movi_i32(ret, 0);
359         break;
360     }
361 }
362 
363 static void move_to_cr(DisasContext *ctx, TCGv val, int cr)
364 {
365     if (cr >= 8 && !is_privileged(ctx, 0)) {
366         /* Some control registers can only be written in privileged mode. */
367         qemu_log_mask(LOG_GUEST_ERROR,
368                       "disallow control register write %s", rx_crname(cr));
369         return;
370     }
371     switch (cr) {
372     case 0:     /* PSW */
373         gen_helper_set_psw(cpu_env, val);
374         if (is_privileged(ctx, 0)) {
375             /* PSW.{I,U} may be updated here. exit TB. */
376             ctx->base.is_jmp = DISAS_UPDATE;
377         }
378         break;
379     /* case 1: to PC not supported */
380     case 2:     /* USP */
381         if (FIELD_EX32(ctx->tb_flags, PSW, U)) {
382             tcg_gen_mov_i32(cpu_sp, val);
383         } else {
384             tcg_gen_mov_i32(cpu_usp, val);
385         }
386         break;
387     case 3:     /* FPSW */
388         gen_helper_set_fpsw(cpu_env, val);
389         break;
390     case 8:     /* BPSW */
391         tcg_gen_mov_i32(cpu_bpsw, val);
392         break;
393     case 9:     /* BPC */
394         tcg_gen_mov_i32(cpu_bpc, val);
395         break;
396     case 10:    /* ISP */
397         if (FIELD_EX32(ctx->tb_flags, PSW, U)) {
398             tcg_gen_mov_i32(cpu_isp, val);
399         } else {
400             tcg_gen_mov_i32(cpu_sp, val);
401         }
402         break;
403     case 11:    /* FINTV */
404         tcg_gen_mov_i32(cpu_fintv, val);
405         break;
406     case 12:    /* INTB */
407         tcg_gen_mov_i32(cpu_intb, val);
408         break;
409     default:
410         qemu_log_mask(LOG_GUEST_ERROR,
411                       "Unimplement control register %d", cr);
412         break;
413     }
414 }
415 
416 static void push(TCGv val)
417 {
418     tcg_gen_subi_i32(cpu_sp, cpu_sp, 4);
419     rx_gen_st(MO_32, val, cpu_sp);
420 }
421 
422 static void pop(TCGv ret)
423 {
424     rx_gen_ld(MO_32, ret, cpu_sp);
425     tcg_gen_addi_i32(cpu_sp, cpu_sp, 4);
426 }
427 
428 /* mov.<bwl> rs,dsp5[rd] */
429 static bool trans_MOV_rm(DisasContext *ctx, arg_MOV_rm *a)
430 {
431     TCGv mem;
432     mem = tcg_temp_new();
433     tcg_gen_addi_i32(mem, cpu_regs[a->rd], a->dsp << a->sz);
434     rx_gen_st(a->sz, cpu_regs[a->rs], mem);
435     return true;
436 }
437 
438 /* mov.<bwl> dsp5[rs],rd */
439 static bool trans_MOV_mr(DisasContext *ctx, arg_MOV_mr *a)
440 {
441     TCGv mem;
442     mem = tcg_temp_new();
443     tcg_gen_addi_i32(mem, cpu_regs[a->rs], a->dsp << a->sz);
444     rx_gen_ld(a->sz, cpu_regs[a->rd], mem);
445     return true;
446 }
447 
448 /* mov.l #uimm4,rd */
449 /* mov.l #uimm8,rd */
450 /* mov.l #imm,rd */
451 static bool trans_MOV_ir(DisasContext *ctx, arg_MOV_ir *a)
452 {
453     tcg_gen_movi_i32(cpu_regs[a->rd], a->imm);
454     return true;
455 }
456 
457 /* mov.<bwl> #uimm8,dsp[rd] */
458 /* mov.<bwl> #imm, dsp[rd] */
459 static bool trans_MOV_im(DisasContext *ctx, arg_MOV_im *a)
460 {
461     TCGv imm, mem;
462     imm = tcg_constant_i32(a->imm);
463     mem = tcg_temp_new();
464     tcg_gen_addi_i32(mem, cpu_regs[a->rd], a->dsp << a->sz);
465     rx_gen_st(a->sz, imm, mem);
466     return true;
467 }
468 
469 /* mov.<bwl> [ri,rb],rd */
470 static bool trans_MOV_ar(DisasContext *ctx, arg_MOV_ar *a)
471 {
472     TCGv mem;
473     mem = tcg_temp_new();
474     rx_gen_regindex(ctx, mem, a->sz, a->ri, a->rb);
475     rx_gen_ld(a->sz, cpu_regs[a->rd], mem);
476     return true;
477 }
478 
479 /* mov.<bwl> rd,[ri,rb] */
480 static bool trans_MOV_ra(DisasContext *ctx, arg_MOV_ra *a)
481 {
482     TCGv mem;
483     mem = tcg_temp_new();
484     rx_gen_regindex(ctx, mem, a->sz, a->ri, a->rb);
485     rx_gen_st(a->sz, cpu_regs[a->rs], mem);
486     return true;
487 }
488 
489 /* mov.<bwl> dsp[rs],dsp[rd] */
490 /* mov.<bwl> rs,dsp[rd] */
491 /* mov.<bwl> dsp[rs],rd */
492 /* mov.<bwl> rs,rd */
493 static bool trans_MOV_mm(DisasContext *ctx, arg_MOV_mm *a)
494 {
495     static void (* const mov[])(TCGv ret, TCGv arg) = {
496         tcg_gen_ext8s_i32, tcg_gen_ext16s_i32, tcg_gen_mov_i32,
497     };
498     TCGv tmp, mem, addr;
499     if (a->lds == 3 && a->ldd == 3) {
500         /* mov.<bwl> rs,rd */
501         mov[a->sz](cpu_regs[a->rd], cpu_regs[a->rs]);
502         return true;
503     }
504 
505     mem = tcg_temp_new();
506     if (a->lds == 3) {
507         /* mov.<bwl> rs,dsp[rd] */
508         addr = rx_index_addr(ctx, mem, a->ldd, a->sz, a->rs);
509         rx_gen_st(a->sz, cpu_regs[a->rd], addr);
510     } else if (a->ldd == 3) {
511         /* mov.<bwl> dsp[rs],rd */
512         addr = rx_index_addr(ctx, mem, a->lds, a->sz, a->rs);
513         rx_gen_ld(a->sz, cpu_regs[a->rd], addr);
514     } else {
515         /* mov.<bwl> dsp[rs],dsp[rd] */
516         tmp = tcg_temp_new();
517         addr = rx_index_addr(ctx, mem, a->lds, a->sz, a->rs);
518         rx_gen_ld(a->sz, tmp, addr);
519         addr = rx_index_addr(ctx, mem, a->ldd, a->sz, a->rd);
520         rx_gen_st(a->sz, tmp, addr);
521     }
522     return true;
523 }
524 
525 /* mov.<bwl> rs,[rd+] */
526 /* mov.<bwl> rs,[-rd] */
527 static bool trans_MOV_rp(DisasContext *ctx, arg_MOV_rp *a)
528 {
529     TCGv val;
530     val = tcg_temp_new();
531     tcg_gen_mov_i32(val, cpu_regs[a->rs]);
532     if (a->ad == 1) {
533         tcg_gen_subi_i32(cpu_regs[a->rd], cpu_regs[a->rd], 1 << a->sz);
534     }
535     rx_gen_st(a->sz, val, cpu_regs[a->rd]);
536     if (a->ad == 0) {
537         tcg_gen_addi_i32(cpu_regs[a->rd], cpu_regs[a->rd], 1 << a->sz);
538     }
539     return true;
540 }
541 
542 /* mov.<bwl> [rd+],rs */
543 /* mov.<bwl> [-rd],rs */
544 static bool trans_MOV_pr(DisasContext *ctx, arg_MOV_pr *a)
545 {
546     TCGv val;
547     val = tcg_temp_new();
548     if (a->ad == 1) {
549         tcg_gen_subi_i32(cpu_regs[a->rd], cpu_regs[a->rd], 1 << a->sz);
550     }
551     rx_gen_ld(a->sz, val, cpu_regs[a->rd]);
552     if (a->ad == 0) {
553         tcg_gen_addi_i32(cpu_regs[a->rd], cpu_regs[a->rd], 1 << a->sz);
554     }
555     tcg_gen_mov_i32(cpu_regs[a->rs], val);
556     return true;
557 }
558 
559 /* movu.<bw> dsp5[rs],rd */
560 /* movu.<bw> dsp[rs],rd */
561 static bool trans_MOVU_mr(DisasContext *ctx, arg_MOVU_mr *a)
562 {
563     TCGv mem;
564     mem = tcg_temp_new();
565     tcg_gen_addi_i32(mem, cpu_regs[a->rs], a->dsp << a->sz);
566     rx_gen_ldu(a->sz, cpu_regs[a->rd], mem);
567     return true;
568 }
569 
570 /* movu.<bw> rs,rd */
571 static bool trans_MOVU_rr(DisasContext *ctx, arg_MOVU_rr *a)
572 {
573     static void (* const ext[])(TCGv ret, TCGv arg) = {
574         tcg_gen_ext8u_i32, tcg_gen_ext16u_i32,
575     };
576     ext[a->sz](cpu_regs[a->rd], cpu_regs[a->rs]);
577     return true;
578 }
579 
580 /* movu.<bw> [ri,rb],rd */
581 static bool trans_MOVU_ar(DisasContext *ctx, arg_MOVU_ar *a)
582 {
583     TCGv mem;
584     mem = tcg_temp_new();
585     rx_gen_regindex(ctx, mem, a->sz, a->ri, a->rb);
586     rx_gen_ldu(a->sz, cpu_regs[a->rd], mem);
587     return true;
588 }
589 
590 /* movu.<bw> [rd+],rs */
591 /* mov.<bw> [-rd],rs */
592 static bool trans_MOVU_pr(DisasContext *ctx, arg_MOVU_pr *a)
593 {
594     TCGv val;
595     val = tcg_temp_new();
596     if (a->ad == 1) {
597         tcg_gen_subi_i32(cpu_regs[a->rd], cpu_regs[a->rd], 1 << a->sz);
598     }
599     rx_gen_ldu(a->sz, val, cpu_regs[a->rd]);
600     if (a->ad == 0) {
601         tcg_gen_addi_i32(cpu_regs[a->rd], cpu_regs[a->rd], 1 << a->sz);
602     }
603     tcg_gen_mov_i32(cpu_regs[a->rs], val);
604     return true;
605 }
606 
607 
608 /* pop rd */
609 static bool trans_POP(DisasContext *ctx, arg_POP *a)
610 {
611     /* mov.l [r0+], rd */
612     arg_MOV_rp mov_a;
613     mov_a.rd = 0;
614     mov_a.rs = a->rd;
615     mov_a.ad = 0;
616     mov_a.sz = MO_32;
617     trans_MOV_pr(ctx, &mov_a);
618     return true;
619 }
620 
621 /* popc cr */
622 static bool trans_POPC(DisasContext *ctx, arg_POPC *a)
623 {
624     TCGv val;
625     val = tcg_temp_new();
626     pop(val);
627     move_to_cr(ctx, val, a->cr);
628     return true;
629 }
630 
631 /* popm rd-rd2 */
632 static bool trans_POPM(DisasContext *ctx, arg_POPM *a)
633 {
634     int r;
635     if (a->rd == 0 || a->rd >= a->rd2) {
636         qemu_log_mask(LOG_GUEST_ERROR,
637                       "Invalid  register ranges r%d-r%d", a->rd, a->rd2);
638     }
639     r = a->rd;
640     while (r <= a->rd2 && r < 16) {
641         pop(cpu_regs[r++]);
642     }
643     return true;
644 }
645 
646 
647 /* push.<bwl> rs */
648 static bool trans_PUSH_r(DisasContext *ctx, arg_PUSH_r *a)
649 {
650     TCGv val;
651     val = tcg_temp_new();
652     tcg_gen_mov_i32(val, cpu_regs[a->rs]);
653     tcg_gen_subi_i32(cpu_sp, cpu_sp, 4);
654     rx_gen_st(a->sz, val, cpu_sp);
655     return true;
656 }
657 
658 /* push.<bwl> dsp[rs] */
659 static bool trans_PUSH_m(DisasContext *ctx, arg_PUSH_m *a)
660 {
661     TCGv mem, val, addr;
662     mem = tcg_temp_new();
663     val = tcg_temp_new();
664     addr = rx_index_addr(ctx, mem, a->ld, a->sz, a->rs);
665     rx_gen_ld(a->sz, val, addr);
666     tcg_gen_subi_i32(cpu_sp, cpu_sp, 4);
667     rx_gen_st(a->sz, val, cpu_sp);
668     return true;
669 }
670 
671 /* pushc rx */
672 static bool trans_PUSHC(DisasContext *ctx, arg_PUSHC *a)
673 {
674     TCGv val;
675     val = tcg_temp_new();
676     move_from_cr(ctx, val, a->cr, ctx->pc);
677     push(val);
678     return true;
679 }
680 
681 /* pushm rs-rs2 */
682 static bool trans_PUSHM(DisasContext *ctx, arg_PUSHM *a)
683 {
684     int r;
685 
686     if (a->rs == 0 || a->rs >= a->rs2) {
687         qemu_log_mask(LOG_GUEST_ERROR,
688                       "Invalid  register ranges r%d-r%d", a->rs, a->rs2);
689     }
690     r = a->rs2;
691     while (r >= a->rs && r >= 0) {
692         push(cpu_regs[r--]);
693     }
694     return true;
695 }
696 
697 /* xchg rs,rd */
698 static bool trans_XCHG_rr(DisasContext *ctx, arg_XCHG_rr *a)
699 {
700     TCGv tmp;
701     tmp = tcg_temp_new();
702     tcg_gen_mov_i32(tmp, cpu_regs[a->rs]);
703     tcg_gen_mov_i32(cpu_regs[a->rs], cpu_regs[a->rd]);
704     tcg_gen_mov_i32(cpu_regs[a->rd], tmp);
705     return true;
706 }
707 
708 /* xchg dsp[rs].<mi>,rd */
709 static bool trans_XCHG_mr(DisasContext *ctx, arg_XCHG_mr *a)
710 {
711     TCGv mem, addr;
712     mem = tcg_temp_new();
713     switch (a->mi) {
714     case 0: /* dsp[rs].b */
715     case 1: /* dsp[rs].w */
716     case 2: /* dsp[rs].l */
717         addr = rx_index_addr(ctx, mem, a->ld, a->mi, a->rs);
718         break;
719     case 3: /* dsp[rs].uw */
720     case 4: /* dsp[rs].ub */
721         addr = rx_index_addr(ctx, mem, a->ld, 4 - a->mi, a->rs);
722         break;
723     default:
724         g_assert_not_reached();
725     }
726     tcg_gen_atomic_xchg_i32(cpu_regs[a->rd], addr, cpu_regs[a->rd],
727                             0, mi_to_mop(a->mi));
728     return true;
729 }
730 
731 static inline void stcond(TCGCond cond, int rd, int imm)
732 {
733     TCGv z;
734     TCGv _imm;
735     z = tcg_constant_i32(0);
736     _imm = tcg_constant_i32(imm);
737     tcg_gen_movcond_i32(cond, cpu_regs[rd], cpu_psw_z, z,
738                         _imm, cpu_regs[rd]);
739 }
740 
741 /* stz #imm,rd */
742 static bool trans_STZ(DisasContext *ctx, arg_STZ *a)
743 {
744     stcond(TCG_COND_EQ, a->rd, a->imm);
745     return true;
746 }
747 
748 /* stnz #imm,rd */
749 static bool trans_STNZ(DisasContext *ctx, arg_STNZ *a)
750 {
751     stcond(TCG_COND_NE, a->rd, a->imm);
752     return true;
753 }
754 
755 /* sccnd.<bwl> rd */
756 /* sccnd.<bwl> dsp:[rd] */
757 static bool trans_SCCnd(DisasContext *ctx, arg_SCCnd *a)
758 {
759     DisasCompare dc;
760     TCGv val, mem, addr;
761     dc.temp = tcg_temp_new();
762     psw_cond(&dc, a->cd);
763     if (a->ld < 3) {
764         val = tcg_temp_new();
765         mem = tcg_temp_new();
766         tcg_gen_setcondi_i32(dc.cond, val, dc.value, 0);
767         addr = rx_index_addr(ctx, mem, a->sz, a->ld, a->rd);
768         rx_gen_st(a->sz, val, addr);
769     } else {
770         tcg_gen_setcondi_i32(dc.cond, cpu_regs[a->rd], dc.value, 0);
771     }
772     return true;
773 }
774 
775 /* rtsd #imm */
776 static bool trans_RTSD_i(DisasContext *ctx, arg_RTSD_i *a)
777 {
778     tcg_gen_addi_i32(cpu_sp, cpu_sp, a->imm  << 2);
779     pop(cpu_pc);
780     ctx->base.is_jmp = DISAS_JUMP;
781     return true;
782 }
783 
784 /* rtsd #imm, rd-rd2 */
785 static bool trans_RTSD_irr(DisasContext *ctx, arg_RTSD_irr *a)
786 {
787     int dst;
788     int adj;
789 
790     if (a->rd2 >= a->rd) {
791         adj = a->imm - (a->rd2 - a->rd + 1);
792     } else {
793         adj = a->imm - (15 - a->rd + 1);
794     }
795 
796     tcg_gen_addi_i32(cpu_sp, cpu_sp, adj << 2);
797     dst = a->rd;
798     while (dst <= a->rd2 && dst < 16) {
799         pop(cpu_regs[dst++]);
800     }
801     pop(cpu_pc);
802     ctx->base.is_jmp = DISAS_JUMP;
803     return true;
804 }
805 
806 typedef void (*op2fn)(TCGv ret, TCGv arg1);
807 typedef void (*op3fn)(TCGv ret, TCGv arg1, TCGv arg2);
808 
809 static inline void rx_gen_op_rr(op2fn opr, int dst, int src)
810 {
811     opr(cpu_regs[dst], cpu_regs[src]);
812 }
813 
814 static inline void rx_gen_op_rrr(op3fn opr, int dst, int src, int src2)
815 {
816     opr(cpu_regs[dst], cpu_regs[src], cpu_regs[src2]);
817 }
818 
819 static inline void rx_gen_op_irr(op3fn opr, int dst, int src, uint32_t src2)
820 {
821     TCGv imm = tcg_constant_i32(src2);
822     opr(cpu_regs[dst], cpu_regs[src], imm);
823 }
824 
825 static inline void rx_gen_op_mr(op3fn opr, DisasContext *ctx,
826                                 int dst, int src, int ld, int mi)
827 {
828     TCGv val, mem;
829     mem = tcg_temp_new();
830     val = rx_load_source(ctx, mem, ld, mi, src);
831     opr(cpu_regs[dst], cpu_regs[dst], val);
832 }
833 
834 static void rx_and(TCGv ret, TCGv arg1, TCGv arg2)
835 {
836     tcg_gen_and_i32(cpu_psw_s, arg1, arg2);
837     tcg_gen_mov_i32(cpu_psw_z, cpu_psw_s);
838     tcg_gen_mov_i32(ret, cpu_psw_s);
839 }
840 
841 /* and #uimm:4, rd */
842 /* and #imm, rd */
843 static bool trans_AND_ir(DisasContext *ctx, arg_AND_ir *a)
844 {
845     rx_gen_op_irr(rx_and, a->rd, a->rd, a->imm);
846     return true;
847 }
848 
849 /* and dsp[rs], rd */
850 /* and rs,rd */
851 static bool trans_AND_mr(DisasContext *ctx, arg_AND_mr *a)
852 {
853     rx_gen_op_mr(rx_and, ctx, a->rd, a->rs, a->ld, a->mi);
854     return true;
855 }
856 
857 /* and rs,rs2,rd */
858 static bool trans_AND_rrr(DisasContext *ctx, arg_AND_rrr *a)
859 {
860     rx_gen_op_rrr(rx_and, a->rd, a->rs, a->rs2);
861     return true;
862 }
863 
864 static void rx_or(TCGv ret, TCGv arg1, TCGv arg2)
865 {
866     tcg_gen_or_i32(cpu_psw_s, arg1, arg2);
867     tcg_gen_mov_i32(cpu_psw_z, cpu_psw_s);
868     tcg_gen_mov_i32(ret, cpu_psw_s);
869 }
870 
871 /* or #uimm:4, rd */
872 /* or #imm, rd */
873 static bool trans_OR_ir(DisasContext *ctx, arg_OR_ir *a)
874 {
875     rx_gen_op_irr(rx_or, a->rd, a->rd, a->imm);
876     return true;
877 }
878 
879 /* or dsp[rs], rd */
880 /* or rs,rd */
881 static bool trans_OR_mr(DisasContext *ctx, arg_OR_mr *a)
882 {
883     rx_gen_op_mr(rx_or, ctx, a->rd, a->rs, a->ld, a->mi);
884     return true;
885 }
886 
887 /* or rs,rs2,rd */
888 static bool trans_OR_rrr(DisasContext *ctx, arg_OR_rrr *a)
889 {
890     rx_gen_op_rrr(rx_or, a->rd, a->rs, a->rs2);
891     return true;
892 }
893 
894 static void rx_xor(TCGv ret, TCGv arg1, TCGv arg2)
895 {
896     tcg_gen_xor_i32(cpu_psw_s, arg1, arg2);
897     tcg_gen_mov_i32(cpu_psw_z, cpu_psw_s);
898     tcg_gen_mov_i32(ret, cpu_psw_s);
899 }
900 
901 /* xor #imm, rd */
902 static bool trans_XOR_ir(DisasContext *ctx, arg_XOR_ir *a)
903 {
904     rx_gen_op_irr(rx_xor, a->rd, a->rd, a->imm);
905     return true;
906 }
907 
908 /* xor dsp[rs], rd */
909 /* xor rs,rd */
910 static bool trans_XOR_mr(DisasContext *ctx, arg_XOR_mr *a)
911 {
912     rx_gen_op_mr(rx_xor, ctx, a->rd, a->rs, a->ld, a->mi);
913     return true;
914 }
915 
916 static void rx_tst(TCGv ret, TCGv arg1, TCGv arg2)
917 {
918     tcg_gen_and_i32(cpu_psw_s, arg1, arg2);
919     tcg_gen_mov_i32(cpu_psw_z, cpu_psw_s);
920 }
921 
922 /* tst #imm, rd */
923 static bool trans_TST_ir(DisasContext *ctx, arg_TST_ir *a)
924 {
925     rx_gen_op_irr(rx_tst, a->rd, a->rd, a->imm);
926     return true;
927 }
928 
929 /* tst dsp[rs], rd */
930 /* tst rs, rd */
931 static bool trans_TST_mr(DisasContext *ctx, arg_TST_mr *a)
932 {
933     rx_gen_op_mr(rx_tst, ctx, a->rd, a->rs, a->ld, a->mi);
934     return true;
935 }
936 
937 static void rx_not(TCGv ret, TCGv arg1)
938 {
939     tcg_gen_not_i32(ret, arg1);
940     tcg_gen_mov_i32(cpu_psw_z, ret);
941     tcg_gen_mov_i32(cpu_psw_s, ret);
942 }
943 
944 /* not rd */
945 /* not rs, rd */
946 static bool trans_NOT_rr(DisasContext *ctx, arg_NOT_rr *a)
947 {
948     rx_gen_op_rr(rx_not, a->rd, a->rs);
949     return true;
950 }
951 
952 static void rx_neg(TCGv ret, TCGv arg1)
953 {
954     tcg_gen_setcondi_i32(TCG_COND_EQ, cpu_psw_o, arg1, 0x80000000);
955     tcg_gen_neg_i32(ret, arg1);
956     tcg_gen_setcondi_i32(TCG_COND_EQ, cpu_psw_c, ret, 0);
957     tcg_gen_mov_i32(cpu_psw_z, ret);
958     tcg_gen_mov_i32(cpu_psw_s, ret);
959 }
960 
961 
962 /* neg rd */
963 /* neg rs, rd */
964 static bool trans_NEG_rr(DisasContext *ctx, arg_NEG_rr *a)
965 {
966     rx_gen_op_rr(rx_neg, a->rd, a->rs);
967     return true;
968 }
969 
970 /* ret = arg1 + arg2 + psw_c */
971 static void rx_adc(TCGv ret, TCGv arg1, TCGv arg2)
972 {
973     TCGv z = tcg_constant_i32(0);
974     tcg_gen_add2_i32(cpu_psw_s, cpu_psw_c, arg1, z, cpu_psw_c, z);
975     tcg_gen_add2_i32(cpu_psw_s, cpu_psw_c, cpu_psw_s, cpu_psw_c, arg2, z);
976     tcg_gen_xor_i32(cpu_psw_o, cpu_psw_s, arg1);
977     tcg_gen_xor_i32(cpu_psw_z, arg1, arg2);
978     tcg_gen_andc_i32(cpu_psw_o, cpu_psw_o, cpu_psw_z);
979     tcg_gen_mov_i32(cpu_psw_z, cpu_psw_s);
980     tcg_gen_mov_i32(ret, cpu_psw_s);
981 }
982 
983 /* adc #imm, rd */
984 static bool trans_ADC_ir(DisasContext *ctx, arg_ADC_ir *a)
985 {
986     rx_gen_op_irr(rx_adc, a->rd, a->rd, a->imm);
987     return true;
988 }
989 
990 /* adc rs, rd */
991 static bool trans_ADC_rr(DisasContext *ctx, arg_ADC_rr *a)
992 {
993     rx_gen_op_rrr(rx_adc, a->rd, a->rd, a->rs);
994     return true;
995 }
996 
997 /* adc dsp[rs], rd */
998 static bool trans_ADC_mr(DisasContext *ctx, arg_ADC_mr *a)
999 {
1000     /* mi only 2 */
1001     if (a->mi != 2) {
1002         return false;
1003     }
1004     rx_gen_op_mr(rx_adc, ctx, a->rd, a->rs, a->ld, a->mi);
1005     return true;
1006 }
1007 
1008 /* ret = arg1 + arg2 */
1009 static void rx_add(TCGv ret, TCGv arg1, TCGv arg2)
1010 {
1011     TCGv z = tcg_constant_i32(0);
1012     tcg_gen_add2_i32(cpu_psw_s, cpu_psw_c, arg1, z, arg2, z);
1013     tcg_gen_xor_i32(cpu_psw_o, cpu_psw_s, arg1);
1014     tcg_gen_xor_i32(cpu_psw_z, arg1, arg2);
1015     tcg_gen_andc_i32(cpu_psw_o, cpu_psw_o, cpu_psw_z);
1016     tcg_gen_mov_i32(cpu_psw_z, cpu_psw_s);
1017     tcg_gen_mov_i32(ret, cpu_psw_s);
1018 }
1019 
1020 /* add #uimm4, rd */
1021 /* add #imm, rs, rd */
1022 static bool trans_ADD_irr(DisasContext *ctx, arg_ADD_irr *a)
1023 {
1024     rx_gen_op_irr(rx_add, a->rd, a->rs2, a->imm);
1025     return true;
1026 }
1027 
1028 /* add rs, rd */
1029 /* add dsp[rs], rd */
1030 static bool trans_ADD_mr(DisasContext *ctx, arg_ADD_mr *a)
1031 {
1032     rx_gen_op_mr(rx_add, ctx, a->rd, a->rs, a->ld, a->mi);
1033     return true;
1034 }
1035 
1036 /* add rs, rs2, rd */
1037 static bool trans_ADD_rrr(DisasContext *ctx, arg_ADD_rrr *a)
1038 {
1039     rx_gen_op_rrr(rx_add, a->rd, a->rs, a->rs2);
1040     return true;
1041 }
1042 
1043 /* ret = arg1 - arg2 */
1044 static void rx_sub(TCGv ret, TCGv arg1, TCGv arg2)
1045 {
1046     tcg_gen_sub_i32(cpu_psw_s, arg1, arg2);
1047     tcg_gen_setcond_i32(TCG_COND_GEU, cpu_psw_c, arg1, arg2);
1048     tcg_gen_xor_i32(cpu_psw_o, cpu_psw_s, arg1);
1049     tcg_gen_xor_i32(cpu_psw_z, arg1, arg2);
1050     tcg_gen_and_i32(cpu_psw_o, cpu_psw_o, cpu_psw_z);
1051     tcg_gen_mov_i32(cpu_psw_z, cpu_psw_s);
1052     /* CMP not required return */
1053     if (ret) {
1054         tcg_gen_mov_i32(ret, cpu_psw_s);
1055     }
1056 }
1057 
1058 static void rx_cmp(TCGv dummy, TCGv arg1, TCGv arg2)
1059 {
1060     rx_sub(NULL, arg1, arg2);
1061 }
1062 
1063 /* ret = arg1 - arg2 - !psw_c */
1064 /* -> ret = arg1 + ~arg2 + psw_c */
1065 static void rx_sbb(TCGv ret, TCGv arg1, TCGv arg2)
1066 {
1067     TCGv temp;
1068     temp = tcg_temp_new();
1069     tcg_gen_not_i32(temp, arg2);
1070     rx_adc(ret, arg1, temp);
1071 }
1072 
1073 /* cmp #imm4, rs2 */
1074 /* cmp #imm8, rs2 */
1075 /* cmp #imm, rs2 */
1076 static bool trans_CMP_ir(DisasContext *ctx, arg_CMP_ir *a)
1077 {
1078     rx_gen_op_irr(rx_cmp, 0, a->rs2, a->imm);
1079     return true;
1080 }
1081 
1082 /* cmp rs, rs2 */
1083 /* cmp dsp[rs], rs2 */
1084 static bool trans_CMP_mr(DisasContext *ctx, arg_CMP_mr *a)
1085 {
1086     rx_gen_op_mr(rx_cmp, ctx, a->rd, a->rs, a->ld, a->mi);
1087     return true;
1088 }
1089 
1090 /* sub #imm4, rd */
1091 static bool trans_SUB_ir(DisasContext *ctx, arg_SUB_ir *a)
1092 {
1093     rx_gen_op_irr(rx_sub, a->rd, a->rd, a->imm);
1094     return true;
1095 }
1096 
1097 /* sub rs, rd */
1098 /* sub dsp[rs], rd */
1099 static bool trans_SUB_mr(DisasContext *ctx, arg_SUB_mr *a)
1100 {
1101     rx_gen_op_mr(rx_sub, ctx, a->rd, a->rs, a->ld, a->mi);
1102     return true;
1103 }
1104 
1105 /* sub rs2, rs, rd */
1106 static bool trans_SUB_rrr(DisasContext *ctx, arg_SUB_rrr *a)
1107 {
1108     rx_gen_op_rrr(rx_sub, a->rd, a->rs2, a->rs);
1109     return true;
1110 }
1111 
1112 /* sbb rs, rd */
1113 static bool trans_SBB_rr(DisasContext *ctx, arg_SBB_rr *a)
1114 {
1115     rx_gen_op_rrr(rx_sbb, a->rd, a->rd, a->rs);
1116     return true;
1117 }
1118 
1119 /* sbb dsp[rs], rd */
1120 static bool trans_SBB_mr(DisasContext *ctx, arg_SBB_mr *a)
1121 {
1122     /* mi only 2 */
1123     if (a->mi != 2) {
1124         return false;
1125     }
1126     rx_gen_op_mr(rx_sbb, ctx, a->rd, a->rs, a->ld, a->mi);
1127     return true;
1128 }
1129 
1130 /* abs rd */
1131 /* abs rs, rd */
1132 static bool trans_ABS_rr(DisasContext *ctx, arg_ABS_rr *a)
1133 {
1134     rx_gen_op_rr(tcg_gen_abs_i32, a->rd, a->rs);
1135     return true;
1136 }
1137 
1138 /* max #imm, rd */
1139 static bool trans_MAX_ir(DisasContext *ctx, arg_MAX_ir *a)
1140 {
1141     rx_gen_op_irr(tcg_gen_smax_i32, a->rd, a->rd, a->imm);
1142     return true;
1143 }
1144 
1145 /* max rs, rd */
1146 /* max dsp[rs], rd */
1147 static bool trans_MAX_mr(DisasContext *ctx, arg_MAX_mr *a)
1148 {
1149     rx_gen_op_mr(tcg_gen_smax_i32, ctx, a->rd, a->rs, a->ld, a->mi);
1150     return true;
1151 }
1152 
1153 /* min #imm, rd */
1154 static bool trans_MIN_ir(DisasContext *ctx, arg_MIN_ir *a)
1155 {
1156     rx_gen_op_irr(tcg_gen_smin_i32, a->rd, a->rd, a->imm);
1157     return true;
1158 }
1159 
1160 /* min rs, rd */
1161 /* min dsp[rs], rd */
1162 static bool trans_MIN_mr(DisasContext *ctx, arg_MIN_mr *a)
1163 {
1164     rx_gen_op_mr(tcg_gen_smin_i32, ctx, a->rd, a->rs, a->ld, a->mi);
1165     return true;
1166 }
1167 
1168 /* mul #uimm4, rd */
1169 /* mul #imm, rd */
1170 static bool trans_MUL_ir(DisasContext *ctx, arg_MUL_ir *a)
1171 {
1172     rx_gen_op_irr(tcg_gen_mul_i32, a->rd, a->rd, a->imm);
1173     return true;
1174 }
1175 
1176 /* mul rs, rd */
1177 /* mul dsp[rs], rd */
1178 static bool trans_MUL_mr(DisasContext *ctx, arg_MUL_mr *a)
1179 {
1180     rx_gen_op_mr(tcg_gen_mul_i32, ctx, a->rd, a->rs, a->ld, a->mi);
1181     return true;
1182 }
1183 
1184 /* mul rs, rs2, rd */
1185 static bool trans_MUL_rrr(DisasContext *ctx, arg_MUL_rrr *a)
1186 {
1187     rx_gen_op_rrr(tcg_gen_mul_i32, a->rd, a->rs, a->rs2);
1188     return true;
1189 }
1190 
1191 /* emul #imm, rd */
1192 static bool trans_EMUL_ir(DisasContext *ctx, arg_EMUL_ir *a)
1193 {
1194     TCGv imm = tcg_constant_i32(a->imm);
1195     if (a->rd > 14) {
1196         qemu_log_mask(LOG_GUEST_ERROR, "rd too large %d", a->rd);
1197     }
1198     tcg_gen_muls2_i32(cpu_regs[a->rd], cpu_regs[(a->rd + 1) & 15],
1199                       cpu_regs[a->rd], imm);
1200     return true;
1201 }
1202 
1203 /* emul rs, rd */
1204 /* emul dsp[rs], rd */
1205 static bool trans_EMUL_mr(DisasContext *ctx, arg_EMUL_mr *a)
1206 {
1207     TCGv val, mem;
1208     if (a->rd > 14) {
1209         qemu_log_mask(LOG_GUEST_ERROR, "rd too large %d", a->rd);
1210     }
1211     mem = tcg_temp_new();
1212     val = rx_load_source(ctx, mem, a->ld, a->mi, a->rs);
1213     tcg_gen_muls2_i32(cpu_regs[a->rd], cpu_regs[(a->rd + 1) & 15],
1214                       cpu_regs[a->rd], val);
1215     return true;
1216 }
1217 
1218 /* emulu #imm, rd */
1219 static bool trans_EMULU_ir(DisasContext *ctx, arg_EMULU_ir *a)
1220 {
1221     TCGv imm = tcg_constant_i32(a->imm);
1222     if (a->rd > 14) {
1223         qemu_log_mask(LOG_GUEST_ERROR, "rd too large %d", a->rd);
1224     }
1225     tcg_gen_mulu2_i32(cpu_regs[a->rd], cpu_regs[(a->rd + 1) & 15],
1226                       cpu_regs[a->rd], imm);
1227     return true;
1228 }
1229 
1230 /* emulu rs, rd */
1231 /* emulu dsp[rs], rd */
1232 static bool trans_EMULU_mr(DisasContext *ctx, arg_EMULU_mr *a)
1233 {
1234     TCGv val, mem;
1235     if (a->rd > 14) {
1236         qemu_log_mask(LOG_GUEST_ERROR, "rd too large %d", a->rd);
1237     }
1238     mem = tcg_temp_new();
1239     val = rx_load_source(ctx, mem, a->ld, a->mi, a->rs);
1240     tcg_gen_mulu2_i32(cpu_regs[a->rd], cpu_regs[(a->rd + 1) & 15],
1241                       cpu_regs[a->rd], val);
1242     return true;
1243 }
1244 
1245 static void rx_div(TCGv ret, TCGv arg1, TCGv arg2)
1246 {
1247     gen_helper_div(ret, cpu_env, arg1, arg2);
1248 }
1249 
1250 static void rx_divu(TCGv ret, TCGv arg1, TCGv arg2)
1251 {
1252     gen_helper_divu(ret, cpu_env, arg1, arg2);
1253 }
1254 
1255 /* div #imm, rd */
1256 static bool trans_DIV_ir(DisasContext *ctx, arg_DIV_ir *a)
1257 {
1258     rx_gen_op_irr(rx_div, a->rd, a->rd, a->imm);
1259     return true;
1260 }
1261 
1262 /* div rs, rd */
1263 /* div dsp[rs], rd */
1264 static bool trans_DIV_mr(DisasContext *ctx, arg_DIV_mr *a)
1265 {
1266     rx_gen_op_mr(rx_div, ctx, a->rd, a->rs, a->ld, a->mi);
1267     return true;
1268 }
1269 
1270 /* divu #imm, rd */
1271 static bool trans_DIVU_ir(DisasContext *ctx, arg_DIVU_ir *a)
1272 {
1273     rx_gen_op_irr(rx_divu, a->rd, a->rd, a->imm);
1274     return true;
1275 }
1276 
1277 /* divu rs, rd */
1278 /* divu dsp[rs], rd */
1279 static bool trans_DIVU_mr(DisasContext *ctx, arg_DIVU_mr *a)
1280 {
1281     rx_gen_op_mr(rx_divu, ctx, a->rd, a->rs, a->ld, a->mi);
1282     return true;
1283 }
1284 
1285 
1286 /* shll #imm:5, rd */
1287 /* shll #imm:5, rs2, rd */
1288 static bool trans_SHLL_irr(DisasContext *ctx, arg_SHLL_irr *a)
1289 {
1290     TCGv tmp;
1291     tmp = tcg_temp_new();
1292     if (a->imm) {
1293         tcg_gen_sari_i32(cpu_psw_c, cpu_regs[a->rs2], 32 - a->imm);
1294         tcg_gen_shli_i32(cpu_regs[a->rd], cpu_regs[a->rs2], a->imm);
1295         tcg_gen_setcondi_i32(TCG_COND_EQ, cpu_psw_o, cpu_psw_c, 0);
1296         tcg_gen_setcondi_i32(TCG_COND_EQ, tmp, cpu_psw_c, 0xffffffff);
1297         tcg_gen_or_i32(cpu_psw_o, cpu_psw_o, tmp);
1298         tcg_gen_setcondi_i32(TCG_COND_NE, cpu_psw_c, cpu_psw_c, 0);
1299     } else {
1300         tcg_gen_mov_i32(cpu_regs[a->rd], cpu_regs[a->rs2]);
1301         tcg_gen_movi_i32(cpu_psw_c, 0);
1302         tcg_gen_movi_i32(cpu_psw_o, 0);
1303     }
1304     tcg_gen_mov_i32(cpu_psw_z, cpu_regs[a->rd]);
1305     tcg_gen_mov_i32(cpu_psw_s, cpu_regs[a->rd]);
1306     return true;
1307 }
1308 
1309 /* shll rs, rd */
1310 static bool trans_SHLL_rr(DisasContext *ctx, arg_SHLL_rr *a)
1311 {
1312     TCGLabel *noshift, *done;
1313     TCGv count, tmp;
1314 
1315     noshift = gen_new_label();
1316     done = gen_new_label();
1317     /* if (cpu_regs[a->rs]) { */
1318     tcg_gen_brcondi_i32(TCG_COND_EQ, cpu_regs[a->rs], 0, noshift);
1319     count = tcg_temp_new();
1320     tmp = tcg_temp_new();
1321     tcg_gen_andi_i32(tmp, cpu_regs[a->rs], 31);
1322     tcg_gen_sub_i32(count, tcg_constant_i32(32), tmp);
1323     tcg_gen_sar_i32(cpu_psw_c, cpu_regs[a->rd], count);
1324     tcg_gen_shl_i32(cpu_regs[a->rd], cpu_regs[a->rd], tmp);
1325     tcg_gen_setcondi_i32(TCG_COND_EQ, cpu_psw_o, cpu_psw_c, 0);
1326     tcg_gen_setcondi_i32(TCG_COND_EQ, tmp, cpu_psw_c, 0xffffffff);
1327     tcg_gen_or_i32(cpu_psw_o, cpu_psw_o, tmp);
1328     tcg_gen_setcondi_i32(TCG_COND_NE, cpu_psw_c, cpu_psw_c, 0);
1329     tcg_gen_br(done);
1330     /* } else { */
1331     gen_set_label(noshift);
1332     tcg_gen_movi_i32(cpu_psw_c, 0);
1333     tcg_gen_movi_i32(cpu_psw_o, 0);
1334     /* } */
1335     gen_set_label(done);
1336     tcg_gen_mov_i32(cpu_psw_z, cpu_regs[a->rd]);
1337     tcg_gen_mov_i32(cpu_psw_s, cpu_regs[a->rd]);
1338     return true;
1339 }
1340 
1341 static inline void shiftr_imm(uint32_t rd, uint32_t rs, uint32_t imm,
1342                               unsigned int alith)
1343 {
1344     static void (* const gen_sXri[])(TCGv ret, TCGv arg1, int arg2) = {
1345         tcg_gen_shri_i32, tcg_gen_sari_i32,
1346     };
1347     tcg_debug_assert(alith < 2);
1348     if (imm) {
1349         gen_sXri[alith](cpu_regs[rd], cpu_regs[rs], imm - 1);
1350         tcg_gen_andi_i32(cpu_psw_c, cpu_regs[rd], 0x00000001);
1351         gen_sXri[alith](cpu_regs[rd], cpu_regs[rd], 1);
1352     } else {
1353         tcg_gen_mov_i32(cpu_regs[rd], cpu_regs[rs]);
1354         tcg_gen_movi_i32(cpu_psw_c, 0);
1355     }
1356     tcg_gen_movi_i32(cpu_psw_o, 0);
1357     tcg_gen_mov_i32(cpu_psw_z, cpu_regs[rd]);
1358     tcg_gen_mov_i32(cpu_psw_s, cpu_regs[rd]);
1359 }
1360 
1361 static inline void shiftr_reg(uint32_t rd, uint32_t rs, unsigned int alith)
1362 {
1363     TCGLabel *noshift, *done;
1364     TCGv count;
1365     static void (* const gen_sXri[])(TCGv ret, TCGv arg1, int arg2) = {
1366         tcg_gen_shri_i32, tcg_gen_sari_i32,
1367     };
1368     static void (* const gen_sXr[])(TCGv ret, TCGv arg1, TCGv arg2) = {
1369         tcg_gen_shr_i32, tcg_gen_sar_i32,
1370     };
1371     tcg_debug_assert(alith < 2);
1372     noshift = gen_new_label();
1373     done = gen_new_label();
1374     count = tcg_temp_new();
1375     /* if (cpu_regs[rs]) { */
1376     tcg_gen_brcondi_i32(TCG_COND_EQ, cpu_regs[rs], 0, noshift);
1377     tcg_gen_andi_i32(count, cpu_regs[rs], 31);
1378     tcg_gen_subi_i32(count, count, 1);
1379     gen_sXr[alith](cpu_regs[rd], cpu_regs[rd], count);
1380     tcg_gen_andi_i32(cpu_psw_c, cpu_regs[rd], 0x00000001);
1381     gen_sXri[alith](cpu_regs[rd], cpu_regs[rd], 1);
1382     tcg_gen_br(done);
1383     /* } else { */
1384     gen_set_label(noshift);
1385     tcg_gen_movi_i32(cpu_psw_c, 0);
1386     /* } */
1387     gen_set_label(done);
1388     tcg_gen_movi_i32(cpu_psw_o, 0);
1389     tcg_gen_mov_i32(cpu_psw_z, cpu_regs[rd]);
1390     tcg_gen_mov_i32(cpu_psw_s, cpu_regs[rd]);
1391 }
1392 
1393 /* shar #imm:5, rd */
1394 /* shar #imm:5, rs2, rd */
1395 static bool trans_SHAR_irr(DisasContext *ctx, arg_SHAR_irr *a)
1396 {
1397     shiftr_imm(a->rd, a->rs2, a->imm, 1);
1398     return true;
1399 }
1400 
1401 /* shar rs, rd */
1402 static bool trans_SHAR_rr(DisasContext *ctx, arg_SHAR_rr *a)
1403 {
1404     shiftr_reg(a->rd, a->rs, 1);
1405     return true;
1406 }
1407 
1408 /* shlr #imm:5, rd */
1409 /* shlr #imm:5, rs2, rd */
1410 static bool trans_SHLR_irr(DisasContext *ctx, arg_SHLR_irr *a)
1411 {
1412     shiftr_imm(a->rd, a->rs2, a->imm, 0);
1413     return true;
1414 }
1415 
1416 /* shlr rs, rd */
1417 static bool trans_SHLR_rr(DisasContext *ctx, arg_SHLR_rr *a)
1418 {
1419     shiftr_reg(a->rd, a->rs, 0);
1420     return true;
1421 }
1422 
1423 /* rolc rd */
1424 static bool trans_ROLC(DisasContext *ctx, arg_ROLC *a)
1425 {
1426     TCGv tmp;
1427     tmp = tcg_temp_new();
1428     tcg_gen_shri_i32(tmp, cpu_regs[a->rd], 31);
1429     tcg_gen_shli_i32(cpu_regs[a->rd], cpu_regs[a->rd], 1);
1430     tcg_gen_or_i32(cpu_regs[a->rd], cpu_regs[a->rd], cpu_psw_c);
1431     tcg_gen_mov_i32(cpu_psw_c, tmp);
1432     tcg_gen_mov_i32(cpu_psw_z, cpu_regs[a->rd]);
1433     tcg_gen_mov_i32(cpu_psw_s, cpu_regs[a->rd]);
1434     return true;
1435 }
1436 
1437 /* rorc rd */
1438 static bool trans_RORC(DisasContext *ctx, arg_RORC *a)
1439 {
1440     TCGv tmp;
1441     tmp = tcg_temp_new();
1442     tcg_gen_andi_i32(tmp, cpu_regs[a->rd], 0x00000001);
1443     tcg_gen_shri_i32(cpu_regs[a->rd], cpu_regs[a->rd], 1);
1444     tcg_gen_shli_i32(cpu_psw_c, cpu_psw_c, 31);
1445     tcg_gen_or_i32(cpu_regs[a->rd], cpu_regs[a->rd], cpu_psw_c);
1446     tcg_gen_mov_i32(cpu_psw_c, tmp);
1447     tcg_gen_mov_i32(cpu_psw_z, cpu_regs[a->rd]);
1448     tcg_gen_mov_i32(cpu_psw_s, cpu_regs[a->rd]);
1449     return true;
1450 }
1451 
1452 enum {ROTR = 0, ROTL = 1};
1453 enum {ROT_IMM = 0, ROT_REG = 1};
1454 static inline void rx_rot(int ir, int dir, int rd, int src)
1455 {
1456     switch (dir) {
1457     case ROTL:
1458         if (ir == ROT_IMM) {
1459             tcg_gen_rotli_i32(cpu_regs[rd], cpu_regs[rd], src);
1460         } else {
1461             tcg_gen_rotl_i32(cpu_regs[rd], cpu_regs[rd], cpu_regs[src]);
1462         }
1463         tcg_gen_andi_i32(cpu_psw_c, cpu_regs[rd], 0x00000001);
1464         break;
1465     case ROTR:
1466         if (ir == ROT_IMM) {
1467             tcg_gen_rotri_i32(cpu_regs[rd], cpu_regs[rd], src);
1468         } else {
1469             tcg_gen_rotr_i32(cpu_regs[rd], cpu_regs[rd], cpu_regs[src]);
1470         }
1471         tcg_gen_shri_i32(cpu_psw_c, cpu_regs[rd], 31);
1472         break;
1473     }
1474     tcg_gen_mov_i32(cpu_psw_z, cpu_regs[rd]);
1475     tcg_gen_mov_i32(cpu_psw_s, cpu_regs[rd]);
1476 }
1477 
1478 /* rotl #imm, rd */
1479 static bool trans_ROTL_ir(DisasContext *ctx, arg_ROTL_ir *a)
1480 {
1481     rx_rot(ROT_IMM, ROTL, a->rd, a->imm);
1482     return true;
1483 }
1484 
1485 /* rotl rs, rd */
1486 static bool trans_ROTL_rr(DisasContext *ctx, arg_ROTL_rr *a)
1487 {
1488     rx_rot(ROT_REG, ROTL, a->rd, a->rs);
1489     return true;
1490 }
1491 
1492 /* rotr #imm, rd */
1493 static bool trans_ROTR_ir(DisasContext *ctx, arg_ROTR_ir *a)
1494 {
1495     rx_rot(ROT_IMM, ROTR, a->rd, a->imm);
1496     return true;
1497 }
1498 
1499 /* rotr rs, rd */
1500 static bool trans_ROTR_rr(DisasContext *ctx, arg_ROTR_rr *a)
1501 {
1502     rx_rot(ROT_REG, ROTR, a->rd, a->rs);
1503     return true;
1504 }
1505 
1506 /* revl rs, rd */
1507 static bool trans_REVL(DisasContext *ctx, arg_REVL *a)
1508 {
1509     tcg_gen_bswap32_i32(cpu_regs[a->rd], cpu_regs[a->rs]);
1510     return true;
1511 }
1512 
1513 /* revw rs, rd */
1514 static bool trans_REVW(DisasContext *ctx, arg_REVW *a)
1515 {
1516     TCGv tmp;
1517     tmp = tcg_temp_new();
1518     tcg_gen_andi_i32(tmp, cpu_regs[a->rs], 0x00ff00ff);
1519     tcg_gen_shli_i32(tmp, tmp, 8);
1520     tcg_gen_shri_i32(cpu_regs[a->rd], cpu_regs[a->rs], 8);
1521     tcg_gen_andi_i32(cpu_regs[a->rd], cpu_regs[a->rd], 0x00ff00ff);
1522     tcg_gen_or_i32(cpu_regs[a->rd], cpu_regs[a->rd], tmp);
1523     return true;
1524 }
1525 
1526 /* conditional branch helper */
1527 static void rx_bcnd_main(DisasContext *ctx, int cd, int dst)
1528 {
1529     DisasCompare dc;
1530     TCGLabel *t, *done;
1531 
1532     switch (cd) {
1533     case 0 ... 13:
1534         dc.temp = tcg_temp_new();
1535         psw_cond(&dc, cd);
1536         t = gen_new_label();
1537         done = gen_new_label();
1538         tcg_gen_brcondi_i32(dc.cond, dc.value, 0, t);
1539         gen_goto_tb(ctx, 0, ctx->base.pc_next);
1540         tcg_gen_br(done);
1541         gen_set_label(t);
1542         gen_goto_tb(ctx, 1, ctx->pc + dst);
1543         gen_set_label(done);
1544         break;
1545     case 14:
1546         /* always true case */
1547         gen_goto_tb(ctx, 0, ctx->pc + dst);
1548         break;
1549     case 15:
1550         /* always false case */
1551         /* Nothing do */
1552         break;
1553     }
1554 }
1555 
1556 /* beq dsp:3 / bne dsp:3 */
1557 /* beq dsp:8 / bne dsp:8 */
1558 /* bc dsp:8 / bnc dsp:8 */
1559 /* bgtu dsp:8 / bleu dsp:8 */
1560 /* bpz dsp:8 / bn dsp:8 */
1561 /* bge dsp:8 / blt dsp:8 */
1562 /* bgt dsp:8 / ble dsp:8 */
1563 /* bo dsp:8 / bno dsp:8 */
1564 /* beq dsp:16 / bne dsp:16 */
1565 static bool trans_BCnd(DisasContext *ctx, arg_BCnd *a)
1566 {
1567     rx_bcnd_main(ctx, a->cd, a->dsp);
1568     return true;
1569 }
1570 
1571 /* bra dsp:3 */
1572 /* bra dsp:8 */
1573 /* bra dsp:16 */
1574 /* bra dsp:24 */
1575 static bool trans_BRA(DisasContext *ctx, arg_BRA *a)
1576 {
1577     rx_bcnd_main(ctx, 14, a->dsp);
1578     return true;
1579 }
1580 
1581 /* bra rs */
1582 static bool trans_BRA_l(DisasContext *ctx, arg_BRA_l *a)
1583 {
1584     tcg_gen_addi_i32(cpu_pc, cpu_regs[a->rd], ctx->pc);
1585     ctx->base.is_jmp = DISAS_JUMP;
1586     return true;
1587 }
1588 
1589 static inline void rx_save_pc(DisasContext *ctx)
1590 {
1591     TCGv pc = tcg_constant_i32(ctx->base.pc_next);
1592     push(pc);
1593 }
1594 
1595 /* jmp rs */
1596 static bool trans_JMP(DisasContext *ctx, arg_JMP *a)
1597 {
1598     tcg_gen_mov_i32(cpu_pc, cpu_regs[a->rs]);
1599     ctx->base.is_jmp = DISAS_JUMP;
1600     return true;
1601 }
1602 
1603 /* jsr rs */
1604 static bool trans_JSR(DisasContext *ctx, arg_JSR *a)
1605 {
1606     rx_save_pc(ctx);
1607     tcg_gen_mov_i32(cpu_pc, cpu_regs[a->rs]);
1608     ctx->base.is_jmp = DISAS_JUMP;
1609     return true;
1610 }
1611 
1612 /* bsr dsp:16 */
1613 /* bsr dsp:24 */
1614 static bool trans_BSR(DisasContext *ctx, arg_BSR *a)
1615 {
1616     rx_save_pc(ctx);
1617     rx_bcnd_main(ctx, 14, a->dsp);
1618     return true;
1619 }
1620 
1621 /* bsr rs */
1622 static bool trans_BSR_l(DisasContext *ctx, arg_BSR_l *a)
1623 {
1624     rx_save_pc(ctx);
1625     tcg_gen_addi_i32(cpu_pc, cpu_regs[a->rd], ctx->pc);
1626     ctx->base.is_jmp = DISAS_JUMP;
1627     return true;
1628 }
1629 
1630 /* rts */
1631 static bool trans_RTS(DisasContext *ctx, arg_RTS *a)
1632 {
1633     pop(cpu_pc);
1634     ctx->base.is_jmp = DISAS_JUMP;
1635     return true;
1636 }
1637 
1638 /* nop */
1639 static bool trans_NOP(DisasContext *ctx, arg_NOP *a)
1640 {
1641     return true;
1642 }
1643 
1644 /* scmpu */
1645 static bool trans_SCMPU(DisasContext *ctx, arg_SCMPU *a)
1646 {
1647     gen_helper_scmpu(cpu_env);
1648     return true;
1649 }
1650 
1651 /* smovu */
1652 static bool trans_SMOVU(DisasContext *ctx, arg_SMOVU *a)
1653 {
1654     gen_helper_smovu(cpu_env);
1655     return true;
1656 }
1657 
1658 /* smovf */
1659 static bool trans_SMOVF(DisasContext *ctx, arg_SMOVF *a)
1660 {
1661     gen_helper_smovf(cpu_env);
1662     return true;
1663 }
1664 
1665 /* smovb */
1666 static bool trans_SMOVB(DisasContext *ctx, arg_SMOVB *a)
1667 {
1668     gen_helper_smovb(cpu_env);
1669     return true;
1670 }
1671 
1672 #define STRING(op)                              \
1673     do {                                        \
1674         TCGv size = tcg_constant_i32(a->sz);    \
1675         gen_helper_##op(cpu_env, size);         \
1676     } while (0)
1677 
1678 /* suntile.<bwl> */
1679 static bool trans_SUNTIL(DisasContext *ctx, arg_SUNTIL *a)
1680 {
1681     STRING(suntil);
1682     return true;
1683 }
1684 
1685 /* swhile.<bwl> */
1686 static bool trans_SWHILE(DisasContext *ctx, arg_SWHILE *a)
1687 {
1688     STRING(swhile);
1689     return true;
1690 }
1691 /* sstr.<bwl> */
1692 static bool trans_SSTR(DisasContext *ctx, arg_SSTR *a)
1693 {
1694     STRING(sstr);
1695     return true;
1696 }
1697 
1698 /* rmpa.<bwl> */
1699 static bool trans_RMPA(DisasContext *ctx, arg_RMPA *a)
1700 {
1701     STRING(rmpa);
1702     return true;
1703 }
1704 
1705 static void rx_mul64hi(TCGv_i64 ret, int rs, int rs2)
1706 {
1707     TCGv_i64 tmp0, tmp1;
1708     tmp0 = tcg_temp_new_i64();
1709     tmp1 = tcg_temp_new_i64();
1710     tcg_gen_ext_i32_i64(tmp0, cpu_regs[rs]);
1711     tcg_gen_sari_i64(tmp0, tmp0, 16);
1712     tcg_gen_ext_i32_i64(tmp1, cpu_regs[rs2]);
1713     tcg_gen_sari_i64(tmp1, tmp1, 16);
1714     tcg_gen_mul_i64(ret, tmp0, tmp1);
1715     tcg_gen_shli_i64(ret, ret, 16);
1716 }
1717 
1718 static void rx_mul64lo(TCGv_i64 ret, int rs, int rs2)
1719 {
1720     TCGv_i64 tmp0, tmp1;
1721     tmp0 = tcg_temp_new_i64();
1722     tmp1 = tcg_temp_new_i64();
1723     tcg_gen_ext_i32_i64(tmp0, cpu_regs[rs]);
1724     tcg_gen_ext16s_i64(tmp0, tmp0);
1725     tcg_gen_ext_i32_i64(tmp1, cpu_regs[rs2]);
1726     tcg_gen_ext16s_i64(tmp1, tmp1);
1727     tcg_gen_mul_i64(ret, tmp0, tmp1);
1728     tcg_gen_shli_i64(ret, ret, 16);
1729 }
1730 
1731 /* mulhi rs,rs2 */
1732 static bool trans_MULHI(DisasContext *ctx, arg_MULHI *a)
1733 {
1734     rx_mul64hi(cpu_acc, a->rs, a->rs2);
1735     return true;
1736 }
1737 
1738 /* mullo rs,rs2 */
1739 static bool trans_MULLO(DisasContext *ctx, arg_MULLO *a)
1740 {
1741     rx_mul64lo(cpu_acc, a->rs, a->rs2);
1742     return true;
1743 }
1744 
1745 /* machi rs,rs2 */
1746 static bool trans_MACHI(DisasContext *ctx, arg_MACHI *a)
1747 {
1748     TCGv_i64 tmp;
1749     tmp = tcg_temp_new_i64();
1750     rx_mul64hi(tmp, a->rs, a->rs2);
1751     tcg_gen_add_i64(cpu_acc, cpu_acc, tmp);
1752     return true;
1753 }
1754 
1755 /* maclo rs,rs2 */
1756 static bool trans_MACLO(DisasContext *ctx, arg_MACLO *a)
1757 {
1758     TCGv_i64 tmp;
1759     tmp = tcg_temp_new_i64();
1760     rx_mul64lo(tmp, a->rs, a->rs2);
1761     tcg_gen_add_i64(cpu_acc, cpu_acc, tmp);
1762     return true;
1763 }
1764 
1765 /* mvfachi rd */
1766 static bool trans_MVFACHI(DisasContext *ctx, arg_MVFACHI *a)
1767 {
1768     tcg_gen_extrh_i64_i32(cpu_regs[a->rd], cpu_acc);
1769     return true;
1770 }
1771 
1772 /* mvfacmi rd */
1773 static bool trans_MVFACMI(DisasContext *ctx, arg_MVFACMI *a)
1774 {
1775     TCGv_i64 rd64;
1776     rd64 = tcg_temp_new_i64();
1777     tcg_gen_extract_i64(rd64, cpu_acc, 16, 32);
1778     tcg_gen_extrl_i64_i32(cpu_regs[a->rd], rd64);
1779     return true;
1780 }
1781 
1782 /* mvtachi rs */
1783 static bool trans_MVTACHI(DisasContext *ctx, arg_MVTACHI *a)
1784 {
1785     TCGv_i64 rs64;
1786     rs64 = tcg_temp_new_i64();
1787     tcg_gen_extu_i32_i64(rs64, cpu_regs[a->rs]);
1788     tcg_gen_deposit_i64(cpu_acc, cpu_acc, rs64, 32, 32);
1789     return true;
1790 }
1791 
1792 /* mvtaclo rs */
1793 static bool trans_MVTACLO(DisasContext *ctx, arg_MVTACLO *a)
1794 {
1795     TCGv_i64 rs64;
1796     rs64 = tcg_temp_new_i64();
1797     tcg_gen_extu_i32_i64(rs64, cpu_regs[a->rs]);
1798     tcg_gen_deposit_i64(cpu_acc, cpu_acc, rs64, 0, 32);
1799     return true;
1800 }
1801 
1802 /* racw #imm */
1803 static bool trans_RACW(DisasContext *ctx, arg_RACW *a)
1804 {
1805     TCGv imm = tcg_constant_i32(a->imm + 1);
1806     gen_helper_racw(cpu_env, imm);
1807     return true;
1808 }
1809 
1810 /* sat rd */
1811 static bool trans_SAT(DisasContext *ctx, arg_SAT *a)
1812 {
1813     TCGv tmp, z;
1814     tmp = tcg_temp_new();
1815     z = tcg_constant_i32(0);
1816     /* S == 1 -> 0xffffffff / S == 0 -> 0x00000000 */
1817     tcg_gen_sari_i32(tmp, cpu_psw_s, 31);
1818     /* S == 1 -> 0x7fffffff / S == 0 -> 0x80000000 */
1819     tcg_gen_xori_i32(tmp, tmp, 0x80000000);
1820     tcg_gen_movcond_i32(TCG_COND_LT, cpu_regs[a->rd],
1821                         cpu_psw_o, z, tmp, cpu_regs[a->rd]);
1822     return true;
1823 }
1824 
1825 /* satr */
1826 static bool trans_SATR(DisasContext *ctx, arg_SATR *a)
1827 {
1828     gen_helper_satr(cpu_env);
1829     return true;
1830 }
1831 
1832 #define cat3(a, b, c) a##b##c
1833 #define FOP(name, op)                                                   \
1834     static bool cat3(trans_, name, _ir)(DisasContext *ctx,              \
1835                                         cat3(arg_, name, _ir) * a)      \
1836     {                                                                   \
1837         TCGv imm = tcg_constant_i32(li(ctx, 0));                        \
1838         gen_helper_##op(cpu_regs[a->rd], cpu_env,                       \
1839                         cpu_regs[a->rd], imm);                          \
1840         return true;                                                    \
1841     }                                                                   \
1842     static bool cat3(trans_, name, _mr)(DisasContext *ctx,              \
1843                                         cat3(arg_, name, _mr) * a)      \
1844     {                                                                   \
1845         TCGv val, mem;                                                  \
1846         mem = tcg_temp_new();                                           \
1847         val = rx_load_source(ctx, mem, a->ld, MO_32, a->rs);            \
1848         gen_helper_##op(cpu_regs[a->rd], cpu_env,                       \
1849                         cpu_regs[a->rd], val);                          \
1850         return true;                                                    \
1851     }
1852 
1853 #define FCONVOP(name, op)                                       \
1854     static bool trans_##name(DisasContext *ctx, arg_##name * a) \
1855     {                                                           \
1856         TCGv val, mem;                                          \
1857         mem = tcg_temp_new();                                   \
1858         val = rx_load_source(ctx, mem, a->ld, MO_32, a->rs);    \
1859         gen_helper_##op(cpu_regs[a->rd], cpu_env, val);         \
1860         return true;                                            \
1861     }
1862 
1863 FOP(FADD, fadd)
1864 FOP(FSUB, fsub)
1865 FOP(FMUL, fmul)
1866 FOP(FDIV, fdiv)
1867 
1868 /* fcmp #imm, rd */
1869 static bool trans_FCMP_ir(DisasContext *ctx, arg_FCMP_ir * a)
1870 {
1871     TCGv imm = tcg_constant_i32(li(ctx, 0));
1872     gen_helper_fcmp(cpu_env, cpu_regs[a->rd], imm);
1873     return true;
1874 }
1875 
1876 /* fcmp dsp[rs], rd */
1877 /* fcmp rs, rd */
1878 static bool trans_FCMP_mr(DisasContext *ctx, arg_FCMP_mr *a)
1879 {
1880     TCGv val, mem;
1881     mem = tcg_temp_new();
1882     val = rx_load_source(ctx, mem, a->ld, MO_32, a->rs);
1883     gen_helper_fcmp(cpu_env, cpu_regs[a->rd], val);
1884     return true;
1885 }
1886 
1887 FCONVOP(FTOI, ftoi)
1888 FCONVOP(ROUND, round)
1889 
1890 /* itof rs, rd */
1891 /* itof dsp[rs], rd */
1892 static bool trans_ITOF(DisasContext *ctx, arg_ITOF * a)
1893 {
1894     TCGv val, mem;
1895     mem = tcg_temp_new();
1896     val = rx_load_source(ctx, mem, a->ld, a->mi, a->rs);
1897     gen_helper_itof(cpu_regs[a->rd], cpu_env, val);
1898     return true;
1899 }
1900 
1901 static void rx_bsetm(TCGv mem, TCGv mask)
1902 {
1903     TCGv val;
1904     val = tcg_temp_new();
1905     rx_gen_ld(MO_8, val, mem);
1906     tcg_gen_or_i32(val, val, mask);
1907     rx_gen_st(MO_8, val, mem);
1908 }
1909 
1910 static void rx_bclrm(TCGv mem, TCGv mask)
1911 {
1912     TCGv val;
1913     val = tcg_temp_new();
1914     rx_gen_ld(MO_8, val, mem);
1915     tcg_gen_andc_i32(val, val, mask);
1916     rx_gen_st(MO_8, val, mem);
1917 }
1918 
1919 static void rx_btstm(TCGv mem, TCGv mask)
1920 {
1921     TCGv val;
1922     val = tcg_temp_new();
1923     rx_gen_ld(MO_8, val, mem);
1924     tcg_gen_and_i32(val, val, mask);
1925     tcg_gen_setcondi_i32(TCG_COND_NE, cpu_psw_c, val, 0);
1926     tcg_gen_mov_i32(cpu_psw_z, cpu_psw_c);
1927 }
1928 
1929 static void rx_bnotm(TCGv mem, TCGv mask)
1930 {
1931     TCGv val;
1932     val = tcg_temp_new();
1933     rx_gen_ld(MO_8, val, mem);
1934     tcg_gen_xor_i32(val, val, mask);
1935     rx_gen_st(MO_8, val, mem);
1936 }
1937 
1938 static void rx_bsetr(TCGv reg, TCGv mask)
1939 {
1940     tcg_gen_or_i32(reg, reg, mask);
1941 }
1942 
1943 static void rx_bclrr(TCGv reg, TCGv mask)
1944 {
1945     tcg_gen_andc_i32(reg, reg, mask);
1946 }
1947 
1948 static inline void rx_btstr(TCGv reg, TCGv mask)
1949 {
1950     TCGv t0;
1951     t0 = tcg_temp_new();
1952     tcg_gen_and_i32(t0, reg, mask);
1953     tcg_gen_setcondi_i32(TCG_COND_NE, cpu_psw_c, t0, 0);
1954     tcg_gen_mov_i32(cpu_psw_z, cpu_psw_c);
1955 }
1956 
1957 static inline void rx_bnotr(TCGv reg, TCGv mask)
1958 {
1959     tcg_gen_xor_i32(reg, reg, mask);
1960 }
1961 
1962 #define BITOP(name, op)                                                 \
1963     static bool cat3(trans_, name, _im)(DisasContext *ctx,              \
1964                                         cat3(arg_, name, _im) * a)      \
1965     {                                                                   \
1966         TCGv mask, mem, addr;                                           \
1967         mem = tcg_temp_new();                                           \
1968         mask = tcg_constant_i32(1 << a->imm);                           \
1969         addr = rx_index_addr(ctx, mem, a->ld, MO_8, a->rs);             \
1970         cat3(rx_, op, m)(addr, mask);                                   \
1971         return true;                                                    \
1972     }                                                                   \
1973     static bool cat3(trans_, name, _ir)(DisasContext *ctx,              \
1974                                         cat3(arg_, name, _ir) * a)      \
1975     {                                                                   \
1976         TCGv mask;                                                      \
1977         mask = tcg_constant_i32(1 << a->imm);                           \
1978         cat3(rx_, op, r)(cpu_regs[a->rd], mask);                        \
1979         return true;                                                    \
1980     }                                                                   \
1981     static bool cat3(trans_, name, _rr)(DisasContext *ctx,              \
1982                                         cat3(arg_, name, _rr) * a)      \
1983     {                                                                   \
1984         TCGv mask, b;                                                   \
1985         mask = tcg_temp_new();                                          \
1986         b = tcg_temp_new();                                             \
1987         tcg_gen_andi_i32(b, cpu_regs[a->rs], 31);                       \
1988         tcg_gen_shl_i32(mask, tcg_constant_i32(1), b);                  \
1989         cat3(rx_, op, r)(cpu_regs[a->rd], mask);                        \
1990         return true;                                                    \
1991     }                                                                   \
1992     static bool cat3(trans_, name, _rm)(DisasContext *ctx,              \
1993                                         cat3(arg_, name, _rm) * a)      \
1994     {                                                                   \
1995         TCGv mask, mem, addr, b;                                        \
1996         mask = tcg_temp_new();                                          \
1997         b = tcg_temp_new();                                             \
1998         tcg_gen_andi_i32(b, cpu_regs[a->rd], 7);                        \
1999         tcg_gen_shl_i32(mask, tcg_constant_i32(1), b);                  \
2000         mem = tcg_temp_new();                                           \
2001         addr = rx_index_addr(ctx, mem, a->ld, MO_8, a->rs);             \
2002         cat3(rx_, op, m)(addr, mask);                                   \
2003         return true;                                                    \
2004     }
2005 
2006 BITOP(BSET, bset)
2007 BITOP(BCLR, bclr)
2008 BITOP(BTST, btst)
2009 BITOP(BNOT, bnot)
2010 
2011 static inline void bmcnd_op(TCGv val, TCGCond cond, int pos)
2012 {
2013     TCGv bit;
2014     DisasCompare dc;
2015     dc.temp = tcg_temp_new();
2016     bit = tcg_temp_new();
2017     psw_cond(&dc, cond);
2018     tcg_gen_andi_i32(val, val, ~(1 << pos));
2019     tcg_gen_setcondi_i32(dc.cond, bit, dc.value, 0);
2020     tcg_gen_deposit_i32(val, val, bit, pos, 1);
2021  }
2022 
2023 /* bmcnd #imm, dsp[rd] */
2024 static bool trans_BMCnd_im(DisasContext *ctx, arg_BMCnd_im *a)
2025 {
2026     TCGv val, mem, addr;
2027     val = tcg_temp_new();
2028     mem = tcg_temp_new();
2029     addr = rx_index_addr(ctx, mem, a->ld, MO_8, a->rd);
2030     rx_gen_ld(MO_8, val, addr);
2031     bmcnd_op(val, a->cd, a->imm);
2032     rx_gen_st(MO_8, val, addr);
2033     return true;
2034 }
2035 
2036 /* bmcond #imm, rd */
2037 static bool trans_BMCnd_ir(DisasContext *ctx, arg_BMCnd_ir *a)
2038 {
2039     bmcnd_op(cpu_regs[a->rd], a->cd, a->imm);
2040     return true;
2041 }
2042 
2043 enum {
2044     PSW_C = 0,
2045     PSW_Z = 1,
2046     PSW_S = 2,
2047     PSW_O = 3,
2048     PSW_I = 8,
2049     PSW_U = 9,
2050 };
2051 
2052 static inline void clrsetpsw(DisasContext *ctx, int cb, int val)
2053 {
2054     if (cb < 8) {
2055         switch (cb) {
2056         case PSW_C:
2057             tcg_gen_movi_i32(cpu_psw_c, val);
2058             break;
2059         case PSW_Z:
2060             tcg_gen_movi_i32(cpu_psw_z, val == 0);
2061             break;
2062         case PSW_S:
2063             tcg_gen_movi_i32(cpu_psw_s, val ? -1 : 0);
2064             break;
2065         case PSW_O:
2066             tcg_gen_movi_i32(cpu_psw_o, val << 31);
2067             break;
2068         default:
2069             qemu_log_mask(LOG_GUEST_ERROR, "Invalid destination %d", cb);
2070             break;
2071         }
2072     } else if (is_privileged(ctx, 0)) {
2073         switch (cb) {
2074         case PSW_I:
2075             tcg_gen_movi_i32(cpu_psw_i, val);
2076             ctx->base.is_jmp = DISAS_UPDATE;
2077             break;
2078         case PSW_U:
2079             if (FIELD_EX32(ctx->tb_flags, PSW, U) != val) {
2080                 ctx->tb_flags = FIELD_DP32(ctx->tb_flags, PSW, U, val);
2081                 tcg_gen_movi_i32(cpu_psw_u, val);
2082                 tcg_gen_mov_i32(val ? cpu_isp : cpu_usp, cpu_sp);
2083                 tcg_gen_mov_i32(cpu_sp, val ? cpu_usp : cpu_isp);
2084             }
2085             break;
2086         default:
2087             qemu_log_mask(LOG_GUEST_ERROR, "Invalid destination %d", cb);
2088             break;
2089         }
2090     }
2091 }
2092 
2093 /* clrpsw psw */
2094 static bool trans_CLRPSW(DisasContext *ctx, arg_CLRPSW *a)
2095 {
2096     clrsetpsw(ctx, a->cb, 0);
2097     return true;
2098 }
2099 
2100 /* setpsw psw */
2101 static bool trans_SETPSW(DisasContext *ctx, arg_SETPSW *a)
2102 {
2103     clrsetpsw(ctx, a->cb, 1);
2104     return true;
2105 }
2106 
2107 /* mvtipl #imm */
2108 static bool trans_MVTIPL(DisasContext *ctx, arg_MVTIPL *a)
2109 {
2110     if (is_privileged(ctx, 1)) {
2111         tcg_gen_movi_i32(cpu_psw_ipl, a->imm);
2112         ctx->base.is_jmp = DISAS_UPDATE;
2113     }
2114     return true;
2115 }
2116 
2117 /* mvtc #imm, rd */
2118 static bool trans_MVTC_i(DisasContext *ctx, arg_MVTC_i *a)
2119 {
2120     TCGv imm;
2121 
2122     imm = tcg_constant_i32(a->imm);
2123     move_to_cr(ctx, imm, a->cr);
2124     return true;
2125 }
2126 
2127 /* mvtc rs, rd */
2128 static bool trans_MVTC_r(DisasContext *ctx, arg_MVTC_r *a)
2129 {
2130     move_to_cr(ctx, cpu_regs[a->rs], a->cr);
2131     return true;
2132 }
2133 
2134 /* mvfc rs, rd */
2135 static bool trans_MVFC(DisasContext *ctx, arg_MVFC *a)
2136 {
2137     move_from_cr(ctx, cpu_regs[a->rd], a->cr, ctx->pc);
2138     return true;
2139 }
2140 
2141 /* rtfi */
2142 static bool trans_RTFI(DisasContext *ctx, arg_RTFI *a)
2143 {
2144     TCGv psw;
2145     if (is_privileged(ctx, 1)) {
2146         psw = tcg_temp_new();
2147         tcg_gen_mov_i32(cpu_pc, cpu_bpc);
2148         tcg_gen_mov_i32(psw, cpu_bpsw);
2149         gen_helper_set_psw_rte(cpu_env, psw);
2150         ctx->base.is_jmp = DISAS_EXIT;
2151     }
2152     return true;
2153 }
2154 
2155 /* rte */
2156 static bool trans_RTE(DisasContext *ctx, arg_RTE *a)
2157 {
2158     TCGv psw;
2159     if (is_privileged(ctx, 1)) {
2160         psw = tcg_temp_new();
2161         pop(cpu_pc);
2162         pop(psw);
2163         gen_helper_set_psw_rte(cpu_env, psw);
2164         ctx->base.is_jmp = DISAS_EXIT;
2165     }
2166     return true;
2167 }
2168 
2169 /* brk */
2170 static bool trans_BRK(DisasContext *ctx, arg_BRK *a)
2171 {
2172     tcg_gen_movi_i32(cpu_pc, ctx->base.pc_next);
2173     gen_helper_rxbrk(cpu_env);
2174     ctx->base.is_jmp = DISAS_NORETURN;
2175     return true;
2176 }
2177 
2178 /* int #imm */
2179 static bool trans_INT(DisasContext *ctx, arg_INT *a)
2180 {
2181     TCGv vec;
2182 
2183     tcg_debug_assert(a->imm < 0x100);
2184     vec = tcg_constant_i32(a->imm);
2185     tcg_gen_movi_i32(cpu_pc, ctx->base.pc_next);
2186     gen_helper_rxint(cpu_env, vec);
2187     ctx->base.is_jmp = DISAS_NORETURN;
2188     return true;
2189 }
2190 
2191 /* wait */
2192 static bool trans_WAIT(DisasContext *ctx, arg_WAIT *a)
2193 {
2194     if (is_privileged(ctx, 1)) {
2195         tcg_gen_movi_i32(cpu_pc, ctx->base.pc_next);
2196         gen_helper_wait(cpu_env);
2197     }
2198     return true;
2199 }
2200 
2201 static void rx_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
2202 {
2203     CPURXState *env = cs->env_ptr;
2204     DisasContext *ctx = container_of(dcbase, DisasContext, base);
2205     ctx->env = env;
2206     ctx->tb_flags = ctx->base.tb->flags;
2207 }
2208 
2209 static void rx_tr_tb_start(DisasContextBase *dcbase, CPUState *cs)
2210 {
2211 }
2212 
2213 static void rx_tr_insn_start(DisasContextBase *dcbase, CPUState *cs)
2214 {
2215     DisasContext *ctx = container_of(dcbase, DisasContext, base);
2216 
2217     tcg_gen_insn_start(ctx->base.pc_next);
2218 }
2219 
2220 static void rx_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
2221 {
2222     DisasContext *ctx = container_of(dcbase, DisasContext, base);
2223     uint32_t insn;
2224 
2225     ctx->pc = ctx->base.pc_next;
2226     insn = decode_load(ctx);
2227     if (!decode(ctx, insn)) {
2228         gen_helper_raise_illegal_instruction(cpu_env);
2229     }
2230 }
2231 
2232 static void rx_tr_tb_stop(DisasContextBase *dcbase, CPUState *cs)
2233 {
2234     DisasContext *ctx = container_of(dcbase, DisasContext, base);
2235 
2236     switch (ctx->base.is_jmp) {
2237     case DISAS_NEXT:
2238     case DISAS_TOO_MANY:
2239         gen_goto_tb(ctx, 0, dcbase->pc_next);
2240         break;
2241     case DISAS_JUMP:
2242         tcg_gen_lookup_and_goto_ptr();
2243         break;
2244     case DISAS_UPDATE:
2245         tcg_gen_movi_i32(cpu_pc, ctx->base.pc_next);
2246         /* fall through */
2247     case DISAS_EXIT:
2248         tcg_gen_exit_tb(NULL, 0);
2249         break;
2250     case DISAS_NORETURN:
2251         break;
2252     default:
2253         g_assert_not_reached();
2254     }
2255 }
2256 
2257 static void rx_tr_disas_log(const DisasContextBase *dcbase,
2258                             CPUState *cs, FILE *logfile)
2259 {
2260     fprintf(logfile, "IN: %s\n", lookup_symbol(dcbase->pc_first));
2261     target_disas(logfile, cs, dcbase->pc_first, dcbase->tb->size);
2262 }
2263 
2264 static const TranslatorOps rx_tr_ops = {
2265     .init_disas_context = rx_tr_init_disas_context,
2266     .tb_start           = rx_tr_tb_start,
2267     .insn_start         = rx_tr_insn_start,
2268     .translate_insn     = rx_tr_translate_insn,
2269     .tb_stop            = rx_tr_tb_stop,
2270     .disas_log          = rx_tr_disas_log,
2271 };
2272 
2273 void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int *max_insns,
2274                            target_ulong pc, void *host_pc)
2275 {
2276     DisasContext dc;
2277 
2278     translator_loop(cs, tb, max_insns, pc, host_pc, &rx_tr_ops, &dc.base);
2279 }
2280 
2281 #define ALLOC_REGISTER(sym, name) \
2282     cpu_##sym = tcg_global_mem_new_i32(cpu_env, \
2283                                        offsetof(CPURXState, sym), name)
2284 
2285 void rx_translate_init(void)
2286 {
2287     static const char * const regnames[NUM_REGS] = {
2288         "R0", "R1", "R2", "R3", "R4", "R5", "R6", "R7",
2289         "R8", "R9", "R10", "R11", "R12", "R13", "R14", "R15"
2290     };
2291     int i;
2292 
2293     for (i = 0; i < NUM_REGS; i++) {
2294         cpu_regs[i] = tcg_global_mem_new_i32(cpu_env,
2295                                               offsetof(CPURXState, regs[i]),
2296                                               regnames[i]);
2297     }
2298     ALLOC_REGISTER(pc, "PC");
2299     ALLOC_REGISTER(psw_o, "PSW(O)");
2300     ALLOC_REGISTER(psw_s, "PSW(S)");
2301     ALLOC_REGISTER(psw_z, "PSW(Z)");
2302     ALLOC_REGISTER(psw_c, "PSW(C)");
2303     ALLOC_REGISTER(psw_u, "PSW(U)");
2304     ALLOC_REGISTER(psw_i, "PSW(I)");
2305     ALLOC_REGISTER(psw_pm, "PSW(PM)");
2306     ALLOC_REGISTER(psw_ipl, "PSW(IPL)");
2307     ALLOC_REGISTER(usp, "USP");
2308     ALLOC_REGISTER(fpsw, "FPSW");
2309     ALLOC_REGISTER(bpsw, "BPSW");
2310     ALLOC_REGISTER(bpc, "BPC");
2311     ALLOC_REGISTER(isp, "ISP");
2312     ALLOC_REGISTER(fintv, "FINTV");
2313     ALLOC_REGISTER(intb, "INTB");
2314     cpu_acc = tcg_global_mem_new_i64(cpu_env,
2315                                      offsetof(CPURXState, acc), "ACC");
2316 }
2317