1*fcf5ef2aSThomas Huth /* 2*fcf5ef2aSThomas Huth * SH4 translation 3*fcf5ef2aSThomas Huth * 4*fcf5ef2aSThomas Huth * Copyright (c) 2005 Samuel Tardieu 5*fcf5ef2aSThomas Huth * 6*fcf5ef2aSThomas Huth * This library is free software; you can redistribute it and/or 7*fcf5ef2aSThomas Huth * modify it under the terms of the GNU Lesser General Public 8*fcf5ef2aSThomas Huth * License as published by the Free Software Foundation; either 9*fcf5ef2aSThomas Huth * version 2 of the License, or (at your option) any later version. 10*fcf5ef2aSThomas Huth * 11*fcf5ef2aSThomas Huth * This library is distributed in the hope that it will be useful, 12*fcf5ef2aSThomas Huth * but WITHOUT ANY WARRANTY; without even the implied warranty of 13*fcf5ef2aSThomas Huth * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14*fcf5ef2aSThomas Huth * Lesser General Public License for more details. 15*fcf5ef2aSThomas Huth * 16*fcf5ef2aSThomas Huth * You should have received a copy of the GNU Lesser General Public 17*fcf5ef2aSThomas Huth * License along with this library; if not, see <http://www.gnu.org/licenses/>. 18*fcf5ef2aSThomas Huth */ 19*fcf5ef2aSThomas Huth 20*fcf5ef2aSThomas Huth #define DEBUG_DISAS 21*fcf5ef2aSThomas Huth 22*fcf5ef2aSThomas Huth #include "qemu/osdep.h" 23*fcf5ef2aSThomas Huth #include "cpu.h" 24*fcf5ef2aSThomas Huth #include "disas/disas.h" 25*fcf5ef2aSThomas Huth #include "exec/exec-all.h" 26*fcf5ef2aSThomas Huth #include "tcg-op.h" 27*fcf5ef2aSThomas Huth #include "exec/cpu_ldst.h" 28*fcf5ef2aSThomas Huth 29*fcf5ef2aSThomas Huth #include "exec/helper-proto.h" 30*fcf5ef2aSThomas Huth #include "exec/helper-gen.h" 31*fcf5ef2aSThomas Huth 32*fcf5ef2aSThomas Huth #include "trace-tcg.h" 33*fcf5ef2aSThomas Huth #include "exec/log.h" 34*fcf5ef2aSThomas Huth 35*fcf5ef2aSThomas Huth 36*fcf5ef2aSThomas Huth typedef struct DisasContext { 37*fcf5ef2aSThomas Huth struct TranslationBlock *tb; 38*fcf5ef2aSThomas Huth target_ulong pc; 39*fcf5ef2aSThomas Huth uint16_t opcode; 40*fcf5ef2aSThomas Huth uint32_t flags; 41*fcf5ef2aSThomas Huth int bstate; 42*fcf5ef2aSThomas Huth int memidx; 43*fcf5ef2aSThomas Huth uint32_t delayed_pc; 44*fcf5ef2aSThomas Huth int singlestep_enabled; 45*fcf5ef2aSThomas Huth uint32_t features; 46*fcf5ef2aSThomas Huth int has_movcal; 47*fcf5ef2aSThomas Huth } DisasContext; 48*fcf5ef2aSThomas Huth 49*fcf5ef2aSThomas Huth #if defined(CONFIG_USER_ONLY) 50*fcf5ef2aSThomas Huth #define IS_USER(ctx) 1 51*fcf5ef2aSThomas Huth #else 52*fcf5ef2aSThomas Huth #define IS_USER(ctx) (!(ctx->flags & (1u << SR_MD))) 53*fcf5ef2aSThomas Huth #endif 54*fcf5ef2aSThomas Huth 55*fcf5ef2aSThomas Huth enum { 56*fcf5ef2aSThomas Huth BS_NONE = 0, /* We go out of the TB without reaching a branch or an 57*fcf5ef2aSThomas Huth * exception condition 58*fcf5ef2aSThomas Huth */ 59*fcf5ef2aSThomas Huth BS_STOP = 1, /* We want to stop translation for any reason */ 60*fcf5ef2aSThomas Huth BS_BRANCH = 2, /* We reached a branch condition */ 61*fcf5ef2aSThomas Huth BS_EXCP = 3, /* We reached an exception condition */ 62*fcf5ef2aSThomas Huth }; 63*fcf5ef2aSThomas Huth 64*fcf5ef2aSThomas Huth /* global register indexes */ 65*fcf5ef2aSThomas Huth static TCGv_env cpu_env; 66*fcf5ef2aSThomas Huth static TCGv cpu_gregs[24]; 67*fcf5ef2aSThomas Huth static TCGv cpu_sr, cpu_sr_m, cpu_sr_q, cpu_sr_t; 68*fcf5ef2aSThomas Huth static TCGv cpu_pc, cpu_ssr, cpu_spc, cpu_gbr; 69*fcf5ef2aSThomas Huth static TCGv cpu_vbr, cpu_sgr, cpu_dbr, cpu_mach, cpu_macl; 70*fcf5ef2aSThomas Huth static TCGv cpu_pr, cpu_fpscr, cpu_fpul, cpu_ldst; 71*fcf5ef2aSThomas Huth static TCGv cpu_fregs[32]; 72*fcf5ef2aSThomas Huth 73*fcf5ef2aSThomas Huth /* internal register indexes */ 74*fcf5ef2aSThomas Huth static TCGv cpu_flags, cpu_delayed_pc; 75*fcf5ef2aSThomas Huth 76*fcf5ef2aSThomas Huth #include "exec/gen-icount.h" 77*fcf5ef2aSThomas Huth 78*fcf5ef2aSThomas Huth void sh4_translate_init(void) 79*fcf5ef2aSThomas Huth { 80*fcf5ef2aSThomas Huth int i; 81*fcf5ef2aSThomas Huth static int done_init = 0; 82*fcf5ef2aSThomas Huth static const char * const gregnames[24] = { 83*fcf5ef2aSThomas Huth "R0_BANK0", "R1_BANK0", "R2_BANK0", "R3_BANK0", 84*fcf5ef2aSThomas Huth "R4_BANK0", "R5_BANK0", "R6_BANK0", "R7_BANK0", 85*fcf5ef2aSThomas Huth "R8", "R9", "R10", "R11", "R12", "R13", "R14", "R15", 86*fcf5ef2aSThomas Huth "R0_BANK1", "R1_BANK1", "R2_BANK1", "R3_BANK1", 87*fcf5ef2aSThomas Huth "R4_BANK1", "R5_BANK1", "R6_BANK1", "R7_BANK1" 88*fcf5ef2aSThomas Huth }; 89*fcf5ef2aSThomas Huth static const char * const fregnames[32] = { 90*fcf5ef2aSThomas Huth "FPR0_BANK0", "FPR1_BANK0", "FPR2_BANK0", "FPR3_BANK0", 91*fcf5ef2aSThomas Huth "FPR4_BANK0", "FPR5_BANK0", "FPR6_BANK0", "FPR7_BANK0", 92*fcf5ef2aSThomas Huth "FPR8_BANK0", "FPR9_BANK0", "FPR10_BANK0", "FPR11_BANK0", 93*fcf5ef2aSThomas Huth "FPR12_BANK0", "FPR13_BANK0", "FPR14_BANK0", "FPR15_BANK0", 94*fcf5ef2aSThomas Huth "FPR0_BANK1", "FPR1_BANK1", "FPR2_BANK1", "FPR3_BANK1", 95*fcf5ef2aSThomas Huth "FPR4_BANK1", "FPR5_BANK1", "FPR6_BANK1", "FPR7_BANK1", 96*fcf5ef2aSThomas Huth "FPR8_BANK1", "FPR9_BANK1", "FPR10_BANK1", "FPR11_BANK1", 97*fcf5ef2aSThomas Huth "FPR12_BANK1", "FPR13_BANK1", "FPR14_BANK1", "FPR15_BANK1", 98*fcf5ef2aSThomas Huth }; 99*fcf5ef2aSThomas Huth 100*fcf5ef2aSThomas Huth if (done_init) 101*fcf5ef2aSThomas Huth return; 102*fcf5ef2aSThomas Huth 103*fcf5ef2aSThomas Huth cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env"); 104*fcf5ef2aSThomas Huth tcg_ctx.tcg_env = cpu_env; 105*fcf5ef2aSThomas Huth 106*fcf5ef2aSThomas Huth for (i = 0; i < 24; i++) 107*fcf5ef2aSThomas Huth cpu_gregs[i] = tcg_global_mem_new_i32(cpu_env, 108*fcf5ef2aSThomas Huth offsetof(CPUSH4State, gregs[i]), 109*fcf5ef2aSThomas Huth gregnames[i]); 110*fcf5ef2aSThomas Huth 111*fcf5ef2aSThomas Huth cpu_pc = tcg_global_mem_new_i32(cpu_env, 112*fcf5ef2aSThomas Huth offsetof(CPUSH4State, pc), "PC"); 113*fcf5ef2aSThomas Huth cpu_sr = tcg_global_mem_new_i32(cpu_env, 114*fcf5ef2aSThomas Huth offsetof(CPUSH4State, sr), "SR"); 115*fcf5ef2aSThomas Huth cpu_sr_m = tcg_global_mem_new_i32(cpu_env, 116*fcf5ef2aSThomas Huth offsetof(CPUSH4State, sr_m), "SR_M"); 117*fcf5ef2aSThomas Huth cpu_sr_q = tcg_global_mem_new_i32(cpu_env, 118*fcf5ef2aSThomas Huth offsetof(CPUSH4State, sr_q), "SR_Q"); 119*fcf5ef2aSThomas Huth cpu_sr_t = tcg_global_mem_new_i32(cpu_env, 120*fcf5ef2aSThomas Huth offsetof(CPUSH4State, sr_t), "SR_T"); 121*fcf5ef2aSThomas Huth cpu_ssr = tcg_global_mem_new_i32(cpu_env, 122*fcf5ef2aSThomas Huth offsetof(CPUSH4State, ssr), "SSR"); 123*fcf5ef2aSThomas Huth cpu_spc = tcg_global_mem_new_i32(cpu_env, 124*fcf5ef2aSThomas Huth offsetof(CPUSH4State, spc), "SPC"); 125*fcf5ef2aSThomas Huth cpu_gbr = tcg_global_mem_new_i32(cpu_env, 126*fcf5ef2aSThomas Huth offsetof(CPUSH4State, gbr), "GBR"); 127*fcf5ef2aSThomas Huth cpu_vbr = tcg_global_mem_new_i32(cpu_env, 128*fcf5ef2aSThomas Huth offsetof(CPUSH4State, vbr), "VBR"); 129*fcf5ef2aSThomas Huth cpu_sgr = tcg_global_mem_new_i32(cpu_env, 130*fcf5ef2aSThomas Huth offsetof(CPUSH4State, sgr), "SGR"); 131*fcf5ef2aSThomas Huth cpu_dbr = tcg_global_mem_new_i32(cpu_env, 132*fcf5ef2aSThomas Huth offsetof(CPUSH4State, dbr), "DBR"); 133*fcf5ef2aSThomas Huth cpu_mach = tcg_global_mem_new_i32(cpu_env, 134*fcf5ef2aSThomas Huth offsetof(CPUSH4State, mach), "MACH"); 135*fcf5ef2aSThomas Huth cpu_macl = tcg_global_mem_new_i32(cpu_env, 136*fcf5ef2aSThomas Huth offsetof(CPUSH4State, macl), "MACL"); 137*fcf5ef2aSThomas Huth cpu_pr = tcg_global_mem_new_i32(cpu_env, 138*fcf5ef2aSThomas Huth offsetof(CPUSH4State, pr), "PR"); 139*fcf5ef2aSThomas Huth cpu_fpscr = tcg_global_mem_new_i32(cpu_env, 140*fcf5ef2aSThomas Huth offsetof(CPUSH4State, fpscr), "FPSCR"); 141*fcf5ef2aSThomas Huth cpu_fpul = tcg_global_mem_new_i32(cpu_env, 142*fcf5ef2aSThomas Huth offsetof(CPUSH4State, fpul), "FPUL"); 143*fcf5ef2aSThomas Huth 144*fcf5ef2aSThomas Huth cpu_flags = tcg_global_mem_new_i32(cpu_env, 145*fcf5ef2aSThomas Huth offsetof(CPUSH4State, flags), "_flags_"); 146*fcf5ef2aSThomas Huth cpu_delayed_pc = tcg_global_mem_new_i32(cpu_env, 147*fcf5ef2aSThomas Huth offsetof(CPUSH4State, delayed_pc), 148*fcf5ef2aSThomas Huth "_delayed_pc_"); 149*fcf5ef2aSThomas Huth cpu_ldst = tcg_global_mem_new_i32(cpu_env, 150*fcf5ef2aSThomas Huth offsetof(CPUSH4State, ldst), "_ldst_"); 151*fcf5ef2aSThomas Huth 152*fcf5ef2aSThomas Huth for (i = 0; i < 32; i++) 153*fcf5ef2aSThomas Huth cpu_fregs[i] = tcg_global_mem_new_i32(cpu_env, 154*fcf5ef2aSThomas Huth offsetof(CPUSH4State, fregs[i]), 155*fcf5ef2aSThomas Huth fregnames[i]); 156*fcf5ef2aSThomas Huth 157*fcf5ef2aSThomas Huth done_init = 1; 158*fcf5ef2aSThomas Huth } 159*fcf5ef2aSThomas Huth 160*fcf5ef2aSThomas Huth void superh_cpu_dump_state(CPUState *cs, FILE *f, 161*fcf5ef2aSThomas Huth fprintf_function cpu_fprintf, int flags) 162*fcf5ef2aSThomas Huth { 163*fcf5ef2aSThomas Huth SuperHCPU *cpu = SUPERH_CPU(cs); 164*fcf5ef2aSThomas Huth CPUSH4State *env = &cpu->env; 165*fcf5ef2aSThomas Huth int i; 166*fcf5ef2aSThomas Huth cpu_fprintf(f, "pc=0x%08x sr=0x%08x pr=0x%08x fpscr=0x%08x\n", 167*fcf5ef2aSThomas Huth env->pc, cpu_read_sr(env), env->pr, env->fpscr); 168*fcf5ef2aSThomas Huth cpu_fprintf(f, "spc=0x%08x ssr=0x%08x gbr=0x%08x vbr=0x%08x\n", 169*fcf5ef2aSThomas Huth env->spc, env->ssr, env->gbr, env->vbr); 170*fcf5ef2aSThomas Huth cpu_fprintf(f, "sgr=0x%08x dbr=0x%08x delayed_pc=0x%08x fpul=0x%08x\n", 171*fcf5ef2aSThomas Huth env->sgr, env->dbr, env->delayed_pc, env->fpul); 172*fcf5ef2aSThomas Huth for (i = 0; i < 24; i += 4) { 173*fcf5ef2aSThomas Huth cpu_fprintf(f, "r%d=0x%08x r%d=0x%08x r%d=0x%08x r%d=0x%08x\n", 174*fcf5ef2aSThomas Huth i, env->gregs[i], i + 1, env->gregs[i + 1], 175*fcf5ef2aSThomas Huth i + 2, env->gregs[i + 2], i + 3, env->gregs[i + 3]); 176*fcf5ef2aSThomas Huth } 177*fcf5ef2aSThomas Huth if (env->flags & DELAY_SLOT) { 178*fcf5ef2aSThomas Huth cpu_fprintf(f, "in delay slot (delayed_pc=0x%08x)\n", 179*fcf5ef2aSThomas Huth env->delayed_pc); 180*fcf5ef2aSThomas Huth } else if (env->flags & DELAY_SLOT_CONDITIONAL) { 181*fcf5ef2aSThomas Huth cpu_fprintf(f, "in conditional delay slot (delayed_pc=0x%08x)\n", 182*fcf5ef2aSThomas Huth env->delayed_pc); 183*fcf5ef2aSThomas Huth } 184*fcf5ef2aSThomas Huth } 185*fcf5ef2aSThomas Huth 186*fcf5ef2aSThomas Huth static void gen_read_sr(TCGv dst) 187*fcf5ef2aSThomas Huth { 188*fcf5ef2aSThomas Huth TCGv t0 = tcg_temp_new(); 189*fcf5ef2aSThomas Huth tcg_gen_shli_i32(t0, cpu_sr_q, SR_Q); 190*fcf5ef2aSThomas Huth tcg_gen_or_i32(dst, dst, t0); 191*fcf5ef2aSThomas Huth tcg_gen_shli_i32(t0, cpu_sr_m, SR_M); 192*fcf5ef2aSThomas Huth tcg_gen_or_i32(dst, dst, t0); 193*fcf5ef2aSThomas Huth tcg_gen_shli_i32(t0, cpu_sr_t, SR_T); 194*fcf5ef2aSThomas Huth tcg_gen_or_i32(dst, cpu_sr, t0); 195*fcf5ef2aSThomas Huth tcg_temp_free_i32(t0); 196*fcf5ef2aSThomas Huth } 197*fcf5ef2aSThomas Huth 198*fcf5ef2aSThomas Huth static void gen_write_sr(TCGv src) 199*fcf5ef2aSThomas Huth { 200*fcf5ef2aSThomas Huth tcg_gen_andi_i32(cpu_sr, src, 201*fcf5ef2aSThomas Huth ~((1u << SR_Q) | (1u << SR_M) | (1u << SR_T))); 202*fcf5ef2aSThomas Huth tcg_gen_shri_i32(cpu_sr_q, src, SR_Q); 203*fcf5ef2aSThomas Huth tcg_gen_andi_i32(cpu_sr_q, cpu_sr_q, 1); 204*fcf5ef2aSThomas Huth tcg_gen_shri_i32(cpu_sr_m, src, SR_M); 205*fcf5ef2aSThomas Huth tcg_gen_andi_i32(cpu_sr_m, cpu_sr_m, 1); 206*fcf5ef2aSThomas Huth tcg_gen_shri_i32(cpu_sr_t, src, SR_T); 207*fcf5ef2aSThomas Huth tcg_gen_andi_i32(cpu_sr_t, cpu_sr_t, 1); 208*fcf5ef2aSThomas Huth } 209*fcf5ef2aSThomas Huth 210*fcf5ef2aSThomas Huth static inline bool use_goto_tb(DisasContext *ctx, target_ulong dest) 211*fcf5ef2aSThomas Huth { 212*fcf5ef2aSThomas Huth if (unlikely(ctx->singlestep_enabled)) { 213*fcf5ef2aSThomas Huth return false; 214*fcf5ef2aSThomas Huth } 215*fcf5ef2aSThomas Huth 216*fcf5ef2aSThomas Huth #ifndef CONFIG_USER_ONLY 217*fcf5ef2aSThomas Huth return (ctx->tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK); 218*fcf5ef2aSThomas Huth #else 219*fcf5ef2aSThomas Huth return true; 220*fcf5ef2aSThomas Huth #endif 221*fcf5ef2aSThomas Huth } 222*fcf5ef2aSThomas Huth 223*fcf5ef2aSThomas Huth static void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest) 224*fcf5ef2aSThomas Huth { 225*fcf5ef2aSThomas Huth if (use_goto_tb(ctx, dest)) { 226*fcf5ef2aSThomas Huth /* Use a direct jump if in same page and singlestep not enabled */ 227*fcf5ef2aSThomas Huth tcg_gen_goto_tb(n); 228*fcf5ef2aSThomas Huth tcg_gen_movi_i32(cpu_pc, dest); 229*fcf5ef2aSThomas Huth tcg_gen_exit_tb((uintptr_t)ctx->tb + n); 230*fcf5ef2aSThomas Huth } else { 231*fcf5ef2aSThomas Huth tcg_gen_movi_i32(cpu_pc, dest); 232*fcf5ef2aSThomas Huth if (ctx->singlestep_enabled) 233*fcf5ef2aSThomas Huth gen_helper_debug(cpu_env); 234*fcf5ef2aSThomas Huth tcg_gen_exit_tb(0); 235*fcf5ef2aSThomas Huth } 236*fcf5ef2aSThomas Huth } 237*fcf5ef2aSThomas Huth 238*fcf5ef2aSThomas Huth static void gen_jump(DisasContext * ctx) 239*fcf5ef2aSThomas Huth { 240*fcf5ef2aSThomas Huth if (ctx->delayed_pc == (uint32_t) - 1) { 241*fcf5ef2aSThomas Huth /* Target is not statically known, it comes necessarily from a 242*fcf5ef2aSThomas Huth delayed jump as immediate jump are conditinal jumps */ 243*fcf5ef2aSThomas Huth tcg_gen_mov_i32(cpu_pc, cpu_delayed_pc); 244*fcf5ef2aSThomas Huth if (ctx->singlestep_enabled) 245*fcf5ef2aSThomas Huth gen_helper_debug(cpu_env); 246*fcf5ef2aSThomas Huth tcg_gen_exit_tb(0); 247*fcf5ef2aSThomas Huth } else { 248*fcf5ef2aSThomas Huth gen_goto_tb(ctx, 0, ctx->delayed_pc); 249*fcf5ef2aSThomas Huth } 250*fcf5ef2aSThomas Huth } 251*fcf5ef2aSThomas Huth 252*fcf5ef2aSThomas Huth static inline void gen_branch_slot(uint32_t delayed_pc, int t) 253*fcf5ef2aSThomas Huth { 254*fcf5ef2aSThomas Huth TCGLabel *label = gen_new_label(); 255*fcf5ef2aSThomas Huth tcg_gen_movi_i32(cpu_delayed_pc, delayed_pc); 256*fcf5ef2aSThomas Huth tcg_gen_brcondi_i32(t ? TCG_COND_EQ : TCG_COND_NE, cpu_sr_t, 0, label); 257*fcf5ef2aSThomas Huth tcg_gen_ori_i32(cpu_flags, cpu_flags, DELAY_SLOT_TRUE); 258*fcf5ef2aSThomas Huth gen_set_label(label); 259*fcf5ef2aSThomas Huth } 260*fcf5ef2aSThomas Huth 261*fcf5ef2aSThomas Huth /* Immediate conditional jump (bt or bf) */ 262*fcf5ef2aSThomas Huth static void gen_conditional_jump(DisasContext * ctx, 263*fcf5ef2aSThomas Huth target_ulong ift, target_ulong ifnott) 264*fcf5ef2aSThomas Huth { 265*fcf5ef2aSThomas Huth TCGLabel *l1 = gen_new_label(); 266*fcf5ef2aSThomas Huth tcg_gen_brcondi_i32(TCG_COND_NE, cpu_sr_t, 0, l1); 267*fcf5ef2aSThomas Huth gen_goto_tb(ctx, 0, ifnott); 268*fcf5ef2aSThomas Huth gen_set_label(l1); 269*fcf5ef2aSThomas Huth gen_goto_tb(ctx, 1, ift); 270*fcf5ef2aSThomas Huth } 271*fcf5ef2aSThomas Huth 272*fcf5ef2aSThomas Huth /* Delayed conditional jump (bt or bf) */ 273*fcf5ef2aSThomas Huth static void gen_delayed_conditional_jump(DisasContext * ctx) 274*fcf5ef2aSThomas Huth { 275*fcf5ef2aSThomas Huth TCGLabel *l1; 276*fcf5ef2aSThomas Huth TCGv ds; 277*fcf5ef2aSThomas Huth 278*fcf5ef2aSThomas Huth l1 = gen_new_label(); 279*fcf5ef2aSThomas Huth ds = tcg_temp_new(); 280*fcf5ef2aSThomas Huth tcg_gen_andi_i32(ds, cpu_flags, DELAY_SLOT_TRUE); 281*fcf5ef2aSThomas Huth tcg_gen_brcondi_i32(TCG_COND_NE, ds, 0, l1); 282*fcf5ef2aSThomas Huth gen_goto_tb(ctx, 1, ctx->pc + 2); 283*fcf5ef2aSThomas Huth gen_set_label(l1); 284*fcf5ef2aSThomas Huth tcg_gen_andi_i32(cpu_flags, cpu_flags, ~DELAY_SLOT_TRUE); 285*fcf5ef2aSThomas Huth gen_jump(ctx); 286*fcf5ef2aSThomas Huth } 287*fcf5ef2aSThomas Huth 288*fcf5ef2aSThomas Huth static inline void gen_store_flags(uint32_t flags) 289*fcf5ef2aSThomas Huth { 290*fcf5ef2aSThomas Huth tcg_gen_andi_i32(cpu_flags, cpu_flags, DELAY_SLOT_TRUE); 291*fcf5ef2aSThomas Huth tcg_gen_ori_i32(cpu_flags, cpu_flags, flags); 292*fcf5ef2aSThomas Huth } 293*fcf5ef2aSThomas Huth 294*fcf5ef2aSThomas Huth static inline void gen_load_fpr64(TCGv_i64 t, int reg) 295*fcf5ef2aSThomas Huth { 296*fcf5ef2aSThomas Huth tcg_gen_concat_i32_i64(t, cpu_fregs[reg + 1], cpu_fregs[reg]); 297*fcf5ef2aSThomas Huth } 298*fcf5ef2aSThomas Huth 299*fcf5ef2aSThomas Huth static inline void gen_store_fpr64 (TCGv_i64 t, int reg) 300*fcf5ef2aSThomas Huth { 301*fcf5ef2aSThomas Huth TCGv_i32 tmp = tcg_temp_new_i32(); 302*fcf5ef2aSThomas Huth tcg_gen_extrl_i64_i32(tmp, t); 303*fcf5ef2aSThomas Huth tcg_gen_mov_i32(cpu_fregs[reg + 1], tmp); 304*fcf5ef2aSThomas Huth tcg_gen_shri_i64(t, t, 32); 305*fcf5ef2aSThomas Huth tcg_gen_extrl_i64_i32(tmp, t); 306*fcf5ef2aSThomas Huth tcg_gen_mov_i32(cpu_fregs[reg], tmp); 307*fcf5ef2aSThomas Huth tcg_temp_free_i32(tmp); 308*fcf5ef2aSThomas Huth } 309*fcf5ef2aSThomas Huth 310*fcf5ef2aSThomas Huth #define B3_0 (ctx->opcode & 0xf) 311*fcf5ef2aSThomas Huth #define B6_4 ((ctx->opcode >> 4) & 0x7) 312*fcf5ef2aSThomas Huth #define B7_4 ((ctx->opcode >> 4) & 0xf) 313*fcf5ef2aSThomas Huth #define B7_0 (ctx->opcode & 0xff) 314*fcf5ef2aSThomas Huth #define B7_0s ((int32_t) (int8_t) (ctx->opcode & 0xff)) 315*fcf5ef2aSThomas Huth #define B11_0s (ctx->opcode & 0x800 ? 0xfffff000 | (ctx->opcode & 0xfff) : \ 316*fcf5ef2aSThomas Huth (ctx->opcode & 0xfff)) 317*fcf5ef2aSThomas Huth #define B11_8 ((ctx->opcode >> 8) & 0xf) 318*fcf5ef2aSThomas Huth #define B15_12 ((ctx->opcode >> 12) & 0xf) 319*fcf5ef2aSThomas Huth 320*fcf5ef2aSThomas Huth #define REG(x) ((x) < 8 && (ctx->flags & (1u << SR_MD))\ 321*fcf5ef2aSThomas Huth && (ctx->flags & (1u << SR_RB))\ 322*fcf5ef2aSThomas Huth ? (cpu_gregs[x + 16]) : (cpu_gregs[x])) 323*fcf5ef2aSThomas Huth 324*fcf5ef2aSThomas Huth #define ALTREG(x) ((x) < 8 && (!(ctx->flags & (1u << SR_MD))\ 325*fcf5ef2aSThomas Huth || !(ctx->flags & (1u << SR_RB)))\ 326*fcf5ef2aSThomas Huth ? (cpu_gregs[x + 16]) : (cpu_gregs[x])) 327*fcf5ef2aSThomas Huth 328*fcf5ef2aSThomas Huth #define FREG(x) (ctx->flags & FPSCR_FR ? (x) ^ 0x10 : (x)) 329*fcf5ef2aSThomas Huth #define XHACK(x) ((((x) & 1 ) << 4) | ((x) & 0xe)) 330*fcf5ef2aSThomas Huth #define XREG(x) (ctx->flags & FPSCR_FR ? XHACK(x) ^ 0x10 : XHACK(x)) 331*fcf5ef2aSThomas Huth #define DREG(x) FREG(x) /* Assumes lsb of (x) is always 0 */ 332*fcf5ef2aSThomas Huth 333*fcf5ef2aSThomas Huth #define CHECK_NOT_DELAY_SLOT \ 334*fcf5ef2aSThomas Huth if (ctx->flags & (DELAY_SLOT | DELAY_SLOT_CONDITIONAL)) \ 335*fcf5ef2aSThomas Huth { \ 336*fcf5ef2aSThomas Huth tcg_gen_movi_i32(cpu_pc, ctx->pc); \ 337*fcf5ef2aSThomas Huth gen_helper_raise_slot_illegal_instruction(cpu_env); \ 338*fcf5ef2aSThomas Huth ctx->bstate = BS_BRANCH; \ 339*fcf5ef2aSThomas Huth return; \ 340*fcf5ef2aSThomas Huth } 341*fcf5ef2aSThomas Huth 342*fcf5ef2aSThomas Huth #define CHECK_PRIVILEGED \ 343*fcf5ef2aSThomas Huth if (IS_USER(ctx)) { \ 344*fcf5ef2aSThomas Huth tcg_gen_movi_i32(cpu_pc, ctx->pc); \ 345*fcf5ef2aSThomas Huth if (ctx->flags & (DELAY_SLOT | DELAY_SLOT_CONDITIONAL)) { \ 346*fcf5ef2aSThomas Huth gen_helper_raise_slot_illegal_instruction(cpu_env); \ 347*fcf5ef2aSThomas Huth } else { \ 348*fcf5ef2aSThomas Huth gen_helper_raise_illegal_instruction(cpu_env); \ 349*fcf5ef2aSThomas Huth } \ 350*fcf5ef2aSThomas Huth ctx->bstate = BS_BRANCH; \ 351*fcf5ef2aSThomas Huth return; \ 352*fcf5ef2aSThomas Huth } 353*fcf5ef2aSThomas Huth 354*fcf5ef2aSThomas Huth #define CHECK_FPU_ENABLED \ 355*fcf5ef2aSThomas Huth if (ctx->flags & (1u << SR_FD)) { \ 356*fcf5ef2aSThomas Huth tcg_gen_movi_i32(cpu_pc, ctx->pc); \ 357*fcf5ef2aSThomas Huth if (ctx->flags & (DELAY_SLOT | DELAY_SLOT_CONDITIONAL)) { \ 358*fcf5ef2aSThomas Huth gen_helper_raise_slot_fpu_disable(cpu_env); \ 359*fcf5ef2aSThomas Huth } else { \ 360*fcf5ef2aSThomas Huth gen_helper_raise_fpu_disable(cpu_env); \ 361*fcf5ef2aSThomas Huth } \ 362*fcf5ef2aSThomas Huth ctx->bstate = BS_BRANCH; \ 363*fcf5ef2aSThomas Huth return; \ 364*fcf5ef2aSThomas Huth } 365*fcf5ef2aSThomas Huth 366*fcf5ef2aSThomas Huth static void _decode_opc(DisasContext * ctx) 367*fcf5ef2aSThomas Huth { 368*fcf5ef2aSThomas Huth /* This code tries to make movcal emulation sufficiently 369*fcf5ef2aSThomas Huth accurate for Linux purposes. This instruction writes 370*fcf5ef2aSThomas Huth memory, and prior to that, always allocates a cache line. 371*fcf5ef2aSThomas Huth It is used in two contexts: 372*fcf5ef2aSThomas Huth - in memcpy, where data is copied in blocks, the first write 373*fcf5ef2aSThomas Huth of to a block uses movca.l for performance. 374*fcf5ef2aSThomas Huth - in arch/sh/mm/cache-sh4.c, movcal.l + ocbi combination is used 375*fcf5ef2aSThomas Huth to flush the cache. Here, the data written by movcal.l is never 376*fcf5ef2aSThomas Huth written to memory, and the data written is just bogus. 377*fcf5ef2aSThomas Huth 378*fcf5ef2aSThomas Huth To simulate this, we simulate movcal.l, we store the value to memory, 379*fcf5ef2aSThomas Huth but we also remember the previous content. If we see ocbi, we check 380*fcf5ef2aSThomas Huth if movcal.l for that address was done previously. If so, the write should 381*fcf5ef2aSThomas Huth not have hit the memory, so we restore the previous content. 382*fcf5ef2aSThomas Huth When we see an instruction that is neither movca.l 383*fcf5ef2aSThomas Huth nor ocbi, the previous content is discarded. 384*fcf5ef2aSThomas Huth 385*fcf5ef2aSThomas Huth To optimize, we only try to flush stores when we're at the start of 386*fcf5ef2aSThomas Huth TB, or if we already saw movca.l in this TB and did not flush stores 387*fcf5ef2aSThomas Huth yet. */ 388*fcf5ef2aSThomas Huth if (ctx->has_movcal) 389*fcf5ef2aSThomas Huth { 390*fcf5ef2aSThomas Huth int opcode = ctx->opcode & 0xf0ff; 391*fcf5ef2aSThomas Huth if (opcode != 0x0093 /* ocbi */ 392*fcf5ef2aSThomas Huth && opcode != 0x00c3 /* movca.l */) 393*fcf5ef2aSThomas Huth { 394*fcf5ef2aSThomas Huth gen_helper_discard_movcal_backup(cpu_env); 395*fcf5ef2aSThomas Huth ctx->has_movcal = 0; 396*fcf5ef2aSThomas Huth } 397*fcf5ef2aSThomas Huth } 398*fcf5ef2aSThomas Huth 399*fcf5ef2aSThomas Huth #if 0 400*fcf5ef2aSThomas Huth fprintf(stderr, "Translating opcode 0x%04x\n", ctx->opcode); 401*fcf5ef2aSThomas Huth #endif 402*fcf5ef2aSThomas Huth 403*fcf5ef2aSThomas Huth switch (ctx->opcode) { 404*fcf5ef2aSThomas Huth case 0x0019: /* div0u */ 405*fcf5ef2aSThomas Huth tcg_gen_movi_i32(cpu_sr_m, 0); 406*fcf5ef2aSThomas Huth tcg_gen_movi_i32(cpu_sr_q, 0); 407*fcf5ef2aSThomas Huth tcg_gen_movi_i32(cpu_sr_t, 0); 408*fcf5ef2aSThomas Huth return; 409*fcf5ef2aSThomas Huth case 0x000b: /* rts */ 410*fcf5ef2aSThomas Huth CHECK_NOT_DELAY_SLOT 411*fcf5ef2aSThomas Huth tcg_gen_mov_i32(cpu_delayed_pc, cpu_pr); 412*fcf5ef2aSThomas Huth ctx->flags |= DELAY_SLOT; 413*fcf5ef2aSThomas Huth ctx->delayed_pc = (uint32_t) - 1; 414*fcf5ef2aSThomas Huth return; 415*fcf5ef2aSThomas Huth case 0x0028: /* clrmac */ 416*fcf5ef2aSThomas Huth tcg_gen_movi_i32(cpu_mach, 0); 417*fcf5ef2aSThomas Huth tcg_gen_movi_i32(cpu_macl, 0); 418*fcf5ef2aSThomas Huth return; 419*fcf5ef2aSThomas Huth case 0x0048: /* clrs */ 420*fcf5ef2aSThomas Huth tcg_gen_andi_i32(cpu_sr, cpu_sr, ~(1u << SR_S)); 421*fcf5ef2aSThomas Huth return; 422*fcf5ef2aSThomas Huth case 0x0008: /* clrt */ 423*fcf5ef2aSThomas Huth tcg_gen_movi_i32(cpu_sr_t, 0); 424*fcf5ef2aSThomas Huth return; 425*fcf5ef2aSThomas Huth case 0x0038: /* ldtlb */ 426*fcf5ef2aSThomas Huth CHECK_PRIVILEGED 427*fcf5ef2aSThomas Huth gen_helper_ldtlb(cpu_env); 428*fcf5ef2aSThomas Huth return; 429*fcf5ef2aSThomas Huth case 0x002b: /* rte */ 430*fcf5ef2aSThomas Huth CHECK_PRIVILEGED 431*fcf5ef2aSThomas Huth CHECK_NOT_DELAY_SLOT 432*fcf5ef2aSThomas Huth gen_write_sr(cpu_ssr); 433*fcf5ef2aSThomas Huth tcg_gen_mov_i32(cpu_delayed_pc, cpu_spc); 434*fcf5ef2aSThomas Huth ctx->flags |= DELAY_SLOT; 435*fcf5ef2aSThomas Huth ctx->delayed_pc = (uint32_t) - 1; 436*fcf5ef2aSThomas Huth return; 437*fcf5ef2aSThomas Huth case 0x0058: /* sets */ 438*fcf5ef2aSThomas Huth tcg_gen_ori_i32(cpu_sr, cpu_sr, (1u << SR_S)); 439*fcf5ef2aSThomas Huth return; 440*fcf5ef2aSThomas Huth case 0x0018: /* sett */ 441*fcf5ef2aSThomas Huth tcg_gen_movi_i32(cpu_sr_t, 1); 442*fcf5ef2aSThomas Huth return; 443*fcf5ef2aSThomas Huth case 0xfbfd: /* frchg */ 444*fcf5ef2aSThomas Huth tcg_gen_xori_i32(cpu_fpscr, cpu_fpscr, FPSCR_FR); 445*fcf5ef2aSThomas Huth ctx->bstate = BS_STOP; 446*fcf5ef2aSThomas Huth return; 447*fcf5ef2aSThomas Huth case 0xf3fd: /* fschg */ 448*fcf5ef2aSThomas Huth tcg_gen_xori_i32(cpu_fpscr, cpu_fpscr, FPSCR_SZ); 449*fcf5ef2aSThomas Huth ctx->bstate = BS_STOP; 450*fcf5ef2aSThomas Huth return; 451*fcf5ef2aSThomas Huth case 0x0009: /* nop */ 452*fcf5ef2aSThomas Huth return; 453*fcf5ef2aSThomas Huth case 0x001b: /* sleep */ 454*fcf5ef2aSThomas Huth CHECK_PRIVILEGED 455*fcf5ef2aSThomas Huth tcg_gen_movi_i32(cpu_pc, ctx->pc + 2); 456*fcf5ef2aSThomas Huth gen_helper_sleep(cpu_env); 457*fcf5ef2aSThomas Huth return; 458*fcf5ef2aSThomas Huth } 459*fcf5ef2aSThomas Huth 460*fcf5ef2aSThomas Huth switch (ctx->opcode & 0xf000) { 461*fcf5ef2aSThomas Huth case 0x1000: /* mov.l Rm,@(disp,Rn) */ 462*fcf5ef2aSThomas Huth { 463*fcf5ef2aSThomas Huth TCGv addr = tcg_temp_new(); 464*fcf5ef2aSThomas Huth tcg_gen_addi_i32(addr, REG(B11_8), B3_0 * 4); 465*fcf5ef2aSThomas Huth tcg_gen_qemu_st_i32(REG(B7_4), addr, ctx->memidx, MO_TEUL); 466*fcf5ef2aSThomas Huth tcg_temp_free(addr); 467*fcf5ef2aSThomas Huth } 468*fcf5ef2aSThomas Huth return; 469*fcf5ef2aSThomas Huth case 0x5000: /* mov.l @(disp,Rm),Rn */ 470*fcf5ef2aSThomas Huth { 471*fcf5ef2aSThomas Huth TCGv addr = tcg_temp_new(); 472*fcf5ef2aSThomas Huth tcg_gen_addi_i32(addr, REG(B7_4), B3_0 * 4); 473*fcf5ef2aSThomas Huth tcg_gen_qemu_ld_i32(REG(B11_8), addr, ctx->memidx, MO_TESL); 474*fcf5ef2aSThomas Huth tcg_temp_free(addr); 475*fcf5ef2aSThomas Huth } 476*fcf5ef2aSThomas Huth return; 477*fcf5ef2aSThomas Huth case 0xe000: /* mov #imm,Rn */ 478*fcf5ef2aSThomas Huth tcg_gen_movi_i32(REG(B11_8), B7_0s); 479*fcf5ef2aSThomas Huth return; 480*fcf5ef2aSThomas Huth case 0x9000: /* mov.w @(disp,PC),Rn */ 481*fcf5ef2aSThomas Huth { 482*fcf5ef2aSThomas Huth TCGv addr = tcg_const_i32(ctx->pc + 4 + B7_0 * 2); 483*fcf5ef2aSThomas Huth tcg_gen_qemu_ld_i32(REG(B11_8), addr, ctx->memidx, MO_TESW); 484*fcf5ef2aSThomas Huth tcg_temp_free(addr); 485*fcf5ef2aSThomas Huth } 486*fcf5ef2aSThomas Huth return; 487*fcf5ef2aSThomas Huth case 0xd000: /* mov.l @(disp,PC),Rn */ 488*fcf5ef2aSThomas Huth { 489*fcf5ef2aSThomas Huth TCGv addr = tcg_const_i32((ctx->pc + 4 + B7_0 * 4) & ~3); 490*fcf5ef2aSThomas Huth tcg_gen_qemu_ld_i32(REG(B11_8), addr, ctx->memidx, MO_TESL); 491*fcf5ef2aSThomas Huth tcg_temp_free(addr); 492*fcf5ef2aSThomas Huth } 493*fcf5ef2aSThomas Huth return; 494*fcf5ef2aSThomas Huth case 0x7000: /* add #imm,Rn */ 495*fcf5ef2aSThomas Huth tcg_gen_addi_i32(REG(B11_8), REG(B11_8), B7_0s); 496*fcf5ef2aSThomas Huth return; 497*fcf5ef2aSThomas Huth case 0xa000: /* bra disp */ 498*fcf5ef2aSThomas Huth CHECK_NOT_DELAY_SLOT 499*fcf5ef2aSThomas Huth ctx->delayed_pc = ctx->pc + 4 + B11_0s * 2; 500*fcf5ef2aSThomas Huth tcg_gen_movi_i32(cpu_delayed_pc, ctx->delayed_pc); 501*fcf5ef2aSThomas Huth ctx->flags |= DELAY_SLOT; 502*fcf5ef2aSThomas Huth return; 503*fcf5ef2aSThomas Huth case 0xb000: /* bsr disp */ 504*fcf5ef2aSThomas Huth CHECK_NOT_DELAY_SLOT 505*fcf5ef2aSThomas Huth tcg_gen_movi_i32(cpu_pr, ctx->pc + 4); 506*fcf5ef2aSThomas Huth ctx->delayed_pc = ctx->pc + 4 + B11_0s * 2; 507*fcf5ef2aSThomas Huth tcg_gen_movi_i32(cpu_delayed_pc, ctx->delayed_pc); 508*fcf5ef2aSThomas Huth ctx->flags |= DELAY_SLOT; 509*fcf5ef2aSThomas Huth return; 510*fcf5ef2aSThomas Huth } 511*fcf5ef2aSThomas Huth 512*fcf5ef2aSThomas Huth switch (ctx->opcode & 0xf00f) { 513*fcf5ef2aSThomas Huth case 0x6003: /* mov Rm,Rn */ 514*fcf5ef2aSThomas Huth tcg_gen_mov_i32(REG(B11_8), REG(B7_4)); 515*fcf5ef2aSThomas Huth return; 516*fcf5ef2aSThomas Huth case 0x2000: /* mov.b Rm,@Rn */ 517*fcf5ef2aSThomas Huth tcg_gen_qemu_st_i32(REG(B7_4), REG(B11_8), ctx->memidx, MO_UB); 518*fcf5ef2aSThomas Huth return; 519*fcf5ef2aSThomas Huth case 0x2001: /* mov.w Rm,@Rn */ 520*fcf5ef2aSThomas Huth tcg_gen_qemu_st_i32(REG(B7_4), REG(B11_8), ctx->memidx, MO_TEUW); 521*fcf5ef2aSThomas Huth return; 522*fcf5ef2aSThomas Huth case 0x2002: /* mov.l Rm,@Rn */ 523*fcf5ef2aSThomas Huth tcg_gen_qemu_st_i32(REG(B7_4), REG(B11_8), ctx->memidx, MO_TEUL); 524*fcf5ef2aSThomas Huth return; 525*fcf5ef2aSThomas Huth case 0x6000: /* mov.b @Rm,Rn */ 526*fcf5ef2aSThomas Huth tcg_gen_qemu_ld_i32(REG(B11_8), REG(B7_4), ctx->memidx, MO_SB); 527*fcf5ef2aSThomas Huth return; 528*fcf5ef2aSThomas Huth case 0x6001: /* mov.w @Rm,Rn */ 529*fcf5ef2aSThomas Huth tcg_gen_qemu_ld_i32(REG(B11_8), REG(B7_4), ctx->memidx, MO_TESW); 530*fcf5ef2aSThomas Huth return; 531*fcf5ef2aSThomas Huth case 0x6002: /* mov.l @Rm,Rn */ 532*fcf5ef2aSThomas Huth tcg_gen_qemu_ld_i32(REG(B11_8), REG(B7_4), ctx->memidx, MO_TESL); 533*fcf5ef2aSThomas Huth return; 534*fcf5ef2aSThomas Huth case 0x2004: /* mov.b Rm,@-Rn */ 535*fcf5ef2aSThomas Huth { 536*fcf5ef2aSThomas Huth TCGv addr = tcg_temp_new(); 537*fcf5ef2aSThomas Huth tcg_gen_subi_i32(addr, REG(B11_8), 1); 538*fcf5ef2aSThomas Huth /* might cause re-execution */ 539*fcf5ef2aSThomas Huth tcg_gen_qemu_st_i32(REG(B7_4), addr, ctx->memidx, MO_UB); 540*fcf5ef2aSThomas Huth tcg_gen_mov_i32(REG(B11_8), addr); /* modify register status */ 541*fcf5ef2aSThomas Huth tcg_temp_free(addr); 542*fcf5ef2aSThomas Huth } 543*fcf5ef2aSThomas Huth return; 544*fcf5ef2aSThomas Huth case 0x2005: /* mov.w Rm,@-Rn */ 545*fcf5ef2aSThomas Huth { 546*fcf5ef2aSThomas Huth TCGv addr = tcg_temp_new(); 547*fcf5ef2aSThomas Huth tcg_gen_subi_i32(addr, REG(B11_8), 2); 548*fcf5ef2aSThomas Huth tcg_gen_qemu_st_i32(REG(B7_4), addr, ctx->memidx, MO_TEUW); 549*fcf5ef2aSThomas Huth tcg_gen_mov_i32(REG(B11_8), addr); 550*fcf5ef2aSThomas Huth tcg_temp_free(addr); 551*fcf5ef2aSThomas Huth } 552*fcf5ef2aSThomas Huth return; 553*fcf5ef2aSThomas Huth case 0x2006: /* mov.l Rm,@-Rn */ 554*fcf5ef2aSThomas Huth { 555*fcf5ef2aSThomas Huth TCGv addr = tcg_temp_new(); 556*fcf5ef2aSThomas Huth tcg_gen_subi_i32(addr, REG(B11_8), 4); 557*fcf5ef2aSThomas Huth tcg_gen_qemu_st_i32(REG(B7_4), addr, ctx->memidx, MO_TEUL); 558*fcf5ef2aSThomas Huth tcg_gen_mov_i32(REG(B11_8), addr); 559*fcf5ef2aSThomas Huth } 560*fcf5ef2aSThomas Huth return; 561*fcf5ef2aSThomas Huth case 0x6004: /* mov.b @Rm+,Rn */ 562*fcf5ef2aSThomas Huth tcg_gen_qemu_ld_i32(REG(B11_8), REG(B7_4), ctx->memidx, MO_SB); 563*fcf5ef2aSThomas Huth if ( B11_8 != B7_4 ) 564*fcf5ef2aSThomas Huth tcg_gen_addi_i32(REG(B7_4), REG(B7_4), 1); 565*fcf5ef2aSThomas Huth return; 566*fcf5ef2aSThomas Huth case 0x6005: /* mov.w @Rm+,Rn */ 567*fcf5ef2aSThomas Huth tcg_gen_qemu_ld_i32(REG(B11_8), REG(B7_4), ctx->memidx, MO_TESW); 568*fcf5ef2aSThomas Huth if ( B11_8 != B7_4 ) 569*fcf5ef2aSThomas Huth tcg_gen_addi_i32(REG(B7_4), REG(B7_4), 2); 570*fcf5ef2aSThomas Huth return; 571*fcf5ef2aSThomas Huth case 0x6006: /* mov.l @Rm+,Rn */ 572*fcf5ef2aSThomas Huth tcg_gen_qemu_ld_i32(REG(B11_8), REG(B7_4), ctx->memidx, MO_TESL); 573*fcf5ef2aSThomas Huth if ( B11_8 != B7_4 ) 574*fcf5ef2aSThomas Huth tcg_gen_addi_i32(REG(B7_4), REG(B7_4), 4); 575*fcf5ef2aSThomas Huth return; 576*fcf5ef2aSThomas Huth case 0x0004: /* mov.b Rm,@(R0,Rn) */ 577*fcf5ef2aSThomas Huth { 578*fcf5ef2aSThomas Huth TCGv addr = tcg_temp_new(); 579*fcf5ef2aSThomas Huth tcg_gen_add_i32(addr, REG(B11_8), REG(0)); 580*fcf5ef2aSThomas Huth tcg_gen_qemu_st_i32(REG(B7_4), addr, ctx->memidx, MO_UB); 581*fcf5ef2aSThomas Huth tcg_temp_free(addr); 582*fcf5ef2aSThomas Huth } 583*fcf5ef2aSThomas Huth return; 584*fcf5ef2aSThomas Huth case 0x0005: /* mov.w Rm,@(R0,Rn) */ 585*fcf5ef2aSThomas Huth { 586*fcf5ef2aSThomas Huth TCGv addr = tcg_temp_new(); 587*fcf5ef2aSThomas Huth tcg_gen_add_i32(addr, REG(B11_8), REG(0)); 588*fcf5ef2aSThomas Huth tcg_gen_qemu_st_i32(REG(B7_4), addr, ctx->memidx, MO_TEUW); 589*fcf5ef2aSThomas Huth tcg_temp_free(addr); 590*fcf5ef2aSThomas Huth } 591*fcf5ef2aSThomas Huth return; 592*fcf5ef2aSThomas Huth case 0x0006: /* mov.l Rm,@(R0,Rn) */ 593*fcf5ef2aSThomas Huth { 594*fcf5ef2aSThomas Huth TCGv addr = tcg_temp_new(); 595*fcf5ef2aSThomas Huth tcg_gen_add_i32(addr, REG(B11_8), REG(0)); 596*fcf5ef2aSThomas Huth tcg_gen_qemu_st_i32(REG(B7_4), addr, ctx->memidx, MO_TEUL); 597*fcf5ef2aSThomas Huth tcg_temp_free(addr); 598*fcf5ef2aSThomas Huth } 599*fcf5ef2aSThomas Huth return; 600*fcf5ef2aSThomas Huth case 0x000c: /* mov.b @(R0,Rm),Rn */ 601*fcf5ef2aSThomas Huth { 602*fcf5ef2aSThomas Huth TCGv addr = tcg_temp_new(); 603*fcf5ef2aSThomas Huth tcg_gen_add_i32(addr, REG(B7_4), REG(0)); 604*fcf5ef2aSThomas Huth tcg_gen_qemu_ld_i32(REG(B11_8), addr, ctx->memidx, MO_SB); 605*fcf5ef2aSThomas Huth tcg_temp_free(addr); 606*fcf5ef2aSThomas Huth } 607*fcf5ef2aSThomas Huth return; 608*fcf5ef2aSThomas Huth case 0x000d: /* mov.w @(R0,Rm),Rn */ 609*fcf5ef2aSThomas Huth { 610*fcf5ef2aSThomas Huth TCGv addr = tcg_temp_new(); 611*fcf5ef2aSThomas Huth tcg_gen_add_i32(addr, REG(B7_4), REG(0)); 612*fcf5ef2aSThomas Huth tcg_gen_qemu_ld_i32(REG(B11_8), addr, ctx->memidx, MO_TESW); 613*fcf5ef2aSThomas Huth tcg_temp_free(addr); 614*fcf5ef2aSThomas Huth } 615*fcf5ef2aSThomas Huth return; 616*fcf5ef2aSThomas Huth case 0x000e: /* mov.l @(R0,Rm),Rn */ 617*fcf5ef2aSThomas Huth { 618*fcf5ef2aSThomas Huth TCGv addr = tcg_temp_new(); 619*fcf5ef2aSThomas Huth tcg_gen_add_i32(addr, REG(B7_4), REG(0)); 620*fcf5ef2aSThomas Huth tcg_gen_qemu_ld_i32(REG(B11_8), addr, ctx->memidx, MO_TESL); 621*fcf5ef2aSThomas Huth tcg_temp_free(addr); 622*fcf5ef2aSThomas Huth } 623*fcf5ef2aSThomas Huth return; 624*fcf5ef2aSThomas Huth case 0x6008: /* swap.b Rm,Rn */ 625*fcf5ef2aSThomas Huth { 626*fcf5ef2aSThomas Huth TCGv low = tcg_temp_new();; 627*fcf5ef2aSThomas Huth tcg_gen_ext16u_i32(low, REG(B7_4)); 628*fcf5ef2aSThomas Huth tcg_gen_bswap16_i32(low, low); 629*fcf5ef2aSThomas Huth tcg_gen_deposit_i32(REG(B11_8), REG(B7_4), low, 0, 16); 630*fcf5ef2aSThomas Huth tcg_temp_free(low); 631*fcf5ef2aSThomas Huth } 632*fcf5ef2aSThomas Huth return; 633*fcf5ef2aSThomas Huth case 0x6009: /* swap.w Rm,Rn */ 634*fcf5ef2aSThomas Huth tcg_gen_rotli_i32(REG(B11_8), REG(B7_4), 16); 635*fcf5ef2aSThomas Huth return; 636*fcf5ef2aSThomas Huth case 0x200d: /* xtrct Rm,Rn */ 637*fcf5ef2aSThomas Huth { 638*fcf5ef2aSThomas Huth TCGv high, low; 639*fcf5ef2aSThomas Huth high = tcg_temp_new(); 640*fcf5ef2aSThomas Huth tcg_gen_shli_i32(high, REG(B7_4), 16); 641*fcf5ef2aSThomas Huth low = tcg_temp_new(); 642*fcf5ef2aSThomas Huth tcg_gen_shri_i32(low, REG(B11_8), 16); 643*fcf5ef2aSThomas Huth tcg_gen_or_i32(REG(B11_8), high, low); 644*fcf5ef2aSThomas Huth tcg_temp_free(low); 645*fcf5ef2aSThomas Huth tcg_temp_free(high); 646*fcf5ef2aSThomas Huth } 647*fcf5ef2aSThomas Huth return; 648*fcf5ef2aSThomas Huth case 0x300c: /* add Rm,Rn */ 649*fcf5ef2aSThomas Huth tcg_gen_add_i32(REG(B11_8), REG(B11_8), REG(B7_4)); 650*fcf5ef2aSThomas Huth return; 651*fcf5ef2aSThomas Huth case 0x300e: /* addc Rm,Rn */ 652*fcf5ef2aSThomas Huth { 653*fcf5ef2aSThomas Huth TCGv t0, t1; 654*fcf5ef2aSThomas Huth t0 = tcg_const_tl(0); 655*fcf5ef2aSThomas Huth t1 = tcg_temp_new(); 656*fcf5ef2aSThomas Huth tcg_gen_add2_i32(t1, cpu_sr_t, cpu_sr_t, t0, REG(B7_4), t0); 657*fcf5ef2aSThomas Huth tcg_gen_add2_i32(REG(B11_8), cpu_sr_t, 658*fcf5ef2aSThomas Huth REG(B11_8), t0, t1, cpu_sr_t); 659*fcf5ef2aSThomas Huth tcg_temp_free(t0); 660*fcf5ef2aSThomas Huth tcg_temp_free(t1); 661*fcf5ef2aSThomas Huth } 662*fcf5ef2aSThomas Huth return; 663*fcf5ef2aSThomas Huth case 0x300f: /* addv Rm,Rn */ 664*fcf5ef2aSThomas Huth { 665*fcf5ef2aSThomas Huth TCGv t0, t1, t2; 666*fcf5ef2aSThomas Huth t0 = tcg_temp_new(); 667*fcf5ef2aSThomas Huth tcg_gen_add_i32(t0, REG(B7_4), REG(B11_8)); 668*fcf5ef2aSThomas Huth t1 = tcg_temp_new(); 669*fcf5ef2aSThomas Huth tcg_gen_xor_i32(t1, t0, REG(B11_8)); 670*fcf5ef2aSThomas Huth t2 = tcg_temp_new(); 671*fcf5ef2aSThomas Huth tcg_gen_xor_i32(t2, REG(B7_4), REG(B11_8)); 672*fcf5ef2aSThomas Huth tcg_gen_andc_i32(cpu_sr_t, t1, t2); 673*fcf5ef2aSThomas Huth tcg_temp_free(t2); 674*fcf5ef2aSThomas Huth tcg_gen_shri_i32(cpu_sr_t, cpu_sr_t, 31); 675*fcf5ef2aSThomas Huth tcg_temp_free(t1); 676*fcf5ef2aSThomas Huth tcg_gen_mov_i32(REG(B7_4), t0); 677*fcf5ef2aSThomas Huth tcg_temp_free(t0); 678*fcf5ef2aSThomas Huth } 679*fcf5ef2aSThomas Huth return; 680*fcf5ef2aSThomas Huth case 0x2009: /* and Rm,Rn */ 681*fcf5ef2aSThomas Huth tcg_gen_and_i32(REG(B11_8), REG(B11_8), REG(B7_4)); 682*fcf5ef2aSThomas Huth return; 683*fcf5ef2aSThomas Huth case 0x3000: /* cmp/eq Rm,Rn */ 684*fcf5ef2aSThomas Huth tcg_gen_setcond_i32(TCG_COND_EQ, cpu_sr_t, REG(B11_8), REG(B7_4)); 685*fcf5ef2aSThomas Huth return; 686*fcf5ef2aSThomas Huth case 0x3003: /* cmp/ge Rm,Rn */ 687*fcf5ef2aSThomas Huth tcg_gen_setcond_i32(TCG_COND_GE, cpu_sr_t, REG(B11_8), REG(B7_4)); 688*fcf5ef2aSThomas Huth return; 689*fcf5ef2aSThomas Huth case 0x3007: /* cmp/gt Rm,Rn */ 690*fcf5ef2aSThomas Huth tcg_gen_setcond_i32(TCG_COND_GT, cpu_sr_t, REG(B11_8), REG(B7_4)); 691*fcf5ef2aSThomas Huth return; 692*fcf5ef2aSThomas Huth case 0x3006: /* cmp/hi Rm,Rn */ 693*fcf5ef2aSThomas Huth tcg_gen_setcond_i32(TCG_COND_GTU, cpu_sr_t, REG(B11_8), REG(B7_4)); 694*fcf5ef2aSThomas Huth return; 695*fcf5ef2aSThomas Huth case 0x3002: /* cmp/hs Rm,Rn */ 696*fcf5ef2aSThomas Huth tcg_gen_setcond_i32(TCG_COND_GEU, cpu_sr_t, REG(B11_8), REG(B7_4)); 697*fcf5ef2aSThomas Huth return; 698*fcf5ef2aSThomas Huth case 0x200c: /* cmp/str Rm,Rn */ 699*fcf5ef2aSThomas Huth { 700*fcf5ef2aSThomas Huth TCGv cmp1 = tcg_temp_new(); 701*fcf5ef2aSThomas Huth TCGv cmp2 = tcg_temp_new(); 702*fcf5ef2aSThomas Huth tcg_gen_xor_i32(cmp2, REG(B7_4), REG(B11_8)); 703*fcf5ef2aSThomas Huth tcg_gen_subi_i32(cmp1, cmp2, 0x01010101); 704*fcf5ef2aSThomas Huth tcg_gen_andc_i32(cmp1, cmp1, cmp2); 705*fcf5ef2aSThomas Huth tcg_gen_andi_i32(cmp1, cmp1, 0x80808080); 706*fcf5ef2aSThomas Huth tcg_gen_setcondi_i32(TCG_COND_NE, cpu_sr_t, cmp1, 0); 707*fcf5ef2aSThomas Huth tcg_temp_free(cmp2); 708*fcf5ef2aSThomas Huth tcg_temp_free(cmp1); 709*fcf5ef2aSThomas Huth } 710*fcf5ef2aSThomas Huth return; 711*fcf5ef2aSThomas Huth case 0x2007: /* div0s Rm,Rn */ 712*fcf5ef2aSThomas Huth tcg_gen_shri_i32(cpu_sr_q, REG(B11_8), 31); /* SR_Q */ 713*fcf5ef2aSThomas Huth tcg_gen_shri_i32(cpu_sr_m, REG(B7_4), 31); /* SR_M */ 714*fcf5ef2aSThomas Huth tcg_gen_xor_i32(cpu_sr_t, cpu_sr_q, cpu_sr_m); /* SR_T */ 715*fcf5ef2aSThomas Huth return; 716*fcf5ef2aSThomas Huth case 0x3004: /* div1 Rm,Rn */ 717*fcf5ef2aSThomas Huth { 718*fcf5ef2aSThomas Huth TCGv t0 = tcg_temp_new(); 719*fcf5ef2aSThomas Huth TCGv t1 = tcg_temp_new(); 720*fcf5ef2aSThomas Huth TCGv t2 = tcg_temp_new(); 721*fcf5ef2aSThomas Huth TCGv zero = tcg_const_i32(0); 722*fcf5ef2aSThomas Huth 723*fcf5ef2aSThomas Huth /* shift left arg1, saving the bit being pushed out and inserting 724*fcf5ef2aSThomas Huth T on the right */ 725*fcf5ef2aSThomas Huth tcg_gen_shri_i32(t0, REG(B11_8), 31); 726*fcf5ef2aSThomas Huth tcg_gen_shli_i32(REG(B11_8), REG(B11_8), 1); 727*fcf5ef2aSThomas Huth tcg_gen_or_i32(REG(B11_8), REG(B11_8), cpu_sr_t); 728*fcf5ef2aSThomas Huth 729*fcf5ef2aSThomas Huth /* Add or subtract arg0 from arg1 depending if Q == M. To avoid 730*fcf5ef2aSThomas Huth using 64-bit temps, we compute arg0's high part from q ^ m, so 731*fcf5ef2aSThomas Huth that it is 0x00000000 when adding the value or 0xffffffff when 732*fcf5ef2aSThomas Huth subtracting it. */ 733*fcf5ef2aSThomas Huth tcg_gen_xor_i32(t1, cpu_sr_q, cpu_sr_m); 734*fcf5ef2aSThomas Huth tcg_gen_subi_i32(t1, t1, 1); 735*fcf5ef2aSThomas Huth tcg_gen_neg_i32(t2, REG(B7_4)); 736*fcf5ef2aSThomas Huth tcg_gen_movcond_i32(TCG_COND_EQ, t2, t1, zero, REG(B7_4), t2); 737*fcf5ef2aSThomas Huth tcg_gen_add2_i32(REG(B11_8), t1, REG(B11_8), zero, t2, t1); 738*fcf5ef2aSThomas Huth 739*fcf5ef2aSThomas Huth /* compute T and Q depending on carry */ 740*fcf5ef2aSThomas Huth tcg_gen_andi_i32(t1, t1, 1); 741*fcf5ef2aSThomas Huth tcg_gen_xor_i32(t1, t1, t0); 742*fcf5ef2aSThomas Huth tcg_gen_xori_i32(cpu_sr_t, t1, 1); 743*fcf5ef2aSThomas Huth tcg_gen_xor_i32(cpu_sr_q, cpu_sr_m, t1); 744*fcf5ef2aSThomas Huth 745*fcf5ef2aSThomas Huth tcg_temp_free(zero); 746*fcf5ef2aSThomas Huth tcg_temp_free(t2); 747*fcf5ef2aSThomas Huth tcg_temp_free(t1); 748*fcf5ef2aSThomas Huth tcg_temp_free(t0); 749*fcf5ef2aSThomas Huth } 750*fcf5ef2aSThomas Huth return; 751*fcf5ef2aSThomas Huth case 0x300d: /* dmuls.l Rm,Rn */ 752*fcf5ef2aSThomas Huth tcg_gen_muls2_i32(cpu_macl, cpu_mach, REG(B7_4), REG(B11_8)); 753*fcf5ef2aSThomas Huth return; 754*fcf5ef2aSThomas Huth case 0x3005: /* dmulu.l Rm,Rn */ 755*fcf5ef2aSThomas Huth tcg_gen_mulu2_i32(cpu_macl, cpu_mach, REG(B7_4), REG(B11_8)); 756*fcf5ef2aSThomas Huth return; 757*fcf5ef2aSThomas Huth case 0x600e: /* exts.b Rm,Rn */ 758*fcf5ef2aSThomas Huth tcg_gen_ext8s_i32(REG(B11_8), REG(B7_4)); 759*fcf5ef2aSThomas Huth return; 760*fcf5ef2aSThomas Huth case 0x600f: /* exts.w Rm,Rn */ 761*fcf5ef2aSThomas Huth tcg_gen_ext16s_i32(REG(B11_8), REG(B7_4)); 762*fcf5ef2aSThomas Huth return; 763*fcf5ef2aSThomas Huth case 0x600c: /* extu.b Rm,Rn */ 764*fcf5ef2aSThomas Huth tcg_gen_ext8u_i32(REG(B11_8), REG(B7_4)); 765*fcf5ef2aSThomas Huth return; 766*fcf5ef2aSThomas Huth case 0x600d: /* extu.w Rm,Rn */ 767*fcf5ef2aSThomas Huth tcg_gen_ext16u_i32(REG(B11_8), REG(B7_4)); 768*fcf5ef2aSThomas Huth return; 769*fcf5ef2aSThomas Huth case 0x000f: /* mac.l @Rm+,@Rn+ */ 770*fcf5ef2aSThomas Huth { 771*fcf5ef2aSThomas Huth TCGv arg0, arg1; 772*fcf5ef2aSThomas Huth arg0 = tcg_temp_new(); 773*fcf5ef2aSThomas Huth tcg_gen_qemu_ld_i32(arg0, REG(B7_4), ctx->memidx, MO_TESL); 774*fcf5ef2aSThomas Huth arg1 = tcg_temp_new(); 775*fcf5ef2aSThomas Huth tcg_gen_qemu_ld_i32(arg1, REG(B11_8), ctx->memidx, MO_TESL); 776*fcf5ef2aSThomas Huth gen_helper_macl(cpu_env, arg0, arg1); 777*fcf5ef2aSThomas Huth tcg_temp_free(arg1); 778*fcf5ef2aSThomas Huth tcg_temp_free(arg0); 779*fcf5ef2aSThomas Huth tcg_gen_addi_i32(REG(B7_4), REG(B7_4), 4); 780*fcf5ef2aSThomas Huth tcg_gen_addi_i32(REG(B11_8), REG(B11_8), 4); 781*fcf5ef2aSThomas Huth } 782*fcf5ef2aSThomas Huth return; 783*fcf5ef2aSThomas Huth case 0x400f: /* mac.w @Rm+,@Rn+ */ 784*fcf5ef2aSThomas Huth { 785*fcf5ef2aSThomas Huth TCGv arg0, arg1; 786*fcf5ef2aSThomas Huth arg0 = tcg_temp_new(); 787*fcf5ef2aSThomas Huth tcg_gen_qemu_ld_i32(arg0, REG(B7_4), ctx->memidx, MO_TESL); 788*fcf5ef2aSThomas Huth arg1 = tcg_temp_new(); 789*fcf5ef2aSThomas Huth tcg_gen_qemu_ld_i32(arg1, REG(B11_8), ctx->memidx, MO_TESL); 790*fcf5ef2aSThomas Huth gen_helper_macw(cpu_env, arg0, arg1); 791*fcf5ef2aSThomas Huth tcg_temp_free(arg1); 792*fcf5ef2aSThomas Huth tcg_temp_free(arg0); 793*fcf5ef2aSThomas Huth tcg_gen_addi_i32(REG(B11_8), REG(B11_8), 2); 794*fcf5ef2aSThomas Huth tcg_gen_addi_i32(REG(B7_4), REG(B7_4), 2); 795*fcf5ef2aSThomas Huth } 796*fcf5ef2aSThomas Huth return; 797*fcf5ef2aSThomas Huth case 0x0007: /* mul.l Rm,Rn */ 798*fcf5ef2aSThomas Huth tcg_gen_mul_i32(cpu_macl, REG(B7_4), REG(B11_8)); 799*fcf5ef2aSThomas Huth return; 800*fcf5ef2aSThomas Huth case 0x200f: /* muls.w Rm,Rn */ 801*fcf5ef2aSThomas Huth { 802*fcf5ef2aSThomas Huth TCGv arg0, arg1; 803*fcf5ef2aSThomas Huth arg0 = tcg_temp_new(); 804*fcf5ef2aSThomas Huth tcg_gen_ext16s_i32(arg0, REG(B7_4)); 805*fcf5ef2aSThomas Huth arg1 = tcg_temp_new(); 806*fcf5ef2aSThomas Huth tcg_gen_ext16s_i32(arg1, REG(B11_8)); 807*fcf5ef2aSThomas Huth tcg_gen_mul_i32(cpu_macl, arg0, arg1); 808*fcf5ef2aSThomas Huth tcg_temp_free(arg1); 809*fcf5ef2aSThomas Huth tcg_temp_free(arg0); 810*fcf5ef2aSThomas Huth } 811*fcf5ef2aSThomas Huth return; 812*fcf5ef2aSThomas Huth case 0x200e: /* mulu.w Rm,Rn */ 813*fcf5ef2aSThomas Huth { 814*fcf5ef2aSThomas Huth TCGv arg0, arg1; 815*fcf5ef2aSThomas Huth arg0 = tcg_temp_new(); 816*fcf5ef2aSThomas Huth tcg_gen_ext16u_i32(arg0, REG(B7_4)); 817*fcf5ef2aSThomas Huth arg1 = tcg_temp_new(); 818*fcf5ef2aSThomas Huth tcg_gen_ext16u_i32(arg1, REG(B11_8)); 819*fcf5ef2aSThomas Huth tcg_gen_mul_i32(cpu_macl, arg0, arg1); 820*fcf5ef2aSThomas Huth tcg_temp_free(arg1); 821*fcf5ef2aSThomas Huth tcg_temp_free(arg0); 822*fcf5ef2aSThomas Huth } 823*fcf5ef2aSThomas Huth return; 824*fcf5ef2aSThomas Huth case 0x600b: /* neg Rm,Rn */ 825*fcf5ef2aSThomas Huth tcg_gen_neg_i32(REG(B11_8), REG(B7_4)); 826*fcf5ef2aSThomas Huth return; 827*fcf5ef2aSThomas Huth case 0x600a: /* negc Rm,Rn */ 828*fcf5ef2aSThomas Huth { 829*fcf5ef2aSThomas Huth TCGv t0 = tcg_const_i32(0); 830*fcf5ef2aSThomas Huth tcg_gen_add2_i32(REG(B11_8), cpu_sr_t, 831*fcf5ef2aSThomas Huth REG(B7_4), t0, cpu_sr_t, t0); 832*fcf5ef2aSThomas Huth tcg_gen_sub2_i32(REG(B11_8), cpu_sr_t, 833*fcf5ef2aSThomas Huth t0, t0, REG(B11_8), cpu_sr_t); 834*fcf5ef2aSThomas Huth tcg_gen_andi_i32(cpu_sr_t, cpu_sr_t, 1); 835*fcf5ef2aSThomas Huth tcg_temp_free(t0); 836*fcf5ef2aSThomas Huth } 837*fcf5ef2aSThomas Huth return; 838*fcf5ef2aSThomas Huth case 0x6007: /* not Rm,Rn */ 839*fcf5ef2aSThomas Huth tcg_gen_not_i32(REG(B11_8), REG(B7_4)); 840*fcf5ef2aSThomas Huth return; 841*fcf5ef2aSThomas Huth case 0x200b: /* or Rm,Rn */ 842*fcf5ef2aSThomas Huth tcg_gen_or_i32(REG(B11_8), REG(B11_8), REG(B7_4)); 843*fcf5ef2aSThomas Huth return; 844*fcf5ef2aSThomas Huth case 0x400c: /* shad Rm,Rn */ 845*fcf5ef2aSThomas Huth { 846*fcf5ef2aSThomas Huth TCGv t0 = tcg_temp_new(); 847*fcf5ef2aSThomas Huth TCGv t1 = tcg_temp_new(); 848*fcf5ef2aSThomas Huth TCGv t2 = tcg_temp_new(); 849*fcf5ef2aSThomas Huth 850*fcf5ef2aSThomas Huth tcg_gen_andi_i32(t0, REG(B7_4), 0x1f); 851*fcf5ef2aSThomas Huth 852*fcf5ef2aSThomas Huth /* positive case: shift to the left */ 853*fcf5ef2aSThomas Huth tcg_gen_shl_i32(t1, REG(B11_8), t0); 854*fcf5ef2aSThomas Huth 855*fcf5ef2aSThomas Huth /* negative case: shift to the right in two steps to 856*fcf5ef2aSThomas Huth correctly handle the -32 case */ 857*fcf5ef2aSThomas Huth tcg_gen_xori_i32(t0, t0, 0x1f); 858*fcf5ef2aSThomas Huth tcg_gen_sar_i32(t2, REG(B11_8), t0); 859*fcf5ef2aSThomas Huth tcg_gen_sari_i32(t2, t2, 1); 860*fcf5ef2aSThomas Huth 861*fcf5ef2aSThomas Huth /* select between the two cases */ 862*fcf5ef2aSThomas Huth tcg_gen_movi_i32(t0, 0); 863*fcf5ef2aSThomas Huth tcg_gen_movcond_i32(TCG_COND_GE, REG(B11_8), REG(B7_4), t0, t1, t2); 864*fcf5ef2aSThomas Huth 865*fcf5ef2aSThomas Huth tcg_temp_free(t0); 866*fcf5ef2aSThomas Huth tcg_temp_free(t1); 867*fcf5ef2aSThomas Huth tcg_temp_free(t2); 868*fcf5ef2aSThomas Huth } 869*fcf5ef2aSThomas Huth return; 870*fcf5ef2aSThomas Huth case 0x400d: /* shld Rm,Rn */ 871*fcf5ef2aSThomas Huth { 872*fcf5ef2aSThomas Huth TCGv t0 = tcg_temp_new(); 873*fcf5ef2aSThomas Huth TCGv t1 = tcg_temp_new(); 874*fcf5ef2aSThomas Huth TCGv t2 = tcg_temp_new(); 875*fcf5ef2aSThomas Huth 876*fcf5ef2aSThomas Huth tcg_gen_andi_i32(t0, REG(B7_4), 0x1f); 877*fcf5ef2aSThomas Huth 878*fcf5ef2aSThomas Huth /* positive case: shift to the left */ 879*fcf5ef2aSThomas Huth tcg_gen_shl_i32(t1, REG(B11_8), t0); 880*fcf5ef2aSThomas Huth 881*fcf5ef2aSThomas Huth /* negative case: shift to the right in two steps to 882*fcf5ef2aSThomas Huth correctly handle the -32 case */ 883*fcf5ef2aSThomas Huth tcg_gen_xori_i32(t0, t0, 0x1f); 884*fcf5ef2aSThomas Huth tcg_gen_shr_i32(t2, REG(B11_8), t0); 885*fcf5ef2aSThomas Huth tcg_gen_shri_i32(t2, t2, 1); 886*fcf5ef2aSThomas Huth 887*fcf5ef2aSThomas Huth /* select between the two cases */ 888*fcf5ef2aSThomas Huth tcg_gen_movi_i32(t0, 0); 889*fcf5ef2aSThomas Huth tcg_gen_movcond_i32(TCG_COND_GE, REG(B11_8), REG(B7_4), t0, t1, t2); 890*fcf5ef2aSThomas Huth 891*fcf5ef2aSThomas Huth tcg_temp_free(t0); 892*fcf5ef2aSThomas Huth tcg_temp_free(t1); 893*fcf5ef2aSThomas Huth tcg_temp_free(t2); 894*fcf5ef2aSThomas Huth } 895*fcf5ef2aSThomas Huth return; 896*fcf5ef2aSThomas Huth case 0x3008: /* sub Rm,Rn */ 897*fcf5ef2aSThomas Huth tcg_gen_sub_i32(REG(B11_8), REG(B11_8), REG(B7_4)); 898*fcf5ef2aSThomas Huth return; 899*fcf5ef2aSThomas Huth case 0x300a: /* subc Rm,Rn */ 900*fcf5ef2aSThomas Huth { 901*fcf5ef2aSThomas Huth TCGv t0, t1; 902*fcf5ef2aSThomas Huth t0 = tcg_const_tl(0); 903*fcf5ef2aSThomas Huth t1 = tcg_temp_new(); 904*fcf5ef2aSThomas Huth tcg_gen_add2_i32(t1, cpu_sr_t, cpu_sr_t, t0, REG(B7_4), t0); 905*fcf5ef2aSThomas Huth tcg_gen_sub2_i32(REG(B11_8), cpu_sr_t, 906*fcf5ef2aSThomas Huth REG(B11_8), t0, t1, cpu_sr_t); 907*fcf5ef2aSThomas Huth tcg_gen_andi_i32(cpu_sr_t, cpu_sr_t, 1); 908*fcf5ef2aSThomas Huth tcg_temp_free(t0); 909*fcf5ef2aSThomas Huth tcg_temp_free(t1); 910*fcf5ef2aSThomas Huth } 911*fcf5ef2aSThomas Huth return; 912*fcf5ef2aSThomas Huth case 0x300b: /* subv Rm,Rn */ 913*fcf5ef2aSThomas Huth { 914*fcf5ef2aSThomas Huth TCGv t0, t1, t2; 915*fcf5ef2aSThomas Huth t0 = tcg_temp_new(); 916*fcf5ef2aSThomas Huth tcg_gen_sub_i32(t0, REG(B11_8), REG(B7_4)); 917*fcf5ef2aSThomas Huth t1 = tcg_temp_new(); 918*fcf5ef2aSThomas Huth tcg_gen_xor_i32(t1, t0, REG(B7_4)); 919*fcf5ef2aSThomas Huth t2 = tcg_temp_new(); 920*fcf5ef2aSThomas Huth tcg_gen_xor_i32(t2, REG(B11_8), REG(B7_4)); 921*fcf5ef2aSThomas Huth tcg_gen_and_i32(t1, t1, t2); 922*fcf5ef2aSThomas Huth tcg_temp_free(t2); 923*fcf5ef2aSThomas Huth tcg_gen_shri_i32(cpu_sr_t, t1, 31); 924*fcf5ef2aSThomas Huth tcg_temp_free(t1); 925*fcf5ef2aSThomas Huth tcg_gen_mov_i32(REG(B11_8), t0); 926*fcf5ef2aSThomas Huth tcg_temp_free(t0); 927*fcf5ef2aSThomas Huth } 928*fcf5ef2aSThomas Huth return; 929*fcf5ef2aSThomas Huth case 0x2008: /* tst Rm,Rn */ 930*fcf5ef2aSThomas Huth { 931*fcf5ef2aSThomas Huth TCGv val = tcg_temp_new(); 932*fcf5ef2aSThomas Huth tcg_gen_and_i32(val, REG(B7_4), REG(B11_8)); 933*fcf5ef2aSThomas Huth tcg_gen_setcondi_i32(TCG_COND_EQ, cpu_sr_t, val, 0); 934*fcf5ef2aSThomas Huth tcg_temp_free(val); 935*fcf5ef2aSThomas Huth } 936*fcf5ef2aSThomas Huth return; 937*fcf5ef2aSThomas Huth case 0x200a: /* xor Rm,Rn */ 938*fcf5ef2aSThomas Huth tcg_gen_xor_i32(REG(B11_8), REG(B11_8), REG(B7_4)); 939*fcf5ef2aSThomas Huth return; 940*fcf5ef2aSThomas Huth case 0xf00c: /* fmov {F,D,X}Rm,{F,D,X}Rn - FPSCR: Nothing */ 941*fcf5ef2aSThomas Huth CHECK_FPU_ENABLED 942*fcf5ef2aSThomas Huth if (ctx->flags & FPSCR_SZ) { 943*fcf5ef2aSThomas Huth TCGv_i64 fp = tcg_temp_new_i64(); 944*fcf5ef2aSThomas Huth gen_load_fpr64(fp, XREG(B7_4)); 945*fcf5ef2aSThomas Huth gen_store_fpr64(fp, XREG(B11_8)); 946*fcf5ef2aSThomas Huth tcg_temp_free_i64(fp); 947*fcf5ef2aSThomas Huth } else { 948*fcf5ef2aSThomas Huth tcg_gen_mov_i32(cpu_fregs[FREG(B11_8)], cpu_fregs[FREG(B7_4)]); 949*fcf5ef2aSThomas Huth } 950*fcf5ef2aSThomas Huth return; 951*fcf5ef2aSThomas Huth case 0xf00a: /* fmov {F,D,X}Rm,@Rn - FPSCR: Nothing */ 952*fcf5ef2aSThomas Huth CHECK_FPU_ENABLED 953*fcf5ef2aSThomas Huth if (ctx->flags & FPSCR_SZ) { 954*fcf5ef2aSThomas Huth TCGv addr_hi = tcg_temp_new(); 955*fcf5ef2aSThomas Huth int fr = XREG(B7_4); 956*fcf5ef2aSThomas Huth tcg_gen_addi_i32(addr_hi, REG(B11_8), 4); 957*fcf5ef2aSThomas Huth tcg_gen_qemu_st_i32(cpu_fregs[fr], REG(B11_8), 958*fcf5ef2aSThomas Huth ctx->memidx, MO_TEUL); 959*fcf5ef2aSThomas Huth tcg_gen_qemu_st_i32(cpu_fregs[fr+1], addr_hi, 960*fcf5ef2aSThomas Huth ctx->memidx, MO_TEUL); 961*fcf5ef2aSThomas Huth tcg_temp_free(addr_hi); 962*fcf5ef2aSThomas Huth } else { 963*fcf5ef2aSThomas Huth tcg_gen_qemu_st_i32(cpu_fregs[FREG(B7_4)], REG(B11_8), 964*fcf5ef2aSThomas Huth ctx->memidx, MO_TEUL); 965*fcf5ef2aSThomas Huth } 966*fcf5ef2aSThomas Huth return; 967*fcf5ef2aSThomas Huth case 0xf008: /* fmov @Rm,{F,D,X}Rn - FPSCR: Nothing */ 968*fcf5ef2aSThomas Huth CHECK_FPU_ENABLED 969*fcf5ef2aSThomas Huth if (ctx->flags & FPSCR_SZ) { 970*fcf5ef2aSThomas Huth TCGv addr_hi = tcg_temp_new(); 971*fcf5ef2aSThomas Huth int fr = XREG(B11_8); 972*fcf5ef2aSThomas Huth tcg_gen_addi_i32(addr_hi, REG(B7_4), 4); 973*fcf5ef2aSThomas Huth tcg_gen_qemu_ld_i32(cpu_fregs[fr], REG(B7_4), ctx->memidx, MO_TEUL); 974*fcf5ef2aSThomas Huth tcg_gen_qemu_ld_i32(cpu_fregs[fr+1], addr_hi, ctx->memidx, MO_TEUL); 975*fcf5ef2aSThomas Huth tcg_temp_free(addr_hi); 976*fcf5ef2aSThomas Huth } else { 977*fcf5ef2aSThomas Huth tcg_gen_qemu_ld_i32(cpu_fregs[FREG(B11_8)], REG(B7_4), 978*fcf5ef2aSThomas Huth ctx->memidx, MO_TEUL); 979*fcf5ef2aSThomas Huth } 980*fcf5ef2aSThomas Huth return; 981*fcf5ef2aSThomas Huth case 0xf009: /* fmov @Rm+,{F,D,X}Rn - FPSCR: Nothing */ 982*fcf5ef2aSThomas Huth CHECK_FPU_ENABLED 983*fcf5ef2aSThomas Huth if (ctx->flags & FPSCR_SZ) { 984*fcf5ef2aSThomas Huth TCGv addr_hi = tcg_temp_new(); 985*fcf5ef2aSThomas Huth int fr = XREG(B11_8); 986*fcf5ef2aSThomas Huth tcg_gen_addi_i32(addr_hi, REG(B7_4), 4); 987*fcf5ef2aSThomas Huth tcg_gen_qemu_ld_i32(cpu_fregs[fr], REG(B7_4), ctx->memidx, MO_TEUL); 988*fcf5ef2aSThomas Huth tcg_gen_qemu_ld_i32(cpu_fregs[fr+1], addr_hi, ctx->memidx, MO_TEUL); 989*fcf5ef2aSThomas Huth tcg_gen_addi_i32(REG(B7_4), REG(B7_4), 8); 990*fcf5ef2aSThomas Huth tcg_temp_free(addr_hi); 991*fcf5ef2aSThomas Huth } else { 992*fcf5ef2aSThomas Huth tcg_gen_qemu_ld_i32(cpu_fregs[FREG(B11_8)], REG(B7_4), 993*fcf5ef2aSThomas Huth ctx->memidx, MO_TEUL); 994*fcf5ef2aSThomas Huth tcg_gen_addi_i32(REG(B7_4), REG(B7_4), 4); 995*fcf5ef2aSThomas Huth } 996*fcf5ef2aSThomas Huth return; 997*fcf5ef2aSThomas Huth case 0xf00b: /* fmov {F,D,X}Rm,@-Rn - FPSCR: Nothing */ 998*fcf5ef2aSThomas Huth CHECK_FPU_ENABLED 999*fcf5ef2aSThomas Huth TCGv addr = tcg_temp_new_i32(); 1000*fcf5ef2aSThomas Huth tcg_gen_subi_i32(addr, REG(B11_8), 4); 1001*fcf5ef2aSThomas Huth if (ctx->flags & FPSCR_SZ) { 1002*fcf5ef2aSThomas Huth int fr = XREG(B7_4); 1003*fcf5ef2aSThomas Huth tcg_gen_qemu_st_i32(cpu_fregs[fr+1], addr, ctx->memidx, MO_TEUL); 1004*fcf5ef2aSThomas Huth tcg_gen_subi_i32(addr, addr, 4); 1005*fcf5ef2aSThomas Huth tcg_gen_qemu_st_i32(cpu_fregs[fr], addr, ctx->memidx, MO_TEUL); 1006*fcf5ef2aSThomas Huth } else { 1007*fcf5ef2aSThomas Huth tcg_gen_qemu_st_i32(cpu_fregs[FREG(B7_4)], addr, 1008*fcf5ef2aSThomas Huth ctx->memidx, MO_TEUL); 1009*fcf5ef2aSThomas Huth } 1010*fcf5ef2aSThomas Huth tcg_gen_mov_i32(REG(B11_8), addr); 1011*fcf5ef2aSThomas Huth tcg_temp_free(addr); 1012*fcf5ef2aSThomas Huth return; 1013*fcf5ef2aSThomas Huth case 0xf006: /* fmov @(R0,Rm),{F,D,X}Rm - FPSCR: Nothing */ 1014*fcf5ef2aSThomas Huth CHECK_FPU_ENABLED 1015*fcf5ef2aSThomas Huth { 1016*fcf5ef2aSThomas Huth TCGv addr = tcg_temp_new_i32(); 1017*fcf5ef2aSThomas Huth tcg_gen_add_i32(addr, REG(B7_4), REG(0)); 1018*fcf5ef2aSThomas Huth if (ctx->flags & FPSCR_SZ) { 1019*fcf5ef2aSThomas Huth int fr = XREG(B11_8); 1020*fcf5ef2aSThomas Huth tcg_gen_qemu_ld_i32(cpu_fregs[fr], addr, 1021*fcf5ef2aSThomas Huth ctx->memidx, MO_TEUL); 1022*fcf5ef2aSThomas Huth tcg_gen_addi_i32(addr, addr, 4); 1023*fcf5ef2aSThomas Huth tcg_gen_qemu_ld_i32(cpu_fregs[fr+1], addr, 1024*fcf5ef2aSThomas Huth ctx->memidx, MO_TEUL); 1025*fcf5ef2aSThomas Huth } else { 1026*fcf5ef2aSThomas Huth tcg_gen_qemu_ld_i32(cpu_fregs[FREG(B11_8)], addr, 1027*fcf5ef2aSThomas Huth ctx->memidx, MO_TEUL); 1028*fcf5ef2aSThomas Huth } 1029*fcf5ef2aSThomas Huth tcg_temp_free(addr); 1030*fcf5ef2aSThomas Huth } 1031*fcf5ef2aSThomas Huth return; 1032*fcf5ef2aSThomas Huth case 0xf007: /* fmov {F,D,X}Rn,@(R0,Rn) - FPSCR: Nothing */ 1033*fcf5ef2aSThomas Huth CHECK_FPU_ENABLED 1034*fcf5ef2aSThomas Huth { 1035*fcf5ef2aSThomas Huth TCGv addr = tcg_temp_new(); 1036*fcf5ef2aSThomas Huth tcg_gen_add_i32(addr, REG(B11_8), REG(0)); 1037*fcf5ef2aSThomas Huth if (ctx->flags & FPSCR_SZ) { 1038*fcf5ef2aSThomas Huth int fr = XREG(B7_4); 1039*fcf5ef2aSThomas Huth tcg_gen_qemu_ld_i32(cpu_fregs[fr], addr, 1040*fcf5ef2aSThomas Huth ctx->memidx, MO_TEUL); 1041*fcf5ef2aSThomas Huth tcg_gen_addi_i32(addr, addr, 4); 1042*fcf5ef2aSThomas Huth tcg_gen_qemu_ld_i32(cpu_fregs[fr+1], addr, 1043*fcf5ef2aSThomas Huth ctx->memidx, MO_TEUL); 1044*fcf5ef2aSThomas Huth } else { 1045*fcf5ef2aSThomas Huth tcg_gen_qemu_st_i32(cpu_fregs[FREG(B7_4)], addr, 1046*fcf5ef2aSThomas Huth ctx->memidx, MO_TEUL); 1047*fcf5ef2aSThomas Huth } 1048*fcf5ef2aSThomas Huth tcg_temp_free(addr); 1049*fcf5ef2aSThomas Huth } 1050*fcf5ef2aSThomas Huth return; 1051*fcf5ef2aSThomas Huth case 0xf000: /* fadd Rm,Rn - FPSCR: R[PR,Enable.O/U/I]/W[Cause,Flag] */ 1052*fcf5ef2aSThomas Huth case 0xf001: /* fsub Rm,Rn - FPSCR: R[PR,Enable.O/U/I]/W[Cause,Flag] */ 1053*fcf5ef2aSThomas Huth case 0xf002: /* fmul Rm,Rn - FPSCR: R[PR,Enable.O/U/I]/W[Cause,Flag] */ 1054*fcf5ef2aSThomas Huth case 0xf003: /* fdiv Rm,Rn - FPSCR: R[PR,Enable.O/U/I]/W[Cause,Flag] */ 1055*fcf5ef2aSThomas Huth case 0xf004: /* fcmp/eq Rm,Rn - FPSCR: R[PR,Enable.V]/W[Cause,Flag] */ 1056*fcf5ef2aSThomas Huth case 0xf005: /* fcmp/gt Rm,Rn - FPSCR: R[PR,Enable.V]/W[Cause,Flag] */ 1057*fcf5ef2aSThomas Huth { 1058*fcf5ef2aSThomas Huth CHECK_FPU_ENABLED 1059*fcf5ef2aSThomas Huth if (ctx->flags & FPSCR_PR) { 1060*fcf5ef2aSThomas Huth TCGv_i64 fp0, fp1; 1061*fcf5ef2aSThomas Huth 1062*fcf5ef2aSThomas Huth if (ctx->opcode & 0x0110) 1063*fcf5ef2aSThomas Huth break; /* illegal instruction */ 1064*fcf5ef2aSThomas Huth fp0 = tcg_temp_new_i64(); 1065*fcf5ef2aSThomas Huth fp1 = tcg_temp_new_i64(); 1066*fcf5ef2aSThomas Huth gen_load_fpr64(fp0, DREG(B11_8)); 1067*fcf5ef2aSThomas Huth gen_load_fpr64(fp1, DREG(B7_4)); 1068*fcf5ef2aSThomas Huth switch (ctx->opcode & 0xf00f) { 1069*fcf5ef2aSThomas Huth case 0xf000: /* fadd Rm,Rn */ 1070*fcf5ef2aSThomas Huth gen_helper_fadd_DT(fp0, cpu_env, fp0, fp1); 1071*fcf5ef2aSThomas Huth break; 1072*fcf5ef2aSThomas Huth case 0xf001: /* fsub Rm,Rn */ 1073*fcf5ef2aSThomas Huth gen_helper_fsub_DT(fp0, cpu_env, fp0, fp1); 1074*fcf5ef2aSThomas Huth break; 1075*fcf5ef2aSThomas Huth case 0xf002: /* fmul Rm,Rn */ 1076*fcf5ef2aSThomas Huth gen_helper_fmul_DT(fp0, cpu_env, fp0, fp1); 1077*fcf5ef2aSThomas Huth break; 1078*fcf5ef2aSThomas Huth case 0xf003: /* fdiv Rm,Rn */ 1079*fcf5ef2aSThomas Huth gen_helper_fdiv_DT(fp0, cpu_env, fp0, fp1); 1080*fcf5ef2aSThomas Huth break; 1081*fcf5ef2aSThomas Huth case 0xf004: /* fcmp/eq Rm,Rn */ 1082*fcf5ef2aSThomas Huth gen_helper_fcmp_eq_DT(cpu_env, fp0, fp1); 1083*fcf5ef2aSThomas Huth return; 1084*fcf5ef2aSThomas Huth case 0xf005: /* fcmp/gt Rm,Rn */ 1085*fcf5ef2aSThomas Huth gen_helper_fcmp_gt_DT(cpu_env, fp0, fp1); 1086*fcf5ef2aSThomas Huth return; 1087*fcf5ef2aSThomas Huth } 1088*fcf5ef2aSThomas Huth gen_store_fpr64(fp0, DREG(B11_8)); 1089*fcf5ef2aSThomas Huth tcg_temp_free_i64(fp0); 1090*fcf5ef2aSThomas Huth tcg_temp_free_i64(fp1); 1091*fcf5ef2aSThomas Huth } else { 1092*fcf5ef2aSThomas Huth switch (ctx->opcode & 0xf00f) { 1093*fcf5ef2aSThomas Huth case 0xf000: /* fadd Rm,Rn */ 1094*fcf5ef2aSThomas Huth gen_helper_fadd_FT(cpu_fregs[FREG(B11_8)], cpu_env, 1095*fcf5ef2aSThomas Huth cpu_fregs[FREG(B11_8)], 1096*fcf5ef2aSThomas Huth cpu_fregs[FREG(B7_4)]); 1097*fcf5ef2aSThomas Huth break; 1098*fcf5ef2aSThomas Huth case 0xf001: /* fsub Rm,Rn */ 1099*fcf5ef2aSThomas Huth gen_helper_fsub_FT(cpu_fregs[FREG(B11_8)], cpu_env, 1100*fcf5ef2aSThomas Huth cpu_fregs[FREG(B11_8)], 1101*fcf5ef2aSThomas Huth cpu_fregs[FREG(B7_4)]); 1102*fcf5ef2aSThomas Huth break; 1103*fcf5ef2aSThomas Huth case 0xf002: /* fmul Rm,Rn */ 1104*fcf5ef2aSThomas Huth gen_helper_fmul_FT(cpu_fregs[FREG(B11_8)], cpu_env, 1105*fcf5ef2aSThomas Huth cpu_fregs[FREG(B11_8)], 1106*fcf5ef2aSThomas Huth cpu_fregs[FREG(B7_4)]); 1107*fcf5ef2aSThomas Huth break; 1108*fcf5ef2aSThomas Huth case 0xf003: /* fdiv Rm,Rn */ 1109*fcf5ef2aSThomas Huth gen_helper_fdiv_FT(cpu_fregs[FREG(B11_8)], cpu_env, 1110*fcf5ef2aSThomas Huth cpu_fregs[FREG(B11_8)], 1111*fcf5ef2aSThomas Huth cpu_fregs[FREG(B7_4)]); 1112*fcf5ef2aSThomas Huth break; 1113*fcf5ef2aSThomas Huth case 0xf004: /* fcmp/eq Rm,Rn */ 1114*fcf5ef2aSThomas Huth gen_helper_fcmp_eq_FT(cpu_env, cpu_fregs[FREG(B11_8)], 1115*fcf5ef2aSThomas Huth cpu_fregs[FREG(B7_4)]); 1116*fcf5ef2aSThomas Huth return; 1117*fcf5ef2aSThomas Huth case 0xf005: /* fcmp/gt Rm,Rn */ 1118*fcf5ef2aSThomas Huth gen_helper_fcmp_gt_FT(cpu_env, cpu_fregs[FREG(B11_8)], 1119*fcf5ef2aSThomas Huth cpu_fregs[FREG(B7_4)]); 1120*fcf5ef2aSThomas Huth return; 1121*fcf5ef2aSThomas Huth } 1122*fcf5ef2aSThomas Huth } 1123*fcf5ef2aSThomas Huth } 1124*fcf5ef2aSThomas Huth return; 1125*fcf5ef2aSThomas Huth case 0xf00e: /* fmac FR0,RM,Rn */ 1126*fcf5ef2aSThomas Huth { 1127*fcf5ef2aSThomas Huth CHECK_FPU_ENABLED 1128*fcf5ef2aSThomas Huth if (ctx->flags & FPSCR_PR) { 1129*fcf5ef2aSThomas Huth break; /* illegal instruction */ 1130*fcf5ef2aSThomas Huth } else { 1131*fcf5ef2aSThomas Huth gen_helper_fmac_FT(cpu_fregs[FREG(B11_8)], cpu_env, 1132*fcf5ef2aSThomas Huth cpu_fregs[FREG(0)], cpu_fregs[FREG(B7_4)], 1133*fcf5ef2aSThomas Huth cpu_fregs[FREG(B11_8)]); 1134*fcf5ef2aSThomas Huth return; 1135*fcf5ef2aSThomas Huth } 1136*fcf5ef2aSThomas Huth } 1137*fcf5ef2aSThomas Huth } 1138*fcf5ef2aSThomas Huth 1139*fcf5ef2aSThomas Huth switch (ctx->opcode & 0xff00) { 1140*fcf5ef2aSThomas Huth case 0xc900: /* and #imm,R0 */ 1141*fcf5ef2aSThomas Huth tcg_gen_andi_i32(REG(0), REG(0), B7_0); 1142*fcf5ef2aSThomas Huth return; 1143*fcf5ef2aSThomas Huth case 0xcd00: /* and.b #imm,@(R0,GBR) */ 1144*fcf5ef2aSThomas Huth { 1145*fcf5ef2aSThomas Huth TCGv addr, val; 1146*fcf5ef2aSThomas Huth addr = tcg_temp_new(); 1147*fcf5ef2aSThomas Huth tcg_gen_add_i32(addr, REG(0), cpu_gbr); 1148*fcf5ef2aSThomas Huth val = tcg_temp_new(); 1149*fcf5ef2aSThomas Huth tcg_gen_qemu_ld_i32(val, addr, ctx->memidx, MO_UB); 1150*fcf5ef2aSThomas Huth tcg_gen_andi_i32(val, val, B7_0); 1151*fcf5ef2aSThomas Huth tcg_gen_qemu_st_i32(val, addr, ctx->memidx, MO_UB); 1152*fcf5ef2aSThomas Huth tcg_temp_free(val); 1153*fcf5ef2aSThomas Huth tcg_temp_free(addr); 1154*fcf5ef2aSThomas Huth } 1155*fcf5ef2aSThomas Huth return; 1156*fcf5ef2aSThomas Huth case 0x8b00: /* bf label */ 1157*fcf5ef2aSThomas Huth CHECK_NOT_DELAY_SLOT 1158*fcf5ef2aSThomas Huth gen_conditional_jump(ctx, ctx->pc + 2, 1159*fcf5ef2aSThomas Huth ctx->pc + 4 + B7_0s * 2); 1160*fcf5ef2aSThomas Huth ctx->bstate = BS_BRANCH; 1161*fcf5ef2aSThomas Huth return; 1162*fcf5ef2aSThomas Huth case 0x8f00: /* bf/s label */ 1163*fcf5ef2aSThomas Huth CHECK_NOT_DELAY_SLOT 1164*fcf5ef2aSThomas Huth gen_branch_slot(ctx->delayed_pc = ctx->pc + 4 + B7_0s * 2, 0); 1165*fcf5ef2aSThomas Huth ctx->flags |= DELAY_SLOT_CONDITIONAL; 1166*fcf5ef2aSThomas Huth return; 1167*fcf5ef2aSThomas Huth case 0x8900: /* bt label */ 1168*fcf5ef2aSThomas Huth CHECK_NOT_DELAY_SLOT 1169*fcf5ef2aSThomas Huth gen_conditional_jump(ctx, ctx->pc + 4 + B7_0s * 2, 1170*fcf5ef2aSThomas Huth ctx->pc + 2); 1171*fcf5ef2aSThomas Huth ctx->bstate = BS_BRANCH; 1172*fcf5ef2aSThomas Huth return; 1173*fcf5ef2aSThomas Huth case 0x8d00: /* bt/s label */ 1174*fcf5ef2aSThomas Huth CHECK_NOT_DELAY_SLOT 1175*fcf5ef2aSThomas Huth gen_branch_slot(ctx->delayed_pc = ctx->pc + 4 + B7_0s * 2, 1); 1176*fcf5ef2aSThomas Huth ctx->flags |= DELAY_SLOT_CONDITIONAL; 1177*fcf5ef2aSThomas Huth return; 1178*fcf5ef2aSThomas Huth case 0x8800: /* cmp/eq #imm,R0 */ 1179*fcf5ef2aSThomas Huth tcg_gen_setcondi_i32(TCG_COND_EQ, cpu_sr_t, REG(0), B7_0s); 1180*fcf5ef2aSThomas Huth return; 1181*fcf5ef2aSThomas Huth case 0xc400: /* mov.b @(disp,GBR),R0 */ 1182*fcf5ef2aSThomas Huth { 1183*fcf5ef2aSThomas Huth TCGv addr = tcg_temp_new(); 1184*fcf5ef2aSThomas Huth tcg_gen_addi_i32(addr, cpu_gbr, B7_0); 1185*fcf5ef2aSThomas Huth tcg_gen_qemu_ld_i32(REG(0), addr, ctx->memidx, MO_SB); 1186*fcf5ef2aSThomas Huth tcg_temp_free(addr); 1187*fcf5ef2aSThomas Huth } 1188*fcf5ef2aSThomas Huth return; 1189*fcf5ef2aSThomas Huth case 0xc500: /* mov.w @(disp,GBR),R0 */ 1190*fcf5ef2aSThomas Huth { 1191*fcf5ef2aSThomas Huth TCGv addr = tcg_temp_new(); 1192*fcf5ef2aSThomas Huth tcg_gen_addi_i32(addr, cpu_gbr, B7_0 * 2); 1193*fcf5ef2aSThomas Huth tcg_gen_qemu_ld_i32(REG(0), addr, ctx->memidx, MO_TESW); 1194*fcf5ef2aSThomas Huth tcg_temp_free(addr); 1195*fcf5ef2aSThomas Huth } 1196*fcf5ef2aSThomas Huth return; 1197*fcf5ef2aSThomas Huth case 0xc600: /* mov.l @(disp,GBR),R0 */ 1198*fcf5ef2aSThomas Huth { 1199*fcf5ef2aSThomas Huth TCGv addr = tcg_temp_new(); 1200*fcf5ef2aSThomas Huth tcg_gen_addi_i32(addr, cpu_gbr, B7_0 * 4); 1201*fcf5ef2aSThomas Huth tcg_gen_qemu_ld_i32(REG(0), addr, ctx->memidx, MO_TESL); 1202*fcf5ef2aSThomas Huth tcg_temp_free(addr); 1203*fcf5ef2aSThomas Huth } 1204*fcf5ef2aSThomas Huth return; 1205*fcf5ef2aSThomas Huth case 0xc000: /* mov.b R0,@(disp,GBR) */ 1206*fcf5ef2aSThomas Huth { 1207*fcf5ef2aSThomas Huth TCGv addr = tcg_temp_new(); 1208*fcf5ef2aSThomas Huth tcg_gen_addi_i32(addr, cpu_gbr, B7_0); 1209*fcf5ef2aSThomas Huth tcg_gen_qemu_st_i32(REG(0), addr, ctx->memidx, MO_UB); 1210*fcf5ef2aSThomas Huth tcg_temp_free(addr); 1211*fcf5ef2aSThomas Huth } 1212*fcf5ef2aSThomas Huth return; 1213*fcf5ef2aSThomas Huth case 0xc100: /* mov.w R0,@(disp,GBR) */ 1214*fcf5ef2aSThomas Huth { 1215*fcf5ef2aSThomas Huth TCGv addr = tcg_temp_new(); 1216*fcf5ef2aSThomas Huth tcg_gen_addi_i32(addr, cpu_gbr, B7_0 * 2); 1217*fcf5ef2aSThomas Huth tcg_gen_qemu_st_i32(REG(0), addr, ctx->memidx, MO_TEUW); 1218*fcf5ef2aSThomas Huth tcg_temp_free(addr); 1219*fcf5ef2aSThomas Huth } 1220*fcf5ef2aSThomas Huth return; 1221*fcf5ef2aSThomas Huth case 0xc200: /* mov.l R0,@(disp,GBR) */ 1222*fcf5ef2aSThomas Huth { 1223*fcf5ef2aSThomas Huth TCGv addr = tcg_temp_new(); 1224*fcf5ef2aSThomas Huth tcg_gen_addi_i32(addr, cpu_gbr, B7_0 * 4); 1225*fcf5ef2aSThomas Huth tcg_gen_qemu_st_i32(REG(0), addr, ctx->memidx, MO_TEUL); 1226*fcf5ef2aSThomas Huth tcg_temp_free(addr); 1227*fcf5ef2aSThomas Huth } 1228*fcf5ef2aSThomas Huth return; 1229*fcf5ef2aSThomas Huth case 0x8000: /* mov.b R0,@(disp,Rn) */ 1230*fcf5ef2aSThomas Huth { 1231*fcf5ef2aSThomas Huth TCGv addr = tcg_temp_new(); 1232*fcf5ef2aSThomas Huth tcg_gen_addi_i32(addr, REG(B7_4), B3_0); 1233*fcf5ef2aSThomas Huth tcg_gen_qemu_st_i32(REG(0), addr, ctx->memidx, MO_UB); 1234*fcf5ef2aSThomas Huth tcg_temp_free(addr); 1235*fcf5ef2aSThomas Huth } 1236*fcf5ef2aSThomas Huth return; 1237*fcf5ef2aSThomas Huth case 0x8100: /* mov.w R0,@(disp,Rn) */ 1238*fcf5ef2aSThomas Huth { 1239*fcf5ef2aSThomas Huth TCGv addr = tcg_temp_new(); 1240*fcf5ef2aSThomas Huth tcg_gen_addi_i32(addr, REG(B7_4), B3_0 * 2); 1241*fcf5ef2aSThomas Huth tcg_gen_qemu_st_i32(REG(0), addr, ctx->memidx, MO_TEUW); 1242*fcf5ef2aSThomas Huth tcg_temp_free(addr); 1243*fcf5ef2aSThomas Huth } 1244*fcf5ef2aSThomas Huth return; 1245*fcf5ef2aSThomas Huth case 0x8400: /* mov.b @(disp,Rn),R0 */ 1246*fcf5ef2aSThomas Huth { 1247*fcf5ef2aSThomas Huth TCGv addr = tcg_temp_new(); 1248*fcf5ef2aSThomas Huth tcg_gen_addi_i32(addr, REG(B7_4), B3_0); 1249*fcf5ef2aSThomas Huth tcg_gen_qemu_ld_i32(REG(0), addr, ctx->memidx, MO_SB); 1250*fcf5ef2aSThomas Huth tcg_temp_free(addr); 1251*fcf5ef2aSThomas Huth } 1252*fcf5ef2aSThomas Huth return; 1253*fcf5ef2aSThomas Huth case 0x8500: /* mov.w @(disp,Rn),R0 */ 1254*fcf5ef2aSThomas Huth { 1255*fcf5ef2aSThomas Huth TCGv addr = tcg_temp_new(); 1256*fcf5ef2aSThomas Huth tcg_gen_addi_i32(addr, REG(B7_4), B3_0 * 2); 1257*fcf5ef2aSThomas Huth tcg_gen_qemu_ld_i32(REG(0), addr, ctx->memidx, MO_TESW); 1258*fcf5ef2aSThomas Huth tcg_temp_free(addr); 1259*fcf5ef2aSThomas Huth } 1260*fcf5ef2aSThomas Huth return; 1261*fcf5ef2aSThomas Huth case 0xc700: /* mova @(disp,PC),R0 */ 1262*fcf5ef2aSThomas Huth tcg_gen_movi_i32(REG(0), ((ctx->pc & 0xfffffffc) + 4 + B7_0 * 4) & ~3); 1263*fcf5ef2aSThomas Huth return; 1264*fcf5ef2aSThomas Huth case 0xcb00: /* or #imm,R0 */ 1265*fcf5ef2aSThomas Huth tcg_gen_ori_i32(REG(0), REG(0), B7_0); 1266*fcf5ef2aSThomas Huth return; 1267*fcf5ef2aSThomas Huth case 0xcf00: /* or.b #imm,@(R0,GBR) */ 1268*fcf5ef2aSThomas Huth { 1269*fcf5ef2aSThomas Huth TCGv addr, val; 1270*fcf5ef2aSThomas Huth addr = tcg_temp_new(); 1271*fcf5ef2aSThomas Huth tcg_gen_add_i32(addr, REG(0), cpu_gbr); 1272*fcf5ef2aSThomas Huth val = tcg_temp_new(); 1273*fcf5ef2aSThomas Huth tcg_gen_qemu_ld_i32(val, addr, ctx->memidx, MO_UB); 1274*fcf5ef2aSThomas Huth tcg_gen_ori_i32(val, val, B7_0); 1275*fcf5ef2aSThomas Huth tcg_gen_qemu_st_i32(val, addr, ctx->memidx, MO_UB); 1276*fcf5ef2aSThomas Huth tcg_temp_free(val); 1277*fcf5ef2aSThomas Huth tcg_temp_free(addr); 1278*fcf5ef2aSThomas Huth } 1279*fcf5ef2aSThomas Huth return; 1280*fcf5ef2aSThomas Huth case 0xc300: /* trapa #imm */ 1281*fcf5ef2aSThomas Huth { 1282*fcf5ef2aSThomas Huth TCGv imm; 1283*fcf5ef2aSThomas Huth CHECK_NOT_DELAY_SLOT 1284*fcf5ef2aSThomas Huth tcg_gen_movi_i32(cpu_pc, ctx->pc); 1285*fcf5ef2aSThomas Huth imm = tcg_const_i32(B7_0); 1286*fcf5ef2aSThomas Huth gen_helper_trapa(cpu_env, imm); 1287*fcf5ef2aSThomas Huth tcg_temp_free(imm); 1288*fcf5ef2aSThomas Huth ctx->bstate = BS_BRANCH; 1289*fcf5ef2aSThomas Huth } 1290*fcf5ef2aSThomas Huth return; 1291*fcf5ef2aSThomas Huth case 0xc800: /* tst #imm,R0 */ 1292*fcf5ef2aSThomas Huth { 1293*fcf5ef2aSThomas Huth TCGv val = tcg_temp_new(); 1294*fcf5ef2aSThomas Huth tcg_gen_andi_i32(val, REG(0), B7_0); 1295*fcf5ef2aSThomas Huth tcg_gen_setcondi_i32(TCG_COND_EQ, cpu_sr_t, val, 0); 1296*fcf5ef2aSThomas Huth tcg_temp_free(val); 1297*fcf5ef2aSThomas Huth } 1298*fcf5ef2aSThomas Huth return; 1299*fcf5ef2aSThomas Huth case 0xcc00: /* tst.b #imm,@(R0,GBR) */ 1300*fcf5ef2aSThomas Huth { 1301*fcf5ef2aSThomas Huth TCGv val = tcg_temp_new(); 1302*fcf5ef2aSThomas Huth tcg_gen_add_i32(val, REG(0), cpu_gbr); 1303*fcf5ef2aSThomas Huth tcg_gen_qemu_ld_i32(val, val, ctx->memidx, MO_UB); 1304*fcf5ef2aSThomas Huth tcg_gen_andi_i32(val, val, B7_0); 1305*fcf5ef2aSThomas Huth tcg_gen_setcondi_i32(TCG_COND_EQ, cpu_sr_t, val, 0); 1306*fcf5ef2aSThomas Huth tcg_temp_free(val); 1307*fcf5ef2aSThomas Huth } 1308*fcf5ef2aSThomas Huth return; 1309*fcf5ef2aSThomas Huth case 0xca00: /* xor #imm,R0 */ 1310*fcf5ef2aSThomas Huth tcg_gen_xori_i32(REG(0), REG(0), B7_0); 1311*fcf5ef2aSThomas Huth return; 1312*fcf5ef2aSThomas Huth case 0xce00: /* xor.b #imm,@(R0,GBR) */ 1313*fcf5ef2aSThomas Huth { 1314*fcf5ef2aSThomas Huth TCGv addr, val; 1315*fcf5ef2aSThomas Huth addr = tcg_temp_new(); 1316*fcf5ef2aSThomas Huth tcg_gen_add_i32(addr, REG(0), cpu_gbr); 1317*fcf5ef2aSThomas Huth val = tcg_temp_new(); 1318*fcf5ef2aSThomas Huth tcg_gen_qemu_ld_i32(val, addr, ctx->memidx, MO_UB); 1319*fcf5ef2aSThomas Huth tcg_gen_xori_i32(val, val, B7_0); 1320*fcf5ef2aSThomas Huth tcg_gen_qemu_st_i32(val, addr, ctx->memidx, MO_UB); 1321*fcf5ef2aSThomas Huth tcg_temp_free(val); 1322*fcf5ef2aSThomas Huth tcg_temp_free(addr); 1323*fcf5ef2aSThomas Huth } 1324*fcf5ef2aSThomas Huth return; 1325*fcf5ef2aSThomas Huth } 1326*fcf5ef2aSThomas Huth 1327*fcf5ef2aSThomas Huth switch (ctx->opcode & 0xf08f) { 1328*fcf5ef2aSThomas Huth case 0x408e: /* ldc Rm,Rn_BANK */ 1329*fcf5ef2aSThomas Huth CHECK_PRIVILEGED 1330*fcf5ef2aSThomas Huth tcg_gen_mov_i32(ALTREG(B6_4), REG(B11_8)); 1331*fcf5ef2aSThomas Huth return; 1332*fcf5ef2aSThomas Huth case 0x4087: /* ldc.l @Rm+,Rn_BANK */ 1333*fcf5ef2aSThomas Huth CHECK_PRIVILEGED 1334*fcf5ef2aSThomas Huth tcg_gen_qemu_ld_i32(ALTREG(B6_4), REG(B11_8), ctx->memidx, MO_TESL); 1335*fcf5ef2aSThomas Huth tcg_gen_addi_i32(REG(B11_8), REG(B11_8), 4); 1336*fcf5ef2aSThomas Huth return; 1337*fcf5ef2aSThomas Huth case 0x0082: /* stc Rm_BANK,Rn */ 1338*fcf5ef2aSThomas Huth CHECK_PRIVILEGED 1339*fcf5ef2aSThomas Huth tcg_gen_mov_i32(REG(B11_8), ALTREG(B6_4)); 1340*fcf5ef2aSThomas Huth return; 1341*fcf5ef2aSThomas Huth case 0x4083: /* stc.l Rm_BANK,@-Rn */ 1342*fcf5ef2aSThomas Huth CHECK_PRIVILEGED 1343*fcf5ef2aSThomas Huth { 1344*fcf5ef2aSThomas Huth TCGv addr = tcg_temp_new(); 1345*fcf5ef2aSThomas Huth tcg_gen_subi_i32(addr, REG(B11_8), 4); 1346*fcf5ef2aSThomas Huth tcg_gen_qemu_st_i32(ALTREG(B6_4), addr, ctx->memidx, MO_TEUL); 1347*fcf5ef2aSThomas Huth tcg_gen_mov_i32(REG(B11_8), addr); 1348*fcf5ef2aSThomas Huth tcg_temp_free(addr); 1349*fcf5ef2aSThomas Huth } 1350*fcf5ef2aSThomas Huth return; 1351*fcf5ef2aSThomas Huth } 1352*fcf5ef2aSThomas Huth 1353*fcf5ef2aSThomas Huth switch (ctx->opcode & 0xf0ff) { 1354*fcf5ef2aSThomas Huth case 0x0023: /* braf Rn */ 1355*fcf5ef2aSThomas Huth CHECK_NOT_DELAY_SLOT 1356*fcf5ef2aSThomas Huth tcg_gen_addi_i32(cpu_delayed_pc, REG(B11_8), ctx->pc + 4); 1357*fcf5ef2aSThomas Huth ctx->flags |= DELAY_SLOT; 1358*fcf5ef2aSThomas Huth ctx->delayed_pc = (uint32_t) - 1; 1359*fcf5ef2aSThomas Huth return; 1360*fcf5ef2aSThomas Huth case 0x0003: /* bsrf Rn */ 1361*fcf5ef2aSThomas Huth CHECK_NOT_DELAY_SLOT 1362*fcf5ef2aSThomas Huth tcg_gen_movi_i32(cpu_pr, ctx->pc + 4); 1363*fcf5ef2aSThomas Huth tcg_gen_add_i32(cpu_delayed_pc, REG(B11_8), cpu_pr); 1364*fcf5ef2aSThomas Huth ctx->flags |= DELAY_SLOT; 1365*fcf5ef2aSThomas Huth ctx->delayed_pc = (uint32_t) - 1; 1366*fcf5ef2aSThomas Huth return; 1367*fcf5ef2aSThomas Huth case 0x4015: /* cmp/pl Rn */ 1368*fcf5ef2aSThomas Huth tcg_gen_setcondi_i32(TCG_COND_GT, cpu_sr_t, REG(B11_8), 0); 1369*fcf5ef2aSThomas Huth return; 1370*fcf5ef2aSThomas Huth case 0x4011: /* cmp/pz Rn */ 1371*fcf5ef2aSThomas Huth tcg_gen_setcondi_i32(TCG_COND_GE, cpu_sr_t, REG(B11_8), 0); 1372*fcf5ef2aSThomas Huth return; 1373*fcf5ef2aSThomas Huth case 0x4010: /* dt Rn */ 1374*fcf5ef2aSThomas Huth tcg_gen_subi_i32(REG(B11_8), REG(B11_8), 1); 1375*fcf5ef2aSThomas Huth tcg_gen_setcondi_i32(TCG_COND_EQ, cpu_sr_t, REG(B11_8), 0); 1376*fcf5ef2aSThomas Huth return; 1377*fcf5ef2aSThomas Huth case 0x402b: /* jmp @Rn */ 1378*fcf5ef2aSThomas Huth CHECK_NOT_DELAY_SLOT 1379*fcf5ef2aSThomas Huth tcg_gen_mov_i32(cpu_delayed_pc, REG(B11_8)); 1380*fcf5ef2aSThomas Huth ctx->flags |= DELAY_SLOT; 1381*fcf5ef2aSThomas Huth ctx->delayed_pc = (uint32_t) - 1; 1382*fcf5ef2aSThomas Huth return; 1383*fcf5ef2aSThomas Huth case 0x400b: /* jsr @Rn */ 1384*fcf5ef2aSThomas Huth CHECK_NOT_DELAY_SLOT 1385*fcf5ef2aSThomas Huth tcg_gen_movi_i32(cpu_pr, ctx->pc + 4); 1386*fcf5ef2aSThomas Huth tcg_gen_mov_i32(cpu_delayed_pc, REG(B11_8)); 1387*fcf5ef2aSThomas Huth ctx->flags |= DELAY_SLOT; 1388*fcf5ef2aSThomas Huth ctx->delayed_pc = (uint32_t) - 1; 1389*fcf5ef2aSThomas Huth return; 1390*fcf5ef2aSThomas Huth case 0x400e: /* ldc Rm,SR */ 1391*fcf5ef2aSThomas Huth CHECK_PRIVILEGED 1392*fcf5ef2aSThomas Huth { 1393*fcf5ef2aSThomas Huth TCGv val = tcg_temp_new(); 1394*fcf5ef2aSThomas Huth tcg_gen_andi_i32(val, REG(B11_8), 0x700083f3); 1395*fcf5ef2aSThomas Huth gen_write_sr(val); 1396*fcf5ef2aSThomas Huth tcg_temp_free(val); 1397*fcf5ef2aSThomas Huth ctx->bstate = BS_STOP; 1398*fcf5ef2aSThomas Huth } 1399*fcf5ef2aSThomas Huth return; 1400*fcf5ef2aSThomas Huth case 0x4007: /* ldc.l @Rm+,SR */ 1401*fcf5ef2aSThomas Huth CHECK_PRIVILEGED 1402*fcf5ef2aSThomas Huth { 1403*fcf5ef2aSThomas Huth TCGv val = tcg_temp_new(); 1404*fcf5ef2aSThomas Huth tcg_gen_qemu_ld_i32(val, REG(B11_8), ctx->memidx, MO_TESL); 1405*fcf5ef2aSThomas Huth tcg_gen_andi_i32(val, val, 0x700083f3); 1406*fcf5ef2aSThomas Huth gen_write_sr(val); 1407*fcf5ef2aSThomas Huth tcg_temp_free(val); 1408*fcf5ef2aSThomas Huth tcg_gen_addi_i32(REG(B11_8), REG(B11_8), 4); 1409*fcf5ef2aSThomas Huth ctx->bstate = BS_STOP; 1410*fcf5ef2aSThomas Huth } 1411*fcf5ef2aSThomas Huth return; 1412*fcf5ef2aSThomas Huth case 0x0002: /* stc SR,Rn */ 1413*fcf5ef2aSThomas Huth CHECK_PRIVILEGED 1414*fcf5ef2aSThomas Huth gen_read_sr(REG(B11_8)); 1415*fcf5ef2aSThomas Huth return; 1416*fcf5ef2aSThomas Huth case 0x4003: /* stc SR,@-Rn */ 1417*fcf5ef2aSThomas Huth CHECK_PRIVILEGED 1418*fcf5ef2aSThomas Huth { 1419*fcf5ef2aSThomas Huth TCGv addr = tcg_temp_new(); 1420*fcf5ef2aSThomas Huth TCGv val = tcg_temp_new(); 1421*fcf5ef2aSThomas Huth tcg_gen_subi_i32(addr, REG(B11_8), 4); 1422*fcf5ef2aSThomas Huth gen_read_sr(val); 1423*fcf5ef2aSThomas Huth tcg_gen_qemu_st_i32(val, addr, ctx->memidx, MO_TEUL); 1424*fcf5ef2aSThomas Huth tcg_gen_mov_i32(REG(B11_8), addr); 1425*fcf5ef2aSThomas Huth tcg_temp_free(val); 1426*fcf5ef2aSThomas Huth tcg_temp_free(addr); 1427*fcf5ef2aSThomas Huth } 1428*fcf5ef2aSThomas Huth return; 1429*fcf5ef2aSThomas Huth #define LD(reg,ldnum,ldpnum,prechk) \ 1430*fcf5ef2aSThomas Huth case ldnum: \ 1431*fcf5ef2aSThomas Huth prechk \ 1432*fcf5ef2aSThomas Huth tcg_gen_mov_i32 (cpu_##reg, REG(B11_8)); \ 1433*fcf5ef2aSThomas Huth return; \ 1434*fcf5ef2aSThomas Huth case ldpnum: \ 1435*fcf5ef2aSThomas Huth prechk \ 1436*fcf5ef2aSThomas Huth tcg_gen_qemu_ld_i32(cpu_##reg, REG(B11_8), ctx->memidx, MO_TESL); \ 1437*fcf5ef2aSThomas Huth tcg_gen_addi_i32(REG(B11_8), REG(B11_8), 4); \ 1438*fcf5ef2aSThomas Huth return; 1439*fcf5ef2aSThomas Huth #define ST(reg,stnum,stpnum,prechk) \ 1440*fcf5ef2aSThomas Huth case stnum: \ 1441*fcf5ef2aSThomas Huth prechk \ 1442*fcf5ef2aSThomas Huth tcg_gen_mov_i32 (REG(B11_8), cpu_##reg); \ 1443*fcf5ef2aSThomas Huth return; \ 1444*fcf5ef2aSThomas Huth case stpnum: \ 1445*fcf5ef2aSThomas Huth prechk \ 1446*fcf5ef2aSThomas Huth { \ 1447*fcf5ef2aSThomas Huth TCGv addr = tcg_temp_new(); \ 1448*fcf5ef2aSThomas Huth tcg_gen_subi_i32(addr, REG(B11_8), 4); \ 1449*fcf5ef2aSThomas Huth tcg_gen_qemu_st_i32(cpu_##reg, addr, ctx->memidx, MO_TEUL); \ 1450*fcf5ef2aSThomas Huth tcg_gen_mov_i32(REG(B11_8), addr); \ 1451*fcf5ef2aSThomas Huth tcg_temp_free(addr); \ 1452*fcf5ef2aSThomas Huth } \ 1453*fcf5ef2aSThomas Huth return; 1454*fcf5ef2aSThomas Huth #define LDST(reg,ldnum,ldpnum,stnum,stpnum,prechk) \ 1455*fcf5ef2aSThomas Huth LD(reg,ldnum,ldpnum,prechk) \ 1456*fcf5ef2aSThomas Huth ST(reg,stnum,stpnum,prechk) 1457*fcf5ef2aSThomas Huth LDST(gbr, 0x401e, 0x4017, 0x0012, 0x4013, {}) 1458*fcf5ef2aSThomas Huth LDST(vbr, 0x402e, 0x4027, 0x0022, 0x4023, CHECK_PRIVILEGED) 1459*fcf5ef2aSThomas Huth LDST(ssr, 0x403e, 0x4037, 0x0032, 0x4033, CHECK_PRIVILEGED) 1460*fcf5ef2aSThomas Huth LDST(spc, 0x404e, 0x4047, 0x0042, 0x4043, CHECK_PRIVILEGED) 1461*fcf5ef2aSThomas Huth ST(sgr, 0x003a, 0x4032, CHECK_PRIVILEGED) 1462*fcf5ef2aSThomas Huth LD(sgr, 0x403a, 0x4036, CHECK_PRIVILEGED if (!(ctx->features & SH_FEATURE_SH4A)) break;) 1463*fcf5ef2aSThomas Huth LDST(dbr, 0x40fa, 0x40f6, 0x00fa, 0x40f2, CHECK_PRIVILEGED) 1464*fcf5ef2aSThomas Huth LDST(mach, 0x400a, 0x4006, 0x000a, 0x4002, {}) 1465*fcf5ef2aSThomas Huth LDST(macl, 0x401a, 0x4016, 0x001a, 0x4012, {}) 1466*fcf5ef2aSThomas Huth LDST(pr, 0x402a, 0x4026, 0x002a, 0x4022, {}) 1467*fcf5ef2aSThomas Huth LDST(fpul, 0x405a, 0x4056, 0x005a, 0x4052, {CHECK_FPU_ENABLED}) 1468*fcf5ef2aSThomas Huth case 0x406a: /* lds Rm,FPSCR */ 1469*fcf5ef2aSThomas Huth CHECK_FPU_ENABLED 1470*fcf5ef2aSThomas Huth gen_helper_ld_fpscr(cpu_env, REG(B11_8)); 1471*fcf5ef2aSThomas Huth ctx->bstate = BS_STOP; 1472*fcf5ef2aSThomas Huth return; 1473*fcf5ef2aSThomas Huth case 0x4066: /* lds.l @Rm+,FPSCR */ 1474*fcf5ef2aSThomas Huth CHECK_FPU_ENABLED 1475*fcf5ef2aSThomas Huth { 1476*fcf5ef2aSThomas Huth TCGv addr = tcg_temp_new(); 1477*fcf5ef2aSThomas Huth tcg_gen_qemu_ld_i32(addr, REG(B11_8), ctx->memidx, MO_TESL); 1478*fcf5ef2aSThomas Huth tcg_gen_addi_i32(REG(B11_8), REG(B11_8), 4); 1479*fcf5ef2aSThomas Huth gen_helper_ld_fpscr(cpu_env, addr); 1480*fcf5ef2aSThomas Huth tcg_temp_free(addr); 1481*fcf5ef2aSThomas Huth ctx->bstate = BS_STOP; 1482*fcf5ef2aSThomas Huth } 1483*fcf5ef2aSThomas Huth return; 1484*fcf5ef2aSThomas Huth case 0x006a: /* sts FPSCR,Rn */ 1485*fcf5ef2aSThomas Huth CHECK_FPU_ENABLED 1486*fcf5ef2aSThomas Huth tcg_gen_andi_i32(REG(B11_8), cpu_fpscr, 0x003fffff); 1487*fcf5ef2aSThomas Huth return; 1488*fcf5ef2aSThomas Huth case 0x4062: /* sts FPSCR,@-Rn */ 1489*fcf5ef2aSThomas Huth CHECK_FPU_ENABLED 1490*fcf5ef2aSThomas Huth { 1491*fcf5ef2aSThomas Huth TCGv addr, val; 1492*fcf5ef2aSThomas Huth val = tcg_temp_new(); 1493*fcf5ef2aSThomas Huth tcg_gen_andi_i32(val, cpu_fpscr, 0x003fffff); 1494*fcf5ef2aSThomas Huth addr = tcg_temp_new(); 1495*fcf5ef2aSThomas Huth tcg_gen_subi_i32(addr, REG(B11_8), 4); 1496*fcf5ef2aSThomas Huth tcg_gen_qemu_st_i32(val, addr, ctx->memidx, MO_TEUL); 1497*fcf5ef2aSThomas Huth tcg_gen_mov_i32(REG(B11_8), addr); 1498*fcf5ef2aSThomas Huth tcg_temp_free(addr); 1499*fcf5ef2aSThomas Huth tcg_temp_free(val); 1500*fcf5ef2aSThomas Huth } 1501*fcf5ef2aSThomas Huth return; 1502*fcf5ef2aSThomas Huth case 0x00c3: /* movca.l R0,@Rm */ 1503*fcf5ef2aSThomas Huth { 1504*fcf5ef2aSThomas Huth TCGv val = tcg_temp_new(); 1505*fcf5ef2aSThomas Huth tcg_gen_qemu_ld_i32(val, REG(B11_8), ctx->memidx, MO_TEUL); 1506*fcf5ef2aSThomas Huth gen_helper_movcal(cpu_env, REG(B11_8), val); 1507*fcf5ef2aSThomas Huth tcg_gen_qemu_st_i32(REG(0), REG(B11_8), ctx->memidx, MO_TEUL); 1508*fcf5ef2aSThomas Huth } 1509*fcf5ef2aSThomas Huth ctx->has_movcal = 1; 1510*fcf5ef2aSThomas Huth return; 1511*fcf5ef2aSThomas Huth case 0x40a9: 1512*fcf5ef2aSThomas Huth /* MOVUA.L @Rm,R0 (Rm) -> R0 1513*fcf5ef2aSThomas Huth Load non-boundary-aligned data */ 1514*fcf5ef2aSThomas Huth tcg_gen_qemu_ld_i32(REG(0), REG(B11_8), ctx->memidx, MO_TEUL); 1515*fcf5ef2aSThomas Huth return; 1516*fcf5ef2aSThomas Huth case 0x40e9: 1517*fcf5ef2aSThomas Huth /* MOVUA.L @Rm+,R0 (Rm) -> R0, Rm + 4 -> Rm 1518*fcf5ef2aSThomas Huth Load non-boundary-aligned data */ 1519*fcf5ef2aSThomas Huth tcg_gen_qemu_ld_i32(REG(0), REG(B11_8), ctx->memidx, MO_TEUL); 1520*fcf5ef2aSThomas Huth tcg_gen_addi_i32(REG(B11_8), REG(B11_8), 4); 1521*fcf5ef2aSThomas Huth return; 1522*fcf5ef2aSThomas Huth case 0x0029: /* movt Rn */ 1523*fcf5ef2aSThomas Huth tcg_gen_mov_i32(REG(B11_8), cpu_sr_t); 1524*fcf5ef2aSThomas Huth return; 1525*fcf5ef2aSThomas Huth case 0x0073: 1526*fcf5ef2aSThomas Huth /* MOVCO.L 1527*fcf5ef2aSThomas Huth LDST -> T 1528*fcf5ef2aSThomas Huth If (T == 1) R0 -> (Rn) 1529*fcf5ef2aSThomas Huth 0 -> LDST 1530*fcf5ef2aSThomas Huth */ 1531*fcf5ef2aSThomas Huth if (ctx->features & SH_FEATURE_SH4A) { 1532*fcf5ef2aSThomas Huth TCGLabel *label = gen_new_label(); 1533*fcf5ef2aSThomas Huth tcg_gen_mov_i32(cpu_sr_t, cpu_ldst); 1534*fcf5ef2aSThomas Huth tcg_gen_brcondi_i32(TCG_COND_EQ, cpu_ldst, 0, label); 1535*fcf5ef2aSThomas Huth tcg_gen_qemu_st_i32(REG(0), REG(B11_8), ctx->memidx, MO_TEUL); 1536*fcf5ef2aSThomas Huth gen_set_label(label); 1537*fcf5ef2aSThomas Huth tcg_gen_movi_i32(cpu_ldst, 0); 1538*fcf5ef2aSThomas Huth return; 1539*fcf5ef2aSThomas Huth } else 1540*fcf5ef2aSThomas Huth break; 1541*fcf5ef2aSThomas Huth case 0x0063: 1542*fcf5ef2aSThomas Huth /* MOVLI.L @Rm,R0 1543*fcf5ef2aSThomas Huth 1 -> LDST 1544*fcf5ef2aSThomas Huth (Rm) -> R0 1545*fcf5ef2aSThomas Huth When interrupt/exception 1546*fcf5ef2aSThomas Huth occurred 0 -> LDST 1547*fcf5ef2aSThomas Huth */ 1548*fcf5ef2aSThomas Huth if (ctx->features & SH_FEATURE_SH4A) { 1549*fcf5ef2aSThomas Huth tcg_gen_movi_i32(cpu_ldst, 0); 1550*fcf5ef2aSThomas Huth tcg_gen_qemu_ld_i32(REG(0), REG(B11_8), ctx->memidx, MO_TESL); 1551*fcf5ef2aSThomas Huth tcg_gen_movi_i32(cpu_ldst, 1); 1552*fcf5ef2aSThomas Huth return; 1553*fcf5ef2aSThomas Huth } else 1554*fcf5ef2aSThomas Huth break; 1555*fcf5ef2aSThomas Huth case 0x0093: /* ocbi @Rn */ 1556*fcf5ef2aSThomas Huth { 1557*fcf5ef2aSThomas Huth gen_helper_ocbi(cpu_env, REG(B11_8)); 1558*fcf5ef2aSThomas Huth } 1559*fcf5ef2aSThomas Huth return; 1560*fcf5ef2aSThomas Huth case 0x00a3: /* ocbp @Rn */ 1561*fcf5ef2aSThomas Huth case 0x00b3: /* ocbwb @Rn */ 1562*fcf5ef2aSThomas Huth /* These instructions are supposed to do nothing in case of 1563*fcf5ef2aSThomas Huth a cache miss. Given that we only partially emulate caches 1564*fcf5ef2aSThomas Huth it is safe to simply ignore them. */ 1565*fcf5ef2aSThomas Huth return; 1566*fcf5ef2aSThomas Huth case 0x0083: /* pref @Rn */ 1567*fcf5ef2aSThomas Huth return; 1568*fcf5ef2aSThomas Huth case 0x00d3: /* prefi @Rn */ 1569*fcf5ef2aSThomas Huth if (ctx->features & SH_FEATURE_SH4A) 1570*fcf5ef2aSThomas Huth return; 1571*fcf5ef2aSThomas Huth else 1572*fcf5ef2aSThomas Huth break; 1573*fcf5ef2aSThomas Huth case 0x00e3: /* icbi @Rn */ 1574*fcf5ef2aSThomas Huth if (ctx->features & SH_FEATURE_SH4A) 1575*fcf5ef2aSThomas Huth return; 1576*fcf5ef2aSThomas Huth else 1577*fcf5ef2aSThomas Huth break; 1578*fcf5ef2aSThomas Huth case 0x00ab: /* synco */ 1579*fcf5ef2aSThomas Huth if (ctx->features & SH_FEATURE_SH4A) 1580*fcf5ef2aSThomas Huth return; 1581*fcf5ef2aSThomas Huth else 1582*fcf5ef2aSThomas Huth break; 1583*fcf5ef2aSThomas Huth case 0x4024: /* rotcl Rn */ 1584*fcf5ef2aSThomas Huth { 1585*fcf5ef2aSThomas Huth TCGv tmp = tcg_temp_new(); 1586*fcf5ef2aSThomas Huth tcg_gen_mov_i32(tmp, cpu_sr_t); 1587*fcf5ef2aSThomas Huth tcg_gen_shri_i32(cpu_sr_t, REG(B11_8), 31); 1588*fcf5ef2aSThomas Huth tcg_gen_shli_i32(REG(B11_8), REG(B11_8), 1); 1589*fcf5ef2aSThomas Huth tcg_gen_or_i32(REG(B11_8), REG(B11_8), tmp); 1590*fcf5ef2aSThomas Huth tcg_temp_free(tmp); 1591*fcf5ef2aSThomas Huth } 1592*fcf5ef2aSThomas Huth return; 1593*fcf5ef2aSThomas Huth case 0x4025: /* rotcr Rn */ 1594*fcf5ef2aSThomas Huth { 1595*fcf5ef2aSThomas Huth TCGv tmp = tcg_temp_new(); 1596*fcf5ef2aSThomas Huth tcg_gen_shli_i32(tmp, cpu_sr_t, 31); 1597*fcf5ef2aSThomas Huth tcg_gen_andi_i32(cpu_sr_t, REG(B11_8), 1); 1598*fcf5ef2aSThomas Huth tcg_gen_shri_i32(REG(B11_8), REG(B11_8), 1); 1599*fcf5ef2aSThomas Huth tcg_gen_or_i32(REG(B11_8), REG(B11_8), tmp); 1600*fcf5ef2aSThomas Huth tcg_temp_free(tmp); 1601*fcf5ef2aSThomas Huth } 1602*fcf5ef2aSThomas Huth return; 1603*fcf5ef2aSThomas Huth case 0x4004: /* rotl Rn */ 1604*fcf5ef2aSThomas Huth tcg_gen_rotli_i32(REG(B11_8), REG(B11_8), 1); 1605*fcf5ef2aSThomas Huth tcg_gen_andi_i32(cpu_sr_t, REG(B11_8), 0); 1606*fcf5ef2aSThomas Huth return; 1607*fcf5ef2aSThomas Huth case 0x4005: /* rotr Rn */ 1608*fcf5ef2aSThomas Huth tcg_gen_andi_i32(cpu_sr_t, REG(B11_8), 0); 1609*fcf5ef2aSThomas Huth tcg_gen_rotri_i32(REG(B11_8), REG(B11_8), 1); 1610*fcf5ef2aSThomas Huth return; 1611*fcf5ef2aSThomas Huth case 0x4000: /* shll Rn */ 1612*fcf5ef2aSThomas Huth case 0x4020: /* shal Rn */ 1613*fcf5ef2aSThomas Huth tcg_gen_shri_i32(cpu_sr_t, REG(B11_8), 31); 1614*fcf5ef2aSThomas Huth tcg_gen_shli_i32(REG(B11_8), REG(B11_8), 1); 1615*fcf5ef2aSThomas Huth return; 1616*fcf5ef2aSThomas Huth case 0x4021: /* shar Rn */ 1617*fcf5ef2aSThomas Huth tcg_gen_andi_i32(cpu_sr_t, REG(B11_8), 1); 1618*fcf5ef2aSThomas Huth tcg_gen_sari_i32(REG(B11_8), REG(B11_8), 1); 1619*fcf5ef2aSThomas Huth return; 1620*fcf5ef2aSThomas Huth case 0x4001: /* shlr Rn */ 1621*fcf5ef2aSThomas Huth tcg_gen_andi_i32(cpu_sr_t, REG(B11_8), 1); 1622*fcf5ef2aSThomas Huth tcg_gen_shri_i32(REG(B11_8), REG(B11_8), 1); 1623*fcf5ef2aSThomas Huth return; 1624*fcf5ef2aSThomas Huth case 0x4008: /* shll2 Rn */ 1625*fcf5ef2aSThomas Huth tcg_gen_shli_i32(REG(B11_8), REG(B11_8), 2); 1626*fcf5ef2aSThomas Huth return; 1627*fcf5ef2aSThomas Huth case 0x4018: /* shll8 Rn */ 1628*fcf5ef2aSThomas Huth tcg_gen_shli_i32(REG(B11_8), REG(B11_8), 8); 1629*fcf5ef2aSThomas Huth return; 1630*fcf5ef2aSThomas Huth case 0x4028: /* shll16 Rn */ 1631*fcf5ef2aSThomas Huth tcg_gen_shli_i32(REG(B11_8), REG(B11_8), 16); 1632*fcf5ef2aSThomas Huth return; 1633*fcf5ef2aSThomas Huth case 0x4009: /* shlr2 Rn */ 1634*fcf5ef2aSThomas Huth tcg_gen_shri_i32(REG(B11_8), REG(B11_8), 2); 1635*fcf5ef2aSThomas Huth return; 1636*fcf5ef2aSThomas Huth case 0x4019: /* shlr8 Rn */ 1637*fcf5ef2aSThomas Huth tcg_gen_shri_i32(REG(B11_8), REG(B11_8), 8); 1638*fcf5ef2aSThomas Huth return; 1639*fcf5ef2aSThomas Huth case 0x4029: /* shlr16 Rn */ 1640*fcf5ef2aSThomas Huth tcg_gen_shri_i32(REG(B11_8), REG(B11_8), 16); 1641*fcf5ef2aSThomas Huth return; 1642*fcf5ef2aSThomas Huth case 0x401b: /* tas.b @Rn */ 1643*fcf5ef2aSThomas Huth { 1644*fcf5ef2aSThomas Huth TCGv addr, val; 1645*fcf5ef2aSThomas Huth addr = tcg_temp_local_new(); 1646*fcf5ef2aSThomas Huth tcg_gen_mov_i32(addr, REG(B11_8)); 1647*fcf5ef2aSThomas Huth val = tcg_temp_local_new(); 1648*fcf5ef2aSThomas Huth tcg_gen_qemu_ld_i32(val, addr, ctx->memidx, MO_UB); 1649*fcf5ef2aSThomas Huth tcg_gen_setcondi_i32(TCG_COND_EQ, cpu_sr_t, val, 0); 1650*fcf5ef2aSThomas Huth tcg_gen_ori_i32(val, val, 0x80); 1651*fcf5ef2aSThomas Huth tcg_gen_qemu_st_i32(val, addr, ctx->memidx, MO_UB); 1652*fcf5ef2aSThomas Huth tcg_temp_free(val); 1653*fcf5ef2aSThomas Huth tcg_temp_free(addr); 1654*fcf5ef2aSThomas Huth } 1655*fcf5ef2aSThomas Huth return; 1656*fcf5ef2aSThomas Huth case 0xf00d: /* fsts FPUL,FRn - FPSCR: Nothing */ 1657*fcf5ef2aSThomas Huth CHECK_FPU_ENABLED 1658*fcf5ef2aSThomas Huth tcg_gen_mov_i32(cpu_fregs[FREG(B11_8)], cpu_fpul); 1659*fcf5ef2aSThomas Huth return; 1660*fcf5ef2aSThomas Huth case 0xf01d: /* flds FRm,FPUL - FPSCR: Nothing */ 1661*fcf5ef2aSThomas Huth CHECK_FPU_ENABLED 1662*fcf5ef2aSThomas Huth tcg_gen_mov_i32(cpu_fpul, cpu_fregs[FREG(B11_8)]); 1663*fcf5ef2aSThomas Huth return; 1664*fcf5ef2aSThomas Huth case 0xf02d: /* float FPUL,FRn/DRn - FPSCR: R[PR,Enable.I]/W[Cause,Flag] */ 1665*fcf5ef2aSThomas Huth CHECK_FPU_ENABLED 1666*fcf5ef2aSThomas Huth if (ctx->flags & FPSCR_PR) { 1667*fcf5ef2aSThomas Huth TCGv_i64 fp; 1668*fcf5ef2aSThomas Huth if (ctx->opcode & 0x0100) 1669*fcf5ef2aSThomas Huth break; /* illegal instruction */ 1670*fcf5ef2aSThomas Huth fp = tcg_temp_new_i64(); 1671*fcf5ef2aSThomas Huth gen_helper_float_DT(fp, cpu_env, cpu_fpul); 1672*fcf5ef2aSThomas Huth gen_store_fpr64(fp, DREG(B11_8)); 1673*fcf5ef2aSThomas Huth tcg_temp_free_i64(fp); 1674*fcf5ef2aSThomas Huth } 1675*fcf5ef2aSThomas Huth else { 1676*fcf5ef2aSThomas Huth gen_helper_float_FT(cpu_fregs[FREG(B11_8)], cpu_env, cpu_fpul); 1677*fcf5ef2aSThomas Huth } 1678*fcf5ef2aSThomas Huth return; 1679*fcf5ef2aSThomas Huth case 0xf03d: /* ftrc FRm/DRm,FPUL - FPSCR: R[PR,Enable.V]/W[Cause,Flag] */ 1680*fcf5ef2aSThomas Huth CHECK_FPU_ENABLED 1681*fcf5ef2aSThomas Huth if (ctx->flags & FPSCR_PR) { 1682*fcf5ef2aSThomas Huth TCGv_i64 fp; 1683*fcf5ef2aSThomas Huth if (ctx->opcode & 0x0100) 1684*fcf5ef2aSThomas Huth break; /* illegal instruction */ 1685*fcf5ef2aSThomas Huth fp = tcg_temp_new_i64(); 1686*fcf5ef2aSThomas Huth gen_load_fpr64(fp, DREG(B11_8)); 1687*fcf5ef2aSThomas Huth gen_helper_ftrc_DT(cpu_fpul, cpu_env, fp); 1688*fcf5ef2aSThomas Huth tcg_temp_free_i64(fp); 1689*fcf5ef2aSThomas Huth } 1690*fcf5ef2aSThomas Huth else { 1691*fcf5ef2aSThomas Huth gen_helper_ftrc_FT(cpu_fpul, cpu_env, cpu_fregs[FREG(B11_8)]); 1692*fcf5ef2aSThomas Huth } 1693*fcf5ef2aSThomas Huth return; 1694*fcf5ef2aSThomas Huth case 0xf04d: /* fneg FRn/DRn - FPSCR: Nothing */ 1695*fcf5ef2aSThomas Huth CHECK_FPU_ENABLED 1696*fcf5ef2aSThomas Huth { 1697*fcf5ef2aSThomas Huth gen_helper_fneg_T(cpu_fregs[FREG(B11_8)], cpu_fregs[FREG(B11_8)]); 1698*fcf5ef2aSThomas Huth } 1699*fcf5ef2aSThomas Huth return; 1700*fcf5ef2aSThomas Huth case 0xf05d: /* fabs FRn/DRn */ 1701*fcf5ef2aSThomas Huth CHECK_FPU_ENABLED 1702*fcf5ef2aSThomas Huth if (ctx->flags & FPSCR_PR) { 1703*fcf5ef2aSThomas Huth if (ctx->opcode & 0x0100) 1704*fcf5ef2aSThomas Huth break; /* illegal instruction */ 1705*fcf5ef2aSThomas Huth TCGv_i64 fp = tcg_temp_new_i64(); 1706*fcf5ef2aSThomas Huth gen_load_fpr64(fp, DREG(B11_8)); 1707*fcf5ef2aSThomas Huth gen_helper_fabs_DT(fp, fp); 1708*fcf5ef2aSThomas Huth gen_store_fpr64(fp, DREG(B11_8)); 1709*fcf5ef2aSThomas Huth tcg_temp_free_i64(fp); 1710*fcf5ef2aSThomas Huth } else { 1711*fcf5ef2aSThomas Huth gen_helper_fabs_FT(cpu_fregs[FREG(B11_8)], cpu_fregs[FREG(B11_8)]); 1712*fcf5ef2aSThomas Huth } 1713*fcf5ef2aSThomas Huth return; 1714*fcf5ef2aSThomas Huth case 0xf06d: /* fsqrt FRn */ 1715*fcf5ef2aSThomas Huth CHECK_FPU_ENABLED 1716*fcf5ef2aSThomas Huth if (ctx->flags & FPSCR_PR) { 1717*fcf5ef2aSThomas Huth if (ctx->opcode & 0x0100) 1718*fcf5ef2aSThomas Huth break; /* illegal instruction */ 1719*fcf5ef2aSThomas Huth TCGv_i64 fp = tcg_temp_new_i64(); 1720*fcf5ef2aSThomas Huth gen_load_fpr64(fp, DREG(B11_8)); 1721*fcf5ef2aSThomas Huth gen_helper_fsqrt_DT(fp, cpu_env, fp); 1722*fcf5ef2aSThomas Huth gen_store_fpr64(fp, DREG(B11_8)); 1723*fcf5ef2aSThomas Huth tcg_temp_free_i64(fp); 1724*fcf5ef2aSThomas Huth } else { 1725*fcf5ef2aSThomas Huth gen_helper_fsqrt_FT(cpu_fregs[FREG(B11_8)], cpu_env, 1726*fcf5ef2aSThomas Huth cpu_fregs[FREG(B11_8)]); 1727*fcf5ef2aSThomas Huth } 1728*fcf5ef2aSThomas Huth return; 1729*fcf5ef2aSThomas Huth case 0xf07d: /* fsrra FRn */ 1730*fcf5ef2aSThomas Huth CHECK_FPU_ENABLED 1731*fcf5ef2aSThomas Huth break; 1732*fcf5ef2aSThomas Huth case 0xf08d: /* fldi0 FRn - FPSCR: R[PR] */ 1733*fcf5ef2aSThomas Huth CHECK_FPU_ENABLED 1734*fcf5ef2aSThomas Huth if (!(ctx->flags & FPSCR_PR)) { 1735*fcf5ef2aSThomas Huth tcg_gen_movi_i32(cpu_fregs[FREG(B11_8)], 0); 1736*fcf5ef2aSThomas Huth } 1737*fcf5ef2aSThomas Huth return; 1738*fcf5ef2aSThomas Huth case 0xf09d: /* fldi1 FRn - FPSCR: R[PR] */ 1739*fcf5ef2aSThomas Huth CHECK_FPU_ENABLED 1740*fcf5ef2aSThomas Huth if (!(ctx->flags & FPSCR_PR)) { 1741*fcf5ef2aSThomas Huth tcg_gen_movi_i32(cpu_fregs[FREG(B11_8)], 0x3f800000); 1742*fcf5ef2aSThomas Huth } 1743*fcf5ef2aSThomas Huth return; 1744*fcf5ef2aSThomas Huth case 0xf0ad: /* fcnvsd FPUL,DRn */ 1745*fcf5ef2aSThomas Huth CHECK_FPU_ENABLED 1746*fcf5ef2aSThomas Huth { 1747*fcf5ef2aSThomas Huth TCGv_i64 fp = tcg_temp_new_i64(); 1748*fcf5ef2aSThomas Huth gen_helper_fcnvsd_FT_DT(fp, cpu_env, cpu_fpul); 1749*fcf5ef2aSThomas Huth gen_store_fpr64(fp, DREG(B11_8)); 1750*fcf5ef2aSThomas Huth tcg_temp_free_i64(fp); 1751*fcf5ef2aSThomas Huth } 1752*fcf5ef2aSThomas Huth return; 1753*fcf5ef2aSThomas Huth case 0xf0bd: /* fcnvds DRn,FPUL */ 1754*fcf5ef2aSThomas Huth CHECK_FPU_ENABLED 1755*fcf5ef2aSThomas Huth { 1756*fcf5ef2aSThomas Huth TCGv_i64 fp = tcg_temp_new_i64(); 1757*fcf5ef2aSThomas Huth gen_load_fpr64(fp, DREG(B11_8)); 1758*fcf5ef2aSThomas Huth gen_helper_fcnvds_DT_FT(cpu_fpul, cpu_env, fp); 1759*fcf5ef2aSThomas Huth tcg_temp_free_i64(fp); 1760*fcf5ef2aSThomas Huth } 1761*fcf5ef2aSThomas Huth return; 1762*fcf5ef2aSThomas Huth case 0xf0ed: /* fipr FVm,FVn */ 1763*fcf5ef2aSThomas Huth CHECK_FPU_ENABLED 1764*fcf5ef2aSThomas Huth if ((ctx->flags & FPSCR_PR) == 0) { 1765*fcf5ef2aSThomas Huth TCGv m, n; 1766*fcf5ef2aSThomas Huth m = tcg_const_i32((ctx->opcode >> 8) & 3); 1767*fcf5ef2aSThomas Huth n = tcg_const_i32((ctx->opcode >> 10) & 3); 1768*fcf5ef2aSThomas Huth gen_helper_fipr(cpu_env, m, n); 1769*fcf5ef2aSThomas Huth tcg_temp_free(m); 1770*fcf5ef2aSThomas Huth tcg_temp_free(n); 1771*fcf5ef2aSThomas Huth return; 1772*fcf5ef2aSThomas Huth } 1773*fcf5ef2aSThomas Huth break; 1774*fcf5ef2aSThomas Huth case 0xf0fd: /* ftrv XMTRX,FVn */ 1775*fcf5ef2aSThomas Huth CHECK_FPU_ENABLED 1776*fcf5ef2aSThomas Huth if ((ctx->opcode & 0x0300) == 0x0100 && 1777*fcf5ef2aSThomas Huth (ctx->flags & FPSCR_PR) == 0) { 1778*fcf5ef2aSThomas Huth TCGv n; 1779*fcf5ef2aSThomas Huth n = tcg_const_i32((ctx->opcode >> 10) & 3); 1780*fcf5ef2aSThomas Huth gen_helper_ftrv(cpu_env, n); 1781*fcf5ef2aSThomas Huth tcg_temp_free(n); 1782*fcf5ef2aSThomas Huth return; 1783*fcf5ef2aSThomas Huth } 1784*fcf5ef2aSThomas Huth break; 1785*fcf5ef2aSThomas Huth } 1786*fcf5ef2aSThomas Huth #if 0 1787*fcf5ef2aSThomas Huth fprintf(stderr, "unknown instruction 0x%04x at pc 0x%08x\n", 1788*fcf5ef2aSThomas Huth ctx->opcode, ctx->pc); 1789*fcf5ef2aSThomas Huth fflush(stderr); 1790*fcf5ef2aSThomas Huth #endif 1791*fcf5ef2aSThomas Huth tcg_gen_movi_i32(cpu_pc, ctx->pc); 1792*fcf5ef2aSThomas Huth if (ctx->flags & (DELAY_SLOT | DELAY_SLOT_CONDITIONAL)) { 1793*fcf5ef2aSThomas Huth gen_helper_raise_slot_illegal_instruction(cpu_env); 1794*fcf5ef2aSThomas Huth } else { 1795*fcf5ef2aSThomas Huth gen_helper_raise_illegal_instruction(cpu_env); 1796*fcf5ef2aSThomas Huth } 1797*fcf5ef2aSThomas Huth ctx->bstate = BS_BRANCH; 1798*fcf5ef2aSThomas Huth } 1799*fcf5ef2aSThomas Huth 1800*fcf5ef2aSThomas Huth static void decode_opc(DisasContext * ctx) 1801*fcf5ef2aSThomas Huth { 1802*fcf5ef2aSThomas Huth uint32_t old_flags = ctx->flags; 1803*fcf5ef2aSThomas Huth 1804*fcf5ef2aSThomas Huth _decode_opc(ctx); 1805*fcf5ef2aSThomas Huth 1806*fcf5ef2aSThomas Huth if (old_flags & (DELAY_SLOT | DELAY_SLOT_CONDITIONAL)) { 1807*fcf5ef2aSThomas Huth if (ctx->flags & DELAY_SLOT_CLEARME) { 1808*fcf5ef2aSThomas Huth gen_store_flags(0); 1809*fcf5ef2aSThomas Huth } else { 1810*fcf5ef2aSThomas Huth /* go out of the delay slot */ 1811*fcf5ef2aSThomas Huth uint32_t new_flags = ctx->flags; 1812*fcf5ef2aSThomas Huth new_flags &= ~(DELAY_SLOT | DELAY_SLOT_CONDITIONAL); 1813*fcf5ef2aSThomas Huth gen_store_flags(new_flags); 1814*fcf5ef2aSThomas Huth } 1815*fcf5ef2aSThomas Huth ctx->flags = 0; 1816*fcf5ef2aSThomas Huth ctx->bstate = BS_BRANCH; 1817*fcf5ef2aSThomas Huth if (old_flags & DELAY_SLOT_CONDITIONAL) { 1818*fcf5ef2aSThomas Huth gen_delayed_conditional_jump(ctx); 1819*fcf5ef2aSThomas Huth } else if (old_flags & DELAY_SLOT) { 1820*fcf5ef2aSThomas Huth gen_jump(ctx); 1821*fcf5ef2aSThomas Huth } 1822*fcf5ef2aSThomas Huth 1823*fcf5ef2aSThomas Huth } 1824*fcf5ef2aSThomas Huth 1825*fcf5ef2aSThomas Huth /* go into a delay slot */ 1826*fcf5ef2aSThomas Huth if (ctx->flags & (DELAY_SLOT | DELAY_SLOT_CONDITIONAL)) 1827*fcf5ef2aSThomas Huth gen_store_flags(ctx->flags); 1828*fcf5ef2aSThomas Huth } 1829*fcf5ef2aSThomas Huth 1830*fcf5ef2aSThomas Huth void gen_intermediate_code(CPUSH4State * env, struct TranslationBlock *tb) 1831*fcf5ef2aSThomas Huth { 1832*fcf5ef2aSThomas Huth SuperHCPU *cpu = sh_env_get_cpu(env); 1833*fcf5ef2aSThomas Huth CPUState *cs = CPU(cpu); 1834*fcf5ef2aSThomas Huth DisasContext ctx; 1835*fcf5ef2aSThomas Huth target_ulong pc_start; 1836*fcf5ef2aSThomas Huth int num_insns; 1837*fcf5ef2aSThomas Huth int max_insns; 1838*fcf5ef2aSThomas Huth 1839*fcf5ef2aSThomas Huth pc_start = tb->pc; 1840*fcf5ef2aSThomas Huth ctx.pc = pc_start; 1841*fcf5ef2aSThomas Huth ctx.flags = (uint32_t)tb->flags; 1842*fcf5ef2aSThomas Huth ctx.bstate = BS_NONE; 1843*fcf5ef2aSThomas Huth ctx.memidx = (ctx.flags & (1u << SR_MD)) == 0 ? 1 : 0; 1844*fcf5ef2aSThomas Huth /* We don't know if the delayed pc came from a dynamic or static branch, 1845*fcf5ef2aSThomas Huth so assume it is a dynamic branch. */ 1846*fcf5ef2aSThomas Huth ctx.delayed_pc = -1; /* use delayed pc from env pointer */ 1847*fcf5ef2aSThomas Huth ctx.tb = tb; 1848*fcf5ef2aSThomas Huth ctx.singlestep_enabled = cs->singlestep_enabled; 1849*fcf5ef2aSThomas Huth ctx.features = env->features; 1850*fcf5ef2aSThomas Huth ctx.has_movcal = (ctx.flags & TB_FLAG_PENDING_MOVCA); 1851*fcf5ef2aSThomas Huth 1852*fcf5ef2aSThomas Huth num_insns = 0; 1853*fcf5ef2aSThomas Huth max_insns = tb->cflags & CF_COUNT_MASK; 1854*fcf5ef2aSThomas Huth if (max_insns == 0) { 1855*fcf5ef2aSThomas Huth max_insns = CF_COUNT_MASK; 1856*fcf5ef2aSThomas Huth } 1857*fcf5ef2aSThomas Huth if (max_insns > TCG_MAX_INSNS) { 1858*fcf5ef2aSThomas Huth max_insns = TCG_MAX_INSNS; 1859*fcf5ef2aSThomas Huth } 1860*fcf5ef2aSThomas Huth 1861*fcf5ef2aSThomas Huth gen_tb_start(tb); 1862*fcf5ef2aSThomas Huth while (ctx.bstate == BS_NONE && !tcg_op_buf_full()) { 1863*fcf5ef2aSThomas Huth tcg_gen_insn_start(ctx.pc, ctx.flags); 1864*fcf5ef2aSThomas Huth num_insns++; 1865*fcf5ef2aSThomas Huth 1866*fcf5ef2aSThomas Huth if (unlikely(cpu_breakpoint_test(cs, ctx.pc, BP_ANY))) { 1867*fcf5ef2aSThomas Huth /* We have hit a breakpoint - make sure PC is up-to-date */ 1868*fcf5ef2aSThomas Huth tcg_gen_movi_i32(cpu_pc, ctx.pc); 1869*fcf5ef2aSThomas Huth gen_helper_debug(cpu_env); 1870*fcf5ef2aSThomas Huth ctx.bstate = BS_BRANCH; 1871*fcf5ef2aSThomas Huth /* The address covered by the breakpoint must be included in 1872*fcf5ef2aSThomas Huth [tb->pc, tb->pc + tb->size) in order to for it to be 1873*fcf5ef2aSThomas Huth properly cleared -- thus we increment the PC here so that 1874*fcf5ef2aSThomas Huth the logic setting tb->size below does the right thing. */ 1875*fcf5ef2aSThomas Huth ctx.pc += 2; 1876*fcf5ef2aSThomas Huth break; 1877*fcf5ef2aSThomas Huth } 1878*fcf5ef2aSThomas Huth 1879*fcf5ef2aSThomas Huth if (num_insns == max_insns && (tb->cflags & CF_LAST_IO)) { 1880*fcf5ef2aSThomas Huth gen_io_start(); 1881*fcf5ef2aSThomas Huth } 1882*fcf5ef2aSThomas Huth 1883*fcf5ef2aSThomas Huth ctx.opcode = cpu_lduw_code(env, ctx.pc); 1884*fcf5ef2aSThomas Huth decode_opc(&ctx); 1885*fcf5ef2aSThomas Huth ctx.pc += 2; 1886*fcf5ef2aSThomas Huth if ((ctx.pc & (TARGET_PAGE_SIZE - 1)) == 0) 1887*fcf5ef2aSThomas Huth break; 1888*fcf5ef2aSThomas Huth if (cs->singlestep_enabled) { 1889*fcf5ef2aSThomas Huth break; 1890*fcf5ef2aSThomas Huth } 1891*fcf5ef2aSThomas Huth if (num_insns >= max_insns) 1892*fcf5ef2aSThomas Huth break; 1893*fcf5ef2aSThomas Huth if (singlestep) 1894*fcf5ef2aSThomas Huth break; 1895*fcf5ef2aSThomas Huth } 1896*fcf5ef2aSThomas Huth if (tb->cflags & CF_LAST_IO) 1897*fcf5ef2aSThomas Huth gen_io_end(); 1898*fcf5ef2aSThomas Huth if (cs->singlestep_enabled) { 1899*fcf5ef2aSThomas Huth tcg_gen_movi_i32(cpu_pc, ctx.pc); 1900*fcf5ef2aSThomas Huth gen_helper_debug(cpu_env); 1901*fcf5ef2aSThomas Huth } else { 1902*fcf5ef2aSThomas Huth switch (ctx.bstate) { 1903*fcf5ef2aSThomas Huth case BS_STOP: 1904*fcf5ef2aSThomas Huth /* gen_op_interrupt_restart(); */ 1905*fcf5ef2aSThomas Huth /* fall through */ 1906*fcf5ef2aSThomas Huth case BS_NONE: 1907*fcf5ef2aSThomas Huth if (ctx.flags) { 1908*fcf5ef2aSThomas Huth gen_store_flags(ctx.flags | DELAY_SLOT_CLEARME); 1909*fcf5ef2aSThomas Huth } 1910*fcf5ef2aSThomas Huth gen_goto_tb(&ctx, 0, ctx.pc); 1911*fcf5ef2aSThomas Huth break; 1912*fcf5ef2aSThomas Huth case BS_EXCP: 1913*fcf5ef2aSThomas Huth /* gen_op_interrupt_restart(); */ 1914*fcf5ef2aSThomas Huth tcg_gen_exit_tb(0); 1915*fcf5ef2aSThomas Huth break; 1916*fcf5ef2aSThomas Huth case BS_BRANCH: 1917*fcf5ef2aSThomas Huth default: 1918*fcf5ef2aSThomas Huth break; 1919*fcf5ef2aSThomas Huth } 1920*fcf5ef2aSThomas Huth } 1921*fcf5ef2aSThomas Huth 1922*fcf5ef2aSThomas Huth gen_tb_end(tb, num_insns); 1923*fcf5ef2aSThomas Huth 1924*fcf5ef2aSThomas Huth tb->size = ctx.pc - pc_start; 1925*fcf5ef2aSThomas Huth tb->icount = num_insns; 1926*fcf5ef2aSThomas Huth 1927*fcf5ef2aSThomas Huth #ifdef DEBUG_DISAS 1928*fcf5ef2aSThomas Huth if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM) 1929*fcf5ef2aSThomas Huth && qemu_log_in_addr_range(pc_start)) { 1930*fcf5ef2aSThomas Huth qemu_log_lock(); 1931*fcf5ef2aSThomas Huth qemu_log("IN:\n"); /* , lookup_symbol(pc_start)); */ 1932*fcf5ef2aSThomas Huth log_target_disas(cs, pc_start, ctx.pc - pc_start, 0); 1933*fcf5ef2aSThomas Huth qemu_log("\n"); 1934*fcf5ef2aSThomas Huth qemu_log_unlock(); 1935*fcf5ef2aSThomas Huth } 1936*fcf5ef2aSThomas Huth #endif 1937*fcf5ef2aSThomas Huth } 1938*fcf5ef2aSThomas Huth 1939*fcf5ef2aSThomas Huth void restore_state_to_opc(CPUSH4State *env, TranslationBlock *tb, 1940*fcf5ef2aSThomas Huth target_ulong *data) 1941*fcf5ef2aSThomas Huth { 1942*fcf5ef2aSThomas Huth env->pc = data[0]; 1943*fcf5ef2aSThomas Huth env->flags = data[1]; 1944*fcf5ef2aSThomas Huth } 1945