1 /* 2 * SH4 translation 3 * 4 * Copyright (c) 2005 Samuel Tardieu 5 * 6 * This library is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU Lesser General Public 8 * License as published by the Free Software Foundation; either 9 * version 2.1 of the License, or (at your option) any later version. 10 * 11 * This library is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 * Lesser General Public License for more details. 15 * 16 * You should have received a copy of the GNU Lesser General Public 17 * License along with this library; if not, see <http://www.gnu.org/licenses/>. 18 */ 19 20 #define DEBUG_DISAS 21 22 #include "qemu/osdep.h" 23 #include "cpu.h" 24 #include "disas/disas.h" 25 #include "exec/exec-all.h" 26 #include "tcg/tcg-op.h" 27 #include "exec/cpu_ldst.h" 28 #include "exec/helper-proto.h" 29 #include "exec/helper-gen.h" 30 #include "exec/translator.h" 31 #include "exec/log.h" 32 #include "qemu/qemu-print.h" 33 34 35 typedef struct DisasContext { 36 DisasContextBase base; 37 38 uint32_t tbflags; /* should stay unmodified during the TB translation */ 39 uint32_t envflags; /* should stay in sync with env->flags using TCG ops */ 40 int memidx; 41 int gbank; 42 int fbank; 43 uint32_t delayed_pc; 44 uint32_t features; 45 46 uint16_t opcode; 47 48 bool has_movcal; 49 } DisasContext; 50 51 #if defined(CONFIG_USER_ONLY) 52 #define IS_USER(ctx) 1 53 #else 54 #define IS_USER(ctx) (!(ctx->tbflags & (1u << SR_MD))) 55 #endif 56 57 /* Target-specific values for ctx->base.is_jmp. */ 58 /* We want to exit back to the cpu loop for some reason. 59 Usually this is to recognize interrupts immediately. */ 60 #define DISAS_STOP DISAS_TARGET_0 61 62 /* global register indexes */ 63 static TCGv cpu_gregs[32]; 64 static TCGv cpu_sr, cpu_sr_m, cpu_sr_q, cpu_sr_t; 65 static TCGv cpu_pc, cpu_ssr, cpu_spc, cpu_gbr; 66 static TCGv cpu_vbr, cpu_sgr, cpu_dbr, cpu_mach, cpu_macl; 67 static TCGv cpu_pr, cpu_fpscr, cpu_fpul; 68 static TCGv cpu_lock_addr, cpu_lock_value; 69 static TCGv cpu_fregs[32]; 70 71 /* internal register indexes */ 72 static TCGv cpu_flags, cpu_delayed_pc, cpu_delayed_cond; 73 74 #include "exec/gen-icount.h" 75 76 void sh4_translate_init(void) 77 { 78 int i; 79 static const char * const gregnames[24] = { 80 "R0_BANK0", "R1_BANK0", "R2_BANK0", "R3_BANK0", 81 "R4_BANK0", "R5_BANK0", "R6_BANK0", "R7_BANK0", 82 "R8", "R9", "R10", "R11", "R12", "R13", "R14", "R15", 83 "R0_BANK1", "R1_BANK1", "R2_BANK1", "R3_BANK1", 84 "R4_BANK1", "R5_BANK1", "R6_BANK1", "R7_BANK1" 85 }; 86 static const char * const fregnames[32] = { 87 "FPR0_BANK0", "FPR1_BANK0", "FPR2_BANK0", "FPR3_BANK0", 88 "FPR4_BANK0", "FPR5_BANK0", "FPR6_BANK0", "FPR7_BANK0", 89 "FPR8_BANK0", "FPR9_BANK0", "FPR10_BANK0", "FPR11_BANK0", 90 "FPR12_BANK0", "FPR13_BANK0", "FPR14_BANK0", "FPR15_BANK0", 91 "FPR0_BANK1", "FPR1_BANK1", "FPR2_BANK1", "FPR3_BANK1", 92 "FPR4_BANK1", "FPR5_BANK1", "FPR6_BANK1", "FPR7_BANK1", 93 "FPR8_BANK1", "FPR9_BANK1", "FPR10_BANK1", "FPR11_BANK1", 94 "FPR12_BANK1", "FPR13_BANK1", "FPR14_BANK1", "FPR15_BANK1", 95 }; 96 97 for (i = 0; i < 24; i++) { 98 cpu_gregs[i] = tcg_global_mem_new_i32(cpu_env, 99 offsetof(CPUSH4State, gregs[i]), 100 gregnames[i]); 101 } 102 memcpy(cpu_gregs + 24, cpu_gregs + 8, 8 * sizeof(TCGv)); 103 104 cpu_pc = tcg_global_mem_new_i32(cpu_env, 105 offsetof(CPUSH4State, pc), "PC"); 106 cpu_sr = tcg_global_mem_new_i32(cpu_env, 107 offsetof(CPUSH4State, sr), "SR"); 108 cpu_sr_m = tcg_global_mem_new_i32(cpu_env, 109 offsetof(CPUSH4State, sr_m), "SR_M"); 110 cpu_sr_q = tcg_global_mem_new_i32(cpu_env, 111 offsetof(CPUSH4State, sr_q), "SR_Q"); 112 cpu_sr_t = tcg_global_mem_new_i32(cpu_env, 113 offsetof(CPUSH4State, sr_t), "SR_T"); 114 cpu_ssr = tcg_global_mem_new_i32(cpu_env, 115 offsetof(CPUSH4State, ssr), "SSR"); 116 cpu_spc = tcg_global_mem_new_i32(cpu_env, 117 offsetof(CPUSH4State, spc), "SPC"); 118 cpu_gbr = tcg_global_mem_new_i32(cpu_env, 119 offsetof(CPUSH4State, gbr), "GBR"); 120 cpu_vbr = tcg_global_mem_new_i32(cpu_env, 121 offsetof(CPUSH4State, vbr), "VBR"); 122 cpu_sgr = tcg_global_mem_new_i32(cpu_env, 123 offsetof(CPUSH4State, sgr), "SGR"); 124 cpu_dbr = tcg_global_mem_new_i32(cpu_env, 125 offsetof(CPUSH4State, dbr), "DBR"); 126 cpu_mach = tcg_global_mem_new_i32(cpu_env, 127 offsetof(CPUSH4State, mach), "MACH"); 128 cpu_macl = tcg_global_mem_new_i32(cpu_env, 129 offsetof(CPUSH4State, macl), "MACL"); 130 cpu_pr = tcg_global_mem_new_i32(cpu_env, 131 offsetof(CPUSH4State, pr), "PR"); 132 cpu_fpscr = tcg_global_mem_new_i32(cpu_env, 133 offsetof(CPUSH4State, fpscr), "FPSCR"); 134 cpu_fpul = tcg_global_mem_new_i32(cpu_env, 135 offsetof(CPUSH4State, fpul), "FPUL"); 136 137 cpu_flags = tcg_global_mem_new_i32(cpu_env, 138 offsetof(CPUSH4State, flags), "_flags_"); 139 cpu_delayed_pc = tcg_global_mem_new_i32(cpu_env, 140 offsetof(CPUSH4State, delayed_pc), 141 "_delayed_pc_"); 142 cpu_delayed_cond = tcg_global_mem_new_i32(cpu_env, 143 offsetof(CPUSH4State, 144 delayed_cond), 145 "_delayed_cond_"); 146 cpu_lock_addr = tcg_global_mem_new_i32(cpu_env, 147 offsetof(CPUSH4State, lock_addr), 148 "_lock_addr_"); 149 cpu_lock_value = tcg_global_mem_new_i32(cpu_env, 150 offsetof(CPUSH4State, lock_value), 151 "_lock_value_"); 152 153 for (i = 0; i < 32; i++) 154 cpu_fregs[i] = tcg_global_mem_new_i32(cpu_env, 155 offsetof(CPUSH4State, fregs[i]), 156 fregnames[i]); 157 } 158 159 void superh_cpu_dump_state(CPUState *cs, FILE *f, int flags) 160 { 161 SuperHCPU *cpu = SUPERH_CPU(cs); 162 CPUSH4State *env = &cpu->env; 163 int i; 164 165 qemu_fprintf(f, "pc=0x%08x sr=0x%08x pr=0x%08x fpscr=0x%08x\n", 166 env->pc, cpu_read_sr(env), env->pr, env->fpscr); 167 qemu_fprintf(f, "spc=0x%08x ssr=0x%08x gbr=0x%08x vbr=0x%08x\n", 168 env->spc, env->ssr, env->gbr, env->vbr); 169 qemu_fprintf(f, "sgr=0x%08x dbr=0x%08x delayed_pc=0x%08x fpul=0x%08x\n", 170 env->sgr, env->dbr, env->delayed_pc, env->fpul); 171 for (i = 0; i < 24; i += 4) { 172 qemu_printf("r%d=0x%08x r%d=0x%08x r%d=0x%08x r%d=0x%08x\n", 173 i, env->gregs[i], i + 1, env->gregs[i + 1], 174 i + 2, env->gregs[i + 2], i + 3, env->gregs[i + 3]); 175 } 176 if (env->flags & DELAY_SLOT) { 177 qemu_printf("in delay slot (delayed_pc=0x%08x)\n", 178 env->delayed_pc); 179 } else if (env->flags & DELAY_SLOT_CONDITIONAL) { 180 qemu_printf("in conditional delay slot (delayed_pc=0x%08x)\n", 181 env->delayed_pc); 182 } else if (env->flags & DELAY_SLOT_RTE) { 183 qemu_fprintf(f, "in rte delay slot (delayed_pc=0x%08x)\n", 184 env->delayed_pc); 185 } 186 } 187 188 static void gen_read_sr(TCGv dst) 189 { 190 TCGv t0 = tcg_temp_new(); 191 tcg_gen_shli_i32(t0, cpu_sr_q, SR_Q); 192 tcg_gen_or_i32(dst, dst, t0); 193 tcg_gen_shli_i32(t0, cpu_sr_m, SR_M); 194 tcg_gen_or_i32(dst, dst, t0); 195 tcg_gen_shli_i32(t0, cpu_sr_t, SR_T); 196 tcg_gen_or_i32(dst, cpu_sr, t0); 197 tcg_temp_free_i32(t0); 198 } 199 200 static void gen_write_sr(TCGv src) 201 { 202 tcg_gen_andi_i32(cpu_sr, src, 203 ~((1u << SR_Q) | (1u << SR_M) | (1u << SR_T))); 204 tcg_gen_extract_i32(cpu_sr_q, src, SR_Q, 1); 205 tcg_gen_extract_i32(cpu_sr_m, src, SR_M, 1); 206 tcg_gen_extract_i32(cpu_sr_t, src, SR_T, 1); 207 } 208 209 static inline void gen_save_cpu_state(DisasContext *ctx, bool save_pc) 210 { 211 if (save_pc) { 212 tcg_gen_movi_i32(cpu_pc, ctx->base.pc_next); 213 } 214 if (ctx->delayed_pc != (uint32_t) -1) { 215 tcg_gen_movi_i32(cpu_delayed_pc, ctx->delayed_pc); 216 } 217 if ((ctx->tbflags & TB_FLAG_ENVFLAGS_MASK) != ctx->envflags) { 218 tcg_gen_movi_i32(cpu_flags, ctx->envflags); 219 } 220 } 221 222 static inline bool use_exit_tb(DisasContext *ctx) 223 { 224 return (ctx->tbflags & GUSA_EXCLUSIVE) != 0; 225 } 226 227 static bool use_goto_tb(DisasContext *ctx, target_ulong dest) 228 { 229 if (use_exit_tb(ctx)) { 230 return false; 231 } 232 return translator_use_goto_tb(&ctx->base, dest); 233 } 234 235 static void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest) 236 { 237 if (use_goto_tb(ctx, dest)) { 238 tcg_gen_goto_tb(n); 239 tcg_gen_movi_i32(cpu_pc, dest); 240 tcg_gen_exit_tb(ctx->base.tb, n); 241 } else { 242 tcg_gen_movi_i32(cpu_pc, dest); 243 if (ctx->base.singlestep_enabled) { 244 gen_helper_debug(cpu_env); 245 } else if (use_exit_tb(ctx)) { 246 tcg_gen_exit_tb(NULL, 0); 247 } else { 248 tcg_gen_lookup_and_goto_ptr(); 249 } 250 } 251 ctx->base.is_jmp = DISAS_NORETURN; 252 } 253 254 static void gen_jump(DisasContext * ctx) 255 { 256 if (ctx->delayed_pc == -1) { 257 /* Target is not statically known, it comes necessarily from a 258 delayed jump as immediate jump are conditinal jumps */ 259 tcg_gen_mov_i32(cpu_pc, cpu_delayed_pc); 260 tcg_gen_discard_i32(cpu_delayed_pc); 261 if (ctx->base.singlestep_enabled) { 262 gen_helper_debug(cpu_env); 263 } else if (use_exit_tb(ctx)) { 264 tcg_gen_exit_tb(NULL, 0); 265 } else { 266 tcg_gen_lookup_and_goto_ptr(); 267 } 268 ctx->base.is_jmp = DISAS_NORETURN; 269 } else { 270 gen_goto_tb(ctx, 0, ctx->delayed_pc); 271 } 272 } 273 274 /* Immediate conditional jump (bt or bf) */ 275 static void gen_conditional_jump(DisasContext *ctx, target_ulong dest, 276 bool jump_if_true) 277 { 278 TCGLabel *l1 = gen_new_label(); 279 TCGCond cond_not_taken = jump_if_true ? TCG_COND_EQ : TCG_COND_NE; 280 281 if (ctx->tbflags & GUSA_EXCLUSIVE) { 282 /* When in an exclusive region, we must continue to the end. 283 Therefore, exit the region on a taken branch, but otherwise 284 fall through to the next instruction. */ 285 tcg_gen_brcondi_i32(cond_not_taken, cpu_sr_t, 0, l1); 286 tcg_gen_movi_i32(cpu_flags, ctx->envflags & ~GUSA_MASK); 287 /* Note that this won't actually use a goto_tb opcode because we 288 disallow it in use_goto_tb, but it handles exit + singlestep. */ 289 gen_goto_tb(ctx, 0, dest); 290 gen_set_label(l1); 291 ctx->base.is_jmp = DISAS_NEXT; 292 return; 293 } 294 295 gen_save_cpu_state(ctx, false); 296 tcg_gen_brcondi_i32(cond_not_taken, cpu_sr_t, 0, l1); 297 gen_goto_tb(ctx, 0, dest); 298 gen_set_label(l1); 299 gen_goto_tb(ctx, 1, ctx->base.pc_next + 2); 300 ctx->base.is_jmp = DISAS_NORETURN; 301 } 302 303 /* Delayed conditional jump (bt or bf) */ 304 static void gen_delayed_conditional_jump(DisasContext * ctx) 305 { 306 TCGLabel *l1 = gen_new_label(); 307 TCGv ds = tcg_temp_new(); 308 309 tcg_gen_mov_i32(ds, cpu_delayed_cond); 310 tcg_gen_discard_i32(cpu_delayed_cond); 311 312 if (ctx->tbflags & GUSA_EXCLUSIVE) { 313 /* When in an exclusive region, we must continue to the end. 314 Therefore, exit the region on a taken branch, but otherwise 315 fall through to the next instruction. */ 316 tcg_gen_brcondi_i32(TCG_COND_EQ, ds, 0, l1); 317 318 /* Leave the gUSA region. */ 319 tcg_gen_movi_i32(cpu_flags, ctx->envflags & ~GUSA_MASK); 320 gen_jump(ctx); 321 322 gen_set_label(l1); 323 ctx->base.is_jmp = DISAS_NEXT; 324 return; 325 } 326 327 tcg_gen_brcondi_i32(TCG_COND_NE, ds, 0, l1); 328 gen_goto_tb(ctx, 1, ctx->base.pc_next + 2); 329 gen_set_label(l1); 330 gen_jump(ctx); 331 } 332 333 static inline void gen_load_fpr64(DisasContext *ctx, TCGv_i64 t, int reg) 334 { 335 /* We have already signaled illegal instruction for odd Dr. */ 336 tcg_debug_assert((reg & 1) == 0); 337 reg ^= ctx->fbank; 338 tcg_gen_concat_i32_i64(t, cpu_fregs[reg + 1], cpu_fregs[reg]); 339 } 340 341 static inline void gen_store_fpr64(DisasContext *ctx, TCGv_i64 t, int reg) 342 { 343 /* We have already signaled illegal instruction for odd Dr. */ 344 tcg_debug_assert((reg & 1) == 0); 345 reg ^= ctx->fbank; 346 tcg_gen_extr_i64_i32(cpu_fregs[reg + 1], cpu_fregs[reg], t); 347 } 348 349 #define B3_0 (ctx->opcode & 0xf) 350 #define B6_4 ((ctx->opcode >> 4) & 0x7) 351 #define B7_4 ((ctx->opcode >> 4) & 0xf) 352 #define B7_0 (ctx->opcode & 0xff) 353 #define B7_0s ((int32_t) (int8_t) (ctx->opcode & 0xff)) 354 #define B11_0s (ctx->opcode & 0x800 ? 0xfffff000 | (ctx->opcode & 0xfff) : \ 355 (ctx->opcode & 0xfff)) 356 #define B11_8 ((ctx->opcode >> 8) & 0xf) 357 #define B15_12 ((ctx->opcode >> 12) & 0xf) 358 359 #define REG(x) cpu_gregs[(x) ^ ctx->gbank] 360 #define ALTREG(x) cpu_gregs[(x) ^ ctx->gbank ^ 0x10] 361 #define FREG(x) cpu_fregs[(x) ^ ctx->fbank] 362 363 #define XHACK(x) ((((x) & 1 ) << 4) | ((x) & 0xe)) 364 365 #define CHECK_NOT_DELAY_SLOT \ 366 if (ctx->envflags & DELAY_SLOT_MASK) { \ 367 goto do_illegal_slot; \ 368 } 369 370 #define CHECK_PRIVILEGED \ 371 if (IS_USER(ctx)) { \ 372 goto do_illegal; \ 373 } 374 375 #define CHECK_FPU_ENABLED \ 376 if (ctx->tbflags & (1u << SR_FD)) { \ 377 goto do_fpu_disabled; \ 378 } 379 380 #define CHECK_FPSCR_PR_0 \ 381 if (ctx->tbflags & FPSCR_PR) { \ 382 goto do_illegal; \ 383 } 384 385 #define CHECK_FPSCR_PR_1 \ 386 if (!(ctx->tbflags & FPSCR_PR)) { \ 387 goto do_illegal; \ 388 } 389 390 #define CHECK_SH4A \ 391 if (!(ctx->features & SH_FEATURE_SH4A)) { \ 392 goto do_illegal; \ 393 } 394 395 static void _decode_opc(DisasContext * ctx) 396 { 397 /* This code tries to make movcal emulation sufficiently 398 accurate for Linux purposes. This instruction writes 399 memory, and prior to that, always allocates a cache line. 400 It is used in two contexts: 401 - in memcpy, where data is copied in blocks, the first write 402 of to a block uses movca.l for performance. 403 - in arch/sh/mm/cache-sh4.c, movcal.l + ocbi combination is used 404 to flush the cache. Here, the data written by movcal.l is never 405 written to memory, and the data written is just bogus. 406 407 To simulate this, we simulate movcal.l, we store the value to memory, 408 but we also remember the previous content. If we see ocbi, we check 409 if movcal.l for that address was done previously. If so, the write should 410 not have hit the memory, so we restore the previous content. 411 When we see an instruction that is neither movca.l 412 nor ocbi, the previous content is discarded. 413 414 To optimize, we only try to flush stores when we're at the start of 415 TB, or if we already saw movca.l in this TB and did not flush stores 416 yet. */ 417 if (ctx->has_movcal) 418 { 419 int opcode = ctx->opcode & 0xf0ff; 420 if (opcode != 0x0093 /* ocbi */ 421 && opcode != 0x00c3 /* movca.l */) 422 { 423 gen_helper_discard_movcal_backup(cpu_env); 424 ctx->has_movcal = 0; 425 } 426 } 427 428 #if 0 429 fprintf(stderr, "Translating opcode 0x%04x\n", ctx->opcode); 430 #endif 431 432 switch (ctx->opcode) { 433 case 0x0019: /* div0u */ 434 tcg_gen_movi_i32(cpu_sr_m, 0); 435 tcg_gen_movi_i32(cpu_sr_q, 0); 436 tcg_gen_movi_i32(cpu_sr_t, 0); 437 return; 438 case 0x000b: /* rts */ 439 CHECK_NOT_DELAY_SLOT 440 tcg_gen_mov_i32(cpu_delayed_pc, cpu_pr); 441 ctx->envflags |= DELAY_SLOT; 442 ctx->delayed_pc = (uint32_t) - 1; 443 return; 444 case 0x0028: /* clrmac */ 445 tcg_gen_movi_i32(cpu_mach, 0); 446 tcg_gen_movi_i32(cpu_macl, 0); 447 return; 448 case 0x0048: /* clrs */ 449 tcg_gen_andi_i32(cpu_sr, cpu_sr, ~(1u << SR_S)); 450 return; 451 case 0x0008: /* clrt */ 452 tcg_gen_movi_i32(cpu_sr_t, 0); 453 return; 454 case 0x0038: /* ldtlb */ 455 CHECK_PRIVILEGED 456 gen_helper_ldtlb(cpu_env); 457 return; 458 case 0x002b: /* rte */ 459 CHECK_PRIVILEGED 460 CHECK_NOT_DELAY_SLOT 461 gen_write_sr(cpu_ssr); 462 tcg_gen_mov_i32(cpu_delayed_pc, cpu_spc); 463 ctx->envflags |= DELAY_SLOT_RTE; 464 ctx->delayed_pc = (uint32_t) - 1; 465 ctx->base.is_jmp = DISAS_STOP; 466 return; 467 case 0x0058: /* sets */ 468 tcg_gen_ori_i32(cpu_sr, cpu_sr, (1u << SR_S)); 469 return; 470 case 0x0018: /* sett */ 471 tcg_gen_movi_i32(cpu_sr_t, 1); 472 return; 473 case 0xfbfd: /* frchg */ 474 CHECK_FPSCR_PR_0 475 tcg_gen_xori_i32(cpu_fpscr, cpu_fpscr, FPSCR_FR); 476 ctx->base.is_jmp = DISAS_STOP; 477 return; 478 case 0xf3fd: /* fschg */ 479 CHECK_FPSCR_PR_0 480 tcg_gen_xori_i32(cpu_fpscr, cpu_fpscr, FPSCR_SZ); 481 ctx->base.is_jmp = DISAS_STOP; 482 return; 483 case 0xf7fd: /* fpchg */ 484 CHECK_SH4A 485 tcg_gen_xori_i32(cpu_fpscr, cpu_fpscr, FPSCR_PR); 486 ctx->base.is_jmp = DISAS_STOP; 487 return; 488 case 0x0009: /* nop */ 489 return; 490 case 0x001b: /* sleep */ 491 CHECK_PRIVILEGED 492 tcg_gen_movi_i32(cpu_pc, ctx->base.pc_next + 2); 493 gen_helper_sleep(cpu_env); 494 return; 495 } 496 497 switch (ctx->opcode & 0xf000) { 498 case 0x1000: /* mov.l Rm,@(disp,Rn) */ 499 { 500 TCGv addr = tcg_temp_new(); 501 tcg_gen_addi_i32(addr, REG(B11_8), B3_0 * 4); 502 tcg_gen_qemu_st_i32(REG(B7_4), addr, ctx->memidx, MO_TEUL); 503 tcg_temp_free(addr); 504 } 505 return; 506 case 0x5000: /* mov.l @(disp,Rm),Rn */ 507 { 508 TCGv addr = tcg_temp_new(); 509 tcg_gen_addi_i32(addr, REG(B7_4), B3_0 * 4); 510 tcg_gen_qemu_ld_i32(REG(B11_8), addr, ctx->memidx, MO_TESL); 511 tcg_temp_free(addr); 512 } 513 return; 514 case 0xe000: /* mov #imm,Rn */ 515 #ifdef CONFIG_USER_ONLY 516 /* Detect the start of a gUSA region. If so, update envflags 517 and end the TB. This will allow us to see the end of the 518 region (stored in R0) in the next TB. */ 519 if (B11_8 == 15 && B7_0s < 0 && 520 (tb_cflags(ctx->base.tb) & CF_PARALLEL)) { 521 ctx->envflags = deposit32(ctx->envflags, GUSA_SHIFT, 8, B7_0s); 522 ctx->base.is_jmp = DISAS_STOP; 523 } 524 #endif 525 tcg_gen_movi_i32(REG(B11_8), B7_0s); 526 return; 527 case 0x9000: /* mov.w @(disp,PC),Rn */ 528 { 529 TCGv addr = tcg_const_i32(ctx->base.pc_next + 4 + B7_0 * 2); 530 tcg_gen_qemu_ld_i32(REG(B11_8), addr, ctx->memidx, MO_TESW); 531 tcg_temp_free(addr); 532 } 533 return; 534 case 0xd000: /* mov.l @(disp,PC),Rn */ 535 { 536 TCGv addr = tcg_const_i32((ctx->base.pc_next + 4 + B7_0 * 4) & ~3); 537 tcg_gen_qemu_ld_i32(REG(B11_8), addr, ctx->memidx, MO_TESL); 538 tcg_temp_free(addr); 539 } 540 return; 541 case 0x7000: /* add #imm,Rn */ 542 tcg_gen_addi_i32(REG(B11_8), REG(B11_8), B7_0s); 543 return; 544 case 0xa000: /* bra disp */ 545 CHECK_NOT_DELAY_SLOT 546 ctx->delayed_pc = ctx->base.pc_next + 4 + B11_0s * 2; 547 ctx->envflags |= DELAY_SLOT; 548 return; 549 case 0xb000: /* bsr disp */ 550 CHECK_NOT_DELAY_SLOT 551 tcg_gen_movi_i32(cpu_pr, ctx->base.pc_next + 4); 552 ctx->delayed_pc = ctx->base.pc_next + 4 + B11_0s * 2; 553 ctx->envflags |= DELAY_SLOT; 554 return; 555 } 556 557 switch (ctx->opcode & 0xf00f) { 558 case 0x6003: /* mov Rm,Rn */ 559 tcg_gen_mov_i32(REG(B11_8), REG(B7_4)); 560 return; 561 case 0x2000: /* mov.b Rm,@Rn */ 562 tcg_gen_qemu_st_i32(REG(B7_4), REG(B11_8), ctx->memidx, MO_UB); 563 return; 564 case 0x2001: /* mov.w Rm,@Rn */ 565 tcg_gen_qemu_st_i32(REG(B7_4), REG(B11_8), ctx->memidx, MO_TEUW); 566 return; 567 case 0x2002: /* mov.l Rm,@Rn */ 568 tcg_gen_qemu_st_i32(REG(B7_4), REG(B11_8), ctx->memidx, MO_TEUL); 569 return; 570 case 0x6000: /* mov.b @Rm,Rn */ 571 tcg_gen_qemu_ld_i32(REG(B11_8), REG(B7_4), ctx->memidx, MO_SB); 572 return; 573 case 0x6001: /* mov.w @Rm,Rn */ 574 tcg_gen_qemu_ld_i32(REG(B11_8), REG(B7_4), ctx->memidx, MO_TESW); 575 return; 576 case 0x6002: /* mov.l @Rm,Rn */ 577 tcg_gen_qemu_ld_i32(REG(B11_8), REG(B7_4), ctx->memidx, MO_TESL); 578 return; 579 case 0x2004: /* mov.b Rm,@-Rn */ 580 { 581 TCGv addr = tcg_temp_new(); 582 tcg_gen_subi_i32(addr, REG(B11_8), 1); 583 /* might cause re-execution */ 584 tcg_gen_qemu_st_i32(REG(B7_4), addr, ctx->memidx, MO_UB); 585 tcg_gen_mov_i32(REG(B11_8), addr); /* modify register status */ 586 tcg_temp_free(addr); 587 } 588 return; 589 case 0x2005: /* mov.w Rm,@-Rn */ 590 { 591 TCGv addr = tcg_temp_new(); 592 tcg_gen_subi_i32(addr, REG(B11_8), 2); 593 tcg_gen_qemu_st_i32(REG(B7_4), addr, ctx->memidx, MO_TEUW); 594 tcg_gen_mov_i32(REG(B11_8), addr); 595 tcg_temp_free(addr); 596 } 597 return; 598 case 0x2006: /* mov.l Rm,@-Rn */ 599 { 600 TCGv addr = tcg_temp_new(); 601 tcg_gen_subi_i32(addr, REG(B11_8), 4); 602 tcg_gen_qemu_st_i32(REG(B7_4), addr, ctx->memidx, MO_TEUL); 603 tcg_gen_mov_i32(REG(B11_8), addr); 604 tcg_temp_free(addr); 605 } 606 return; 607 case 0x6004: /* mov.b @Rm+,Rn */ 608 tcg_gen_qemu_ld_i32(REG(B11_8), REG(B7_4), ctx->memidx, MO_SB); 609 if ( B11_8 != B7_4 ) 610 tcg_gen_addi_i32(REG(B7_4), REG(B7_4), 1); 611 return; 612 case 0x6005: /* mov.w @Rm+,Rn */ 613 tcg_gen_qemu_ld_i32(REG(B11_8), REG(B7_4), ctx->memidx, MO_TESW); 614 if ( B11_8 != B7_4 ) 615 tcg_gen_addi_i32(REG(B7_4), REG(B7_4), 2); 616 return; 617 case 0x6006: /* mov.l @Rm+,Rn */ 618 tcg_gen_qemu_ld_i32(REG(B11_8), REG(B7_4), ctx->memidx, MO_TESL); 619 if ( B11_8 != B7_4 ) 620 tcg_gen_addi_i32(REG(B7_4), REG(B7_4), 4); 621 return; 622 case 0x0004: /* mov.b Rm,@(R0,Rn) */ 623 { 624 TCGv addr = tcg_temp_new(); 625 tcg_gen_add_i32(addr, REG(B11_8), REG(0)); 626 tcg_gen_qemu_st_i32(REG(B7_4), addr, ctx->memidx, MO_UB); 627 tcg_temp_free(addr); 628 } 629 return; 630 case 0x0005: /* mov.w Rm,@(R0,Rn) */ 631 { 632 TCGv addr = tcg_temp_new(); 633 tcg_gen_add_i32(addr, REG(B11_8), REG(0)); 634 tcg_gen_qemu_st_i32(REG(B7_4), addr, ctx->memidx, MO_TEUW); 635 tcg_temp_free(addr); 636 } 637 return; 638 case 0x0006: /* mov.l Rm,@(R0,Rn) */ 639 { 640 TCGv addr = tcg_temp_new(); 641 tcg_gen_add_i32(addr, REG(B11_8), REG(0)); 642 tcg_gen_qemu_st_i32(REG(B7_4), addr, ctx->memidx, MO_TEUL); 643 tcg_temp_free(addr); 644 } 645 return; 646 case 0x000c: /* mov.b @(R0,Rm),Rn */ 647 { 648 TCGv addr = tcg_temp_new(); 649 tcg_gen_add_i32(addr, REG(B7_4), REG(0)); 650 tcg_gen_qemu_ld_i32(REG(B11_8), addr, ctx->memidx, MO_SB); 651 tcg_temp_free(addr); 652 } 653 return; 654 case 0x000d: /* mov.w @(R0,Rm),Rn */ 655 { 656 TCGv addr = tcg_temp_new(); 657 tcg_gen_add_i32(addr, REG(B7_4), REG(0)); 658 tcg_gen_qemu_ld_i32(REG(B11_8), addr, ctx->memidx, MO_TESW); 659 tcg_temp_free(addr); 660 } 661 return; 662 case 0x000e: /* mov.l @(R0,Rm),Rn */ 663 { 664 TCGv addr = tcg_temp_new(); 665 tcg_gen_add_i32(addr, REG(B7_4), REG(0)); 666 tcg_gen_qemu_ld_i32(REG(B11_8), addr, ctx->memidx, MO_TESL); 667 tcg_temp_free(addr); 668 } 669 return; 670 case 0x6008: /* swap.b Rm,Rn */ 671 { 672 TCGv low = tcg_temp_new(); 673 tcg_gen_bswap16_i32(low, REG(B7_4), 0); 674 tcg_gen_deposit_i32(REG(B11_8), REG(B7_4), low, 0, 16); 675 tcg_temp_free(low); 676 } 677 return; 678 case 0x6009: /* swap.w Rm,Rn */ 679 tcg_gen_rotli_i32(REG(B11_8), REG(B7_4), 16); 680 return; 681 case 0x200d: /* xtrct Rm,Rn */ 682 { 683 TCGv high, low; 684 high = tcg_temp_new(); 685 tcg_gen_shli_i32(high, REG(B7_4), 16); 686 low = tcg_temp_new(); 687 tcg_gen_shri_i32(low, REG(B11_8), 16); 688 tcg_gen_or_i32(REG(B11_8), high, low); 689 tcg_temp_free(low); 690 tcg_temp_free(high); 691 } 692 return; 693 case 0x300c: /* add Rm,Rn */ 694 tcg_gen_add_i32(REG(B11_8), REG(B11_8), REG(B7_4)); 695 return; 696 case 0x300e: /* addc Rm,Rn */ 697 { 698 TCGv t0, t1; 699 t0 = tcg_const_tl(0); 700 t1 = tcg_temp_new(); 701 tcg_gen_add2_i32(t1, cpu_sr_t, cpu_sr_t, t0, REG(B7_4), t0); 702 tcg_gen_add2_i32(REG(B11_8), cpu_sr_t, 703 REG(B11_8), t0, t1, cpu_sr_t); 704 tcg_temp_free(t0); 705 tcg_temp_free(t1); 706 } 707 return; 708 case 0x300f: /* addv Rm,Rn */ 709 { 710 TCGv t0, t1, t2; 711 t0 = tcg_temp_new(); 712 tcg_gen_add_i32(t0, REG(B7_4), REG(B11_8)); 713 t1 = tcg_temp_new(); 714 tcg_gen_xor_i32(t1, t0, REG(B11_8)); 715 t2 = tcg_temp_new(); 716 tcg_gen_xor_i32(t2, REG(B7_4), REG(B11_8)); 717 tcg_gen_andc_i32(cpu_sr_t, t1, t2); 718 tcg_temp_free(t2); 719 tcg_gen_shri_i32(cpu_sr_t, cpu_sr_t, 31); 720 tcg_temp_free(t1); 721 tcg_gen_mov_i32(REG(B7_4), t0); 722 tcg_temp_free(t0); 723 } 724 return; 725 case 0x2009: /* and Rm,Rn */ 726 tcg_gen_and_i32(REG(B11_8), REG(B11_8), REG(B7_4)); 727 return; 728 case 0x3000: /* cmp/eq Rm,Rn */ 729 tcg_gen_setcond_i32(TCG_COND_EQ, cpu_sr_t, REG(B11_8), REG(B7_4)); 730 return; 731 case 0x3003: /* cmp/ge Rm,Rn */ 732 tcg_gen_setcond_i32(TCG_COND_GE, cpu_sr_t, REG(B11_8), REG(B7_4)); 733 return; 734 case 0x3007: /* cmp/gt Rm,Rn */ 735 tcg_gen_setcond_i32(TCG_COND_GT, cpu_sr_t, REG(B11_8), REG(B7_4)); 736 return; 737 case 0x3006: /* cmp/hi Rm,Rn */ 738 tcg_gen_setcond_i32(TCG_COND_GTU, cpu_sr_t, REG(B11_8), REG(B7_4)); 739 return; 740 case 0x3002: /* cmp/hs Rm,Rn */ 741 tcg_gen_setcond_i32(TCG_COND_GEU, cpu_sr_t, REG(B11_8), REG(B7_4)); 742 return; 743 case 0x200c: /* cmp/str Rm,Rn */ 744 { 745 TCGv cmp1 = tcg_temp_new(); 746 TCGv cmp2 = tcg_temp_new(); 747 tcg_gen_xor_i32(cmp2, REG(B7_4), REG(B11_8)); 748 tcg_gen_subi_i32(cmp1, cmp2, 0x01010101); 749 tcg_gen_andc_i32(cmp1, cmp1, cmp2); 750 tcg_gen_andi_i32(cmp1, cmp1, 0x80808080); 751 tcg_gen_setcondi_i32(TCG_COND_NE, cpu_sr_t, cmp1, 0); 752 tcg_temp_free(cmp2); 753 tcg_temp_free(cmp1); 754 } 755 return; 756 case 0x2007: /* div0s Rm,Rn */ 757 tcg_gen_shri_i32(cpu_sr_q, REG(B11_8), 31); /* SR_Q */ 758 tcg_gen_shri_i32(cpu_sr_m, REG(B7_4), 31); /* SR_M */ 759 tcg_gen_xor_i32(cpu_sr_t, cpu_sr_q, cpu_sr_m); /* SR_T */ 760 return; 761 case 0x3004: /* div1 Rm,Rn */ 762 { 763 TCGv t0 = tcg_temp_new(); 764 TCGv t1 = tcg_temp_new(); 765 TCGv t2 = tcg_temp_new(); 766 TCGv zero = tcg_const_i32(0); 767 768 /* shift left arg1, saving the bit being pushed out and inserting 769 T on the right */ 770 tcg_gen_shri_i32(t0, REG(B11_8), 31); 771 tcg_gen_shli_i32(REG(B11_8), REG(B11_8), 1); 772 tcg_gen_or_i32(REG(B11_8), REG(B11_8), cpu_sr_t); 773 774 /* Add or subtract arg0 from arg1 depending if Q == M. To avoid 775 using 64-bit temps, we compute arg0's high part from q ^ m, so 776 that it is 0x00000000 when adding the value or 0xffffffff when 777 subtracting it. */ 778 tcg_gen_xor_i32(t1, cpu_sr_q, cpu_sr_m); 779 tcg_gen_subi_i32(t1, t1, 1); 780 tcg_gen_neg_i32(t2, REG(B7_4)); 781 tcg_gen_movcond_i32(TCG_COND_EQ, t2, t1, zero, REG(B7_4), t2); 782 tcg_gen_add2_i32(REG(B11_8), t1, REG(B11_8), zero, t2, t1); 783 784 /* compute T and Q depending on carry */ 785 tcg_gen_andi_i32(t1, t1, 1); 786 tcg_gen_xor_i32(t1, t1, t0); 787 tcg_gen_xori_i32(cpu_sr_t, t1, 1); 788 tcg_gen_xor_i32(cpu_sr_q, cpu_sr_m, t1); 789 790 tcg_temp_free(zero); 791 tcg_temp_free(t2); 792 tcg_temp_free(t1); 793 tcg_temp_free(t0); 794 } 795 return; 796 case 0x300d: /* dmuls.l Rm,Rn */ 797 tcg_gen_muls2_i32(cpu_macl, cpu_mach, REG(B7_4), REG(B11_8)); 798 return; 799 case 0x3005: /* dmulu.l Rm,Rn */ 800 tcg_gen_mulu2_i32(cpu_macl, cpu_mach, REG(B7_4), REG(B11_8)); 801 return; 802 case 0x600e: /* exts.b Rm,Rn */ 803 tcg_gen_ext8s_i32(REG(B11_8), REG(B7_4)); 804 return; 805 case 0x600f: /* exts.w Rm,Rn */ 806 tcg_gen_ext16s_i32(REG(B11_8), REG(B7_4)); 807 return; 808 case 0x600c: /* extu.b Rm,Rn */ 809 tcg_gen_ext8u_i32(REG(B11_8), REG(B7_4)); 810 return; 811 case 0x600d: /* extu.w Rm,Rn */ 812 tcg_gen_ext16u_i32(REG(B11_8), REG(B7_4)); 813 return; 814 case 0x000f: /* mac.l @Rm+,@Rn+ */ 815 { 816 TCGv arg0, arg1; 817 arg0 = tcg_temp_new(); 818 tcg_gen_qemu_ld_i32(arg0, REG(B7_4), ctx->memidx, MO_TESL); 819 arg1 = tcg_temp_new(); 820 tcg_gen_qemu_ld_i32(arg1, REG(B11_8), ctx->memidx, MO_TESL); 821 gen_helper_macl(cpu_env, arg0, arg1); 822 tcg_temp_free(arg1); 823 tcg_temp_free(arg0); 824 tcg_gen_addi_i32(REG(B7_4), REG(B7_4), 4); 825 tcg_gen_addi_i32(REG(B11_8), REG(B11_8), 4); 826 } 827 return; 828 case 0x400f: /* mac.w @Rm+,@Rn+ */ 829 { 830 TCGv arg0, arg1; 831 arg0 = tcg_temp_new(); 832 tcg_gen_qemu_ld_i32(arg0, REG(B7_4), ctx->memidx, MO_TESL); 833 arg1 = tcg_temp_new(); 834 tcg_gen_qemu_ld_i32(arg1, REG(B11_8), ctx->memidx, MO_TESL); 835 gen_helper_macw(cpu_env, arg0, arg1); 836 tcg_temp_free(arg1); 837 tcg_temp_free(arg0); 838 tcg_gen_addi_i32(REG(B11_8), REG(B11_8), 2); 839 tcg_gen_addi_i32(REG(B7_4), REG(B7_4), 2); 840 } 841 return; 842 case 0x0007: /* mul.l Rm,Rn */ 843 tcg_gen_mul_i32(cpu_macl, REG(B7_4), REG(B11_8)); 844 return; 845 case 0x200f: /* muls.w Rm,Rn */ 846 { 847 TCGv arg0, arg1; 848 arg0 = tcg_temp_new(); 849 tcg_gen_ext16s_i32(arg0, REG(B7_4)); 850 arg1 = tcg_temp_new(); 851 tcg_gen_ext16s_i32(arg1, REG(B11_8)); 852 tcg_gen_mul_i32(cpu_macl, arg0, arg1); 853 tcg_temp_free(arg1); 854 tcg_temp_free(arg0); 855 } 856 return; 857 case 0x200e: /* mulu.w Rm,Rn */ 858 { 859 TCGv arg0, arg1; 860 arg0 = tcg_temp_new(); 861 tcg_gen_ext16u_i32(arg0, REG(B7_4)); 862 arg1 = tcg_temp_new(); 863 tcg_gen_ext16u_i32(arg1, REG(B11_8)); 864 tcg_gen_mul_i32(cpu_macl, arg0, arg1); 865 tcg_temp_free(arg1); 866 tcg_temp_free(arg0); 867 } 868 return; 869 case 0x600b: /* neg Rm,Rn */ 870 tcg_gen_neg_i32(REG(B11_8), REG(B7_4)); 871 return; 872 case 0x600a: /* negc Rm,Rn */ 873 { 874 TCGv t0 = tcg_const_i32(0); 875 tcg_gen_add2_i32(REG(B11_8), cpu_sr_t, 876 REG(B7_4), t0, cpu_sr_t, t0); 877 tcg_gen_sub2_i32(REG(B11_8), cpu_sr_t, 878 t0, t0, REG(B11_8), cpu_sr_t); 879 tcg_gen_andi_i32(cpu_sr_t, cpu_sr_t, 1); 880 tcg_temp_free(t0); 881 } 882 return; 883 case 0x6007: /* not Rm,Rn */ 884 tcg_gen_not_i32(REG(B11_8), REG(B7_4)); 885 return; 886 case 0x200b: /* or Rm,Rn */ 887 tcg_gen_or_i32(REG(B11_8), REG(B11_8), REG(B7_4)); 888 return; 889 case 0x400c: /* shad Rm,Rn */ 890 { 891 TCGv t0 = tcg_temp_new(); 892 TCGv t1 = tcg_temp_new(); 893 TCGv t2 = tcg_temp_new(); 894 895 tcg_gen_andi_i32(t0, REG(B7_4), 0x1f); 896 897 /* positive case: shift to the left */ 898 tcg_gen_shl_i32(t1, REG(B11_8), t0); 899 900 /* negative case: shift to the right in two steps to 901 correctly handle the -32 case */ 902 tcg_gen_xori_i32(t0, t0, 0x1f); 903 tcg_gen_sar_i32(t2, REG(B11_8), t0); 904 tcg_gen_sari_i32(t2, t2, 1); 905 906 /* select between the two cases */ 907 tcg_gen_movi_i32(t0, 0); 908 tcg_gen_movcond_i32(TCG_COND_GE, REG(B11_8), REG(B7_4), t0, t1, t2); 909 910 tcg_temp_free(t0); 911 tcg_temp_free(t1); 912 tcg_temp_free(t2); 913 } 914 return; 915 case 0x400d: /* shld Rm,Rn */ 916 { 917 TCGv t0 = tcg_temp_new(); 918 TCGv t1 = tcg_temp_new(); 919 TCGv t2 = tcg_temp_new(); 920 921 tcg_gen_andi_i32(t0, REG(B7_4), 0x1f); 922 923 /* positive case: shift to the left */ 924 tcg_gen_shl_i32(t1, REG(B11_8), t0); 925 926 /* negative case: shift to the right in two steps to 927 correctly handle the -32 case */ 928 tcg_gen_xori_i32(t0, t0, 0x1f); 929 tcg_gen_shr_i32(t2, REG(B11_8), t0); 930 tcg_gen_shri_i32(t2, t2, 1); 931 932 /* select between the two cases */ 933 tcg_gen_movi_i32(t0, 0); 934 tcg_gen_movcond_i32(TCG_COND_GE, REG(B11_8), REG(B7_4), t0, t1, t2); 935 936 tcg_temp_free(t0); 937 tcg_temp_free(t1); 938 tcg_temp_free(t2); 939 } 940 return; 941 case 0x3008: /* sub Rm,Rn */ 942 tcg_gen_sub_i32(REG(B11_8), REG(B11_8), REG(B7_4)); 943 return; 944 case 0x300a: /* subc Rm,Rn */ 945 { 946 TCGv t0, t1; 947 t0 = tcg_const_tl(0); 948 t1 = tcg_temp_new(); 949 tcg_gen_add2_i32(t1, cpu_sr_t, cpu_sr_t, t0, REG(B7_4), t0); 950 tcg_gen_sub2_i32(REG(B11_8), cpu_sr_t, 951 REG(B11_8), t0, t1, cpu_sr_t); 952 tcg_gen_andi_i32(cpu_sr_t, cpu_sr_t, 1); 953 tcg_temp_free(t0); 954 tcg_temp_free(t1); 955 } 956 return; 957 case 0x300b: /* subv Rm,Rn */ 958 { 959 TCGv t0, t1, t2; 960 t0 = tcg_temp_new(); 961 tcg_gen_sub_i32(t0, REG(B11_8), REG(B7_4)); 962 t1 = tcg_temp_new(); 963 tcg_gen_xor_i32(t1, t0, REG(B7_4)); 964 t2 = tcg_temp_new(); 965 tcg_gen_xor_i32(t2, REG(B11_8), REG(B7_4)); 966 tcg_gen_and_i32(t1, t1, t2); 967 tcg_temp_free(t2); 968 tcg_gen_shri_i32(cpu_sr_t, t1, 31); 969 tcg_temp_free(t1); 970 tcg_gen_mov_i32(REG(B11_8), t0); 971 tcg_temp_free(t0); 972 } 973 return; 974 case 0x2008: /* tst Rm,Rn */ 975 { 976 TCGv val = tcg_temp_new(); 977 tcg_gen_and_i32(val, REG(B7_4), REG(B11_8)); 978 tcg_gen_setcondi_i32(TCG_COND_EQ, cpu_sr_t, val, 0); 979 tcg_temp_free(val); 980 } 981 return; 982 case 0x200a: /* xor Rm,Rn */ 983 tcg_gen_xor_i32(REG(B11_8), REG(B11_8), REG(B7_4)); 984 return; 985 case 0xf00c: /* fmov {F,D,X}Rm,{F,D,X}Rn - FPSCR: Nothing */ 986 CHECK_FPU_ENABLED 987 if (ctx->tbflags & FPSCR_SZ) { 988 int xsrc = XHACK(B7_4); 989 int xdst = XHACK(B11_8); 990 tcg_gen_mov_i32(FREG(xdst), FREG(xsrc)); 991 tcg_gen_mov_i32(FREG(xdst + 1), FREG(xsrc + 1)); 992 } else { 993 tcg_gen_mov_i32(FREG(B11_8), FREG(B7_4)); 994 } 995 return; 996 case 0xf00a: /* fmov {F,D,X}Rm,@Rn - FPSCR: Nothing */ 997 CHECK_FPU_ENABLED 998 if (ctx->tbflags & FPSCR_SZ) { 999 TCGv_i64 fp = tcg_temp_new_i64(); 1000 gen_load_fpr64(ctx, fp, XHACK(B7_4)); 1001 tcg_gen_qemu_st_i64(fp, REG(B11_8), ctx->memidx, MO_TEQ); 1002 tcg_temp_free_i64(fp); 1003 } else { 1004 tcg_gen_qemu_st_i32(FREG(B7_4), REG(B11_8), ctx->memidx, MO_TEUL); 1005 } 1006 return; 1007 case 0xf008: /* fmov @Rm,{F,D,X}Rn - FPSCR: Nothing */ 1008 CHECK_FPU_ENABLED 1009 if (ctx->tbflags & FPSCR_SZ) { 1010 TCGv_i64 fp = tcg_temp_new_i64(); 1011 tcg_gen_qemu_ld_i64(fp, REG(B7_4), ctx->memidx, MO_TEQ); 1012 gen_store_fpr64(ctx, fp, XHACK(B11_8)); 1013 tcg_temp_free_i64(fp); 1014 } else { 1015 tcg_gen_qemu_ld_i32(FREG(B11_8), REG(B7_4), ctx->memidx, MO_TEUL); 1016 } 1017 return; 1018 case 0xf009: /* fmov @Rm+,{F,D,X}Rn - FPSCR: Nothing */ 1019 CHECK_FPU_ENABLED 1020 if (ctx->tbflags & FPSCR_SZ) { 1021 TCGv_i64 fp = tcg_temp_new_i64(); 1022 tcg_gen_qemu_ld_i64(fp, REG(B7_4), ctx->memidx, MO_TEQ); 1023 gen_store_fpr64(ctx, fp, XHACK(B11_8)); 1024 tcg_temp_free_i64(fp); 1025 tcg_gen_addi_i32(REG(B7_4), REG(B7_4), 8); 1026 } else { 1027 tcg_gen_qemu_ld_i32(FREG(B11_8), REG(B7_4), ctx->memidx, MO_TEUL); 1028 tcg_gen_addi_i32(REG(B7_4), REG(B7_4), 4); 1029 } 1030 return; 1031 case 0xf00b: /* fmov {F,D,X}Rm,@-Rn - FPSCR: Nothing */ 1032 CHECK_FPU_ENABLED 1033 { 1034 TCGv addr = tcg_temp_new_i32(); 1035 if (ctx->tbflags & FPSCR_SZ) { 1036 TCGv_i64 fp = tcg_temp_new_i64(); 1037 gen_load_fpr64(ctx, fp, XHACK(B7_4)); 1038 tcg_gen_subi_i32(addr, REG(B11_8), 8); 1039 tcg_gen_qemu_st_i64(fp, addr, ctx->memidx, MO_TEQ); 1040 tcg_temp_free_i64(fp); 1041 } else { 1042 tcg_gen_subi_i32(addr, REG(B11_8), 4); 1043 tcg_gen_qemu_st_i32(FREG(B7_4), addr, ctx->memidx, MO_TEUL); 1044 } 1045 tcg_gen_mov_i32(REG(B11_8), addr); 1046 tcg_temp_free(addr); 1047 } 1048 return; 1049 case 0xf006: /* fmov @(R0,Rm),{F,D,X}Rm - FPSCR: Nothing */ 1050 CHECK_FPU_ENABLED 1051 { 1052 TCGv addr = tcg_temp_new_i32(); 1053 tcg_gen_add_i32(addr, REG(B7_4), REG(0)); 1054 if (ctx->tbflags & FPSCR_SZ) { 1055 TCGv_i64 fp = tcg_temp_new_i64(); 1056 tcg_gen_qemu_ld_i64(fp, addr, ctx->memidx, MO_TEQ); 1057 gen_store_fpr64(ctx, fp, XHACK(B11_8)); 1058 tcg_temp_free_i64(fp); 1059 } else { 1060 tcg_gen_qemu_ld_i32(FREG(B11_8), addr, ctx->memidx, MO_TEUL); 1061 } 1062 tcg_temp_free(addr); 1063 } 1064 return; 1065 case 0xf007: /* fmov {F,D,X}Rn,@(R0,Rn) - FPSCR: Nothing */ 1066 CHECK_FPU_ENABLED 1067 { 1068 TCGv addr = tcg_temp_new(); 1069 tcg_gen_add_i32(addr, REG(B11_8), REG(0)); 1070 if (ctx->tbflags & FPSCR_SZ) { 1071 TCGv_i64 fp = tcg_temp_new_i64(); 1072 gen_load_fpr64(ctx, fp, XHACK(B7_4)); 1073 tcg_gen_qemu_st_i64(fp, addr, ctx->memidx, MO_TEQ); 1074 tcg_temp_free_i64(fp); 1075 } else { 1076 tcg_gen_qemu_st_i32(FREG(B7_4), addr, ctx->memidx, MO_TEUL); 1077 } 1078 tcg_temp_free(addr); 1079 } 1080 return; 1081 case 0xf000: /* fadd Rm,Rn - FPSCR: R[PR,Enable.O/U/I]/W[Cause,Flag] */ 1082 case 0xf001: /* fsub Rm,Rn - FPSCR: R[PR,Enable.O/U/I]/W[Cause,Flag] */ 1083 case 0xf002: /* fmul Rm,Rn - FPSCR: R[PR,Enable.O/U/I]/W[Cause,Flag] */ 1084 case 0xf003: /* fdiv Rm,Rn - FPSCR: R[PR,Enable.O/U/I]/W[Cause,Flag] */ 1085 case 0xf004: /* fcmp/eq Rm,Rn - FPSCR: R[PR,Enable.V]/W[Cause,Flag] */ 1086 case 0xf005: /* fcmp/gt Rm,Rn - FPSCR: R[PR,Enable.V]/W[Cause,Flag] */ 1087 { 1088 CHECK_FPU_ENABLED 1089 if (ctx->tbflags & FPSCR_PR) { 1090 TCGv_i64 fp0, fp1; 1091 1092 if (ctx->opcode & 0x0110) { 1093 goto do_illegal; 1094 } 1095 fp0 = tcg_temp_new_i64(); 1096 fp1 = tcg_temp_new_i64(); 1097 gen_load_fpr64(ctx, fp0, B11_8); 1098 gen_load_fpr64(ctx, fp1, B7_4); 1099 switch (ctx->opcode & 0xf00f) { 1100 case 0xf000: /* fadd Rm,Rn */ 1101 gen_helper_fadd_DT(fp0, cpu_env, fp0, fp1); 1102 break; 1103 case 0xf001: /* fsub Rm,Rn */ 1104 gen_helper_fsub_DT(fp0, cpu_env, fp0, fp1); 1105 break; 1106 case 0xf002: /* fmul Rm,Rn */ 1107 gen_helper_fmul_DT(fp0, cpu_env, fp0, fp1); 1108 break; 1109 case 0xf003: /* fdiv Rm,Rn */ 1110 gen_helper_fdiv_DT(fp0, cpu_env, fp0, fp1); 1111 break; 1112 case 0xf004: /* fcmp/eq Rm,Rn */ 1113 gen_helper_fcmp_eq_DT(cpu_sr_t, cpu_env, fp0, fp1); 1114 return; 1115 case 0xf005: /* fcmp/gt Rm,Rn */ 1116 gen_helper_fcmp_gt_DT(cpu_sr_t, cpu_env, fp0, fp1); 1117 return; 1118 } 1119 gen_store_fpr64(ctx, fp0, B11_8); 1120 tcg_temp_free_i64(fp0); 1121 tcg_temp_free_i64(fp1); 1122 } else { 1123 switch (ctx->opcode & 0xf00f) { 1124 case 0xf000: /* fadd Rm,Rn */ 1125 gen_helper_fadd_FT(FREG(B11_8), cpu_env, 1126 FREG(B11_8), FREG(B7_4)); 1127 break; 1128 case 0xf001: /* fsub Rm,Rn */ 1129 gen_helper_fsub_FT(FREG(B11_8), cpu_env, 1130 FREG(B11_8), FREG(B7_4)); 1131 break; 1132 case 0xf002: /* fmul Rm,Rn */ 1133 gen_helper_fmul_FT(FREG(B11_8), cpu_env, 1134 FREG(B11_8), FREG(B7_4)); 1135 break; 1136 case 0xf003: /* fdiv Rm,Rn */ 1137 gen_helper_fdiv_FT(FREG(B11_8), cpu_env, 1138 FREG(B11_8), FREG(B7_4)); 1139 break; 1140 case 0xf004: /* fcmp/eq Rm,Rn */ 1141 gen_helper_fcmp_eq_FT(cpu_sr_t, cpu_env, 1142 FREG(B11_8), FREG(B7_4)); 1143 return; 1144 case 0xf005: /* fcmp/gt Rm,Rn */ 1145 gen_helper_fcmp_gt_FT(cpu_sr_t, cpu_env, 1146 FREG(B11_8), FREG(B7_4)); 1147 return; 1148 } 1149 } 1150 } 1151 return; 1152 case 0xf00e: /* fmac FR0,RM,Rn */ 1153 CHECK_FPU_ENABLED 1154 CHECK_FPSCR_PR_0 1155 gen_helper_fmac_FT(FREG(B11_8), cpu_env, 1156 FREG(0), FREG(B7_4), FREG(B11_8)); 1157 return; 1158 } 1159 1160 switch (ctx->opcode & 0xff00) { 1161 case 0xc900: /* and #imm,R0 */ 1162 tcg_gen_andi_i32(REG(0), REG(0), B7_0); 1163 return; 1164 case 0xcd00: /* and.b #imm,@(R0,GBR) */ 1165 { 1166 TCGv addr, val; 1167 addr = tcg_temp_new(); 1168 tcg_gen_add_i32(addr, REG(0), cpu_gbr); 1169 val = tcg_temp_new(); 1170 tcg_gen_qemu_ld_i32(val, addr, ctx->memidx, MO_UB); 1171 tcg_gen_andi_i32(val, val, B7_0); 1172 tcg_gen_qemu_st_i32(val, addr, ctx->memidx, MO_UB); 1173 tcg_temp_free(val); 1174 tcg_temp_free(addr); 1175 } 1176 return; 1177 case 0x8b00: /* bf label */ 1178 CHECK_NOT_DELAY_SLOT 1179 gen_conditional_jump(ctx, ctx->base.pc_next + 4 + B7_0s * 2, false); 1180 return; 1181 case 0x8f00: /* bf/s label */ 1182 CHECK_NOT_DELAY_SLOT 1183 tcg_gen_xori_i32(cpu_delayed_cond, cpu_sr_t, 1); 1184 ctx->delayed_pc = ctx->base.pc_next + 4 + B7_0s * 2; 1185 ctx->envflags |= DELAY_SLOT_CONDITIONAL; 1186 return; 1187 case 0x8900: /* bt label */ 1188 CHECK_NOT_DELAY_SLOT 1189 gen_conditional_jump(ctx, ctx->base.pc_next + 4 + B7_0s * 2, true); 1190 return; 1191 case 0x8d00: /* bt/s label */ 1192 CHECK_NOT_DELAY_SLOT 1193 tcg_gen_mov_i32(cpu_delayed_cond, cpu_sr_t); 1194 ctx->delayed_pc = ctx->base.pc_next + 4 + B7_0s * 2; 1195 ctx->envflags |= DELAY_SLOT_CONDITIONAL; 1196 return; 1197 case 0x8800: /* cmp/eq #imm,R0 */ 1198 tcg_gen_setcondi_i32(TCG_COND_EQ, cpu_sr_t, REG(0), B7_0s); 1199 return; 1200 case 0xc400: /* mov.b @(disp,GBR),R0 */ 1201 { 1202 TCGv addr = tcg_temp_new(); 1203 tcg_gen_addi_i32(addr, cpu_gbr, B7_0); 1204 tcg_gen_qemu_ld_i32(REG(0), addr, ctx->memidx, MO_SB); 1205 tcg_temp_free(addr); 1206 } 1207 return; 1208 case 0xc500: /* mov.w @(disp,GBR),R0 */ 1209 { 1210 TCGv addr = tcg_temp_new(); 1211 tcg_gen_addi_i32(addr, cpu_gbr, B7_0 * 2); 1212 tcg_gen_qemu_ld_i32(REG(0), addr, ctx->memidx, MO_TESW); 1213 tcg_temp_free(addr); 1214 } 1215 return; 1216 case 0xc600: /* mov.l @(disp,GBR),R0 */ 1217 { 1218 TCGv addr = tcg_temp_new(); 1219 tcg_gen_addi_i32(addr, cpu_gbr, B7_0 * 4); 1220 tcg_gen_qemu_ld_i32(REG(0), addr, ctx->memidx, MO_TESL); 1221 tcg_temp_free(addr); 1222 } 1223 return; 1224 case 0xc000: /* mov.b R0,@(disp,GBR) */ 1225 { 1226 TCGv addr = tcg_temp_new(); 1227 tcg_gen_addi_i32(addr, cpu_gbr, B7_0); 1228 tcg_gen_qemu_st_i32(REG(0), addr, ctx->memidx, MO_UB); 1229 tcg_temp_free(addr); 1230 } 1231 return; 1232 case 0xc100: /* mov.w R0,@(disp,GBR) */ 1233 { 1234 TCGv addr = tcg_temp_new(); 1235 tcg_gen_addi_i32(addr, cpu_gbr, B7_0 * 2); 1236 tcg_gen_qemu_st_i32(REG(0), addr, ctx->memidx, MO_TEUW); 1237 tcg_temp_free(addr); 1238 } 1239 return; 1240 case 0xc200: /* mov.l R0,@(disp,GBR) */ 1241 { 1242 TCGv addr = tcg_temp_new(); 1243 tcg_gen_addi_i32(addr, cpu_gbr, B7_0 * 4); 1244 tcg_gen_qemu_st_i32(REG(0), addr, ctx->memidx, MO_TEUL); 1245 tcg_temp_free(addr); 1246 } 1247 return; 1248 case 0x8000: /* mov.b R0,@(disp,Rn) */ 1249 { 1250 TCGv addr = tcg_temp_new(); 1251 tcg_gen_addi_i32(addr, REG(B7_4), B3_0); 1252 tcg_gen_qemu_st_i32(REG(0), addr, ctx->memidx, MO_UB); 1253 tcg_temp_free(addr); 1254 } 1255 return; 1256 case 0x8100: /* mov.w R0,@(disp,Rn) */ 1257 { 1258 TCGv addr = tcg_temp_new(); 1259 tcg_gen_addi_i32(addr, REG(B7_4), B3_0 * 2); 1260 tcg_gen_qemu_st_i32(REG(0), addr, ctx->memidx, MO_TEUW); 1261 tcg_temp_free(addr); 1262 } 1263 return; 1264 case 0x8400: /* mov.b @(disp,Rn),R0 */ 1265 { 1266 TCGv addr = tcg_temp_new(); 1267 tcg_gen_addi_i32(addr, REG(B7_4), B3_0); 1268 tcg_gen_qemu_ld_i32(REG(0), addr, ctx->memidx, MO_SB); 1269 tcg_temp_free(addr); 1270 } 1271 return; 1272 case 0x8500: /* mov.w @(disp,Rn),R0 */ 1273 { 1274 TCGv addr = tcg_temp_new(); 1275 tcg_gen_addi_i32(addr, REG(B7_4), B3_0 * 2); 1276 tcg_gen_qemu_ld_i32(REG(0), addr, ctx->memidx, MO_TESW); 1277 tcg_temp_free(addr); 1278 } 1279 return; 1280 case 0xc700: /* mova @(disp,PC),R0 */ 1281 tcg_gen_movi_i32(REG(0), ((ctx->base.pc_next & 0xfffffffc) + 1282 4 + B7_0 * 4) & ~3); 1283 return; 1284 case 0xcb00: /* or #imm,R0 */ 1285 tcg_gen_ori_i32(REG(0), REG(0), B7_0); 1286 return; 1287 case 0xcf00: /* or.b #imm,@(R0,GBR) */ 1288 { 1289 TCGv addr, val; 1290 addr = tcg_temp_new(); 1291 tcg_gen_add_i32(addr, REG(0), cpu_gbr); 1292 val = tcg_temp_new(); 1293 tcg_gen_qemu_ld_i32(val, addr, ctx->memidx, MO_UB); 1294 tcg_gen_ori_i32(val, val, B7_0); 1295 tcg_gen_qemu_st_i32(val, addr, ctx->memidx, MO_UB); 1296 tcg_temp_free(val); 1297 tcg_temp_free(addr); 1298 } 1299 return; 1300 case 0xc300: /* trapa #imm */ 1301 { 1302 TCGv imm; 1303 CHECK_NOT_DELAY_SLOT 1304 gen_save_cpu_state(ctx, true); 1305 imm = tcg_const_i32(B7_0); 1306 gen_helper_trapa(cpu_env, imm); 1307 tcg_temp_free(imm); 1308 ctx->base.is_jmp = DISAS_NORETURN; 1309 } 1310 return; 1311 case 0xc800: /* tst #imm,R0 */ 1312 { 1313 TCGv val = tcg_temp_new(); 1314 tcg_gen_andi_i32(val, REG(0), B7_0); 1315 tcg_gen_setcondi_i32(TCG_COND_EQ, cpu_sr_t, val, 0); 1316 tcg_temp_free(val); 1317 } 1318 return; 1319 case 0xcc00: /* tst.b #imm,@(R0,GBR) */ 1320 { 1321 TCGv val = tcg_temp_new(); 1322 tcg_gen_add_i32(val, REG(0), cpu_gbr); 1323 tcg_gen_qemu_ld_i32(val, val, ctx->memidx, MO_UB); 1324 tcg_gen_andi_i32(val, val, B7_0); 1325 tcg_gen_setcondi_i32(TCG_COND_EQ, cpu_sr_t, val, 0); 1326 tcg_temp_free(val); 1327 } 1328 return; 1329 case 0xca00: /* xor #imm,R0 */ 1330 tcg_gen_xori_i32(REG(0), REG(0), B7_0); 1331 return; 1332 case 0xce00: /* xor.b #imm,@(R0,GBR) */ 1333 { 1334 TCGv addr, val; 1335 addr = tcg_temp_new(); 1336 tcg_gen_add_i32(addr, REG(0), cpu_gbr); 1337 val = tcg_temp_new(); 1338 tcg_gen_qemu_ld_i32(val, addr, ctx->memidx, MO_UB); 1339 tcg_gen_xori_i32(val, val, B7_0); 1340 tcg_gen_qemu_st_i32(val, addr, ctx->memidx, MO_UB); 1341 tcg_temp_free(val); 1342 tcg_temp_free(addr); 1343 } 1344 return; 1345 } 1346 1347 switch (ctx->opcode & 0xf08f) { 1348 case 0x408e: /* ldc Rm,Rn_BANK */ 1349 CHECK_PRIVILEGED 1350 tcg_gen_mov_i32(ALTREG(B6_4), REG(B11_8)); 1351 return; 1352 case 0x4087: /* ldc.l @Rm+,Rn_BANK */ 1353 CHECK_PRIVILEGED 1354 tcg_gen_qemu_ld_i32(ALTREG(B6_4), REG(B11_8), ctx->memidx, MO_TESL); 1355 tcg_gen_addi_i32(REG(B11_8), REG(B11_8), 4); 1356 return; 1357 case 0x0082: /* stc Rm_BANK,Rn */ 1358 CHECK_PRIVILEGED 1359 tcg_gen_mov_i32(REG(B11_8), ALTREG(B6_4)); 1360 return; 1361 case 0x4083: /* stc.l Rm_BANK,@-Rn */ 1362 CHECK_PRIVILEGED 1363 { 1364 TCGv addr = tcg_temp_new(); 1365 tcg_gen_subi_i32(addr, REG(B11_8), 4); 1366 tcg_gen_qemu_st_i32(ALTREG(B6_4), addr, ctx->memidx, MO_TEUL); 1367 tcg_gen_mov_i32(REG(B11_8), addr); 1368 tcg_temp_free(addr); 1369 } 1370 return; 1371 } 1372 1373 switch (ctx->opcode & 0xf0ff) { 1374 case 0x0023: /* braf Rn */ 1375 CHECK_NOT_DELAY_SLOT 1376 tcg_gen_addi_i32(cpu_delayed_pc, REG(B11_8), ctx->base.pc_next + 4); 1377 ctx->envflags |= DELAY_SLOT; 1378 ctx->delayed_pc = (uint32_t) - 1; 1379 return; 1380 case 0x0003: /* bsrf Rn */ 1381 CHECK_NOT_DELAY_SLOT 1382 tcg_gen_movi_i32(cpu_pr, ctx->base.pc_next + 4); 1383 tcg_gen_add_i32(cpu_delayed_pc, REG(B11_8), cpu_pr); 1384 ctx->envflags |= DELAY_SLOT; 1385 ctx->delayed_pc = (uint32_t) - 1; 1386 return; 1387 case 0x4015: /* cmp/pl Rn */ 1388 tcg_gen_setcondi_i32(TCG_COND_GT, cpu_sr_t, REG(B11_8), 0); 1389 return; 1390 case 0x4011: /* cmp/pz Rn */ 1391 tcg_gen_setcondi_i32(TCG_COND_GE, cpu_sr_t, REG(B11_8), 0); 1392 return; 1393 case 0x4010: /* dt Rn */ 1394 tcg_gen_subi_i32(REG(B11_8), REG(B11_8), 1); 1395 tcg_gen_setcondi_i32(TCG_COND_EQ, cpu_sr_t, REG(B11_8), 0); 1396 return; 1397 case 0x402b: /* jmp @Rn */ 1398 CHECK_NOT_DELAY_SLOT 1399 tcg_gen_mov_i32(cpu_delayed_pc, REG(B11_8)); 1400 ctx->envflags |= DELAY_SLOT; 1401 ctx->delayed_pc = (uint32_t) - 1; 1402 return; 1403 case 0x400b: /* jsr @Rn */ 1404 CHECK_NOT_DELAY_SLOT 1405 tcg_gen_movi_i32(cpu_pr, ctx->base.pc_next + 4); 1406 tcg_gen_mov_i32(cpu_delayed_pc, REG(B11_8)); 1407 ctx->envflags |= DELAY_SLOT; 1408 ctx->delayed_pc = (uint32_t) - 1; 1409 return; 1410 case 0x400e: /* ldc Rm,SR */ 1411 CHECK_PRIVILEGED 1412 { 1413 TCGv val = tcg_temp_new(); 1414 tcg_gen_andi_i32(val, REG(B11_8), 0x700083f3); 1415 gen_write_sr(val); 1416 tcg_temp_free(val); 1417 ctx->base.is_jmp = DISAS_STOP; 1418 } 1419 return; 1420 case 0x4007: /* ldc.l @Rm+,SR */ 1421 CHECK_PRIVILEGED 1422 { 1423 TCGv val = tcg_temp_new(); 1424 tcg_gen_qemu_ld_i32(val, REG(B11_8), ctx->memidx, MO_TESL); 1425 tcg_gen_andi_i32(val, val, 0x700083f3); 1426 gen_write_sr(val); 1427 tcg_temp_free(val); 1428 tcg_gen_addi_i32(REG(B11_8), REG(B11_8), 4); 1429 ctx->base.is_jmp = DISAS_STOP; 1430 } 1431 return; 1432 case 0x0002: /* stc SR,Rn */ 1433 CHECK_PRIVILEGED 1434 gen_read_sr(REG(B11_8)); 1435 return; 1436 case 0x4003: /* stc SR,@-Rn */ 1437 CHECK_PRIVILEGED 1438 { 1439 TCGv addr = tcg_temp_new(); 1440 TCGv val = tcg_temp_new(); 1441 tcg_gen_subi_i32(addr, REG(B11_8), 4); 1442 gen_read_sr(val); 1443 tcg_gen_qemu_st_i32(val, addr, ctx->memidx, MO_TEUL); 1444 tcg_gen_mov_i32(REG(B11_8), addr); 1445 tcg_temp_free(val); 1446 tcg_temp_free(addr); 1447 } 1448 return; 1449 #define LD(reg,ldnum,ldpnum,prechk) \ 1450 case ldnum: \ 1451 prechk \ 1452 tcg_gen_mov_i32 (cpu_##reg, REG(B11_8)); \ 1453 return; \ 1454 case ldpnum: \ 1455 prechk \ 1456 tcg_gen_qemu_ld_i32(cpu_##reg, REG(B11_8), ctx->memidx, MO_TESL); \ 1457 tcg_gen_addi_i32(REG(B11_8), REG(B11_8), 4); \ 1458 return; 1459 #define ST(reg,stnum,stpnum,prechk) \ 1460 case stnum: \ 1461 prechk \ 1462 tcg_gen_mov_i32 (REG(B11_8), cpu_##reg); \ 1463 return; \ 1464 case stpnum: \ 1465 prechk \ 1466 { \ 1467 TCGv addr = tcg_temp_new(); \ 1468 tcg_gen_subi_i32(addr, REG(B11_8), 4); \ 1469 tcg_gen_qemu_st_i32(cpu_##reg, addr, ctx->memidx, MO_TEUL); \ 1470 tcg_gen_mov_i32(REG(B11_8), addr); \ 1471 tcg_temp_free(addr); \ 1472 } \ 1473 return; 1474 #define LDST(reg,ldnum,ldpnum,stnum,stpnum,prechk) \ 1475 LD(reg,ldnum,ldpnum,prechk) \ 1476 ST(reg,stnum,stpnum,prechk) 1477 LDST(gbr, 0x401e, 0x4017, 0x0012, 0x4013, {}) 1478 LDST(vbr, 0x402e, 0x4027, 0x0022, 0x4023, CHECK_PRIVILEGED) 1479 LDST(ssr, 0x403e, 0x4037, 0x0032, 0x4033, CHECK_PRIVILEGED) 1480 LDST(spc, 0x404e, 0x4047, 0x0042, 0x4043, CHECK_PRIVILEGED) 1481 ST(sgr, 0x003a, 0x4032, CHECK_PRIVILEGED) 1482 LD(sgr, 0x403a, 0x4036, CHECK_PRIVILEGED CHECK_SH4A) 1483 LDST(dbr, 0x40fa, 0x40f6, 0x00fa, 0x40f2, CHECK_PRIVILEGED) 1484 LDST(mach, 0x400a, 0x4006, 0x000a, 0x4002, {}) 1485 LDST(macl, 0x401a, 0x4016, 0x001a, 0x4012, {}) 1486 LDST(pr, 0x402a, 0x4026, 0x002a, 0x4022, {}) 1487 LDST(fpul, 0x405a, 0x4056, 0x005a, 0x4052, {CHECK_FPU_ENABLED}) 1488 case 0x406a: /* lds Rm,FPSCR */ 1489 CHECK_FPU_ENABLED 1490 gen_helper_ld_fpscr(cpu_env, REG(B11_8)); 1491 ctx->base.is_jmp = DISAS_STOP; 1492 return; 1493 case 0x4066: /* lds.l @Rm+,FPSCR */ 1494 CHECK_FPU_ENABLED 1495 { 1496 TCGv addr = tcg_temp_new(); 1497 tcg_gen_qemu_ld_i32(addr, REG(B11_8), ctx->memidx, MO_TESL); 1498 tcg_gen_addi_i32(REG(B11_8), REG(B11_8), 4); 1499 gen_helper_ld_fpscr(cpu_env, addr); 1500 tcg_temp_free(addr); 1501 ctx->base.is_jmp = DISAS_STOP; 1502 } 1503 return; 1504 case 0x006a: /* sts FPSCR,Rn */ 1505 CHECK_FPU_ENABLED 1506 tcg_gen_andi_i32(REG(B11_8), cpu_fpscr, 0x003fffff); 1507 return; 1508 case 0x4062: /* sts FPSCR,@-Rn */ 1509 CHECK_FPU_ENABLED 1510 { 1511 TCGv addr, val; 1512 val = tcg_temp_new(); 1513 tcg_gen_andi_i32(val, cpu_fpscr, 0x003fffff); 1514 addr = tcg_temp_new(); 1515 tcg_gen_subi_i32(addr, REG(B11_8), 4); 1516 tcg_gen_qemu_st_i32(val, addr, ctx->memidx, MO_TEUL); 1517 tcg_gen_mov_i32(REG(B11_8), addr); 1518 tcg_temp_free(addr); 1519 tcg_temp_free(val); 1520 } 1521 return; 1522 case 0x00c3: /* movca.l R0,@Rm */ 1523 { 1524 TCGv val = tcg_temp_new(); 1525 tcg_gen_qemu_ld_i32(val, REG(B11_8), ctx->memidx, MO_TEUL); 1526 gen_helper_movcal(cpu_env, REG(B11_8), val); 1527 tcg_gen_qemu_st_i32(REG(0), REG(B11_8), ctx->memidx, MO_TEUL); 1528 tcg_temp_free(val); 1529 } 1530 ctx->has_movcal = 1; 1531 return; 1532 case 0x40a9: /* movua.l @Rm,R0 */ 1533 CHECK_SH4A 1534 /* Load non-boundary-aligned data */ 1535 tcg_gen_qemu_ld_i32(REG(0), REG(B11_8), ctx->memidx, 1536 MO_TEUL | MO_UNALN); 1537 return; 1538 case 0x40e9: /* movua.l @Rm+,R0 */ 1539 CHECK_SH4A 1540 /* Load non-boundary-aligned data */ 1541 tcg_gen_qemu_ld_i32(REG(0), REG(B11_8), ctx->memidx, 1542 MO_TEUL | MO_UNALN); 1543 tcg_gen_addi_i32(REG(B11_8), REG(B11_8), 4); 1544 return; 1545 case 0x0029: /* movt Rn */ 1546 tcg_gen_mov_i32(REG(B11_8), cpu_sr_t); 1547 return; 1548 case 0x0073: 1549 /* MOVCO.L 1550 * LDST -> T 1551 * If (T == 1) R0 -> (Rn) 1552 * 0 -> LDST 1553 * 1554 * The above description doesn't work in a parallel context. 1555 * Since we currently support no smp boards, this implies user-mode. 1556 * But we can still support the official mechanism while user-mode 1557 * is single-threaded. */ 1558 CHECK_SH4A 1559 { 1560 TCGLabel *fail = gen_new_label(); 1561 TCGLabel *done = gen_new_label(); 1562 1563 if ((tb_cflags(ctx->base.tb) & CF_PARALLEL)) { 1564 TCGv tmp; 1565 1566 tcg_gen_brcond_i32(TCG_COND_NE, REG(B11_8), 1567 cpu_lock_addr, fail); 1568 tmp = tcg_temp_new(); 1569 tcg_gen_atomic_cmpxchg_i32(tmp, REG(B11_8), cpu_lock_value, 1570 REG(0), ctx->memidx, MO_TEUL); 1571 tcg_gen_setcond_i32(TCG_COND_EQ, cpu_sr_t, tmp, cpu_lock_value); 1572 tcg_temp_free(tmp); 1573 } else { 1574 tcg_gen_brcondi_i32(TCG_COND_EQ, cpu_lock_addr, -1, fail); 1575 tcg_gen_qemu_st_i32(REG(0), REG(B11_8), ctx->memidx, MO_TEUL); 1576 tcg_gen_movi_i32(cpu_sr_t, 1); 1577 } 1578 tcg_gen_br(done); 1579 1580 gen_set_label(fail); 1581 tcg_gen_movi_i32(cpu_sr_t, 0); 1582 1583 gen_set_label(done); 1584 tcg_gen_movi_i32(cpu_lock_addr, -1); 1585 } 1586 return; 1587 case 0x0063: 1588 /* MOVLI.L @Rm,R0 1589 * 1 -> LDST 1590 * (Rm) -> R0 1591 * When interrupt/exception 1592 * occurred 0 -> LDST 1593 * 1594 * In a parallel context, we must also save the loaded value 1595 * for use with the cmpxchg that we'll use with movco.l. */ 1596 CHECK_SH4A 1597 if ((tb_cflags(ctx->base.tb) & CF_PARALLEL)) { 1598 TCGv tmp = tcg_temp_new(); 1599 tcg_gen_mov_i32(tmp, REG(B11_8)); 1600 tcg_gen_qemu_ld_i32(REG(0), REG(B11_8), ctx->memidx, MO_TESL); 1601 tcg_gen_mov_i32(cpu_lock_value, REG(0)); 1602 tcg_gen_mov_i32(cpu_lock_addr, tmp); 1603 tcg_temp_free(tmp); 1604 } else { 1605 tcg_gen_qemu_ld_i32(REG(0), REG(B11_8), ctx->memidx, MO_TESL); 1606 tcg_gen_movi_i32(cpu_lock_addr, 0); 1607 } 1608 return; 1609 case 0x0093: /* ocbi @Rn */ 1610 { 1611 gen_helper_ocbi(cpu_env, REG(B11_8)); 1612 } 1613 return; 1614 case 0x00a3: /* ocbp @Rn */ 1615 case 0x00b3: /* ocbwb @Rn */ 1616 /* These instructions are supposed to do nothing in case of 1617 a cache miss. Given that we only partially emulate caches 1618 it is safe to simply ignore them. */ 1619 return; 1620 case 0x0083: /* pref @Rn */ 1621 return; 1622 case 0x00d3: /* prefi @Rn */ 1623 CHECK_SH4A 1624 return; 1625 case 0x00e3: /* icbi @Rn */ 1626 CHECK_SH4A 1627 return; 1628 case 0x00ab: /* synco */ 1629 CHECK_SH4A 1630 tcg_gen_mb(TCG_MO_ALL | TCG_BAR_SC); 1631 return; 1632 case 0x4024: /* rotcl Rn */ 1633 { 1634 TCGv tmp = tcg_temp_new(); 1635 tcg_gen_mov_i32(tmp, cpu_sr_t); 1636 tcg_gen_shri_i32(cpu_sr_t, REG(B11_8), 31); 1637 tcg_gen_shli_i32(REG(B11_8), REG(B11_8), 1); 1638 tcg_gen_or_i32(REG(B11_8), REG(B11_8), tmp); 1639 tcg_temp_free(tmp); 1640 } 1641 return; 1642 case 0x4025: /* rotcr Rn */ 1643 { 1644 TCGv tmp = tcg_temp_new(); 1645 tcg_gen_shli_i32(tmp, cpu_sr_t, 31); 1646 tcg_gen_andi_i32(cpu_sr_t, REG(B11_8), 1); 1647 tcg_gen_shri_i32(REG(B11_8), REG(B11_8), 1); 1648 tcg_gen_or_i32(REG(B11_8), REG(B11_8), tmp); 1649 tcg_temp_free(tmp); 1650 } 1651 return; 1652 case 0x4004: /* rotl Rn */ 1653 tcg_gen_rotli_i32(REG(B11_8), REG(B11_8), 1); 1654 tcg_gen_andi_i32(cpu_sr_t, REG(B11_8), 0); 1655 return; 1656 case 0x4005: /* rotr Rn */ 1657 tcg_gen_andi_i32(cpu_sr_t, REG(B11_8), 0); 1658 tcg_gen_rotri_i32(REG(B11_8), REG(B11_8), 1); 1659 return; 1660 case 0x4000: /* shll Rn */ 1661 case 0x4020: /* shal Rn */ 1662 tcg_gen_shri_i32(cpu_sr_t, REG(B11_8), 31); 1663 tcg_gen_shli_i32(REG(B11_8), REG(B11_8), 1); 1664 return; 1665 case 0x4021: /* shar Rn */ 1666 tcg_gen_andi_i32(cpu_sr_t, REG(B11_8), 1); 1667 tcg_gen_sari_i32(REG(B11_8), REG(B11_8), 1); 1668 return; 1669 case 0x4001: /* shlr Rn */ 1670 tcg_gen_andi_i32(cpu_sr_t, REG(B11_8), 1); 1671 tcg_gen_shri_i32(REG(B11_8), REG(B11_8), 1); 1672 return; 1673 case 0x4008: /* shll2 Rn */ 1674 tcg_gen_shli_i32(REG(B11_8), REG(B11_8), 2); 1675 return; 1676 case 0x4018: /* shll8 Rn */ 1677 tcg_gen_shli_i32(REG(B11_8), REG(B11_8), 8); 1678 return; 1679 case 0x4028: /* shll16 Rn */ 1680 tcg_gen_shli_i32(REG(B11_8), REG(B11_8), 16); 1681 return; 1682 case 0x4009: /* shlr2 Rn */ 1683 tcg_gen_shri_i32(REG(B11_8), REG(B11_8), 2); 1684 return; 1685 case 0x4019: /* shlr8 Rn */ 1686 tcg_gen_shri_i32(REG(B11_8), REG(B11_8), 8); 1687 return; 1688 case 0x4029: /* shlr16 Rn */ 1689 tcg_gen_shri_i32(REG(B11_8), REG(B11_8), 16); 1690 return; 1691 case 0x401b: /* tas.b @Rn */ 1692 { 1693 TCGv val = tcg_const_i32(0x80); 1694 tcg_gen_atomic_fetch_or_i32(val, REG(B11_8), val, 1695 ctx->memidx, MO_UB); 1696 tcg_gen_setcondi_i32(TCG_COND_EQ, cpu_sr_t, val, 0); 1697 tcg_temp_free(val); 1698 } 1699 return; 1700 case 0xf00d: /* fsts FPUL,FRn - FPSCR: Nothing */ 1701 CHECK_FPU_ENABLED 1702 tcg_gen_mov_i32(FREG(B11_8), cpu_fpul); 1703 return; 1704 case 0xf01d: /* flds FRm,FPUL - FPSCR: Nothing */ 1705 CHECK_FPU_ENABLED 1706 tcg_gen_mov_i32(cpu_fpul, FREG(B11_8)); 1707 return; 1708 case 0xf02d: /* float FPUL,FRn/DRn - FPSCR: R[PR,Enable.I]/W[Cause,Flag] */ 1709 CHECK_FPU_ENABLED 1710 if (ctx->tbflags & FPSCR_PR) { 1711 TCGv_i64 fp; 1712 if (ctx->opcode & 0x0100) { 1713 goto do_illegal; 1714 } 1715 fp = tcg_temp_new_i64(); 1716 gen_helper_float_DT(fp, cpu_env, cpu_fpul); 1717 gen_store_fpr64(ctx, fp, B11_8); 1718 tcg_temp_free_i64(fp); 1719 } 1720 else { 1721 gen_helper_float_FT(FREG(B11_8), cpu_env, cpu_fpul); 1722 } 1723 return; 1724 case 0xf03d: /* ftrc FRm/DRm,FPUL - FPSCR: R[PR,Enable.V]/W[Cause,Flag] */ 1725 CHECK_FPU_ENABLED 1726 if (ctx->tbflags & FPSCR_PR) { 1727 TCGv_i64 fp; 1728 if (ctx->opcode & 0x0100) { 1729 goto do_illegal; 1730 } 1731 fp = tcg_temp_new_i64(); 1732 gen_load_fpr64(ctx, fp, B11_8); 1733 gen_helper_ftrc_DT(cpu_fpul, cpu_env, fp); 1734 tcg_temp_free_i64(fp); 1735 } 1736 else { 1737 gen_helper_ftrc_FT(cpu_fpul, cpu_env, FREG(B11_8)); 1738 } 1739 return; 1740 case 0xf04d: /* fneg FRn/DRn - FPSCR: Nothing */ 1741 CHECK_FPU_ENABLED 1742 tcg_gen_xori_i32(FREG(B11_8), FREG(B11_8), 0x80000000); 1743 return; 1744 case 0xf05d: /* fabs FRn/DRn - FPCSR: Nothing */ 1745 CHECK_FPU_ENABLED 1746 tcg_gen_andi_i32(FREG(B11_8), FREG(B11_8), 0x7fffffff); 1747 return; 1748 case 0xf06d: /* fsqrt FRn */ 1749 CHECK_FPU_ENABLED 1750 if (ctx->tbflags & FPSCR_PR) { 1751 if (ctx->opcode & 0x0100) { 1752 goto do_illegal; 1753 } 1754 TCGv_i64 fp = tcg_temp_new_i64(); 1755 gen_load_fpr64(ctx, fp, B11_8); 1756 gen_helper_fsqrt_DT(fp, cpu_env, fp); 1757 gen_store_fpr64(ctx, fp, B11_8); 1758 tcg_temp_free_i64(fp); 1759 } else { 1760 gen_helper_fsqrt_FT(FREG(B11_8), cpu_env, FREG(B11_8)); 1761 } 1762 return; 1763 case 0xf07d: /* fsrra FRn */ 1764 CHECK_FPU_ENABLED 1765 CHECK_FPSCR_PR_0 1766 gen_helper_fsrra_FT(FREG(B11_8), cpu_env, FREG(B11_8)); 1767 break; 1768 case 0xf08d: /* fldi0 FRn - FPSCR: R[PR] */ 1769 CHECK_FPU_ENABLED 1770 CHECK_FPSCR_PR_0 1771 tcg_gen_movi_i32(FREG(B11_8), 0); 1772 return; 1773 case 0xf09d: /* fldi1 FRn - FPSCR: R[PR] */ 1774 CHECK_FPU_ENABLED 1775 CHECK_FPSCR_PR_0 1776 tcg_gen_movi_i32(FREG(B11_8), 0x3f800000); 1777 return; 1778 case 0xf0ad: /* fcnvsd FPUL,DRn */ 1779 CHECK_FPU_ENABLED 1780 { 1781 TCGv_i64 fp = tcg_temp_new_i64(); 1782 gen_helper_fcnvsd_FT_DT(fp, cpu_env, cpu_fpul); 1783 gen_store_fpr64(ctx, fp, B11_8); 1784 tcg_temp_free_i64(fp); 1785 } 1786 return; 1787 case 0xf0bd: /* fcnvds DRn,FPUL */ 1788 CHECK_FPU_ENABLED 1789 { 1790 TCGv_i64 fp = tcg_temp_new_i64(); 1791 gen_load_fpr64(ctx, fp, B11_8); 1792 gen_helper_fcnvds_DT_FT(cpu_fpul, cpu_env, fp); 1793 tcg_temp_free_i64(fp); 1794 } 1795 return; 1796 case 0xf0ed: /* fipr FVm,FVn */ 1797 CHECK_FPU_ENABLED 1798 CHECK_FPSCR_PR_1 1799 { 1800 TCGv m = tcg_const_i32((ctx->opcode >> 8) & 3); 1801 TCGv n = tcg_const_i32((ctx->opcode >> 10) & 3); 1802 gen_helper_fipr(cpu_env, m, n); 1803 tcg_temp_free(m); 1804 tcg_temp_free(n); 1805 return; 1806 } 1807 break; 1808 case 0xf0fd: /* ftrv XMTRX,FVn */ 1809 CHECK_FPU_ENABLED 1810 CHECK_FPSCR_PR_1 1811 { 1812 if ((ctx->opcode & 0x0300) != 0x0100) { 1813 goto do_illegal; 1814 } 1815 TCGv n = tcg_const_i32((ctx->opcode >> 10) & 3); 1816 gen_helper_ftrv(cpu_env, n); 1817 tcg_temp_free(n); 1818 return; 1819 } 1820 break; 1821 } 1822 #if 0 1823 fprintf(stderr, "unknown instruction 0x%04x at pc 0x%08x\n", 1824 ctx->opcode, ctx->base.pc_next); 1825 fflush(stderr); 1826 #endif 1827 do_illegal: 1828 if (ctx->envflags & DELAY_SLOT_MASK) { 1829 do_illegal_slot: 1830 gen_save_cpu_state(ctx, true); 1831 gen_helper_raise_slot_illegal_instruction(cpu_env); 1832 } else { 1833 gen_save_cpu_state(ctx, true); 1834 gen_helper_raise_illegal_instruction(cpu_env); 1835 } 1836 ctx->base.is_jmp = DISAS_NORETURN; 1837 return; 1838 1839 do_fpu_disabled: 1840 gen_save_cpu_state(ctx, true); 1841 if (ctx->envflags & DELAY_SLOT_MASK) { 1842 gen_helper_raise_slot_fpu_disable(cpu_env); 1843 } else { 1844 gen_helper_raise_fpu_disable(cpu_env); 1845 } 1846 ctx->base.is_jmp = DISAS_NORETURN; 1847 return; 1848 } 1849 1850 static void decode_opc(DisasContext * ctx) 1851 { 1852 uint32_t old_flags = ctx->envflags; 1853 1854 _decode_opc(ctx); 1855 1856 if (old_flags & DELAY_SLOT_MASK) { 1857 /* go out of the delay slot */ 1858 ctx->envflags &= ~DELAY_SLOT_MASK; 1859 1860 /* When in an exclusive region, we must continue to the end 1861 for conditional branches. */ 1862 if (ctx->tbflags & GUSA_EXCLUSIVE 1863 && old_flags & DELAY_SLOT_CONDITIONAL) { 1864 gen_delayed_conditional_jump(ctx); 1865 return; 1866 } 1867 /* Otherwise this is probably an invalid gUSA region. 1868 Drop the GUSA bits so the next TB doesn't see them. */ 1869 ctx->envflags &= ~GUSA_MASK; 1870 1871 tcg_gen_movi_i32(cpu_flags, ctx->envflags); 1872 if (old_flags & DELAY_SLOT_CONDITIONAL) { 1873 gen_delayed_conditional_jump(ctx); 1874 } else { 1875 gen_jump(ctx); 1876 } 1877 } 1878 } 1879 1880 #ifdef CONFIG_USER_ONLY 1881 /* For uniprocessors, SH4 uses optimistic restartable atomic sequences. 1882 Upon an interrupt, a real kernel would simply notice magic values in 1883 the registers and reset the PC to the start of the sequence. 1884 1885 For QEMU, we cannot do this in quite the same way. Instead, we notice 1886 the normal start of such a sequence (mov #-x,r15). While we can handle 1887 any sequence via cpu_exec_step_atomic, we can recognize the "normal" 1888 sequences and transform them into atomic operations as seen by the host. 1889 */ 1890 static void decode_gusa(DisasContext *ctx, CPUSH4State *env) 1891 { 1892 uint16_t insns[5]; 1893 int ld_adr, ld_dst, ld_mop; 1894 int op_dst, op_src, op_opc; 1895 int mv_src, mt_dst, st_src, st_mop; 1896 TCGv op_arg; 1897 uint32_t pc = ctx->base.pc_next; 1898 uint32_t pc_end = ctx->base.tb->cs_base; 1899 int max_insns = (pc_end - pc) / 2; 1900 int i; 1901 1902 /* The state machine below will consume only a few insns. 1903 If there are more than that in a region, fail now. */ 1904 if (max_insns > ARRAY_SIZE(insns)) { 1905 goto fail; 1906 } 1907 1908 /* Read all of the insns for the region. */ 1909 for (i = 0; i < max_insns; ++i) { 1910 insns[i] = translator_lduw(env, &ctx->base, pc + i * 2); 1911 } 1912 1913 ld_adr = ld_dst = ld_mop = -1; 1914 mv_src = -1; 1915 op_dst = op_src = op_opc = -1; 1916 mt_dst = -1; 1917 st_src = st_mop = -1; 1918 op_arg = NULL; 1919 i = 0; 1920 1921 #define NEXT_INSN \ 1922 do { if (i >= max_insns) goto fail; ctx->opcode = insns[i++]; } while (0) 1923 1924 /* 1925 * Expect a load to begin the region. 1926 */ 1927 NEXT_INSN; 1928 switch (ctx->opcode & 0xf00f) { 1929 case 0x6000: /* mov.b @Rm,Rn */ 1930 ld_mop = MO_SB; 1931 break; 1932 case 0x6001: /* mov.w @Rm,Rn */ 1933 ld_mop = MO_TESW; 1934 break; 1935 case 0x6002: /* mov.l @Rm,Rn */ 1936 ld_mop = MO_TESL; 1937 break; 1938 default: 1939 goto fail; 1940 } 1941 ld_adr = B7_4; 1942 ld_dst = B11_8; 1943 if (ld_adr == ld_dst) { 1944 goto fail; 1945 } 1946 /* Unless we see a mov, any two-operand operation must use ld_dst. */ 1947 op_dst = ld_dst; 1948 1949 /* 1950 * Expect an optional register move. 1951 */ 1952 NEXT_INSN; 1953 switch (ctx->opcode & 0xf00f) { 1954 case 0x6003: /* mov Rm,Rn */ 1955 /* 1956 * Here we want to recognize ld_dst being saved for later consumption, 1957 * or for another input register being copied so that ld_dst need not 1958 * be clobbered during the operation. 1959 */ 1960 op_dst = B11_8; 1961 mv_src = B7_4; 1962 if (op_dst == ld_dst) { 1963 /* Overwriting the load output. */ 1964 goto fail; 1965 } 1966 if (mv_src != ld_dst) { 1967 /* Copying a new input; constrain op_src to match the load. */ 1968 op_src = ld_dst; 1969 } 1970 break; 1971 1972 default: 1973 /* Put back and re-examine as operation. */ 1974 --i; 1975 } 1976 1977 /* 1978 * Expect the operation. 1979 */ 1980 NEXT_INSN; 1981 switch (ctx->opcode & 0xf00f) { 1982 case 0x300c: /* add Rm,Rn */ 1983 op_opc = INDEX_op_add_i32; 1984 goto do_reg_op; 1985 case 0x2009: /* and Rm,Rn */ 1986 op_opc = INDEX_op_and_i32; 1987 goto do_reg_op; 1988 case 0x200a: /* xor Rm,Rn */ 1989 op_opc = INDEX_op_xor_i32; 1990 goto do_reg_op; 1991 case 0x200b: /* or Rm,Rn */ 1992 op_opc = INDEX_op_or_i32; 1993 do_reg_op: 1994 /* The operation register should be as expected, and the 1995 other input cannot depend on the load. */ 1996 if (op_dst != B11_8) { 1997 goto fail; 1998 } 1999 if (op_src < 0) { 2000 /* Unconstrainted input. */ 2001 op_src = B7_4; 2002 } else if (op_src == B7_4) { 2003 /* Constrained input matched load. All operations are 2004 commutative; "swap" them by "moving" the load output 2005 to the (implicit) first argument and the move source 2006 to the (explicit) second argument. */ 2007 op_src = mv_src; 2008 } else { 2009 goto fail; 2010 } 2011 op_arg = REG(op_src); 2012 break; 2013 2014 case 0x6007: /* not Rm,Rn */ 2015 if (ld_dst != B7_4 || mv_src >= 0) { 2016 goto fail; 2017 } 2018 op_dst = B11_8; 2019 op_opc = INDEX_op_xor_i32; 2020 op_arg = tcg_const_i32(-1); 2021 break; 2022 2023 case 0x7000 ... 0x700f: /* add #imm,Rn */ 2024 if (op_dst != B11_8 || mv_src >= 0) { 2025 goto fail; 2026 } 2027 op_opc = INDEX_op_add_i32; 2028 op_arg = tcg_const_i32(B7_0s); 2029 break; 2030 2031 case 0x3000: /* cmp/eq Rm,Rn */ 2032 /* Looking for the middle of a compare-and-swap sequence, 2033 beginning with the compare. Operands can be either order, 2034 but with only one overlapping the load. */ 2035 if ((ld_dst == B11_8) + (ld_dst == B7_4) != 1 || mv_src >= 0) { 2036 goto fail; 2037 } 2038 op_opc = INDEX_op_setcond_i32; /* placeholder */ 2039 op_src = (ld_dst == B11_8 ? B7_4 : B11_8); 2040 op_arg = REG(op_src); 2041 2042 NEXT_INSN; 2043 switch (ctx->opcode & 0xff00) { 2044 case 0x8b00: /* bf label */ 2045 case 0x8f00: /* bf/s label */ 2046 if (pc + (i + 1 + B7_0s) * 2 != pc_end) { 2047 goto fail; 2048 } 2049 if ((ctx->opcode & 0xff00) == 0x8b00) { /* bf label */ 2050 break; 2051 } 2052 /* We're looking to unconditionally modify Rn with the 2053 result of the comparison, within the delay slot of 2054 the branch. This is used by older gcc. */ 2055 NEXT_INSN; 2056 if ((ctx->opcode & 0xf0ff) == 0x0029) { /* movt Rn */ 2057 mt_dst = B11_8; 2058 } else { 2059 goto fail; 2060 } 2061 break; 2062 2063 default: 2064 goto fail; 2065 } 2066 break; 2067 2068 case 0x2008: /* tst Rm,Rn */ 2069 /* Looking for a compare-and-swap against zero. */ 2070 if (ld_dst != B11_8 || ld_dst != B7_4 || mv_src >= 0) { 2071 goto fail; 2072 } 2073 op_opc = INDEX_op_setcond_i32; 2074 op_arg = tcg_const_i32(0); 2075 2076 NEXT_INSN; 2077 if ((ctx->opcode & 0xff00) != 0x8900 /* bt label */ 2078 || pc + (i + 1 + B7_0s) * 2 != pc_end) { 2079 goto fail; 2080 } 2081 break; 2082 2083 default: 2084 /* Put back and re-examine as store. */ 2085 --i; 2086 } 2087 2088 /* 2089 * Expect the store. 2090 */ 2091 /* The store must be the last insn. */ 2092 if (i != max_insns - 1) { 2093 goto fail; 2094 } 2095 NEXT_INSN; 2096 switch (ctx->opcode & 0xf00f) { 2097 case 0x2000: /* mov.b Rm,@Rn */ 2098 st_mop = MO_UB; 2099 break; 2100 case 0x2001: /* mov.w Rm,@Rn */ 2101 st_mop = MO_UW; 2102 break; 2103 case 0x2002: /* mov.l Rm,@Rn */ 2104 st_mop = MO_UL; 2105 break; 2106 default: 2107 goto fail; 2108 } 2109 /* The store must match the load. */ 2110 if (ld_adr != B11_8 || st_mop != (ld_mop & MO_SIZE)) { 2111 goto fail; 2112 } 2113 st_src = B7_4; 2114 2115 #undef NEXT_INSN 2116 2117 /* 2118 * Emit the operation. 2119 */ 2120 switch (op_opc) { 2121 case -1: 2122 /* No operation found. Look for exchange pattern. */ 2123 if (st_src == ld_dst || mv_src >= 0) { 2124 goto fail; 2125 } 2126 tcg_gen_atomic_xchg_i32(REG(ld_dst), REG(ld_adr), REG(st_src), 2127 ctx->memidx, ld_mop); 2128 break; 2129 2130 case INDEX_op_add_i32: 2131 if (op_dst != st_src) { 2132 goto fail; 2133 } 2134 if (op_dst == ld_dst && st_mop == MO_UL) { 2135 tcg_gen_atomic_add_fetch_i32(REG(ld_dst), REG(ld_adr), 2136 op_arg, ctx->memidx, ld_mop); 2137 } else { 2138 tcg_gen_atomic_fetch_add_i32(REG(ld_dst), REG(ld_adr), 2139 op_arg, ctx->memidx, ld_mop); 2140 if (op_dst != ld_dst) { 2141 /* Note that mop sizes < 4 cannot use add_fetch 2142 because it won't carry into the higher bits. */ 2143 tcg_gen_add_i32(REG(op_dst), REG(ld_dst), op_arg); 2144 } 2145 } 2146 break; 2147 2148 case INDEX_op_and_i32: 2149 if (op_dst != st_src) { 2150 goto fail; 2151 } 2152 if (op_dst == ld_dst) { 2153 tcg_gen_atomic_and_fetch_i32(REG(ld_dst), REG(ld_adr), 2154 op_arg, ctx->memidx, ld_mop); 2155 } else { 2156 tcg_gen_atomic_fetch_and_i32(REG(ld_dst), REG(ld_adr), 2157 op_arg, ctx->memidx, ld_mop); 2158 tcg_gen_and_i32(REG(op_dst), REG(ld_dst), op_arg); 2159 } 2160 break; 2161 2162 case INDEX_op_or_i32: 2163 if (op_dst != st_src) { 2164 goto fail; 2165 } 2166 if (op_dst == ld_dst) { 2167 tcg_gen_atomic_or_fetch_i32(REG(ld_dst), REG(ld_adr), 2168 op_arg, ctx->memidx, ld_mop); 2169 } else { 2170 tcg_gen_atomic_fetch_or_i32(REG(ld_dst), REG(ld_adr), 2171 op_arg, ctx->memidx, ld_mop); 2172 tcg_gen_or_i32(REG(op_dst), REG(ld_dst), op_arg); 2173 } 2174 break; 2175 2176 case INDEX_op_xor_i32: 2177 if (op_dst != st_src) { 2178 goto fail; 2179 } 2180 if (op_dst == ld_dst) { 2181 tcg_gen_atomic_xor_fetch_i32(REG(ld_dst), REG(ld_adr), 2182 op_arg, ctx->memidx, ld_mop); 2183 } else { 2184 tcg_gen_atomic_fetch_xor_i32(REG(ld_dst), REG(ld_adr), 2185 op_arg, ctx->memidx, ld_mop); 2186 tcg_gen_xor_i32(REG(op_dst), REG(ld_dst), op_arg); 2187 } 2188 break; 2189 2190 case INDEX_op_setcond_i32: 2191 if (st_src == ld_dst) { 2192 goto fail; 2193 } 2194 tcg_gen_atomic_cmpxchg_i32(REG(ld_dst), REG(ld_adr), op_arg, 2195 REG(st_src), ctx->memidx, ld_mop); 2196 tcg_gen_setcond_i32(TCG_COND_EQ, cpu_sr_t, REG(ld_dst), op_arg); 2197 if (mt_dst >= 0) { 2198 tcg_gen_mov_i32(REG(mt_dst), cpu_sr_t); 2199 } 2200 break; 2201 2202 default: 2203 g_assert_not_reached(); 2204 } 2205 2206 /* If op_src is not a valid register, then op_arg was a constant. */ 2207 if (op_src < 0 && op_arg) { 2208 tcg_temp_free_i32(op_arg); 2209 } 2210 2211 /* The entire region has been translated. */ 2212 ctx->envflags &= ~GUSA_MASK; 2213 ctx->base.pc_next = pc_end; 2214 ctx->base.num_insns += max_insns - 1; 2215 return; 2216 2217 fail: 2218 qemu_log_mask(LOG_UNIMP, "Unrecognized gUSA sequence %08x-%08x\n", 2219 pc, pc_end); 2220 2221 /* Restart with the EXCLUSIVE bit set, within a TB run via 2222 cpu_exec_step_atomic holding the exclusive lock. */ 2223 ctx->envflags |= GUSA_EXCLUSIVE; 2224 gen_save_cpu_state(ctx, false); 2225 gen_helper_exclusive(cpu_env); 2226 ctx->base.is_jmp = DISAS_NORETURN; 2227 2228 /* We're not executing an instruction, but we must report one for the 2229 purposes of accounting within the TB. We might as well report the 2230 entire region consumed via ctx->base.pc_next so that it's immediately 2231 available in the disassembly dump. */ 2232 ctx->base.pc_next = pc_end; 2233 ctx->base.num_insns += max_insns - 1; 2234 } 2235 #endif 2236 2237 static void sh4_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs) 2238 { 2239 DisasContext *ctx = container_of(dcbase, DisasContext, base); 2240 CPUSH4State *env = cs->env_ptr; 2241 uint32_t tbflags; 2242 int bound; 2243 2244 ctx->tbflags = tbflags = ctx->base.tb->flags; 2245 ctx->envflags = tbflags & TB_FLAG_ENVFLAGS_MASK; 2246 ctx->memidx = (tbflags & (1u << SR_MD)) == 0 ? 1 : 0; 2247 /* We don't know if the delayed pc came from a dynamic or static branch, 2248 so assume it is a dynamic branch. */ 2249 ctx->delayed_pc = -1; /* use delayed pc from env pointer */ 2250 ctx->features = env->features; 2251 ctx->has_movcal = (tbflags & TB_FLAG_PENDING_MOVCA); 2252 ctx->gbank = ((tbflags & (1 << SR_MD)) && 2253 (tbflags & (1 << SR_RB))) * 0x10; 2254 ctx->fbank = tbflags & FPSCR_FR ? 0x10 : 0; 2255 2256 if (tbflags & GUSA_MASK) { 2257 uint32_t pc = ctx->base.pc_next; 2258 uint32_t pc_end = ctx->base.tb->cs_base; 2259 int backup = sextract32(ctx->tbflags, GUSA_SHIFT, 8); 2260 int max_insns = (pc_end - pc) / 2; 2261 2262 if (pc != pc_end + backup || max_insns < 2) { 2263 /* This is a malformed gUSA region. Don't do anything special, 2264 since the interpreter is likely to get confused. */ 2265 ctx->envflags &= ~GUSA_MASK; 2266 } else if (tbflags & GUSA_EXCLUSIVE) { 2267 /* Regardless of single-stepping or the end of the page, 2268 we must complete execution of the gUSA region while 2269 holding the exclusive lock. */ 2270 ctx->base.max_insns = max_insns; 2271 return; 2272 } 2273 } 2274 2275 /* Since the ISA is fixed-width, we can bound by the number 2276 of instructions remaining on the page. */ 2277 bound = -(ctx->base.pc_next | TARGET_PAGE_MASK) / 2; 2278 ctx->base.max_insns = MIN(ctx->base.max_insns, bound); 2279 } 2280 2281 static void sh4_tr_tb_start(DisasContextBase *dcbase, CPUState *cs) 2282 { 2283 } 2284 2285 static void sh4_tr_insn_start(DisasContextBase *dcbase, CPUState *cs) 2286 { 2287 DisasContext *ctx = container_of(dcbase, DisasContext, base); 2288 2289 tcg_gen_insn_start(ctx->base.pc_next, ctx->envflags); 2290 } 2291 2292 static void sh4_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs) 2293 { 2294 CPUSH4State *env = cs->env_ptr; 2295 DisasContext *ctx = container_of(dcbase, DisasContext, base); 2296 2297 #ifdef CONFIG_USER_ONLY 2298 if (unlikely(ctx->envflags & GUSA_MASK) 2299 && !(ctx->envflags & GUSA_EXCLUSIVE)) { 2300 /* We're in an gUSA region, and we have not already fallen 2301 back on using an exclusive region. Attempt to parse the 2302 region into a single supported atomic operation. Failure 2303 is handled within the parser by raising an exception to 2304 retry using an exclusive region. */ 2305 decode_gusa(ctx, env); 2306 return; 2307 } 2308 #endif 2309 2310 ctx->opcode = translator_lduw(env, &ctx->base, ctx->base.pc_next); 2311 decode_opc(ctx); 2312 ctx->base.pc_next += 2; 2313 } 2314 2315 static void sh4_tr_tb_stop(DisasContextBase *dcbase, CPUState *cs) 2316 { 2317 DisasContext *ctx = container_of(dcbase, DisasContext, base); 2318 2319 if (ctx->tbflags & GUSA_EXCLUSIVE) { 2320 /* Ending the region of exclusivity. Clear the bits. */ 2321 ctx->envflags &= ~GUSA_MASK; 2322 } 2323 2324 switch (ctx->base.is_jmp) { 2325 case DISAS_STOP: 2326 gen_save_cpu_state(ctx, true); 2327 if (ctx->base.singlestep_enabled) { 2328 gen_helper_debug(cpu_env); 2329 } else { 2330 tcg_gen_exit_tb(NULL, 0); 2331 } 2332 break; 2333 case DISAS_NEXT: 2334 case DISAS_TOO_MANY: 2335 gen_save_cpu_state(ctx, false); 2336 gen_goto_tb(ctx, 0, ctx->base.pc_next); 2337 break; 2338 case DISAS_NORETURN: 2339 break; 2340 default: 2341 g_assert_not_reached(); 2342 } 2343 } 2344 2345 static void sh4_tr_disas_log(const DisasContextBase *dcbase, CPUState *cs) 2346 { 2347 qemu_log("IN: %s\n", lookup_symbol(dcbase->pc_first)); 2348 log_target_disas(cs, dcbase->pc_first, dcbase->tb->size); 2349 } 2350 2351 static const TranslatorOps sh4_tr_ops = { 2352 .init_disas_context = sh4_tr_init_disas_context, 2353 .tb_start = sh4_tr_tb_start, 2354 .insn_start = sh4_tr_insn_start, 2355 .translate_insn = sh4_tr_translate_insn, 2356 .tb_stop = sh4_tr_tb_stop, 2357 .disas_log = sh4_tr_disas_log, 2358 }; 2359 2360 void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int max_insns) 2361 { 2362 DisasContext ctx; 2363 2364 translator_loop(&sh4_tr_ops, &ctx.base, cs, tb, max_insns); 2365 } 2366 2367 void restore_state_to_opc(CPUSH4State *env, TranslationBlock *tb, 2368 target_ulong *data) 2369 { 2370 env->pc = data[0]; 2371 env->flags = data[1]; 2372 /* Theoretically delayed_pc should also be restored. In practice the 2373 branch instruction is re-executed after exception, so the delayed 2374 branch target will be recomputed. */ 2375 } 2376