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 { 699 TCGv t0, t1; 700 t0 = tcg_constant_tl(0); 701 t1 = tcg_temp_new(); 702 tcg_gen_add2_i32(t1, cpu_sr_t, cpu_sr_t, t0, REG(B7_4), t0); 703 tcg_gen_add2_i32(REG(B11_8), cpu_sr_t, 704 REG(B11_8), t0, t1, cpu_sr_t); 705 } 706 return; 707 case 0x300f: /* addv Rm,Rn */ 708 { 709 TCGv Rn = REG(B11_8); 710 TCGv Rm = REG(B7_4); 711 TCGv result, t1, t2; 712 713 result = tcg_temp_new(); 714 t1 = tcg_temp_new(); 715 t2 = tcg_temp_new(); 716 tcg_gen_add_i32(result, Rm, Rn); 717 /* T = ((Rn ^ Rm) & (Result ^ Rn)) >> 31 */ 718 tcg_gen_xor_i32(t1, result, Rn); 719 tcg_gen_xor_i32(t2, Rm, Rn); 720 tcg_gen_andc_i32(cpu_sr_t, t1, t2); 721 tcg_gen_shri_i32(cpu_sr_t, cpu_sr_t, 31); 722 tcg_gen_mov_i32(Rn, result); 723 } 724 return; 725 case 0x2009: /* and Rm,Rn */ 726 tcg_gen_and_i32(REG(B11_8), REG(B11_8), REG(B7_4)); 727 return; 728 case 0x3000: /* cmp/eq Rm,Rn */ 729 tcg_gen_setcond_i32(TCG_COND_EQ, cpu_sr_t, REG(B11_8), REG(B7_4)); 730 return; 731 case 0x3003: /* cmp/ge Rm,Rn */ 732 tcg_gen_setcond_i32(TCG_COND_GE, cpu_sr_t, REG(B11_8), REG(B7_4)); 733 return; 734 case 0x3007: /* cmp/gt Rm,Rn */ 735 tcg_gen_setcond_i32(TCG_COND_GT, cpu_sr_t, REG(B11_8), REG(B7_4)); 736 return; 737 case 0x3006: /* cmp/hi Rm,Rn */ 738 tcg_gen_setcond_i32(TCG_COND_GTU, cpu_sr_t, REG(B11_8), REG(B7_4)); 739 return; 740 case 0x3002: /* cmp/hs Rm,Rn */ 741 tcg_gen_setcond_i32(TCG_COND_GEU, cpu_sr_t, REG(B11_8), REG(B7_4)); 742 return; 743 case 0x200c: /* cmp/str Rm,Rn */ 744 { 745 TCGv cmp1 = tcg_temp_new(); 746 TCGv cmp2 = tcg_temp_new(); 747 tcg_gen_xor_i32(cmp2, REG(B7_4), REG(B11_8)); 748 tcg_gen_subi_i32(cmp1, cmp2, 0x01010101); 749 tcg_gen_andc_i32(cmp1, cmp1, cmp2); 750 tcg_gen_andi_i32(cmp1, cmp1, 0x80808080); 751 tcg_gen_setcondi_i32(TCG_COND_NE, cpu_sr_t, cmp1, 0); 752 } 753 return; 754 case 0x2007: /* div0s Rm,Rn */ 755 tcg_gen_shri_i32(cpu_sr_q, REG(B11_8), 31); /* SR_Q */ 756 tcg_gen_shri_i32(cpu_sr_m, REG(B7_4), 31); /* SR_M */ 757 tcg_gen_xor_i32(cpu_sr_t, cpu_sr_q, cpu_sr_m); /* SR_T */ 758 return; 759 case 0x3004: /* div1 Rm,Rn */ 760 { 761 TCGv t0 = tcg_temp_new(); 762 TCGv t1 = tcg_temp_new(); 763 TCGv t2 = tcg_temp_new(); 764 TCGv zero = tcg_constant_i32(0); 765 766 /* shift left arg1, saving the bit being pushed out and inserting 767 T on the right */ 768 tcg_gen_shri_i32(t0, REG(B11_8), 31); 769 tcg_gen_shli_i32(REG(B11_8), REG(B11_8), 1); 770 tcg_gen_or_i32(REG(B11_8), REG(B11_8), cpu_sr_t); 771 772 /* Add or subtract arg0 from arg1 depending if Q == M. To avoid 773 using 64-bit temps, we compute arg0's high part from q ^ m, so 774 that it is 0x00000000 when adding the value or 0xffffffff when 775 subtracting it. */ 776 tcg_gen_xor_i32(t1, cpu_sr_q, cpu_sr_m); 777 tcg_gen_subi_i32(t1, t1, 1); 778 tcg_gen_neg_i32(t2, REG(B7_4)); 779 tcg_gen_movcond_i32(TCG_COND_EQ, t2, t1, zero, REG(B7_4), t2); 780 tcg_gen_add2_i32(REG(B11_8), t1, REG(B11_8), zero, t2, t1); 781 782 /* compute T and Q depending on carry */ 783 tcg_gen_andi_i32(t1, t1, 1); 784 tcg_gen_xor_i32(t1, t1, t0); 785 tcg_gen_xori_i32(cpu_sr_t, t1, 1); 786 tcg_gen_xor_i32(cpu_sr_q, cpu_sr_m, t1); 787 } 788 return; 789 case 0x300d: /* dmuls.l Rm,Rn */ 790 tcg_gen_muls2_i32(cpu_macl, cpu_mach, REG(B7_4), REG(B11_8)); 791 return; 792 case 0x3005: /* dmulu.l Rm,Rn */ 793 tcg_gen_mulu2_i32(cpu_macl, cpu_mach, REG(B7_4), REG(B11_8)); 794 return; 795 case 0x600e: /* exts.b Rm,Rn */ 796 tcg_gen_ext8s_i32(REG(B11_8), REG(B7_4)); 797 return; 798 case 0x600f: /* exts.w Rm,Rn */ 799 tcg_gen_ext16s_i32(REG(B11_8), REG(B7_4)); 800 return; 801 case 0x600c: /* extu.b Rm,Rn */ 802 tcg_gen_ext8u_i32(REG(B11_8), REG(B7_4)); 803 return; 804 case 0x600d: /* extu.w Rm,Rn */ 805 tcg_gen_ext16u_i32(REG(B11_8), REG(B7_4)); 806 return; 807 case 0x000f: /* mac.l @Rm+,@Rn+ */ 808 { 809 TCGv arg0, arg1; 810 arg0 = tcg_temp_new(); 811 tcg_gen_qemu_ld_i32(arg0, REG(B7_4), ctx->memidx, 812 MO_TESL | MO_ALIGN); 813 arg1 = tcg_temp_new(); 814 tcg_gen_qemu_ld_i32(arg1, REG(B11_8), ctx->memidx, 815 MO_TESL | MO_ALIGN); 816 gen_helper_macl(tcg_env, arg0, arg1); 817 tcg_gen_addi_i32(REG(B7_4), REG(B7_4), 4); 818 tcg_gen_addi_i32(REG(B11_8), REG(B11_8), 4); 819 } 820 return; 821 case 0x400f: /* mac.w @Rm+,@Rn+ */ 822 { 823 TCGv arg0, arg1; 824 arg0 = tcg_temp_new(); 825 tcg_gen_qemu_ld_i32(arg0, REG(B7_4), ctx->memidx, 826 MO_TESW | MO_ALIGN); 827 arg1 = tcg_temp_new(); 828 tcg_gen_qemu_ld_i32(arg1, REG(B11_8), ctx->memidx, 829 MO_TESW | MO_ALIGN); 830 gen_helper_macw(tcg_env, arg0, arg1); 831 tcg_gen_addi_i32(REG(B11_8), REG(B11_8), 2); 832 tcg_gen_addi_i32(REG(B7_4), REG(B7_4), 2); 833 } 834 return; 835 case 0x0007: /* mul.l Rm,Rn */ 836 tcg_gen_mul_i32(cpu_macl, REG(B7_4), REG(B11_8)); 837 return; 838 case 0x200f: /* muls.w Rm,Rn */ 839 { 840 TCGv arg0, arg1; 841 arg0 = tcg_temp_new(); 842 tcg_gen_ext16s_i32(arg0, REG(B7_4)); 843 arg1 = tcg_temp_new(); 844 tcg_gen_ext16s_i32(arg1, REG(B11_8)); 845 tcg_gen_mul_i32(cpu_macl, arg0, arg1); 846 } 847 return; 848 case 0x200e: /* mulu.w Rm,Rn */ 849 { 850 TCGv arg0, arg1; 851 arg0 = tcg_temp_new(); 852 tcg_gen_ext16u_i32(arg0, REG(B7_4)); 853 arg1 = tcg_temp_new(); 854 tcg_gen_ext16u_i32(arg1, REG(B11_8)); 855 tcg_gen_mul_i32(cpu_macl, arg0, arg1); 856 } 857 return; 858 case 0x600b: /* neg Rm,Rn */ 859 tcg_gen_neg_i32(REG(B11_8), REG(B7_4)); 860 return; 861 case 0x600a: /* negc Rm,Rn */ 862 { 863 TCGv t0 = tcg_constant_i32(0); 864 tcg_gen_add2_i32(REG(B11_8), cpu_sr_t, 865 REG(B7_4), t0, cpu_sr_t, t0); 866 tcg_gen_sub2_i32(REG(B11_8), cpu_sr_t, 867 t0, t0, REG(B11_8), cpu_sr_t); 868 tcg_gen_andi_i32(cpu_sr_t, cpu_sr_t, 1); 869 } 870 return; 871 case 0x6007: /* not Rm,Rn */ 872 tcg_gen_not_i32(REG(B11_8), REG(B7_4)); 873 return; 874 case 0x200b: /* or Rm,Rn */ 875 tcg_gen_or_i32(REG(B11_8), REG(B11_8), REG(B7_4)); 876 return; 877 case 0x400c: /* shad Rm,Rn */ 878 { 879 TCGv t0 = tcg_temp_new(); 880 TCGv t1 = tcg_temp_new(); 881 TCGv t2 = tcg_temp_new(); 882 883 tcg_gen_andi_i32(t0, REG(B7_4), 0x1f); 884 885 /* positive case: shift to the left */ 886 tcg_gen_shl_i32(t1, REG(B11_8), t0); 887 888 /* negative case: shift to the right in two steps to 889 correctly handle the -32 case */ 890 tcg_gen_xori_i32(t0, t0, 0x1f); 891 tcg_gen_sar_i32(t2, REG(B11_8), t0); 892 tcg_gen_sari_i32(t2, t2, 1); 893 894 /* select between the two cases */ 895 tcg_gen_movi_i32(t0, 0); 896 tcg_gen_movcond_i32(TCG_COND_GE, REG(B11_8), REG(B7_4), t0, t1, t2); 897 } 898 return; 899 case 0x400d: /* shld Rm,Rn */ 900 { 901 TCGv t0 = tcg_temp_new(); 902 TCGv t1 = tcg_temp_new(); 903 TCGv t2 = tcg_temp_new(); 904 905 tcg_gen_andi_i32(t0, REG(B7_4), 0x1f); 906 907 /* positive case: shift to the left */ 908 tcg_gen_shl_i32(t1, REG(B11_8), t0); 909 910 /* negative case: shift to the right in two steps to 911 correctly handle the -32 case */ 912 tcg_gen_xori_i32(t0, t0, 0x1f); 913 tcg_gen_shr_i32(t2, REG(B11_8), t0); 914 tcg_gen_shri_i32(t2, t2, 1); 915 916 /* select between the two cases */ 917 tcg_gen_movi_i32(t0, 0); 918 tcg_gen_movcond_i32(TCG_COND_GE, REG(B11_8), REG(B7_4), t0, t1, t2); 919 } 920 return; 921 case 0x3008: /* sub Rm,Rn */ 922 tcg_gen_sub_i32(REG(B11_8), REG(B11_8), REG(B7_4)); 923 return; 924 case 0x300a: /* subc Rm,Rn */ 925 { 926 TCGv t0, t1; 927 t0 = tcg_constant_tl(0); 928 t1 = tcg_temp_new(); 929 tcg_gen_add2_i32(t1, cpu_sr_t, cpu_sr_t, t0, REG(B7_4), t0); 930 tcg_gen_sub2_i32(REG(B11_8), cpu_sr_t, 931 REG(B11_8), t0, t1, cpu_sr_t); 932 tcg_gen_andi_i32(cpu_sr_t, cpu_sr_t, 1); 933 } 934 return; 935 case 0x300b: /* subv Rm,Rn */ 936 { 937 TCGv Rn = REG(B11_8); 938 TCGv Rm = REG(B7_4); 939 TCGv result, t1, t2; 940 941 result = tcg_temp_new(); 942 t1 = tcg_temp_new(); 943 t2 = tcg_temp_new(); 944 tcg_gen_sub_i32(result, Rn, Rm); 945 /* T = ((Rn ^ Rm) & (Result ^ Rn)) >> 31 */ 946 tcg_gen_xor_i32(t1, result, Rn); 947 tcg_gen_xor_i32(t2, Rn, Rm); 948 tcg_gen_and_i32(t1, t1, t2); 949 tcg_gen_shri_i32(cpu_sr_t, t1, 31); 950 tcg_gen_mov_i32(Rn, result); 951 } 952 return; 953 case 0x2008: /* tst Rm,Rn */ 954 { 955 TCGv val = tcg_temp_new(); 956 tcg_gen_and_i32(val, REG(B7_4), REG(B11_8)); 957 tcg_gen_setcondi_i32(TCG_COND_EQ, cpu_sr_t, val, 0); 958 } 959 return; 960 case 0x200a: /* xor Rm,Rn */ 961 tcg_gen_xor_i32(REG(B11_8), REG(B11_8), REG(B7_4)); 962 return; 963 case 0xf00c: /* fmov {F,D,X}Rm,{F,D,X}Rn - FPSCR: Nothing */ 964 CHECK_FPU_ENABLED 965 if (ctx->tbflags & FPSCR_SZ) { 966 int xsrc = XHACK(B7_4); 967 int xdst = XHACK(B11_8); 968 tcg_gen_mov_i32(FREG(xdst), FREG(xsrc)); 969 tcg_gen_mov_i32(FREG(xdst + 1), FREG(xsrc + 1)); 970 } else { 971 tcg_gen_mov_i32(FREG(B11_8), FREG(B7_4)); 972 } 973 return; 974 case 0xf00a: /* fmov {F,D,X}Rm,@Rn - FPSCR: Nothing */ 975 CHECK_FPU_ENABLED 976 if (ctx->tbflags & FPSCR_SZ) { 977 TCGv_i64 fp = tcg_temp_new_i64(); 978 gen_load_fpr64(ctx, fp, XHACK(B7_4)); 979 tcg_gen_qemu_st_i64(fp, REG(B11_8), ctx->memidx, 980 MO_TEUQ | MO_ALIGN); 981 } else { 982 tcg_gen_qemu_st_i32(FREG(B7_4), REG(B11_8), ctx->memidx, 983 MO_TEUL | MO_ALIGN); 984 } 985 return; 986 case 0xf008: /* fmov @Rm,{F,D,X}Rn - FPSCR: Nothing */ 987 CHECK_FPU_ENABLED 988 if (ctx->tbflags & FPSCR_SZ) { 989 TCGv_i64 fp = tcg_temp_new_i64(); 990 tcg_gen_qemu_ld_i64(fp, REG(B7_4), ctx->memidx, 991 MO_TEUQ | MO_ALIGN); 992 gen_store_fpr64(ctx, fp, XHACK(B11_8)); 993 } else { 994 tcg_gen_qemu_ld_i32(FREG(B11_8), REG(B7_4), ctx->memidx, 995 MO_TEUL | MO_ALIGN); 996 } 997 return; 998 case 0xf009: /* fmov @Rm+,{F,D,X}Rn - FPSCR: Nothing */ 999 CHECK_FPU_ENABLED 1000 if (ctx->tbflags & FPSCR_SZ) { 1001 TCGv_i64 fp = tcg_temp_new_i64(); 1002 tcg_gen_qemu_ld_i64(fp, REG(B7_4), ctx->memidx, 1003 MO_TEUQ | MO_ALIGN); 1004 gen_store_fpr64(ctx, fp, XHACK(B11_8)); 1005 tcg_gen_addi_i32(REG(B7_4), REG(B7_4), 8); 1006 } else { 1007 tcg_gen_qemu_ld_i32(FREG(B11_8), REG(B7_4), ctx->memidx, 1008 MO_TEUL | MO_ALIGN); 1009 tcg_gen_addi_i32(REG(B7_4), REG(B7_4), 4); 1010 } 1011 return; 1012 case 0xf00b: /* fmov {F,D,X}Rm,@-Rn - FPSCR: Nothing */ 1013 CHECK_FPU_ENABLED 1014 { 1015 TCGv addr = tcg_temp_new_i32(); 1016 if (ctx->tbflags & FPSCR_SZ) { 1017 TCGv_i64 fp = tcg_temp_new_i64(); 1018 gen_load_fpr64(ctx, fp, XHACK(B7_4)); 1019 tcg_gen_subi_i32(addr, REG(B11_8), 8); 1020 tcg_gen_qemu_st_i64(fp, addr, ctx->memidx, 1021 MO_TEUQ | MO_ALIGN); 1022 } else { 1023 tcg_gen_subi_i32(addr, REG(B11_8), 4); 1024 tcg_gen_qemu_st_i32(FREG(B7_4), addr, ctx->memidx, 1025 MO_TEUL | MO_ALIGN); 1026 } 1027 tcg_gen_mov_i32(REG(B11_8), addr); 1028 } 1029 return; 1030 case 0xf006: /* fmov @(R0,Rm),{F,D,X}Rm - FPSCR: Nothing */ 1031 CHECK_FPU_ENABLED 1032 { 1033 TCGv addr = tcg_temp_new_i32(); 1034 tcg_gen_add_i32(addr, REG(B7_4), REG(0)); 1035 if (ctx->tbflags & FPSCR_SZ) { 1036 TCGv_i64 fp = tcg_temp_new_i64(); 1037 tcg_gen_qemu_ld_i64(fp, addr, ctx->memidx, 1038 MO_TEUQ | MO_ALIGN); 1039 gen_store_fpr64(ctx, fp, XHACK(B11_8)); 1040 } else { 1041 tcg_gen_qemu_ld_i32(FREG(B11_8), addr, ctx->memidx, 1042 MO_TEUL | MO_ALIGN); 1043 } 1044 } 1045 return; 1046 case 0xf007: /* fmov {F,D,X}Rn,@(R0,Rn) - FPSCR: Nothing */ 1047 CHECK_FPU_ENABLED 1048 { 1049 TCGv addr = tcg_temp_new(); 1050 tcg_gen_add_i32(addr, REG(B11_8), REG(0)); 1051 if (ctx->tbflags & FPSCR_SZ) { 1052 TCGv_i64 fp = tcg_temp_new_i64(); 1053 gen_load_fpr64(ctx, fp, XHACK(B7_4)); 1054 tcg_gen_qemu_st_i64(fp, addr, ctx->memidx, 1055 MO_TEUQ | MO_ALIGN); 1056 } else { 1057 tcg_gen_qemu_st_i32(FREG(B7_4), addr, ctx->memidx, 1058 MO_TEUL | MO_ALIGN); 1059 } 1060 } 1061 return; 1062 case 0xf000: /* fadd Rm,Rn - FPSCR: R[PR,Enable.O/U/I]/W[Cause,Flag] */ 1063 case 0xf001: /* fsub Rm,Rn - FPSCR: R[PR,Enable.O/U/I]/W[Cause,Flag] */ 1064 case 0xf002: /* fmul Rm,Rn - FPSCR: R[PR,Enable.O/U/I]/W[Cause,Flag] */ 1065 case 0xf003: /* fdiv Rm,Rn - FPSCR: R[PR,Enable.O/U/I]/W[Cause,Flag] */ 1066 case 0xf004: /* fcmp/eq Rm,Rn - FPSCR: R[PR,Enable.V]/W[Cause,Flag] */ 1067 case 0xf005: /* fcmp/gt Rm,Rn - FPSCR: R[PR,Enable.V]/W[Cause,Flag] */ 1068 { 1069 CHECK_FPU_ENABLED 1070 if (ctx->tbflags & FPSCR_PR) { 1071 TCGv_i64 fp0, fp1; 1072 1073 if (ctx->opcode & 0x0110) { 1074 goto do_illegal; 1075 } 1076 fp0 = tcg_temp_new_i64(); 1077 fp1 = tcg_temp_new_i64(); 1078 gen_load_fpr64(ctx, fp0, B11_8); 1079 gen_load_fpr64(ctx, fp1, B7_4); 1080 switch (ctx->opcode & 0xf00f) { 1081 case 0xf000: /* fadd Rm,Rn */ 1082 gen_helper_fadd_DT(fp0, tcg_env, fp0, fp1); 1083 break; 1084 case 0xf001: /* fsub Rm,Rn */ 1085 gen_helper_fsub_DT(fp0, tcg_env, fp0, fp1); 1086 break; 1087 case 0xf002: /* fmul Rm,Rn */ 1088 gen_helper_fmul_DT(fp0, tcg_env, fp0, fp1); 1089 break; 1090 case 0xf003: /* fdiv Rm,Rn */ 1091 gen_helper_fdiv_DT(fp0, tcg_env, fp0, fp1); 1092 break; 1093 case 0xf004: /* fcmp/eq Rm,Rn */ 1094 gen_helper_fcmp_eq_DT(cpu_sr_t, tcg_env, fp0, fp1); 1095 return; 1096 case 0xf005: /* fcmp/gt Rm,Rn */ 1097 gen_helper_fcmp_gt_DT(cpu_sr_t, tcg_env, fp0, fp1); 1098 return; 1099 } 1100 gen_store_fpr64(ctx, fp0, B11_8); 1101 } else { 1102 switch (ctx->opcode & 0xf00f) { 1103 case 0xf000: /* fadd Rm,Rn */ 1104 gen_helper_fadd_FT(FREG(B11_8), tcg_env, 1105 FREG(B11_8), FREG(B7_4)); 1106 break; 1107 case 0xf001: /* fsub Rm,Rn */ 1108 gen_helper_fsub_FT(FREG(B11_8), tcg_env, 1109 FREG(B11_8), FREG(B7_4)); 1110 break; 1111 case 0xf002: /* fmul Rm,Rn */ 1112 gen_helper_fmul_FT(FREG(B11_8), tcg_env, 1113 FREG(B11_8), FREG(B7_4)); 1114 break; 1115 case 0xf003: /* fdiv Rm,Rn */ 1116 gen_helper_fdiv_FT(FREG(B11_8), tcg_env, 1117 FREG(B11_8), FREG(B7_4)); 1118 break; 1119 case 0xf004: /* fcmp/eq Rm,Rn */ 1120 gen_helper_fcmp_eq_FT(cpu_sr_t, tcg_env, 1121 FREG(B11_8), FREG(B7_4)); 1122 return; 1123 case 0xf005: /* fcmp/gt Rm,Rn */ 1124 gen_helper_fcmp_gt_FT(cpu_sr_t, tcg_env, 1125 FREG(B11_8), FREG(B7_4)); 1126 return; 1127 } 1128 } 1129 } 1130 return; 1131 case 0xf00e: /* fmac FR0,RM,Rn */ 1132 CHECK_FPU_ENABLED 1133 CHECK_FPSCR_PR_0 1134 gen_helper_fmac_FT(FREG(B11_8), tcg_env, 1135 FREG(0), FREG(B7_4), FREG(B11_8)); 1136 return; 1137 } 1138 1139 switch (ctx->opcode & 0xff00) { 1140 case 0xc900: /* and #imm,R0 */ 1141 tcg_gen_andi_i32(REG(0), REG(0), B7_0); 1142 return; 1143 case 0xcd00: /* and.b #imm,@(R0,GBR) */ 1144 { 1145 TCGv addr, val; 1146 addr = tcg_temp_new(); 1147 tcg_gen_add_i32(addr, REG(0), cpu_gbr); 1148 val = tcg_temp_new(); 1149 tcg_gen_qemu_ld_i32(val, addr, ctx->memidx, MO_UB); 1150 tcg_gen_andi_i32(val, val, B7_0); 1151 tcg_gen_qemu_st_i32(val, addr, ctx->memidx, MO_UB); 1152 } 1153 return; 1154 case 0x8b00: /* bf label */ 1155 CHECK_NOT_DELAY_SLOT 1156 gen_conditional_jump(ctx, ctx->base.pc_next + 4 + B7_0s * 2, false); 1157 return; 1158 case 0x8f00: /* bf/s label */ 1159 CHECK_NOT_DELAY_SLOT 1160 tcg_gen_xori_i32(cpu_delayed_cond, cpu_sr_t, 1); 1161 ctx->delayed_pc = ctx->base.pc_next + 4 + B7_0s * 2; 1162 ctx->envflags |= TB_FLAG_DELAY_SLOT_COND; 1163 return; 1164 case 0x8900: /* bt label */ 1165 CHECK_NOT_DELAY_SLOT 1166 gen_conditional_jump(ctx, ctx->base.pc_next + 4 + B7_0s * 2, true); 1167 return; 1168 case 0x8d00: /* bt/s label */ 1169 CHECK_NOT_DELAY_SLOT 1170 tcg_gen_mov_i32(cpu_delayed_cond, cpu_sr_t); 1171 ctx->delayed_pc = ctx->base.pc_next + 4 + B7_0s * 2; 1172 ctx->envflags |= TB_FLAG_DELAY_SLOT_COND; 1173 return; 1174 case 0x8800: /* cmp/eq #imm,R0 */ 1175 tcg_gen_setcondi_i32(TCG_COND_EQ, cpu_sr_t, REG(0), B7_0s); 1176 return; 1177 case 0xc400: /* mov.b @(disp,GBR),R0 */ 1178 { 1179 TCGv addr = tcg_temp_new(); 1180 tcg_gen_addi_i32(addr, cpu_gbr, B7_0); 1181 tcg_gen_qemu_ld_i32(REG(0), addr, ctx->memidx, MO_SB); 1182 } 1183 return; 1184 case 0xc500: /* mov.w @(disp,GBR),R0 */ 1185 { 1186 TCGv addr = tcg_temp_new(); 1187 tcg_gen_addi_i32(addr, cpu_gbr, B7_0 * 2); 1188 tcg_gen_qemu_ld_i32(REG(0), addr, ctx->memidx, MO_TESW | MO_ALIGN); 1189 } 1190 return; 1191 case 0xc600: /* mov.l @(disp,GBR),R0 */ 1192 { 1193 TCGv addr = tcg_temp_new(); 1194 tcg_gen_addi_i32(addr, cpu_gbr, B7_0 * 4); 1195 tcg_gen_qemu_ld_i32(REG(0), addr, ctx->memidx, MO_TESL | MO_ALIGN); 1196 } 1197 return; 1198 case 0xc000: /* mov.b R0,@(disp,GBR) */ 1199 { 1200 TCGv addr = tcg_temp_new(); 1201 tcg_gen_addi_i32(addr, cpu_gbr, B7_0); 1202 tcg_gen_qemu_st_i32(REG(0), addr, ctx->memidx, MO_UB); 1203 } 1204 return; 1205 case 0xc100: /* mov.w R0,@(disp,GBR) */ 1206 { 1207 TCGv addr = tcg_temp_new(); 1208 tcg_gen_addi_i32(addr, cpu_gbr, B7_0 * 2); 1209 tcg_gen_qemu_st_i32(REG(0), addr, ctx->memidx, MO_TEUW | MO_ALIGN); 1210 } 1211 return; 1212 case 0xc200: /* mov.l R0,@(disp,GBR) */ 1213 { 1214 TCGv addr = tcg_temp_new(); 1215 tcg_gen_addi_i32(addr, cpu_gbr, B7_0 * 4); 1216 tcg_gen_qemu_st_i32(REG(0), addr, ctx->memidx, MO_TEUL | MO_ALIGN); 1217 } 1218 return; 1219 case 0x8000: /* mov.b R0,@(disp,Rn) */ 1220 { 1221 TCGv addr = tcg_temp_new(); 1222 tcg_gen_addi_i32(addr, REG(B7_4), B3_0); 1223 tcg_gen_qemu_st_i32(REG(0), addr, ctx->memidx, MO_UB); 1224 } 1225 return; 1226 case 0x8100: /* mov.w R0,@(disp,Rn) */ 1227 { 1228 TCGv addr = tcg_temp_new(); 1229 tcg_gen_addi_i32(addr, REG(B7_4), B3_0 * 2); 1230 tcg_gen_qemu_st_i32(REG(0), addr, ctx->memidx, 1231 MO_TEUW | UNALIGN(ctx)); 1232 } 1233 return; 1234 case 0x8400: /* mov.b @(disp,Rn),R0 */ 1235 { 1236 TCGv addr = tcg_temp_new(); 1237 tcg_gen_addi_i32(addr, REG(B7_4), B3_0); 1238 tcg_gen_qemu_ld_i32(REG(0), addr, ctx->memidx, MO_SB); 1239 } 1240 return; 1241 case 0x8500: /* mov.w @(disp,Rn),R0 */ 1242 { 1243 TCGv addr = tcg_temp_new(); 1244 tcg_gen_addi_i32(addr, REG(B7_4), B3_0 * 2); 1245 tcg_gen_qemu_ld_i32(REG(0), addr, ctx->memidx, 1246 MO_TESW | UNALIGN(ctx)); 1247 } 1248 return; 1249 case 0xc700: /* mova @(disp,PC),R0 */ 1250 CHECK_NOT_DELAY_SLOT 1251 tcg_gen_movi_i32(REG(0), ((ctx->base.pc_next & 0xfffffffc) + 1252 4 + B7_0 * 4) & ~3); 1253 return; 1254 case 0xcb00: /* or #imm,R0 */ 1255 tcg_gen_ori_i32(REG(0), REG(0), B7_0); 1256 return; 1257 case 0xcf00: /* or.b #imm,@(R0,GBR) */ 1258 { 1259 TCGv addr, val; 1260 addr = tcg_temp_new(); 1261 tcg_gen_add_i32(addr, REG(0), cpu_gbr); 1262 val = tcg_temp_new(); 1263 tcg_gen_qemu_ld_i32(val, addr, ctx->memidx, MO_UB); 1264 tcg_gen_ori_i32(val, val, B7_0); 1265 tcg_gen_qemu_st_i32(val, addr, ctx->memidx, MO_UB); 1266 } 1267 return; 1268 case 0xc300: /* trapa #imm */ 1269 { 1270 TCGv imm; 1271 CHECK_NOT_DELAY_SLOT 1272 gen_save_cpu_state(ctx, true); 1273 imm = tcg_constant_i32(B7_0); 1274 gen_helper_trapa(tcg_env, imm); 1275 ctx->base.is_jmp = DISAS_NORETURN; 1276 } 1277 return; 1278 case 0xc800: /* tst #imm,R0 */ 1279 { 1280 TCGv val = tcg_temp_new(); 1281 tcg_gen_andi_i32(val, REG(0), B7_0); 1282 tcg_gen_setcondi_i32(TCG_COND_EQ, cpu_sr_t, val, 0); 1283 } 1284 return; 1285 case 0xcc00: /* tst.b #imm,@(R0,GBR) */ 1286 { 1287 TCGv val = tcg_temp_new(); 1288 tcg_gen_add_i32(val, REG(0), cpu_gbr); 1289 tcg_gen_qemu_ld_i32(val, val, ctx->memidx, MO_UB); 1290 tcg_gen_andi_i32(val, val, B7_0); 1291 tcg_gen_setcondi_i32(TCG_COND_EQ, cpu_sr_t, val, 0); 1292 } 1293 return; 1294 case 0xca00: /* xor #imm,R0 */ 1295 tcg_gen_xori_i32(REG(0), REG(0), B7_0); 1296 return; 1297 case 0xce00: /* xor.b #imm,@(R0,GBR) */ 1298 { 1299 TCGv addr, val; 1300 addr = tcg_temp_new(); 1301 tcg_gen_add_i32(addr, REG(0), cpu_gbr); 1302 val = tcg_temp_new(); 1303 tcg_gen_qemu_ld_i32(val, addr, ctx->memidx, MO_UB); 1304 tcg_gen_xori_i32(val, val, B7_0); 1305 tcg_gen_qemu_st_i32(val, addr, ctx->memidx, MO_UB); 1306 } 1307 return; 1308 } 1309 1310 switch (ctx->opcode & 0xf08f) { 1311 case 0x408e: /* ldc Rm,Rn_BANK */ 1312 CHECK_PRIVILEGED 1313 tcg_gen_mov_i32(ALTREG(B6_4), REG(B11_8)); 1314 return; 1315 case 0x4087: /* ldc.l @Rm+,Rn_BANK */ 1316 CHECK_PRIVILEGED 1317 tcg_gen_qemu_ld_i32(ALTREG(B6_4), REG(B11_8), ctx->memidx, 1318 MO_TESL | MO_ALIGN); 1319 tcg_gen_addi_i32(REG(B11_8), REG(B11_8), 4); 1320 return; 1321 case 0x0082: /* stc Rm_BANK,Rn */ 1322 CHECK_PRIVILEGED 1323 tcg_gen_mov_i32(REG(B11_8), ALTREG(B6_4)); 1324 return; 1325 case 0x4083: /* stc.l Rm_BANK,@-Rn */ 1326 CHECK_PRIVILEGED 1327 { 1328 TCGv addr = tcg_temp_new(); 1329 tcg_gen_subi_i32(addr, REG(B11_8), 4); 1330 tcg_gen_qemu_st_i32(ALTREG(B6_4), addr, ctx->memidx, 1331 MO_TEUL | MO_ALIGN); 1332 tcg_gen_mov_i32(REG(B11_8), addr); 1333 } 1334 return; 1335 } 1336 1337 switch (ctx->opcode & 0xf0ff) { 1338 case 0x0023: /* braf Rn */ 1339 CHECK_NOT_DELAY_SLOT 1340 tcg_gen_addi_i32(cpu_delayed_pc, REG(B11_8), ctx->base.pc_next + 4); 1341 ctx->envflags |= TB_FLAG_DELAY_SLOT; 1342 ctx->delayed_pc = (uint32_t) - 1; 1343 return; 1344 case 0x0003: /* bsrf Rn */ 1345 CHECK_NOT_DELAY_SLOT 1346 tcg_gen_movi_i32(cpu_pr, ctx->base.pc_next + 4); 1347 tcg_gen_add_i32(cpu_delayed_pc, REG(B11_8), cpu_pr); 1348 ctx->envflags |= TB_FLAG_DELAY_SLOT; 1349 ctx->delayed_pc = (uint32_t) - 1; 1350 return; 1351 case 0x4015: /* cmp/pl Rn */ 1352 tcg_gen_setcondi_i32(TCG_COND_GT, cpu_sr_t, REG(B11_8), 0); 1353 return; 1354 case 0x4011: /* cmp/pz Rn */ 1355 tcg_gen_setcondi_i32(TCG_COND_GE, cpu_sr_t, REG(B11_8), 0); 1356 return; 1357 case 0x4010: /* dt Rn */ 1358 tcg_gen_subi_i32(REG(B11_8), REG(B11_8), 1); 1359 tcg_gen_setcondi_i32(TCG_COND_EQ, cpu_sr_t, REG(B11_8), 0); 1360 return; 1361 case 0x402b: /* jmp @Rn */ 1362 CHECK_NOT_DELAY_SLOT 1363 tcg_gen_mov_i32(cpu_delayed_pc, REG(B11_8)); 1364 ctx->envflags |= TB_FLAG_DELAY_SLOT; 1365 ctx->delayed_pc = (uint32_t) - 1; 1366 return; 1367 case 0x400b: /* jsr @Rn */ 1368 CHECK_NOT_DELAY_SLOT 1369 tcg_gen_movi_i32(cpu_pr, ctx->base.pc_next + 4); 1370 tcg_gen_mov_i32(cpu_delayed_pc, REG(B11_8)); 1371 ctx->envflags |= TB_FLAG_DELAY_SLOT; 1372 ctx->delayed_pc = (uint32_t) - 1; 1373 return; 1374 case 0x400e: /* ldc Rm,SR */ 1375 CHECK_PRIVILEGED 1376 { 1377 TCGv val = tcg_temp_new(); 1378 tcg_gen_andi_i32(val, REG(B11_8), 0x700083f3); 1379 gen_write_sr(val); 1380 ctx->base.is_jmp = DISAS_STOP; 1381 } 1382 return; 1383 case 0x4007: /* ldc.l @Rm+,SR */ 1384 CHECK_PRIVILEGED 1385 { 1386 TCGv val = tcg_temp_new(); 1387 tcg_gen_qemu_ld_i32(val, REG(B11_8), ctx->memidx, 1388 MO_TESL | MO_ALIGN); 1389 tcg_gen_andi_i32(val, val, 0x700083f3); 1390 gen_write_sr(val); 1391 tcg_gen_addi_i32(REG(B11_8), REG(B11_8), 4); 1392 ctx->base.is_jmp = DISAS_STOP; 1393 } 1394 return; 1395 case 0x0002: /* stc SR,Rn */ 1396 CHECK_PRIVILEGED 1397 gen_read_sr(REG(B11_8)); 1398 return; 1399 case 0x4003: /* stc SR,@-Rn */ 1400 CHECK_PRIVILEGED 1401 { 1402 TCGv addr = tcg_temp_new(); 1403 TCGv val = tcg_temp_new(); 1404 tcg_gen_subi_i32(addr, REG(B11_8), 4); 1405 gen_read_sr(val); 1406 tcg_gen_qemu_st_i32(val, addr, ctx->memidx, MO_TEUL | MO_ALIGN); 1407 tcg_gen_mov_i32(REG(B11_8), addr); 1408 } 1409 return; 1410 #define LD(reg,ldnum,ldpnum,prechk) \ 1411 case ldnum: \ 1412 prechk \ 1413 tcg_gen_mov_i32 (cpu_##reg, REG(B11_8)); \ 1414 return; \ 1415 case ldpnum: \ 1416 prechk \ 1417 tcg_gen_qemu_ld_i32(cpu_##reg, REG(B11_8), ctx->memidx, \ 1418 MO_TESL | MO_ALIGN); \ 1419 tcg_gen_addi_i32(REG(B11_8), REG(B11_8), 4); \ 1420 return; 1421 #define ST(reg,stnum,stpnum,prechk) \ 1422 case stnum: \ 1423 prechk \ 1424 tcg_gen_mov_i32 (REG(B11_8), cpu_##reg); \ 1425 return; \ 1426 case stpnum: \ 1427 prechk \ 1428 { \ 1429 TCGv addr = tcg_temp_new(); \ 1430 tcg_gen_subi_i32(addr, REG(B11_8), 4); \ 1431 tcg_gen_qemu_st_i32(cpu_##reg, addr, ctx->memidx, \ 1432 MO_TEUL | MO_ALIGN); \ 1433 tcg_gen_mov_i32(REG(B11_8), addr); \ 1434 } \ 1435 return; 1436 #define LDST(reg,ldnum,ldpnum,stnum,stpnum,prechk) \ 1437 LD(reg,ldnum,ldpnum,prechk) \ 1438 ST(reg,stnum,stpnum,prechk) 1439 LDST(gbr, 0x401e, 0x4017, 0x0012, 0x4013, {}) 1440 LDST(vbr, 0x402e, 0x4027, 0x0022, 0x4023, CHECK_PRIVILEGED) 1441 LDST(ssr, 0x403e, 0x4037, 0x0032, 0x4033, CHECK_PRIVILEGED) 1442 LDST(spc, 0x404e, 0x4047, 0x0042, 0x4043, CHECK_PRIVILEGED) 1443 ST(sgr, 0x003a, 0x4032, CHECK_PRIVILEGED) 1444 LD(sgr, 0x403a, 0x4036, CHECK_PRIVILEGED CHECK_SH4A) 1445 LDST(dbr, 0x40fa, 0x40f6, 0x00fa, 0x40f2, CHECK_PRIVILEGED) 1446 LDST(mach, 0x400a, 0x4006, 0x000a, 0x4002, {}) 1447 LDST(macl, 0x401a, 0x4016, 0x001a, 0x4012, {}) 1448 LDST(pr, 0x402a, 0x4026, 0x002a, 0x4022, {}) 1449 LDST(fpul, 0x405a, 0x4056, 0x005a, 0x4052, {CHECK_FPU_ENABLED}) 1450 case 0x406a: /* lds Rm,FPSCR */ 1451 CHECK_FPU_ENABLED 1452 gen_helper_ld_fpscr(tcg_env, REG(B11_8)); 1453 ctx->base.is_jmp = DISAS_STOP; 1454 return; 1455 case 0x4066: /* lds.l @Rm+,FPSCR */ 1456 CHECK_FPU_ENABLED 1457 { 1458 TCGv addr = tcg_temp_new(); 1459 tcg_gen_qemu_ld_i32(addr, REG(B11_8), ctx->memidx, 1460 MO_TESL | MO_ALIGN); 1461 tcg_gen_addi_i32(REG(B11_8), REG(B11_8), 4); 1462 gen_helper_ld_fpscr(tcg_env, addr); 1463 ctx->base.is_jmp = DISAS_STOP; 1464 } 1465 return; 1466 case 0x006a: /* sts FPSCR,Rn */ 1467 CHECK_FPU_ENABLED 1468 tcg_gen_andi_i32(REG(B11_8), cpu_fpscr, 0x003fffff); 1469 return; 1470 case 0x4062: /* sts FPSCR,@-Rn */ 1471 CHECK_FPU_ENABLED 1472 { 1473 TCGv addr, val; 1474 val = tcg_temp_new(); 1475 tcg_gen_andi_i32(val, cpu_fpscr, 0x003fffff); 1476 addr = tcg_temp_new(); 1477 tcg_gen_subi_i32(addr, REG(B11_8), 4); 1478 tcg_gen_qemu_st_i32(val, addr, ctx->memidx, MO_TEUL | MO_ALIGN); 1479 tcg_gen_mov_i32(REG(B11_8), addr); 1480 } 1481 return; 1482 case 0x00c3: /* movca.l R0,@Rm */ 1483 { 1484 TCGv val = tcg_temp_new(); 1485 tcg_gen_qemu_ld_i32(val, REG(B11_8), ctx->memidx, 1486 MO_TEUL | MO_ALIGN); 1487 gen_helper_movcal(tcg_env, REG(B11_8), val); 1488 tcg_gen_qemu_st_i32(REG(0), REG(B11_8), ctx->memidx, 1489 MO_TEUL | MO_ALIGN); 1490 } 1491 ctx->has_movcal = 1; 1492 return; 1493 case 0x40a9: /* 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 return; 1499 case 0x40e9: /* movua.l @Rm+,R0 */ 1500 CHECK_SH4A 1501 /* Load non-boundary-aligned data */ 1502 tcg_gen_qemu_ld_i32(REG(0), REG(B11_8), ctx->memidx, 1503 MO_TEUL | MO_UNALN); 1504 tcg_gen_addi_i32(REG(B11_8), REG(B11_8), 4); 1505 return; 1506 case 0x0029: /* movt Rn */ 1507 tcg_gen_mov_i32(REG(B11_8), cpu_sr_t); 1508 return; 1509 case 0x0073: 1510 /* MOVCO.L 1511 * LDST -> T 1512 * If (T == 1) R0 -> (Rn) 1513 * 0 -> LDST 1514 * 1515 * The above description doesn't work in a parallel context. 1516 * Since we currently support no smp boards, this implies user-mode. 1517 * But we can still support the official mechanism while user-mode 1518 * is single-threaded. */ 1519 CHECK_SH4A 1520 { 1521 TCGLabel *fail = gen_new_label(); 1522 TCGLabel *done = gen_new_label(); 1523 1524 if ((tb_cflags(ctx->base.tb) & CF_PARALLEL)) { 1525 TCGv tmp; 1526 1527 tcg_gen_brcond_i32(TCG_COND_NE, REG(B11_8), 1528 cpu_lock_addr, fail); 1529 tmp = tcg_temp_new(); 1530 tcg_gen_atomic_cmpxchg_i32(tmp, REG(B11_8), cpu_lock_value, 1531 REG(0), ctx->memidx, 1532 MO_TEUL | MO_ALIGN); 1533 tcg_gen_setcond_i32(TCG_COND_EQ, cpu_sr_t, tmp, cpu_lock_value); 1534 } else { 1535 tcg_gen_brcondi_i32(TCG_COND_EQ, cpu_lock_addr, -1, fail); 1536 tcg_gen_qemu_st_i32(REG(0), REG(B11_8), ctx->memidx, 1537 MO_TEUL | MO_ALIGN); 1538 tcg_gen_movi_i32(cpu_sr_t, 1); 1539 } 1540 tcg_gen_br(done); 1541 1542 gen_set_label(fail); 1543 tcg_gen_movi_i32(cpu_sr_t, 0); 1544 1545 gen_set_label(done); 1546 tcg_gen_movi_i32(cpu_lock_addr, -1); 1547 } 1548 return; 1549 case 0x0063: 1550 /* MOVLI.L @Rm,R0 1551 * 1 -> LDST 1552 * (Rm) -> R0 1553 * When interrupt/exception 1554 * occurred 0 -> LDST 1555 * 1556 * In a parallel context, we must also save the loaded value 1557 * for use with the cmpxchg that we'll use with movco.l. */ 1558 CHECK_SH4A 1559 if ((tb_cflags(ctx->base.tb) & CF_PARALLEL)) { 1560 TCGv tmp = tcg_temp_new(); 1561 tcg_gen_mov_i32(tmp, REG(B11_8)); 1562 tcg_gen_qemu_ld_i32(REG(0), REG(B11_8), ctx->memidx, 1563 MO_TESL | MO_ALIGN); 1564 tcg_gen_mov_i32(cpu_lock_value, REG(0)); 1565 tcg_gen_mov_i32(cpu_lock_addr, tmp); 1566 } else { 1567 tcg_gen_qemu_ld_i32(REG(0), REG(B11_8), ctx->memidx, 1568 MO_TESL | MO_ALIGN); 1569 tcg_gen_movi_i32(cpu_lock_addr, 0); 1570 } 1571 return; 1572 case 0x0093: /* ocbi @Rn */ 1573 { 1574 gen_helper_ocbi(tcg_env, REG(B11_8)); 1575 } 1576 return; 1577 case 0x00a3: /* ocbp @Rn */ 1578 case 0x00b3: /* ocbwb @Rn */ 1579 /* These instructions are supposed to do nothing in case of 1580 a cache miss. Given that we only partially emulate caches 1581 it is safe to simply ignore them. */ 1582 return; 1583 case 0x0083: /* pref @Rn */ 1584 return; 1585 case 0x00d3: /* prefi @Rn */ 1586 CHECK_SH4A 1587 return; 1588 case 0x00e3: /* icbi @Rn */ 1589 CHECK_SH4A 1590 return; 1591 case 0x00ab: /* synco */ 1592 CHECK_SH4A 1593 tcg_gen_mb(TCG_MO_ALL | TCG_BAR_SC); 1594 return; 1595 case 0x4024: /* rotcl Rn */ 1596 { 1597 TCGv tmp = tcg_temp_new(); 1598 tcg_gen_mov_i32(tmp, cpu_sr_t); 1599 tcg_gen_shri_i32(cpu_sr_t, REG(B11_8), 31); 1600 tcg_gen_shli_i32(REG(B11_8), REG(B11_8), 1); 1601 tcg_gen_or_i32(REG(B11_8), REG(B11_8), tmp); 1602 } 1603 return; 1604 case 0x4025: /* rotcr Rn */ 1605 { 1606 TCGv tmp = tcg_temp_new(); 1607 tcg_gen_shli_i32(tmp, cpu_sr_t, 31); 1608 tcg_gen_andi_i32(cpu_sr_t, REG(B11_8), 1); 1609 tcg_gen_shri_i32(REG(B11_8), REG(B11_8), 1); 1610 tcg_gen_or_i32(REG(B11_8), REG(B11_8), tmp); 1611 } 1612 return; 1613 case 0x4004: /* rotl Rn */ 1614 tcg_gen_rotli_i32(REG(B11_8), REG(B11_8), 1); 1615 tcg_gen_andi_i32(cpu_sr_t, REG(B11_8), 0); 1616 return; 1617 case 0x4005: /* rotr Rn */ 1618 tcg_gen_andi_i32(cpu_sr_t, REG(B11_8), 0); 1619 tcg_gen_rotri_i32(REG(B11_8), REG(B11_8), 1); 1620 return; 1621 case 0x4000: /* shll Rn */ 1622 case 0x4020: /* shal Rn */ 1623 tcg_gen_shri_i32(cpu_sr_t, REG(B11_8), 31); 1624 tcg_gen_shli_i32(REG(B11_8), REG(B11_8), 1); 1625 return; 1626 case 0x4021: /* shar Rn */ 1627 tcg_gen_andi_i32(cpu_sr_t, REG(B11_8), 1); 1628 tcg_gen_sari_i32(REG(B11_8), REG(B11_8), 1); 1629 return; 1630 case 0x4001: /* shlr Rn */ 1631 tcg_gen_andi_i32(cpu_sr_t, REG(B11_8), 1); 1632 tcg_gen_shri_i32(REG(B11_8), REG(B11_8), 1); 1633 return; 1634 case 0x4008: /* shll2 Rn */ 1635 tcg_gen_shli_i32(REG(B11_8), REG(B11_8), 2); 1636 return; 1637 case 0x4018: /* shll8 Rn */ 1638 tcg_gen_shli_i32(REG(B11_8), REG(B11_8), 8); 1639 return; 1640 case 0x4028: /* shll16 Rn */ 1641 tcg_gen_shli_i32(REG(B11_8), REG(B11_8), 16); 1642 return; 1643 case 0x4009: /* shlr2 Rn */ 1644 tcg_gen_shri_i32(REG(B11_8), REG(B11_8), 2); 1645 return; 1646 case 0x4019: /* shlr8 Rn */ 1647 tcg_gen_shri_i32(REG(B11_8), REG(B11_8), 8); 1648 return; 1649 case 0x4029: /* shlr16 Rn */ 1650 tcg_gen_shri_i32(REG(B11_8), REG(B11_8), 16); 1651 return; 1652 case 0x401b: /* tas.b @Rn */ 1653 tcg_gen_atomic_fetch_or_i32(cpu_sr_t, REG(B11_8), 1654 tcg_constant_i32(0x80), ctx->memidx, MO_UB); 1655 tcg_gen_setcondi_i32(TCG_COND_EQ, cpu_sr_t, cpu_sr_t, 0); 1656 return; 1657 case 0xf00d: /* fsts FPUL,FRn - FPSCR: Nothing */ 1658 CHECK_FPU_ENABLED 1659 tcg_gen_mov_i32(FREG(B11_8), cpu_fpul); 1660 return; 1661 case 0xf01d: /* flds FRm,FPUL - FPSCR: Nothing */ 1662 CHECK_FPU_ENABLED 1663 tcg_gen_mov_i32(cpu_fpul, FREG(B11_8)); 1664 return; 1665 case 0xf02d: /* float FPUL,FRn/DRn - FPSCR: R[PR,Enable.I]/W[Cause,Flag] */ 1666 CHECK_FPU_ENABLED 1667 if (ctx->tbflags & FPSCR_PR) { 1668 TCGv_i64 fp; 1669 if (ctx->opcode & 0x0100) { 1670 goto do_illegal; 1671 } 1672 fp = tcg_temp_new_i64(); 1673 gen_helper_float_DT(fp, tcg_env, cpu_fpul); 1674 gen_store_fpr64(ctx, fp, B11_8); 1675 } 1676 else { 1677 gen_helper_float_FT(FREG(B11_8), tcg_env, cpu_fpul); 1678 } 1679 return; 1680 case 0xf03d: /* ftrc FRm/DRm,FPUL - FPSCR: R[PR,Enable.V]/W[Cause,Flag] */ 1681 CHECK_FPU_ENABLED 1682 if (ctx->tbflags & FPSCR_PR) { 1683 TCGv_i64 fp; 1684 if (ctx->opcode & 0x0100) { 1685 goto do_illegal; 1686 } 1687 fp = tcg_temp_new_i64(); 1688 gen_load_fpr64(ctx, fp, B11_8); 1689 gen_helper_ftrc_DT(cpu_fpul, tcg_env, fp); 1690 } 1691 else { 1692 gen_helper_ftrc_FT(cpu_fpul, tcg_env, FREG(B11_8)); 1693 } 1694 return; 1695 case 0xf04d: /* fneg FRn/DRn - FPSCR: Nothing */ 1696 CHECK_FPU_ENABLED 1697 tcg_gen_xori_i32(FREG(B11_8), FREG(B11_8), 0x80000000); 1698 return; 1699 case 0xf05d: /* fabs FRn/DRn - FPCSR: Nothing */ 1700 CHECK_FPU_ENABLED 1701 tcg_gen_andi_i32(FREG(B11_8), FREG(B11_8), 0x7fffffff); 1702 return; 1703 case 0xf06d: /* fsqrt FRn */ 1704 CHECK_FPU_ENABLED 1705 if (ctx->tbflags & FPSCR_PR) { 1706 if (ctx->opcode & 0x0100) { 1707 goto do_illegal; 1708 } 1709 TCGv_i64 fp = tcg_temp_new_i64(); 1710 gen_load_fpr64(ctx, fp, B11_8); 1711 gen_helper_fsqrt_DT(fp, tcg_env, fp); 1712 gen_store_fpr64(ctx, fp, B11_8); 1713 } else { 1714 gen_helper_fsqrt_FT(FREG(B11_8), tcg_env, FREG(B11_8)); 1715 } 1716 return; 1717 case 0xf07d: /* fsrra FRn */ 1718 CHECK_FPU_ENABLED 1719 CHECK_FPSCR_PR_0 1720 gen_helper_fsrra_FT(FREG(B11_8), tcg_env, FREG(B11_8)); 1721 break; 1722 case 0xf08d: /* fldi0 FRn - FPSCR: R[PR] */ 1723 CHECK_FPU_ENABLED 1724 CHECK_FPSCR_PR_0 1725 tcg_gen_movi_i32(FREG(B11_8), 0); 1726 return; 1727 case 0xf09d: /* fldi1 FRn - FPSCR: R[PR] */ 1728 CHECK_FPU_ENABLED 1729 CHECK_FPSCR_PR_0 1730 tcg_gen_movi_i32(FREG(B11_8), 0x3f800000); 1731 return; 1732 case 0xf0ad: /* fcnvsd FPUL,DRn */ 1733 CHECK_FPU_ENABLED 1734 { 1735 TCGv_i64 fp = tcg_temp_new_i64(); 1736 gen_helper_fcnvsd_FT_DT(fp, tcg_env, cpu_fpul); 1737 gen_store_fpr64(ctx, fp, B11_8); 1738 } 1739 return; 1740 case 0xf0bd: /* fcnvds DRn,FPUL */ 1741 CHECK_FPU_ENABLED 1742 { 1743 TCGv_i64 fp = tcg_temp_new_i64(); 1744 gen_load_fpr64(ctx, fp, B11_8); 1745 gen_helper_fcnvds_DT_FT(cpu_fpul, tcg_env, fp); 1746 } 1747 return; 1748 case 0xf0ed: /* fipr FVm,FVn */ 1749 CHECK_FPU_ENABLED 1750 CHECK_FPSCR_PR_1 1751 { 1752 TCGv m = tcg_constant_i32((ctx->opcode >> 8) & 3); 1753 TCGv n = tcg_constant_i32((ctx->opcode >> 10) & 3); 1754 gen_helper_fipr(tcg_env, m, n); 1755 return; 1756 } 1757 break; 1758 case 0xf0fd: /* ftrv XMTRX,FVn */ 1759 CHECK_FPU_ENABLED 1760 CHECK_FPSCR_PR_1 1761 { 1762 if ((ctx->opcode & 0x0300) != 0x0100) { 1763 goto do_illegal; 1764 } 1765 TCGv n = tcg_constant_i32((ctx->opcode >> 10) & 3); 1766 gen_helper_ftrv(tcg_env, n); 1767 return; 1768 } 1769 break; 1770 } 1771 #if 0 1772 fprintf(stderr, "unknown instruction 0x%04x at pc 0x%08x\n", 1773 ctx->opcode, ctx->base.pc_next); 1774 fflush(stderr); 1775 #endif 1776 do_illegal: 1777 if (ctx->envflags & TB_FLAG_DELAY_SLOT_MASK) { 1778 do_illegal_slot: 1779 gen_save_cpu_state(ctx, true); 1780 gen_helper_raise_slot_illegal_instruction(tcg_env); 1781 } else { 1782 gen_save_cpu_state(ctx, true); 1783 gen_helper_raise_illegal_instruction(tcg_env); 1784 } 1785 ctx->base.is_jmp = DISAS_NORETURN; 1786 return; 1787 1788 do_fpu_disabled: 1789 gen_save_cpu_state(ctx, true); 1790 if (ctx->envflags & TB_FLAG_DELAY_SLOT_MASK) { 1791 gen_helper_raise_slot_fpu_disable(tcg_env); 1792 } else { 1793 gen_helper_raise_fpu_disable(tcg_env); 1794 } 1795 ctx->base.is_jmp = DISAS_NORETURN; 1796 } 1797 1798 static void decode_opc(DisasContext * ctx) 1799 { 1800 uint32_t old_flags = ctx->envflags; 1801 1802 _decode_opc(ctx); 1803 1804 if (old_flags & TB_FLAG_DELAY_SLOT_MASK) { 1805 /* go out of the delay slot */ 1806 ctx->envflags &= ~TB_FLAG_DELAY_SLOT_MASK; 1807 1808 /* When in an exclusive region, we must continue to the end 1809 for conditional branches. */ 1810 if (ctx->tbflags & TB_FLAG_GUSA_EXCLUSIVE 1811 && old_flags & TB_FLAG_DELAY_SLOT_COND) { 1812 gen_delayed_conditional_jump(ctx); 1813 return; 1814 } 1815 /* Otherwise this is probably an invalid gUSA region. 1816 Drop the GUSA bits so the next TB doesn't see them. */ 1817 ctx->envflags &= ~TB_FLAG_GUSA_MASK; 1818 1819 tcg_gen_movi_i32(cpu_flags, ctx->envflags); 1820 if (old_flags & TB_FLAG_DELAY_SLOT_COND) { 1821 gen_delayed_conditional_jump(ctx); 1822 } else { 1823 gen_jump(ctx); 1824 } 1825 } 1826 } 1827 1828 #ifdef CONFIG_USER_ONLY 1829 /* 1830 * Restart with the EXCLUSIVE bit set, within a TB run via 1831 * cpu_exec_step_atomic holding the exclusive lock. 1832 */ 1833 static void gen_restart_exclusive(DisasContext *ctx) 1834 { 1835 ctx->envflags |= TB_FLAG_GUSA_EXCLUSIVE; 1836 gen_save_cpu_state(ctx, false); 1837 gen_helper_exclusive(tcg_env); 1838 ctx->base.is_jmp = DISAS_NORETURN; 1839 } 1840 1841 /* For uniprocessors, SH4 uses optimistic restartable atomic sequences. 1842 Upon an interrupt, a real kernel would simply notice magic values in 1843 the registers and reset the PC to the start of the sequence. 1844 1845 For QEMU, we cannot do this in quite the same way. Instead, we notice 1846 the normal start of such a sequence (mov #-x,r15). While we can handle 1847 any sequence via cpu_exec_step_atomic, we can recognize the "normal" 1848 sequences and transform them into atomic operations as seen by the host. 1849 */ 1850 static void decode_gusa(DisasContext *ctx, CPUSH4State *env) 1851 { 1852 uint16_t insns[5]; 1853 int ld_adr, ld_dst, ld_mop; 1854 int op_dst, op_src, op_opc; 1855 int mv_src, mt_dst, st_src, st_mop; 1856 TCGv op_arg; 1857 uint32_t pc = ctx->base.pc_next; 1858 uint32_t pc_end = ctx->base.tb->cs_base; 1859 int max_insns = (pc_end - pc) / 2; 1860 int i; 1861 1862 /* The state machine below will consume only a few insns. 1863 If there are more than that in a region, fail now. */ 1864 if (max_insns > ARRAY_SIZE(insns)) { 1865 goto fail; 1866 } 1867 1868 /* Read all of the insns for the region. */ 1869 for (i = 0; i < max_insns; ++i) { 1870 insns[i] = translator_lduw(env, &ctx->base, pc + i * 2); 1871 } 1872 1873 ld_adr = ld_dst = ld_mop = -1; 1874 mv_src = -1; 1875 op_dst = op_src = op_opc = -1; 1876 mt_dst = -1; 1877 st_src = st_mop = -1; 1878 op_arg = NULL; 1879 i = 0; 1880 1881 #define NEXT_INSN \ 1882 do { if (i >= max_insns) goto fail; ctx->opcode = insns[i++]; } while (0) 1883 1884 /* 1885 * Expect a load to begin the region. 1886 */ 1887 NEXT_INSN; 1888 switch (ctx->opcode & 0xf00f) { 1889 case 0x6000: /* mov.b @Rm,Rn */ 1890 ld_mop = MO_SB; 1891 break; 1892 case 0x6001: /* mov.w @Rm,Rn */ 1893 ld_mop = MO_TESW; 1894 break; 1895 case 0x6002: /* mov.l @Rm,Rn */ 1896 ld_mop = MO_TESL; 1897 break; 1898 default: 1899 goto fail; 1900 } 1901 ld_adr = B7_4; 1902 ld_dst = B11_8; 1903 if (ld_adr == ld_dst) { 1904 goto fail; 1905 } 1906 /* Unless we see a mov, any two-operand operation must use ld_dst. */ 1907 op_dst = ld_dst; 1908 1909 /* 1910 * Expect an optional register move. 1911 */ 1912 NEXT_INSN; 1913 switch (ctx->opcode & 0xf00f) { 1914 case 0x6003: /* mov Rm,Rn */ 1915 /* 1916 * Here we want to recognize ld_dst being saved for later consumption, 1917 * or for another input register being copied so that ld_dst need not 1918 * be clobbered during the operation. 1919 */ 1920 op_dst = B11_8; 1921 mv_src = B7_4; 1922 if (op_dst == ld_dst) { 1923 /* Overwriting the load output. */ 1924 goto fail; 1925 } 1926 if (mv_src != ld_dst) { 1927 /* Copying a new input; constrain op_src to match the load. */ 1928 op_src = ld_dst; 1929 } 1930 break; 1931 1932 default: 1933 /* Put back and re-examine as operation. */ 1934 --i; 1935 } 1936 1937 /* 1938 * Expect the operation. 1939 */ 1940 NEXT_INSN; 1941 switch (ctx->opcode & 0xf00f) { 1942 case 0x300c: /* add Rm,Rn */ 1943 op_opc = INDEX_op_add_i32; 1944 goto do_reg_op; 1945 case 0x2009: /* and Rm,Rn */ 1946 op_opc = INDEX_op_and_i32; 1947 goto do_reg_op; 1948 case 0x200a: /* xor Rm,Rn */ 1949 op_opc = INDEX_op_xor_i32; 1950 goto do_reg_op; 1951 case 0x200b: /* or Rm,Rn */ 1952 op_opc = INDEX_op_or_i32; 1953 do_reg_op: 1954 /* The operation register should be as expected, and the 1955 other input cannot depend on the load. */ 1956 if (op_dst != B11_8) { 1957 goto fail; 1958 } 1959 if (op_src < 0) { 1960 /* Unconstrainted input. */ 1961 op_src = B7_4; 1962 } else if (op_src == B7_4) { 1963 /* Constrained input matched load. All operations are 1964 commutative; "swap" them by "moving" the load output 1965 to the (implicit) first argument and the move source 1966 to the (explicit) second argument. */ 1967 op_src = mv_src; 1968 } else { 1969 goto fail; 1970 } 1971 op_arg = REG(op_src); 1972 break; 1973 1974 case 0x6007: /* not Rm,Rn */ 1975 if (ld_dst != B7_4 || mv_src >= 0) { 1976 goto fail; 1977 } 1978 op_dst = B11_8; 1979 op_opc = INDEX_op_xor_i32; 1980 op_arg = tcg_constant_i32(-1); 1981 break; 1982 1983 case 0x7000 ... 0x700f: /* add #imm,Rn */ 1984 if (op_dst != B11_8 || mv_src >= 0) { 1985 goto fail; 1986 } 1987 op_opc = INDEX_op_add_i32; 1988 op_arg = tcg_constant_i32(B7_0s); 1989 break; 1990 1991 case 0x3000: /* cmp/eq Rm,Rn */ 1992 /* Looking for the middle of a compare-and-swap sequence, 1993 beginning with the compare. Operands can be either order, 1994 but with only one overlapping the load. */ 1995 if ((ld_dst == B11_8) + (ld_dst == B7_4) != 1 || mv_src >= 0) { 1996 goto fail; 1997 } 1998 op_opc = INDEX_op_setcond_i32; /* placeholder */ 1999 op_src = (ld_dst == B11_8 ? B7_4 : B11_8); 2000 op_arg = REG(op_src); 2001 2002 NEXT_INSN; 2003 switch (ctx->opcode & 0xff00) { 2004 case 0x8b00: /* bf label */ 2005 case 0x8f00: /* bf/s label */ 2006 if (pc + (i + 1 + B7_0s) * 2 != pc_end) { 2007 goto fail; 2008 } 2009 if ((ctx->opcode & 0xff00) == 0x8b00) { /* bf label */ 2010 break; 2011 } 2012 /* We're looking to unconditionally modify Rn with the 2013 result of the comparison, within the delay slot of 2014 the branch. This is used by older gcc. */ 2015 NEXT_INSN; 2016 if ((ctx->opcode & 0xf0ff) == 0x0029) { /* movt Rn */ 2017 mt_dst = B11_8; 2018 } else { 2019 goto fail; 2020 } 2021 break; 2022 2023 default: 2024 goto fail; 2025 } 2026 break; 2027 2028 case 0x2008: /* tst Rm,Rn */ 2029 /* Looking for a compare-and-swap against zero. */ 2030 if (ld_dst != B11_8 || ld_dst != B7_4 || mv_src >= 0) { 2031 goto fail; 2032 } 2033 op_opc = INDEX_op_setcond_i32; 2034 op_arg = tcg_constant_i32(0); 2035 2036 NEXT_INSN; 2037 if ((ctx->opcode & 0xff00) != 0x8900 /* bt label */ 2038 || pc + (i + 1 + B7_0s) * 2 != pc_end) { 2039 goto fail; 2040 } 2041 break; 2042 2043 default: 2044 /* Put back and re-examine as store. */ 2045 --i; 2046 } 2047 2048 /* 2049 * Expect the store. 2050 */ 2051 /* The store must be the last insn. */ 2052 if (i != max_insns - 1) { 2053 goto fail; 2054 } 2055 NEXT_INSN; 2056 switch (ctx->opcode & 0xf00f) { 2057 case 0x2000: /* mov.b Rm,@Rn */ 2058 st_mop = MO_UB; 2059 break; 2060 case 0x2001: /* mov.w Rm,@Rn */ 2061 st_mop = MO_UW; 2062 break; 2063 case 0x2002: /* mov.l Rm,@Rn */ 2064 st_mop = MO_UL; 2065 break; 2066 default: 2067 goto fail; 2068 } 2069 /* The store must match the load. */ 2070 if (ld_adr != B11_8 || st_mop != (ld_mop & MO_SIZE)) { 2071 goto fail; 2072 } 2073 st_src = B7_4; 2074 2075 #undef NEXT_INSN 2076 2077 /* 2078 * Emit the operation. 2079 */ 2080 switch (op_opc) { 2081 case -1: 2082 /* No operation found. Look for exchange pattern. */ 2083 if (st_src == ld_dst || mv_src >= 0) { 2084 goto fail; 2085 } 2086 tcg_gen_atomic_xchg_i32(REG(ld_dst), REG(ld_adr), REG(st_src), 2087 ctx->memidx, ld_mop); 2088 break; 2089 2090 case INDEX_op_add_i32: 2091 if (op_dst != st_src) { 2092 goto fail; 2093 } 2094 if (op_dst == ld_dst && st_mop == MO_UL) { 2095 tcg_gen_atomic_add_fetch_i32(REG(ld_dst), REG(ld_adr), 2096 op_arg, ctx->memidx, ld_mop); 2097 } else { 2098 tcg_gen_atomic_fetch_add_i32(REG(ld_dst), REG(ld_adr), 2099 op_arg, ctx->memidx, ld_mop); 2100 if (op_dst != ld_dst) { 2101 /* Note that mop sizes < 4 cannot use add_fetch 2102 because it won't carry into the higher bits. */ 2103 tcg_gen_add_i32(REG(op_dst), REG(ld_dst), op_arg); 2104 } 2105 } 2106 break; 2107 2108 case INDEX_op_and_i32: 2109 if (op_dst != st_src) { 2110 goto fail; 2111 } 2112 if (op_dst == ld_dst) { 2113 tcg_gen_atomic_and_fetch_i32(REG(ld_dst), REG(ld_adr), 2114 op_arg, ctx->memidx, ld_mop); 2115 } else { 2116 tcg_gen_atomic_fetch_and_i32(REG(ld_dst), REG(ld_adr), 2117 op_arg, ctx->memidx, ld_mop); 2118 tcg_gen_and_i32(REG(op_dst), REG(ld_dst), op_arg); 2119 } 2120 break; 2121 2122 case INDEX_op_or_i32: 2123 if (op_dst != st_src) { 2124 goto fail; 2125 } 2126 if (op_dst == ld_dst) { 2127 tcg_gen_atomic_or_fetch_i32(REG(ld_dst), REG(ld_adr), 2128 op_arg, ctx->memidx, ld_mop); 2129 } else { 2130 tcg_gen_atomic_fetch_or_i32(REG(ld_dst), REG(ld_adr), 2131 op_arg, ctx->memidx, ld_mop); 2132 tcg_gen_or_i32(REG(op_dst), REG(ld_dst), op_arg); 2133 } 2134 break; 2135 2136 case INDEX_op_xor_i32: 2137 if (op_dst != st_src) { 2138 goto fail; 2139 } 2140 if (op_dst == ld_dst) { 2141 tcg_gen_atomic_xor_fetch_i32(REG(ld_dst), REG(ld_adr), 2142 op_arg, ctx->memidx, ld_mop); 2143 } else { 2144 tcg_gen_atomic_fetch_xor_i32(REG(ld_dst), REG(ld_adr), 2145 op_arg, ctx->memidx, ld_mop); 2146 tcg_gen_xor_i32(REG(op_dst), REG(ld_dst), op_arg); 2147 } 2148 break; 2149 2150 case INDEX_op_setcond_i32: 2151 if (st_src == ld_dst) { 2152 goto fail; 2153 } 2154 tcg_gen_atomic_cmpxchg_i32(REG(ld_dst), REG(ld_adr), op_arg, 2155 REG(st_src), ctx->memidx, ld_mop); 2156 tcg_gen_setcond_i32(TCG_COND_EQ, cpu_sr_t, REG(ld_dst), op_arg); 2157 if (mt_dst >= 0) { 2158 tcg_gen_mov_i32(REG(mt_dst), cpu_sr_t); 2159 } 2160 break; 2161 2162 default: 2163 g_assert_not_reached(); 2164 } 2165 2166 /* The entire region has been translated. */ 2167 ctx->envflags &= ~TB_FLAG_GUSA_MASK; 2168 goto done; 2169 2170 fail: 2171 qemu_log_mask(LOG_UNIMP, "Unrecognized gUSA sequence %08x-%08x\n", 2172 pc, pc_end); 2173 2174 gen_restart_exclusive(ctx); 2175 2176 /* We're not executing an instruction, but we must report one for the 2177 purposes of accounting within the TB. We might as well report the 2178 entire region consumed via ctx->base.pc_next so that it's immediately 2179 available in the disassembly dump. */ 2180 2181 done: 2182 ctx->base.pc_next = pc_end; 2183 ctx->base.num_insns += max_insns - 1; 2184 2185 /* 2186 * Emit insn_start to cover each of the insns in the region. 2187 * This matches an assert in tcg.c making sure that we have 2188 * tb->icount * insn_start. 2189 */ 2190 for (i = 1; i < max_insns; ++i) { 2191 tcg_gen_insn_start(pc + i * 2, ctx->envflags); 2192 ctx->base.insn_start = tcg_last_op(); 2193 } 2194 } 2195 #endif 2196 2197 static void sh4_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs) 2198 { 2199 DisasContext *ctx = container_of(dcbase, DisasContext, base); 2200 uint32_t tbflags; 2201 int bound; 2202 2203 ctx->tbflags = tbflags = ctx->base.tb->flags; 2204 ctx->envflags = tbflags & TB_FLAG_ENVFLAGS_MASK; 2205 ctx->memidx = (tbflags & (1u << SR_MD)) == 0 ? 1 : 0; 2206 /* We don't know if the delayed pc came from a dynamic or static branch, 2207 so assume it is a dynamic branch. */ 2208 ctx->delayed_pc = -1; /* use delayed pc from env pointer */ 2209 ctx->features = cpu_env(cs)->features; 2210 ctx->has_movcal = (tbflags & TB_FLAG_PENDING_MOVCA); 2211 ctx->gbank = ((tbflags & (1 << SR_MD)) && 2212 (tbflags & (1 << SR_RB))) * 0x10; 2213 ctx->fbank = tbflags & FPSCR_FR ? 0x10 : 0; 2214 2215 #ifdef CONFIG_USER_ONLY 2216 if (tbflags & TB_FLAG_GUSA_MASK) { 2217 /* In gUSA exclusive region. */ 2218 uint32_t pc = ctx->base.pc_next; 2219 uint32_t pc_end = ctx->base.tb->cs_base; 2220 int backup = sextract32(ctx->tbflags, TB_FLAG_GUSA_SHIFT, 8); 2221 int max_insns = (pc_end - pc) / 2; 2222 2223 if (pc != pc_end + backup || max_insns < 2) { 2224 /* This is a malformed gUSA region. Don't do anything special, 2225 since the interpreter is likely to get confused. */ 2226 ctx->envflags &= ~TB_FLAG_GUSA_MASK; 2227 } else if (tbflags & TB_FLAG_GUSA_EXCLUSIVE) { 2228 /* Regardless of single-stepping or the end of the page, 2229 we must complete execution of the gUSA region while 2230 holding the exclusive lock. */ 2231 ctx->base.max_insns = max_insns; 2232 return; 2233 } 2234 } 2235 #endif 2236 2237 /* Since the ISA is fixed-width, we can bound by the number 2238 of instructions remaining on the page. */ 2239 bound = -(ctx->base.pc_next | TARGET_PAGE_MASK) / 2; 2240 ctx->base.max_insns = MIN(ctx->base.max_insns, bound); 2241 } 2242 2243 static void sh4_tr_tb_start(DisasContextBase *dcbase, CPUState *cs) 2244 { 2245 } 2246 2247 static void sh4_tr_insn_start(DisasContextBase *dcbase, CPUState *cs) 2248 { 2249 DisasContext *ctx = container_of(dcbase, DisasContext, base); 2250 2251 tcg_gen_insn_start(ctx->base.pc_next, ctx->envflags); 2252 } 2253 2254 static void sh4_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs) 2255 { 2256 CPUSH4State *env = cpu_env(cs); 2257 DisasContext *ctx = container_of(dcbase, DisasContext, base); 2258 2259 #ifdef CONFIG_USER_ONLY 2260 if (unlikely(ctx->envflags & TB_FLAG_GUSA_MASK) 2261 && !(ctx->envflags & TB_FLAG_GUSA_EXCLUSIVE)) { 2262 /* 2263 * We're in an gUSA region, and we have not already fallen 2264 * back on using an exclusive region. Attempt to parse the 2265 * region into a single supported atomic operation. Failure 2266 * is handled within the parser by raising an exception to 2267 * retry using an exclusive region. 2268 * 2269 * Parsing the region in one block conflicts with plugins, 2270 * so always use exclusive mode if plugins enabled. 2271 */ 2272 if (ctx->base.plugin_enabled) { 2273 gen_restart_exclusive(ctx); 2274 ctx->base.pc_next += 2; 2275 } else { 2276 decode_gusa(ctx, env); 2277 } 2278 return; 2279 } 2280 #endif 2281 2282 ctx->opcode = translator_lduw(env, &ctx->base, ctx->base.pc_next); 2283 decode_opc(ctx); 2284 ctx->base.pc_next += 2; 2285 } 2286 2287 static void sh4_tr_tb_stop(DisasContextBase *dcbase, CPUState *cs) 2288 { 2289 DisasContext *ctx = container_of(dcbase, DisasContext, base); 2290 2291 if (ctx->tbflags & TB_FLAG_GUSA_EXCLUSIVE) { 2292 /* Ending the region of exclusivity. Clear the bits. */ 2293 ctx->envflags &= ~TB_FLAG_GUSA_MASK; 2294 } 2295 2296 switch (ctx->base.is_jmp) { 2297 case DISAS_STOP: 2298 gen_save_cpu_state(ctx, true); 2299 tcg_gen_exit_tb(NULL, 0); 2300 break; 2301 case DISAS_NEXT: 2302 case DISAS_TOO_MANY: 2303 gen_save_cpu_state(ctx, false); 2304 gen_goto_tb(ctx, 0, ctx->base.pc_next); 2305 break; 2306 case DISAS_NORETURN: 2307 break; 2308 default: 2309 g_assert_not_reached(); 2310 } 2311 } 2312 2313 static const TranslatorOps sh4_tr_ops = { 2314 .init_disas_context = sh4_tr_init_disas_context, 2315 .tb_start = sh4_tr_tb_start, 2316 .insn_start = sh4_tr_insn_start, 2317 .translate_insn = sh4_tr_translate_insn, 2318 .tb_stop = sh4_tr_tb_stop, 2319 }; 2320 2321 void sh4_translate_code(CPUState *cs, TranslationBlock *tb, 2322 int *max_insns, vaddr pc, void *host_pc) 2323 { 2324 DisasContext ctx; 2325 2326 translator_loop(cs, tb, max_insns, pc, host_pc, &sh4_tr_ops, &ctx.base); 2327 } 2328