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