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