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