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