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