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