1 /* 2 * Xilinx MicroBlaze emulation for qemu: main translation routines. 3 * 4 * Copyright (c) 2009 Edgar E. Iglesias. 5 * Copyright (c) 2009-2012 PetaLogix Qld Pty Ltd. 6 * 7 * This library is free software; you can redistribute it and/or 8 * modify it under the terms of the GNU Lesser General Public 9 * License as published by the Free Software Foundation; either 10 * version 2.1 of the License, or (at your option) any later version. 11 * 12 * This library is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 * Lesser General Public License for more details. 16 * 17 * You should have received a copy of the GNU Lesser General Public 18 * License along with this library; if not, see <http://www.gnu.org/licenses/>. 19 */ 20 21 #include "qemu/osdep.h" 22 #include "cpu.h" 23 #include "accel/tcg/cpu-ldst.h" 24 #include "tcg/tcg-op.h" 25 #include "exec/helper-proto.h" 26 #include "exec/helper-gen.h" 27 #include "exec/translator.h" 28 #include "exec/translation-block.h" 29 #include "exec/target_page.h" 30 #include "qemu/qemu-print.h" 31 32 #include "exec/log.h" 33 34 #define HELPER_H "helper.h" 35 #include "exec/helper-info.c.inc" 36 #undef HELPER_H 37 38 #define EXTRACT_FIELD(src, start, end) \ 39 (((src) >> start) & ((1 << (end - start + 1)) - 1)) 40 41 /* is_jmp field values */ 42 #define DISAS_JUMP DISAS_TARGET_0 /* only pc was modified dynamically */ 43 #define DISAS_EXIT DISAS_TARGET_1 /* all cpu state modified dynamically */ 44 45 /* cpu state besides pc was modified dynamically; update pc to next */ 46 #define DISAS_EXIT_NEXT DISAS_TARGET_2 47 /* cpu state besides pc was modified dynamically; update pc to btarget */ 48 #define DISAS_EXIT_JUMP DISAS_TARGET_3 49 50 static TCGv_i32 cpu_R[32]; 51 static TCGv_i32 cpu_pc; 52 static TCGv_i32 cpu_msr; 53 static TCGv_i32 cpu_msr_c; 54 static TCGv_i32 cpu_imm; 55 static TCGv_i32 cpu_bvalue; 56 static TCGv_i32 cpu_btarget; 57 static TCGv_i32 cpu_iflags; 58 static TCGv cpu_res_addr; 59 static TCGv_i32 cpu_res_val; 60 61 /* This is the state at translation time. */ 62 typedef struct DisasContext { 63 DisasContextBase base; 64 const MicroBlazeCPUConfig *cfg; 65 66 /* Decoder. */ 67 uint32_t ext_imm; 68 unsigned int tb_flags; 69 unsigned int tb_flags_to_set; 70 int mem_index; 71 72 /* Condition under which to jump, including NEVER and ALWAYS. */ 73 TCGCond jmp_cond; 74 75 /* Immediate branch-taken destination, or -1 for indirect. */ 76 uint32_t jmp_dest; 77 } DisasContext; 78 79 static int typeb_imm(DisasContext *dc, int x) 80 { 81 if (dc->tb_flags & IMM_FLAG) { 82 return deposit32(dc->ext_imm, 0, 16, x); 83 } 84 return x; 85 } 86 87 /* Include the auto-generated decoder. */ 88 #include "decode-insns.c.inc" 89 90 static void t_sync_flags(DisasContext *dc) 91 { 92 /* Synch the tb dependent flags between translator and runtime. */ 93 if ((dc->tb_flags ^ dc->base.tb->flags) & IFLAGS_TB_MASK) { 94 tcg_gen_movi_i32(cpu_iflags, dc->tb_flags & IFLAGS_TB_MASK); 95 } 96 } 97 98 static void gen_raise_exception(DisasContext *dc, uint32_t index) 99 { 100 gen_helper_raise_exception(tcg_env, tcg_constant_i32(index)); 101 dc->base.is_jmp = DISAS_NORETURN; 102 } 103 104 static void gen_raise_exception_sync(DisasContext *dc, uint32_t index) 105 { 106 t_sync_flags(dc); 107 tcg_gen_movi_i32(cpu_pc, dc->base.pc_next); 108 gen_raise_exception(dc, index); 109 } 110 111 static void gen_raise_hw_excp(DisasContext *dc, uint32_t esr_ec) 112 { 113 TCGv_i32 tmp = tcg_constant_i32(esr_ec); 114 tcg_gen_st_i32(tmp, tcg_env, offsetof(CPUMBState, esr)); 115 116 gen_raise_exception_sync(dc, EXCP_HW_EXCP); 117 } 118 119 static void gen_goto_tb(DisasContext *dc, int n, target_ulong dest) 120 { 121 if (translator_use_goto_tb(&dc->base, dest)) { 122 tcg_gen_goto_tb(n); 123 tcg_gen_movi_i32(cpu_pc, dest); 124 tcg_gen_exit_tb(dc->base.tb, n); 125 } else { 126 tcg_gen_movi_i32(cpu_pc, dest); 127 tcg_gen_lookup_and_goto_ptr(); 128 } 129 dc->base.is_jmp = DISAS_NORETURN; 130 } 131 132 /* 133 * Returns true if the insn an illegal operation. 134 * If exceptions are enabled, an exception is raised. 135 */ 136 static bool trap_illegal(DisasContext *dc, bool cond) 137 { 138 if (cond && (dc->tb_flags & MSR_EE) 139 && dc->cfg->illegal_opcode_exception) { 140 gen_raise_hw_excp(dc, ESR_EC_ILLEGAL_OP); 141 } 142 return cond; 143 } 144 145 /* 146 * Returns true if the insn is illegal in userspace. 147 * If exceptions are enabled, an exception is raised. 148 */ 149 static bool trap_userspace(DisasContext *dc, bool cond) 150 { 151 bool cond_user = cond && dc->mem_index == MMU_USER_IDX; 152 153 if (cond_user && (dc->tb_flags & MSR_EE)) { 154 gen_raise_hw_excp(dc, ESR_EC_PRIVINSN); 155 } 156 return cond_user; 157 } 158 159 /* 160 * Return true, and log an error, if the current insn is 161 * within a delay slot. 162 */ 163 static bool invalid_delay_slot(DisasContext *dc, const char *insn_type) 164 { 165 if (dc->tb_flags & D_FLAG) { 166 qemu_log_mask(LOG_GUEST_ERROR, 167 "Invalid insn in delay slot: %s at %08x\n", 168 insn_type, (uint32_t)dc->base.pc_next); 169 return true; 170 } 171 return false; 172 } 173 174 static TCGv_i32 reg_for_read(DisasContext *dc, int reg) 175 { 176 if (likely(reg != 0)) { 177 return cpu_R[reg]; 178 } 179 return tcg_constant_i32(0); 180 } 181 182 static TCGv_i32 reg_for_write(DisasContext *dc, int reg) 183 { 184 if (likely(reg != 0)) { 185 return cpu_R[reg]; 186 } 187 return tcg_temp_new_i32(); 188 } 189 190 static bool do_typea(DisasContext *dc, arg_typea *arg, bool side_effects, 191 void (*fn)(TCGv_i32, TCGv_i32, TCGv_i32)) 192 { 193 TCGv_i32 rd, ra, rb; 194 195 if (arg->rd == 0 && !side_effects) { 196 return true; 197 } 198 199 rd = reg_for_write(dc, arg->rd); 200 ra = reg_for_read(dc, arg->ra); 201 rb = reg_for_read(dc, arg->rb); 202 fn(rd, ra, rb); 203 return true; 204 } 205 206 static bool do_typea0(DisasContext *dc, arg_typea0 *arg, bool side_effects, 207 void (*fn)(TCGv_i32, TCGv_i32)) 208 { 209 TCGv_i32 rd, ra; 210 211 if (arg->rd == 0 && !side_effects) { 212 return true; 213 } 214 215 rd = reg_for_write(dc, arg->rd); 216 ra = reg_for_read(dc, arg->ra); 217 fn(rd, ra); 218 return true; 219 } 220 221 static bool do_typeb_imm(DisasContext *dc, arg_typeb *arg, bool side_effects, 222 void (*fni)(TCGv_i32, TCGv_i32, int32_t)) 223 { 224 TCGv_i32 rd, ra; 225 226 if (arg->rd == 0 && !side_effects) { 227 return true; 228 } 229 230 rd = reg_for_write(dc, arg->rd); 231 ra = reg_for_read(dc, arg->ra); 232 fni(rd, ra, arg->imm); 233 return true; 234 } 235 236 static bool do_typeb_val(DisasContext *dc, arg_typeb *arg, bool side_effects, 237 void (*fn)(TCGv_i32, TCGv_i32, TCGv_i32)) 238 { 239 TCGv_i32 rd, ra, imm; 240 241 if (arg->rd == 0 && !side_effects) { 242 return true; 243 } 244 245 rd = reg_for_write(dc, arg->rd); 246 ra = reg_for_read(dc, arg->ra); 247 imm = tcg_constant_i32(arg->imm); 248 249 fn(rd, ra, imm); 250 return true; 251 } 252 253 #define DO_TYPEA(NAME, SE, FN) \ 254 static bool trans_##NAME(DisasContext *dc, arg_typea *a) \ 255 { return do_typea(dc, a, SE, FN); } 256 257 #define DO_TYPEA_CFG(NAME, CFG, SE, FN) \ 258 static bool trans_##NAME(DisasContext *dc, arg_typea *a) \ 259 { return dc->cfg->CFG && do_typea(dc, a, SE, FN); } 260 261 #define DO_TYPEA0(NAME, SE, FN) \ 262 static bool trans_##NAME(DisasContext *dc, arg_typea0 *a) \ 263 { return do_typea0(dc, a, SE, FN); } 264 265 #define DO_TYPEA0_CFG(NAME, CFG, SE, FN) \ 266 static bool trans_##NAME(DisasContext *dc, arg_typea0 *a) \ 267 { return dc->cfg->CFG && do_typea0(dc, a, SE, FN); } 268 269 #define DO_TYPEBI(NAME, SE, FNI) \ 270 static bool trans_##NAME(DisasContext *dc, arg_typeb *a) \ 271 { return do_typeb_imm(dc, a, SE, FNI); } 272 273 #define DO_TYPEBI_CFG(NAME, CFG, SE, FNI) \ 274 static bool trans_##NAME(DisasContext *dc, arg_typeb *a) \ 275 { return dc->cfg->CFG && do_typeb_imm(dc, a, SE, FNI); } 276 277 #define DO_TYPEBV(NAME, SE, FN) \ 278 static bool trans_##NAME(DisasContext *dc, arg_typeb *a) \ 279 { return do_typeb_val(dc, a, SE, FN); } 280 281 #define ENV_WRAPPER2(NAME, HELPER) \ 282 static void NAME(TCGv_i32 out, TCGv_i32 ina) \ 283 { HELPER(out, tcg_env, ina); } 284 285 #define ENV_WRAPPER3(NAME, HELPER) \ 286 static void NAME(TCGv_i32 out, TCGv_i32 ina, TCGv_i32 inb) \ 287 { HELPER(out, tcg_env, ina, inb); } 288 289 /* No input carry, but output carry. */ 290 static void gen_add(TCGv_i32 out, TCGv_i32 ina, TCGv_i32 inb) 291 { 292 TCGv_i32 zero = tcg_constant_i32(0); 293 294 tcg_gen_add2_i32(out, cpu_msr_c, ina, zero, inb, zero); 295 } 296 297 /* Input and output carry. */ 298 static void gen_addc(TCGv_i32 out, TCGv_i32 ina, TCGv_i32 inb) 299 { 300 tcg_gen_addcio_i32(out, cpu_msr_c, ina, inb, cpu_msr_c); 301 } 302 303 /* Input carry, but no output carry. */ 304 static void gen_addkc(TCGv_i32 out, TCGv_i32 ina, TCGv_i32 inb) 305 { 306 tcg_gen_add_i32(out, ina, inb); 307 tcg_gen_add_i32(out, out, cpu_msr_c); 308 } 309 310 DO_TYPEA(add, true, gen_add) 311 DO_TYPEA(addc, true, gen_addc) 312 DO_TYPEA(addk, false, tcg_gen_add_i32) 313 DO_TYPEA(addkc, true, gen_addkc) 314 315 DO_TYPEBV(addi, true, gen_add) 316 DO_TYPEBV(addic, true, gen_addc) 317 DO_TYPEBI(addik, false, tcg_gen_addi_i32) 318 DO_TYPEBV(addikc, true, gen_addkc) 319 320 static void gen_andni(TCGv_i32 out, TCGv_i32 ina, int32_t imm) 321 { 322 tcg_gen_andi_i32(out, ina, ~imm); 323 } 324 325 DO_TYPEA(and, false, tcg_gen_and_i32) 326 DO_TYPEBI(andi, false, tcg_gen_andi_i32) 327 DO_TYPEA(andn, false, tcg_gen_andc_i32) 328 DO_TYPEBI(andni, false, gen_andni) 329 330 static void gen_bsra(TCGv_i32 out, TCGv_i32 ina, TCGv_i32 inb) 331 { 332 TCGv_i32 tmp = tcg_temp_new_i32(); 333 tcg_gen_andi_i32(tmp, inb, 31); 334 tcg_gen_sar_i32(out, ina, tmp); 335 } 336 337 static void gen_bsrl(TCGv_i32 out, TCGv_i32 ina, TCGv_i32 inb) 338 { 339 TCGv_i32 tmp = tcg_temp_new_i32(); 340 tcg_gen_andi_i32(tmp, inb, 31); 341 tcg_gen_shr_i32(out, ina, tmp); 342 } 343 344 static void gen_bsll(TCGv_i32 out, TCGv_i32 ina, TCGv_i32 inb) 345 { 346 TCGv_i32 tmp = tcg_temp_new_i32(); 347 tcg_gen_andi_i32(tmp, inb, 31); 348 tcg_gen_shl_i32(out, ina, tmp); 349 } 350 351 static void gen_bsefi(TCGv_i32 out, TCGv_i32 ina, int32_t imm) 352 { 353 /* Note that decodetree has extracted and reassembled imm_w/imm_s. */ 354 int imm_w = extract32(imm, 5, 5); 355 int imm_s = extract32(imm, 0, 5); 356 357 if (imm_w + imm_s > 32 || imm_w == 0) { 358 /* These inputs have an undefined behavior. */ 359 qemu_log_mask(LOG_GUEST_ERROR, "bsefi: Bad input w=%d s=%d\n", 360 imm_w, imm_s); 361 } else { 362 tcg_gen_extract_i32(out, ina, imm_s, imm_w); 363 } 364 } 365 366 static void gen_bsifi(TCGv_i32 out, TCGv_i32 ina, int32_t imm) 367 { 368 /* Note that decodetree has extracted and reassembled imm_w/imm_s. */ 369 int imm_w = extract32(imm, 5, 5); 370 int imm_s = extract32(imm, 0, 5); 371 int width = imm_w - imm_s + 1; 372 373 if (imm_w < imm_s) { 374 /* These inputs have an undefined behavior. */ 375 qemu_log_mask(LOG_GUEST_ERROR, "bsifi: Bad input w=%d s=%d\n", 376 imm_w, imm_s); 377 } else { 378 tcg_gen_deposit_i32(out, out, ina, imm_s, width); 379 } 380 } 381 382 DO_TYPEA_CFG(bsra, use_barrel, false, gen_bsra) 383 DO_TYPEA_CFG(bsrl, use_barrel, false, gen_bsrl) 384 DO_TYPEA_CFG(bsll, use_barrel, false, gen_bsll) 385 386 DO_TYPEBI_CFG(bsrai, use_barrel, false, tcg_gen_sari_i32) 387 DO_TYPEBI_CFG(bsrli, use_barrel, false, tcg_gen_shri_i32) 388 DO_TYPEBI_CFG(bslli, use_barrel, false, tcg_gen_shli_i32) 389 390 DO_TYPEBI_CFG(bsefi, use_barrel, false, gen_bsefi) 391 DO_TYPEBI_CFG(bsifi, use_barrel, false, gen_bsifi) 392 393 static void gen_clz(TCGv_i32 out, TCGv_i32 ina) 394 { 395 tcg_gen_clzi_i32(out, ina, 32); 396 } 397 398 DO_TYPEA0_CFG(clz, use_pcmp_instr, false, gen_clz) 399 400 static void gen_cmp(TCGv_i32 out, TCGv_i32 ina, TCGv_i32 inb) 401 { 402 TCGv_i32 lt = tcg_temp_new_i32(); 403 404 tcg_gen_setcond_i32(TCG_COND_LT, lt, inb, ina); 405 tcg_gen_sub_i32(out, inb, ina); 406 tcg_gen_deposit_i32(out, out, lt, 31, 1); 407 } 408 409 static void gen_cmpu(TCGv_i32 out, TCGv_i32 ina, TCGv_i32 inb) 410 { 411 TCGv_i32 lt = tcg_temp_new_i32(); 412 413 tcg_gen_setcond_i32(TCG_COND_LTU, lt, inb, ina); 414 tcg_gen_sub_i32(out, inb, ina); 415 tcg_gen_deposit_i32(out, out, lt, 31, 1); 416 } 417 418 DO_TYPEA(cmp, false, gen_cmp) 419 DO_TYPEA(cmpu, false, gen_cmpu) 420 421 ENV_WRAPPER3(gen_fadd, gen_helper_fadd) 422 ENV_WRAPPER3(gen_frsub, gen_helper_frsub) 423 ENV_WRAPPER3(gen_fmul, gen_helper_fmul) 424 ENV_WRAPPER3(gen_fdiv, gen_helper_fdiv) 425 ENV_WRAPPER3(gen_fcmp_un, gen_helper_fcmp_un) 426 ENV_WRAPPER3(gen_fcmp_lt, gen_helper_fcmp_lt) 427 ENV_WRAPPER3(gen_fcmp_eq, gen_helper_fcmp_eq) 428 ENV_WRAPPER3(gen_fcmp_le, gen_helper_fcmp_le) 429 ENV_WRAPPER3(gen_fcmp_gt, gen_helper_fcmp_gt) 430 ENV_WRAPPER3(gen_fcmp_ne, gen_helper_fcmp_ne) 431 ENV_WRAPPER3(gen_fcmp_ge, gen_helper_fcmp_ge) 432 433 DO_TYPEA_CFG(fadd, use_fpu, true, gen_fadd) 434 DO_TYPEA_CFG(frsub, use_fpu, true, gen_frsub) 435 DO_TYPEA_CFG(fmul, use_fpu, true, gen_fmul) 436 DO_TYPEA_CFG(fdiv, use_fpu, true, gen_fdiv) 437 DO_TYPEA_CFG(fcmp_un, use_fpu, true, gen_fcmp_un) 438 DO_TYPEA_CFG(fcmp_lt, use_fpu, true, gen_fcmp_lt) 439 DO_TYPEA_CFG(fcmp_eq, use_fpu, true, gen_fcmp_eq) 440 DO_TYPEA_CFG(fcmp_le, use_fpu, true, gen_fcmp_le) 441 DO_TYPEA_CFG(fcmp_gt, use_fpu, true, gen_fcmp_gt) 442 DO_TYPEA_CFG(fcmp_ne, use_fpu, true, gen_fcmp_ne) 443 DO_TYPEA_CFG(fcmp_ge, use_fpu, true, gen_fcmp_ge) 444 445 ENV_WRAPPER2(gen_flt, gen_helper_flt) 446 ENV_WRAPPER2(gen_fint, gen_helper_fint) 447 ENV_WRAPPER2(gen_fsqrt, gen_helper_fsqrt) 448 449 DO_TYPEA0_CFG(flt, use_fpu >= 2, true, gen_flt) 450 DO_TYPEA0_CFG(fint, use_fpu >= 2, true, gen_fint) 451 DO_TYPEA0_CFG(fsqrt, use_fpu >= 2, true, gen_fsqrt) 452 453 /* Does not use ENV_WRAPPER3, because arguments are swapped as well. */ 454 static void gen_idiv(TCGv_i32 out, TCGv_i32 ina, TCGv_i32 inb) 455 { 456 gen_helper_divs(out, tcg_env, inb, ina); 457 } 458 459 static void gen_idivu(TCGv_i32 out, TCGv_i32 ina, TCGv_i32 inb) 460 { 461 gen_helper_divu(out, tcg_env, inb, ina); 462 } 463 464 DO_TYPEA_CFG(idiv, use_div, true, gen_idiv) 465 DO_TYPEA_CFG(idivu, use_div, true, gen_idivu) 466 467 static bool trans_imm(DisasContext *dc, arg_imm *arg) 468 { 469 if (invalid_delay_slot(dc, "imm")) { 470 return true; 471 } 472 dc->ext_imm = arg->imm << 16; 473 tcg_gen_movi_i32(cpu_imm, dc->ext_imm); 474 dc->tb_flags_to_set = IMM_FLAG; 475 return true; 476 } 477 478 static void gen_mulh(TCGv_i32 out, TCGv_i32 ina, TCGv_i32 inb) 479 { 480 TCGv_i32 tmp = tcg_temp_new_i32(); 481 tcg_gen_muls2_i32(tmp, out, ina, inb); 482 } 483 484 static void gen_mulhu(TCGv_i32 out, TCGv_i32 ina, TCGv_i32 inb) 485 { 486 TCGv_i32 tmp = tcg_temp_new_i32(); 487 tcg_gen_mulu2_i32(tmp, out, ina, inb); 488 } 489 490 static void gen_mulhsu(TCGv_i32 out, TCGv_i32 ina, TCGv_i32 inb) 491 { 492 TCGv_i32 tmp = tcg_temp_new_i32(); 493 tcg_gen_mulsu2_i32(tmp, out, ina, inb); 494 } 495 496 DO_TYPEA_CFG(mul, use_hw_mul, false, tcg_gen_mul_i32) 497 DO_TYPEA_CFG(mulh, use_hw_mul >= 2, false, gen_mulh) 498 DO_TYPEA_CFG(mulhu, use_hw_mul >= 2, false, gen_mulhu) 499 DO_TYPEA_CFG(mulhsu, use_hw_mul >= 2, false, gen_mulhsu) 500 DO_TYPEBI_CFG(muli, use_hw_mul, false, tcg_gen_muli_i32) 501 502 DO_TYPEA(or, false, tcg_gen_or_i32) 503 DO_TYPEBI(ori, false, tcg_gen_ori_i32) 504 505 static void gen_pcmpeq(TCGv_i32 out, TCGv_i32 ina, TCGv_i32 inb) 506 { 507 tcg_gen_setcond_i32(TCG_COND_EQ, out, ina, inb); 508 } 509 510 static void gen_pcmpne(TCGv_i32 out, TCGv_i32 ina, TCGv_i32 inb) 511 { 512 tcg_gen_setcond_i32(TCG_COND_NE, out, ina, inb); 513 } 514 515 DO_TYPEA_CFG(pcmpbf, use_pcmp_instr, false, gen_helper_pcmpbf) 516 DO_TYPEA_CFG(pcmpeq, use_pcmp_instr, false, gen_pcmpeq) 517 DO_TYPEA_CFG(pcmpne, use_pcmp_instr, false, gen_pcmpne) 518 519 /* No input carry, but output carry. */ 520 static void gen_rsub(TCGv_i32 out, TCGv_i32 ina, TCGv_i32 inb) 521 { 522 tcg_gen_setcond_i32(TCG_COND_GEU, cpu_msr_c, inb, ina); 523 tcg_gen_sub_i32(out, inb, ina); 524 } 525 526 /* Input and output carry. */ 527 static void gen_rsubc(TCGv_i32 out, TCGv_i32 ina, TCGv_i32 inb) 528 { 529 TCGv_i32 tmp = tcg_temp_new_i32(); 530 531 tcg_gen_not_i32(tmp, ina); 532 tcg_gen_addcio_i32(out, cpu_msr_c, tmp, inb, cpu_msr_c); 533 } 534 535 /* No input or output carry. */ 536 static void gen_rsubk(TCGv_i32 out, TCGv_i32 ina, TCGv_i32 inb) 537 { 538 tcg_gen_sub_i32(out, inb, ina); 539 } 540 541 /* Input carry, no output carry. */ 542 static void gen_rsubkc(TCGv_i32 out, TCGv_i32 ina, TCGv_i32 inb) 543 { 544 TCGv_i32 nota = tcg_temp_new_i32(); 545 546 tcg_gen_not_i32(nota, ina); 547 tcg_gen_add_i32(out, inb, nota); 548 tcg_gen_add_i32(out, out, cpu_msr_c); 549 } 550 551 DO_TYPEA(rsub, true, gen_rsub) 552 DO_TYPEA(rsubc, true, gen_rsubc) 553 DO_TYPEA(rsubk, false, gen_rsubk) 554 DO_TYPEA(rsubkc, true, gen_rsubkc) 555 556 DO_TYPEBV(rsubi, true, gen_rsub) 557 DO_TYPEBV(rsubic, true, gen_rsubc) 558 DO_TYPEBV(rsubik, false, gen_rsubk) 559 DO_TYPEBV(rsubikc, true, gen_rsubkc) 560 561 DO_TYPEA0(sext8, false, tcg_gen_ext8s_i32) 562 DO_TYPEA0(sext16, false, tcg_gen_ext16s_i32) 563 564 static void gen_sra(TCGv_i32 out, TCGv_i32 ina) 565 { 566 tcg_gen_andi_i32(cpu_msr_c, ina, 1); 567 tcg_gen_sari_i32(out, ina, 1); 568 } 569 570 static void gen_src(TCGv_i32 out, TCGv_i32 ina) 571 { 572 TCGv_i32 tmp = tcg_temp_new_i32(); 573 574 tcg_gen_mov_i32(tmp, cpu_msr_c); 575 tcg_gen_andi_i32(cpu_msr_c, ina, 1); 576 tcg_gen_extract2_i32(out, ina, tmp, 1); 577 } 578 579 static void gen_srl(TCGv_i32 out, TCGv_i32 ina) 580 { 581 tcg_gen_andi_i32(cpu_msr_c, ina, 1); 582 tcg_gen_shri_i32(out, ina, 1); 583 } 584 585 DO_TYPEA0(sra, false, gen_sra) 586 DO_TYPEA0(src, false, gen_src) 587 DO_TYPEA0(srl, false, gen_srl) 588 589 static void gen_swaph(TCGv_i32 out, TCGv_i32 ina) 590 { 591 tcg_gen_rotri_i32(out, ina, 16); 592 } 593 594 DO_TYPEA0(swapb, false, tcg_gen_bswap32_i32) 595 DO_TYPEA0(swaph, false, gen_swaph) 596 597 static bool trans_wdic(DisasContext *dc, arg_wdic *a) 598 { 599 /* Cache operations are nops: only check for supervisor mode. */ 600 trap_userspace(dc, true); 601 return true; 602 } 603 604 DO_TYPEA(xor, false, tcg_gen_xor_i32) 605 DO_TYPEBI(xori, false, tcg_gen_xori_i32) 606 607 static TCGv compute_ldst_addr_typea(DisasContext *dc, int ra, int rb) 608 { 609 TCGv ret; 610 611 /* If any of the regs is r0, set t to the value of the other reg. */ 612 if (ra && rb) { 613 ret = tcg_temp_new_i32(); 614 tcg_gen_add_i32(ret, cpu_R[ra], cpu_R[rb]); 615 } else if (ra) { 616 ret = cpu_R[ra]; 617 } else if (rb) { 618 ret = cpu_R[rb]; 619 } else { 620 ret = tcg_constant_i32(0); 621 } 622 623 if ((ra == 1 || rb == 1) && dc->cfg->stackprot) { 624 gen_helper_stackprot(tcg_env, ret); 625 } 626 return ret; 627 } 628 629 static TCGv compute_ldst_addr_typeb(DisasContext *dc, int ra, int imm) 630 { 631 TCGv ret; 632 633 /* If any of the regs is r0, set t to the value of the other reg. */ 634 if (ra && imm) { 635 ret = tcg_temp_new_i32(); 636 tcg_gen_addi_i32(ret, cpu_R[ra], imm); 637 } else if (ra) { 638 ret = cpu_R[ra]; 639 } else { 640 ret = tcg_constant_i32(imm); 641 } 642 643 if (ra == 1 && dc->cfg->stackprot) { 644 gen_helper_stackprot(tcg_env, ret); 645 } 646 return ret; 647 } 648 649 #ifndef CONFIG_USER_ONLY 650 static TCGv_i64 compute_ldst_addr_ea(DisasContext *dc, int ra, int rb) 651 { 652 int addr_size = dc->cfg->addr_size; 653 TCGv_i64 ret = tcg_temp_new_i64(); 654 655 if (addr_size == 32 || ra == 0) { 656 if (rb) { 657 tcg_gen_extu_i32_i64(ret, cpu_R[rb]); 658 } else { 659 return tcg_constant_i64(0); 660 } 661 } else { 662 if (rb) { 663 tcg_gen_concat_i32_i64(ret, cpu_R[rb], cpu_R[ra]); 664 } else { 665 tcg_gen_extu_i32_i64(ret, cpu_R[ra]); 666 tcg_gen_shli_i64(ret, ret, 32); 667 } 668 if (addr_size < 64) { 669 /* Mask off out of range bits. */ 670 tcg_gen_andi_i64(ret, ret, MAKE_64BIT_MASK(0, addr_size)); 671 } 672 } 673 return ret; 674 } 675 #endif 676 677 #ifndef CONFIG_USER_ONLY 678 static void record_unaligned_ess(DisasContext *dc, int rd, 679 MemOp size, bool store) 680 { 681 uint32_t iflags = tcg_get_insn_start_param(dc->base.insn_start, 1); 682 683 iflags |= ESR_ESS_FLAG; 684 iflags |= rd << 5; 685 iflags |= store * ESR_S; 686 iflags |= (size == MO_32) * ESR_W; 687 688 tcg_set_insn_start_param(dc->base.insn_start, 1, iflags); 689 } 690 691 static void gen_alignment_check_ea(DisasContext *dc, TCGv_i64 ea, int rb, 692 int rd, MemOp size, bool store) 693 { 694 if (rb && (dc->tb_flags & MSR_EE) && dc->cfg->unaligned_exceptions) { 695 TCGLabel *over = gen_new_label(); 696 697 record_unaligned_ess(dc, rd, size, store); 698 699 tcg_gen_brcondi_i64(TCG_COND_TSTEQ, ea, (1 << size) - 1, over); 700 gen_helper_unaligned_access(tcg_env, ea); 701 gen_set_label(over); 702 } 703 } 704 #endif 705 706 static inline MemOp mo_endian(DisasContext *dc) 707 { 708 return dc->cfg->endi ? MO_LE : MO_BE; 709 } 710 711 static bool do_load(DisasContext *dc, int rd, TCGv addr, MemOp mop, 712 int mem_index, bool rev) 713 { 714 MemOp size = mop & MO_SIZE; 715 716 mop |= mo_endian(dc); 717 718 /* 719 * When doing reverse accesses we need to do two things. 720 * 721 * 1. Reverse the address wrt endianness. 722 * 2. Byteswap the data lanes on the way back into the CPU core. 723 */ 724 if (rev) { 725 if (size > MO_8) { 726 mop ^= MO_BSWAP; 727 } 728 if (size < MO_32) { 729 tcg_gen_xori_tl(addr, addr, 3 - size); 730 } 731 } 732 733 /* 734 * For system mode, enforce alignment if the cpu configuration 735 * requires it. For user-mode, the Linux kernel will have fixed up 736 * any unaligned access, so emulate that by *not* setting MO_ALIGN. 737 */ 738 #ifndef CONFIG_USER_ONLY 739 if (size > MO_8 && 740 (dc->tb_flags & MSR_EE) && 741 dc->cfg->unaligned_exceptions) { 742 record_unaligned_ess(dc, rd, size, false); 743 mop |= MO_ALIGN; 744 } 745 #endif 746 747 tcg_gen_qemu_ld_i32(reg_for_write(dc, rd), addr, mem_index, mop); 748 return true; 749 } 750 751 static bool trans_lbu(DisasContext *dc, arg_typea *arg) 752 { 753 TCGv addr = compute_ldst_addr_typea(dc, arg->ra, arg->rb); 754 return do_load(dc, arg->rd, addr, MO_UB, dc->mem_index, false); 755 } 756 757 static bool trans_lbur(DisasContext *dc, arg_typea *arg) 758 { 759 TCGv addr = compute_ldst_addr_typea(dc, arg->ra, arg->rb); 760 return do_load(dc, arg->rd, addr, MO_UB, dc->mem_index, true); 761 } 762 763 static bool trans_lbuea(DisasContext *dc, arg_typea *arg) 764 { 765 if (trap_userspace(dc, true)) { 766 return true; 767 } 768 #ifdef CONFIG_USER_ONLY 769 g_assert_not_reached(); 770 #else 771 TCGv_i64 addr = compute_ldst_addr_ea(dc, arg->ra, arg->rb); 772 gen_helper_lbuea(reg_for_write(dc, arg->rd), tcg_env, addr); 773 return true; 774 #endif 775 } 776 777 static bool trans_lbui(DisasContext *dc, arg_typeb *arg) 778 { 779 TCGv addr = compute_ldst_addr_typeb(dc, arg->ra, arg->imm); 780 return do_load(dc, arg->rd, addr, MO_UB, dc->mem_index, false); 781 } 782 783 static bool trans_lhu(DisasContext *dc, arg_typea *arg) 784 { 785 TCGv addr = compute_ldst_addr_typea(dc, arg->ra, arg->rb); 786 return do_load(dc, arg->rd, addr, MO_UW, dc->mem_index, false); 787 } 788 789 static bool trans_lhur(DisasContext *dc, arg_typea *arg) 790 { 791 TCGv addr = compute_ldst_addr_typea(dc, arg->ra, arg->rb); 792 return do_load(dc, arg->rd, addr, MO_UW, dc->mem_index, true); 793 } 794 795 static bool trans_lhuea(DisasContext *dc, arg_typea *arg) 796 { 797 if (trap_userspace(dc, true)) { 798 return true; 799 } 800 #ifdef CONFIG_USER_ONLY 801 g_assert_not_reached(); 802 #else 803 TCGv_i64 addr = compute_ldst_addr_ea(dc, arg->ra, arg->rb); 804 gen_alignment_check_ea(dc, addr, arg->rb, arg->rd, MO_16, false); 805 (mo_endian(dc) == MO_BE ? gen_helper_lhuea_be : gen_helper_lhuea_le) 806 (reg_for_write(dc, arg->rd), tcg_env, addr); 807 return true; 808 #endif 809 } 810 811 static bool trans_lhui(DisasContext *dc, arg_typeb *arg) 812 { 813 TCGv addr = compute_ldst_addr_typeb(dc, arg->ra, arg->imm); 814 return do_load(dc, arg->rd, addr, MO_UW, dc->mem_index, false); 815 } 816 817 static bool trans_lw(DisasContext *dc, arg_typea *arg) 818 { 819 TCGv addr = compute_ldst_addr_typea(dc, arg->ra, arg->rb); 820 return do_load(dc, arg->rd, addr, MO_UL, dc->mem_index, false); 821 } 822 823 static bool trans_lwr(DisasContext *dc, arg_typea *arg) 824 { 825 TCGv addr = compute_ldst_addr_typea(dc, arg->ra, arg->rb); 826 return do_load(dc, arg->rd, addr, MO_UL, dc->mem_index, true); 827 } 828 829 static bool trans_lwea(DisasContext *dc, arg_typea *arg) 830 { 831 if (trap_userspace(dc, true)) { 832 return true; 833 } 834 #ifdef CONFIG_USER_ONLY 835 g_assert_not_reached(); 836 #else 837 TCGv_i64 addr = compute_ldst_addr_ea(dc, arg->ra, arg->rb); 838 gen_alignment_check_ea(dc, addr, arg->rb, arg->rd, MO_32, false); 839 (mo_endian(dc) == MO_BE ? gen_helper_lwea_be : gen_helper_lwea_le) 840 (reg_for_write(dc, arg->rd), tcg_env, addr); 841 return true; 842 #endif 843 } 844 845 static bool trans_lwi(DisasContext *dc, arg_typeb *arg) 846 { 847 TCGv addr = compute_ldst_addr_typeb(dc, arg->ra, arg->imm); 848 return do_load(dc, arg->rd, addr, MO_UL, dc->mem_index, false); 849 } 850 851 static bool trans_lwx(DisasContext *dc, arg_typea *arg) 852 { 853 TCGv addr = compute_ldst_addr_typea(dc, arg->ra, arg->rb); 854 855 /* lwx does not throw unaligned access errors, so force alignment */ 856 tcg_gen_andi_tl(addr, addr, ~3); 857 858 tcg_gen_qemu_ld_i32(cpu_res_val, addr, dc->mem_index, 859 mo_endian(dc) | MO_UL); 860 tcg_gen_mov_tl(cpu_res_addr, addr); 861 862 if (arg->rd) { 863 tcg_gen_mov_i32(cpu_R[arg->rd], cpu_res_val); 864 } 865 866 /* No support for AXI exclusive so always clear C */ 867 tcg_gen_movi_i32(cpu_msr_c, 0); 868 return true; 869 } 870 871 static bool do_store(DisasContext *dc, int rd, TCGv addr, MemOp mop, 872 int mem_index, bool rev) 873 { 874 MemOp size = mop & MO_SIZE; 875 876 mop |= mo_endian(dc); 877 878 /* 879 * When doing reverse accesses we need to do two things. 880 * 881 * 1. Reverse the address wrt endianness. 882 * 2. Byteswap the data lanes on the way back into the CPU core. 883 */ 884 if (rev) { 885 if (size > MO_8) { 886 mop ^= MO_BSWAP; 887 } 888 if (size < MO_32) { 889 tcg_gen_xori_tl(addr, addr, 3 - size); 890 } 891 } 892 893 /* 894 * For system mode, enforce alignment if the cpu configuration 895 * requires it. For user-mode, the Linux kernel will have fixed up 896 * any unaligned access, so emulate that by *not* setting MO_ALIGN. 897 */ 898 #ifndef CONFIG_USER_ONLY 899 if (size > MO_8 && 900 (dc->tb_flags & MSR_EE) && 901 dc->cfg->unaligned_exceptions) { 902 record_unaligned_ess(dc, rd, size, true); 903 mop |= MO_ALIGN; 904 } 905 #endif 906 907 tcg_gen_qemu_st_i32(reg_for_read(dc, rd), addr, mem_index, mop); 908 return true; 909 } 910 911 static bool trans_sb(DisasContext *dc, arg_typea *arg) 912 { 913 TCGv addr = compute_ldst_addr_typea(dc, arg->ra, arg->rb); 914 return do_store(dc, arg->rd, addr, MO_UB, dc->mem_index, false); 915 } 916 917 static bool trans_sbr(DisasContext *dc, arg_typea *arg) 918 { 919 TCGv addr = compute_ldst_addr_typea(dc, arg->ra, arg->rb); 920 return do_store(dc, arg->rd, addr, MO_UB, dc->mem_index, true); 921 } 922 923 static bool trans_sbea(DisasContext *dc, arg_typea *arg) 924 { 925 if (trap_userspace(dc, true)) { 926 return true; 927 } 928 #ifdef CONFIG_USER_ONLY 929 g_assert_not_reached(); 930 #else 931 TCGv_i64 addr = compute_ldst_addr_ea(dc, arg->ra, arg->rb); 932 gen_helper_sbea(tcg_env, reg_for_read(dc, arg->rd), addr); 933 return true; 934 #endif 935 } 936 937 static bool trans_sbi(DisasContext *dc, arg_typeb *arg) 938 { 939 TCGv addr = compute_ldst_addr_typeb(dc, arg->ra, arg->imm); 940 return do_store(dc, arg->rd, addr, MO_UB, dc->mem_index, false); 941 } 942 943 static bool trans_sh(DisasContext *dc, arg_typea *arg) 944 { 945 TCGv addr = compute_ldst_addr_typea(dc, arg->ra, arg->rb); 946 return do_store(dc, arg->rd, addr, MO_UW, dc->mem_index, false); 947 } 948 949 static bool trans_shr(DisasContext *dc, arg_typea *arg) 950 { 951 TCGv addr = compute_ldst_addr_typea(dc, arg->ra, arg->rb); 952 return do_store(dc, arg->rd, addr, MO_UW, dc->mem_index, true); 953 } 954 955 static bool trans_shea(DisasContext *dc, arg_typea *arg) 956 { 957 if (trap_userspace(dc, true)) { 958 return true; 959 } 960 #ifdef CONFIG_USER_ONLY 961 g_assert_not_reached(); 962 #else 963 TCGv_i64 addr = compute_ldst_addr_ea(dc, arg->ra, arg->rb); 964 gen_alignment_check_ea(dc, addr, arg->rb, arg->rd, MO_16, true); 965 (mo_endian(dc) == MO_BE ? gen_helper_shea_be : gen_helper_shea_le) 966 (tcg_env, reg_for_read(dc, arg->rd), addr); 967 return true; 968 #endif 969 } 970 971 static bool trans_shi(DisasContext *dc, arg_typeb *arg) 972 { 973 TCGv addr = compute_ldst_addr_typeb(dc, arg->ra, arg->imm); 974 return do_store(dc, arg->rd, addr, MO_UW, dc->mem_index, false); 975 } 976 977 static bool trans_sw(DisasContext *dc, arg_typea *arg) 978 { 979 TCGv addr = compute_ldst_addr_typea(dc, arg->ra, arg->rb); 980 return do_store(dc, arg->rd, addr, MO_UL, dc->mem_index, false); 981 } 982 983 static bool trans_swr(DisasContext *dc, arg_typea *arg) 984 { 985 TCGv addr = compute_ldst_addr_typea(dc, arg->ra, arg->rb); 986 return do_store(dc, arg->rd, addr, MO_UL, dc->mem_index, true); 987 } 988 989 static bool trans_swea(DisasContext *dc, arg_typea *arg) 990 { 991 if (trap_userspace(dc, true)) { 992 return true; 993 } 994 #ifdef CONFIG_USER_ONLY 995 g_assert_not_reached(); 996 #else 997 TCGv_i64 addr = compute_ldst_addr_ea(dc, arg->ra, arg->rb); 998 gen_alignment_check_ea(dc, addr, arg->rb, arg->rd, MO_32, true); 999 (mo_endian(dc) == MO_BE ? gen_helper_swea_be : gen_helper_swea_le) 1000 (tcg_env, reg_for_read(dc, arg->rd), addr); 1001 return true; 1002 #endif 1003 } 1004 1005 static bool trans_swi(DisasContext *dc, arg_typeb *arg) 1006 { 1007 TCGv addr = compute_ldst_addr_typeb(dc, arg->ra, arg->imm); 1008 return do_store(dc, arg->rd, addr, MO_UL, dc->mem_index, false); 1009 } 1010 1011 static bool trans_swx(DisasContext *dc, arg_typea *arg) 1012 { 1013 TCGv addr = compute_ldst_addr_typea(dc, arg->ra, arg->rb); 1014 TCGLabel *swx_done = gen_new_label(); 1015 TCGLabel *swx_fail = gen_new_label(); 1016 TCGv_i32 tval; 1017 1018 /* swx does not throw unaligned access errors, so force alignment */ 1019 tcg_gen_andi_tl(addr, addr, ~3); 1020 1021 /* 1022 * Compare the address vs the one we used during lwx. 1023 * On mismatch, the operation fails. On match, addr dies at the 1024 * branch, but we know we can use the equal version in the global. 1025 * In either case, addr is no longer needed. 1026 */ 1027 tcg_gen_brcond_tl(TCG_COND_NE, cpu_res_addr, addr, swx_fail); 1028 1029 /* 1030 * Compare the value loaded during lwx with current contents of 1031 * the reserved location. 1032 */ 1033 tval = tcg_temp_new_i32(); 1034 1035 tcg_gen_atomic_cmpxchg_i32(tval, cpu_res_addr, cpu_res_val, 1036 reg_for_write(dc, arg->rd), 1037 dc->mem_index, mo_endian(dc) | MO_UL); 1038 1039 tcg_gen_brcond_i32(TCG_COND_NE, cpu_res_val, tval, swx_fail); 1040 1041 /* Success */ 1042 tcg_gen_movi_i32(cpu_msr_c, 0); 1043 tcg_gen_br(swx_done); 1044 1045 /* Failure */ 1046 gen_set_label(swx_fail); 1047 tcg_gen_movi_i32(cpu_msr_c, 1); 1048 1049 gen_set_label(swx_done); 1050 1051 /* 1052 * Prevent the saved address from working again without another ldx. 1053 * Akin to the pseudocode setting reservation = 0. 1054 */ 1055 tcg_gen_movi_tl(cpu_res_addr, -1); 1056 return true; 1057 } 1058 1059 static void setup_dslot(DisasContext *dc, bool type_b) 1060 { 1061 dc->tb_flags_to_set |= D_FLAG; 1062 if (type_b && (dc->tb_flags & IMM_FLAG)) { 1063 dc->tb_flags_to_set |= BIMM_FLAG; 1064 } 1065 } 1066 1067 static bool do_branch(DisasContext *dc, int dest_rb, int dest_imm, 1068 bool delay, bool abs, int link) 1069 { 1070 uint32_t add_pc; 1071 1072 if (invalid_delay_slot(dc, "branch")) { 1073 return true; 1074 } 1075 if (delay) { 1076 setup_dslot(dc, dest_rb < 0); 1077 } 1078 1079 if (link) { 1080 tcg_gen_movi_i32(cpu_R[link], dc->base.pc_next); 1081 } 1082 1083 /* Store the branch taken destination into btarget. */ 1084 add_pc = abs ? 0 : dc->base.pc_next; 1085 if (dest_rb > 0) { 1086 dc->jmp_dest = -1; 1087 tcg_gen_addi_i32(cpu_btarget, cpu_R[dest_rb], add_pc); 1088 } else { 1089 dc->jmp_dest = add_pc + dest_imm; 1090 tcg_gen_movi_i32(cpu_btarget, dc->jmp_dest); 1091 } 1092 dc->jmp_cond = TCG_COND_ALWAYS; 1093 return true; 1094 } 1095 1096 #define DO_BR(NAME, NAMEI, DELAY, ABS, LINK) \ 1097 static bool trans_##NAME(DisasContext *dc, arg_typea_br *arg) \ 1098 { return do_branch(dc, arg->rb, 0, DELAY, ABS, LINK ? arg->rd : 0); } \ 1099 static bool trans_##NAMEI(DisasContext *dc, arg_typeb_br *arg) \ 1100 { return do_branch(dc, -1, arg->imm, DELAY, ABS, LINK ? arg->rd : 0); } 1101 1102 DO_BR(br, bri, false, false, false) 1103 DO_BR(bra, brai, false, true, false) 1104 DO_BR(brd, brid, true, false, false) 1105 DO_BR(brad, braid, true, true, false) 1106 DO_BR(brld, brlid, true, false, true) 1107 DO_BR(brald, bralid, true, true, true) 1108 1109 static bool do_bcc(DisasContext *dc, int dest_rb, int dest_imm, 1110 TCGCond cond, int ra, bool delay) 1111 { 1112 TCGv_i32 zero, next; 1113 1114 if (invalid_delay_slot(dc, "bcc")) { 1115 return true; 1116 } 1117 if (delay) { 1118 setup_dslot(dc, dest_rb < 0); 1119 } 1120 1121 dc->jmp_cond = cond; 1122 1123 /* Cache the condition register in cpu_bvalue across any delay slot. */ 1124 tcg_gen_mov_i32(cpu_bvalue, reg_for_read(dc, ra)); 1125 1126 /* Store the branch taken destination into btarget. */ 1127 if (dest_rb > 0) { 1128 dc->jmp_dest = -1; 1129 tcg_gen_addi_i32(cpu_btarget, cpu_R[dest_rb], dc->base.pc_next); 1130 } else { 1131 dc->jmp_dest = dc->base.pc_next + dest_imm; 1132 tcg_gen_movi_i32(cpu_btarget, dc->jmp_dest); 1133 } 1134 1135 /* Compute the final destination into btarget. */ 1136 zero = tcg_constant_i32(0); 1137 next = tcg_constant_i32(dc->base.pc_next + (delay + 1) * 4); 1138 tcg_gen_movcond_i32(dc->jmp_cond, cpu_btarget, 1139 reg_for_read(dc, ra), zero, 1140 cpu_btarget, next); 1141 1142 return true; 1143 } 1144 1145 #define DO_BCC(NAME, COND) \ 1146 static bool trans_##NAME(DisasContext *dc, arg_typea_bc *arg) \ 1147 { return do_bcc(dc, arg->rb, 0, COND, arg->ra, false); } \ 1148 static bool trans_##NAME##d(DisasContext *dc, arg_typea_bc *arg) \ 1149 { return do_bcc(dc, arg->rb, 0, COND, arg->ra, true); } \ 1150 static bool trans_##NAME##i(DisasContext *dc, arg_typeb_bc *arg) \ 1151 { return do_bcc(dc, -1, arg->imm, COND, arg->ra, false); } \ 1152 static bool trans_##NAME##id(DisasContext *dc, arg_typeb_bc *arg) \ 1153 { return do_bcc(dc, -1, arg->imm, COND, arg->ra, true); } 1154 1155 DO_BCC(beq, TCG_COND_EQ) 1156 DO_BCC(bge, TCG_COND_GE) 1157 DO_BCC(bgt, TCG_COND_GT) 1158 DO_BCC(ble, TCG_COND_LE) 1159 DO_BCC(blt, TCG_COND_LT) 1160 DO_BCC(bne, TCG_COND_NE) 1161 1162 static bool trans_brk(DisasContext *dc, arg_typea_br *arg) 1163 { 1164 if (trap_userspace(dc, true)) { 1165 return true; 1166 } 1167 if (invalid_delay_slot(dc, "brk")) { 1168 return true; 1169 } 1170 1171 tcg_gen_mov_i32(cpu_pc, reg_for_read(dc, arg->rb)); 1172 if (arg->rd) { 1173 tcg_gen_movi_i32(cpu_R[arg->rd], dc->base.pc_next); 1174 } 1175 tcg_gen_ori_i32(cpu_msr, cpu_msr, MSR_BIP); 1176 tcg_gen_movi_tl(cpu_res_addr, -1); 1177 1178 dc->base.is_jmp = DISAS_EXIT; 1179 return true; 1180 } 1181 1182 static bool trans_brki(DisasContext *dc, arg_typeb_br *arg) 1183 { 1184 uint32_t imm = arg->imm; 1185 1186 if (trap_userspace(dc, imm != 0x8 && imm != 0x18)) { 1187 return true; 1188 } 1189 if (invalid_delay_slot(dc, "brki")) { 1190 return true; 1191 } 1192 1193 tcg_gen_movi_i32(cpu_pc, imm); 1194 if (arg->rd) { 1195 tcg_gen_movi_i32(cpu_R[arg->rd], dc->base.pc_next); 1196 } 1197 tcg_gen_movi_tl(cpu_res_addr, -1); 1198 1199 #ifdef CONFIG_USER_ONLY 1200 switch (imm) { 1201 case 0x8: /* syscall trap */ 1202 gen_raise_exception_sync(dc, EXCP_SYSCALL); 1203 break; 1204 case 0x18: /* debug trap */ 1205 gen_raise_exception_sync(dc, EXCP_DEBUG); 1206 break; 1207 default: /* eliminated with trap_userspace check */ 1208 g_assert_not_reached(); 1209 } 1210 #else 1211 uint32_t msr_to_set = 0; 1212 1213 if (imm != 0x18) { 1214 msr_to_set |= MSR_BIP; 1215 } 1216 if (imm == 0x8 || imm == 0x18) { 1217 /* MSR_UM and MSR_VM are in tb_flags, so we know their value. */ 1218 msr_to_set |= (dc->tb_flags & (MSR_UM | MSR_VM)) << 1; 1219 tcg_gen_andi_i32(cpu_msr, cpu_msr, 1220 ~(MSR_VMS | MSR_UMS | MSR_VM | MSR_UM)); 1221 } 1222 tcg_gen_ori_i32(cpu_msr, cpu_msr, msr_to_set); 1223 dc->base.is_jmp = DISAS_EXIT; 1224 #endif 1225 1226 return true; 1227 } 1228 1229 static bool trans_mbar(DisasContext *dc, arg_mbar *arg) 1230 { 1231 int mbar_imm = arg->imm; 1232 1233 /* Note that mbar is a specialized branch instruction. */ 1234 if (invalid_delay_slot(dc, "mbar")) { 1235 return true; 1236 } 1237 1238 /* Data access memory barrier. */ 1239 if ((mbar_imm & 2) == 0) { 1240 tcg_gen_mb(TCG_BAR_SC | TCG_MO_ALL); 1241 } 1242 1243 /* Sleep. */ 1244 if (mbar_imm & 16) { 1245 if (trap_userspace(dc, true)) { 1246 /* Sleep is a privileged instruction. */ 1247 return true; 1248 } 1249 1250 t_sync_flags(dc); 1251 1252 tcg_gen_st_i32(tcg_constant_i32(1), tcg_env, 1253 -offsetof(MicroBlazeCPU, env) 1254 +offsetof(CPUState, halted)); 1255 1256 tcg_gen_movi_i32(cpu_pc, dc->base.pc_next + 4); 1257 1258 gen_raise_exception(dc, EXCP_HLT); 1259 } 1260 1261 /* 1262 * If !(mbar_imm & 1), this is an instruction access memory barrier 1263 * and we need to end the TB so that we recognize self-modified 1264 * code immediately. 1265 * 1266 * However, there are some data mbars that need the TB break 1267 * (and return to main loop) to recognize interrupts right away. 1268 * E.g. recognizing a change to an interrupt controller register. 1269 * 1270 * Therefore, choose to end the TB always. 1271 */ 1272 dc->base.is_jmp = DISAS_EXIT_NEXT; 1273 return true; 1274 } 1275 1276 static bool do_rts(DisasContext *dc, arg_typeb_bc *arg, int to_set) 1277 { 1278 if (trap_userspace(dc, to_set)) { 1279 return true; 1280 } 1281 if (invalid_delay_slot(dc, "rts")) { 1282 return true; 1283 } 1284 1285 dc->tb_flags_to_set |= to_set; 1286 setup_dslot(dc, true); 1287 1288 dc->jmp_cond = TCG_COND_ALWAYS; 1289 dc->jmp_dest = -1; 1290 tcg_gen_addi_i32(cpu_btarget, reg_for_read(dc, arg->ra), arg->imm); 1291 return true; 1292 } 1293 1294 #define DO_RTS(NAME, IFLAG) \ 1295 static bool trans_##NAME(DisasContext *dc, arg_typeb_bc *arg) \ 1296 { return do_rts(dc, arg, IFLAG); } 1297 1298 DO_RTS(rtbd, DRTB_FLAG) 1299 DO_RTS(rtid, DRTI_FLAG) 1300 DO_RTS(rted, DRTE_FLAG) 1301 DO_RTS(rtsd, 0) 1302 1303 static bool trans_zero(DisasContext *dc, arg_zero *arg) 1304 { 1305 /* If opcode_0_illegal, trap. */ 1306 if (dc->cfg->opcode_0_illegal) { 1307 trap_illegal(dc, true); 1308 return true; 1309 } 1310 /* 1311 * Otherwise, this is "add r0, r0, r0". 1312 * Continue to trans_add so that MSR[C] gets cleared. 1313 */ 1314 return false; 1315 } 1316 1317 static void msr_read(DisasContext *dc, TCGv_i32 d) 1318 { 1319 TCGv_i32 t; 1320 1321 /* Replicate the cpu_msr_c boolean into the proper bit and the copy. */ 1322 t = tcg_temp_new_i32(); 1323 tcg_gen_muli_i32(t, cpu_msr_c, MSR_C | MSR_CC); 1324 tcg_gen_or_i32(d, cpu_msr, t); 1325 } 1326 1327 static bool do_msrclrset(DisasContext *dc, arg_type_msr *arg, bool set) 1328 { 1329 uint32_t imm = arg->imm; 1330 1331 if (trap_userspace(dc, imm != MSR_C)) { 1332 return true; 1333 } 1334 1335 if (arg->rd) { 1336 msr_read(dc, cpu_R[arg->rd]); 1337 } 1338 1339 /* 1340 * Handle the carry bit separately. 1341 * This is the only bit that userspace can modify. 1342 */ 1343 if (imm & MSR_C) { 1344 tcg_gen_movi_i32(cpu_msr_c, set); 1345 } 1346 1347 /* 1348 * MSR_C and MSR_CC set above. 1349 * MSR_PVR is not writable, and is always clear. 1350 */ 1351 imm &= ~(MSR_C | MSR_CC | MSR_PVR); 1352 1353 if (imm != 0) { 1354 if (set) { 1355 tcg_gen_ori_i32(cpu_msr, cpu_msr, imm); 1356 } else { 1357 tcg_gen_andi_i32(cpu_msr, cpu_msr, ~imm); 1358 } 1359 dc->base.is_jmp = DISAS_EXIT_NEXT; 1360 } 1361 return true; 1362 } 1363 1364 static bool trans_msrclr(DisasContext *dc, arg_type_msr *arg) 1365 { 1366 return do_msrclrset(dc, arg, false); 1367 } 1368 1369 static bool trans_msrset(DisasContext *dc, arg_type_msr *arg) 1370 { 1371 return do_msrclrset(dc, arg, true); 1372 } 1373 1374 static bool trans_mts(DisasContext *dc, arg_mts *arg) 1375 { 1376 if (trap_userspace(dc, true)) { 1377 return true; 1378 } 1379 1380 #ifdef CONFIG_USER_ONLY 1381 g_assert_not_reached(); 1382 #else 1383 if (arg->e && arg->rs != 0x1003) { 1384 qemu_log_mask(LOG_GUEST_ERROR, 1385 "Invalid extended mts reg 0x%x\n", arg->rs); 1386 return true; 1387 } 1388 1389 TCGv_i32 src = reg_for_read(dc, arg->ra); 1390 switch (arg->rs) { 1391 case SR_MSR: 1392 /* Install MSR_C. */ 1393 tcg_gen_extract_i32(cpu_msr_c, src, 2, 1); 1394 /* 1395 * Clear MSR_C and MSR_CC; 1396 * MSR_PVR is not writable, and is always clear. 1397 */ 1398 tcg_gen_andi_i32(cpu_msr, src, ~(MSR_C | MSR_CC | MSR_PVR)); 1399 break; 1400 case SR_FSR: 1401 tcg_gen_st_i32(src, tcg_env, offsetof(CPUMBState, fsr)); 1402 break; 1403 case 0x800: 1404 tcg_gen_st_i32(src, tcg_env, offsetof(CPUMBState, slr)); 1405 break; 1406 case 0x802: 1407 tcg_gen_st_i32(src, tcg_env, offsetof(CPUMBState, shr)); 1408 break; 1409 1410 case 0x1000: /* PID */ 1411 case 0x1001: /* ZPR */ 1412 case 0x1002: /* TLBX */ 1413 case 0x1003: /* TLBLO */ 1414 case 0x1004: /* TLBHI */ 1415 case 0x1005: /* TLBSX */ 1416 { 1417 TCGv_i32 tmp_ext = tcg_constant_i32(arg->e); 1418 TCGv_i32 tmp_reg = tcg_constant_i32(arg->rs & 7); 1419 1420 gen_helper_mmu_write(tcg_env, tmp_ext, tmp_reg, src); 1421 } 1422 break; 1423 1424 default: 1425 qemu_log_mask(LOG_GUEST_ERROR, "Invalid mts reg 0x%x\n", arg->rs); 1426 return true; 1427 } 1428 dc->base.is_jmp = DISAS_EXIT_NEXT; 1429 return true; 1430 #endif 1431 } 1432 1433 static bool trans_mfs(DisasContext *dc, arg_mfs *arg) 1434 { 1435 TCGv_i32 dest = reg_for_write(dc, arg->rd); 1436 1437 if (arg->e) { 1438 switch (arg->rs) { 1439 case SR_EAR: 1440 { 1441 TCGv_i64 t64 = tcg_temp_new_i64(); 1442 tcg_gen_ld_i64(t64, tcg_env, offsetof(CPUMBState, ear)); 1443 tcg_gen_extrh_i64_i32(dest, t64); 1444 } 1445 return true; 1446 #ifndef CONFIG_USER_ONLY 1447 case 0x1003: /* TLBLO */ 1448 /* Handled below. */ 1449 break; 1450 #endif 1451 case 0x2006 ... 0x2009: 1452 /* High bits of PVR6-9 not implemented. */ 1453 tcg_gen_movi_i32(dest, 0); 1454 return true; 1455 default: 1456 qemu_log_mask(LOG_GUEST_ERROR, 1457 "Invalid extended mfs reg 0x%x\n", arg->rs); 1458 return true; 1459 } 1460 } 1461 1462 switch (arg->rs) { 1463 case SR_PC: 1464 tcg_gen_movi_i32(dest, dc->base.pc_next); 1465 break; 1466 case SR_MSR: 1467 msr_read(dc, dest); 1468 break; 1469 case SR_EAR: 1470 { 1471 TCGv_i64 t64 = tcg_temp_new_i64(); 1472 tcg_gen_ld_i64(t64, tcg_env, offsetof(CPUMBState, ear)); 1473 tcg_gen_extrl_i64_i32(dest, t64); 1474 } 1475 break; 1476 case SR_ESR: 1477 tcg_gen_ld_i32(dest, tcg_env, offsetof(CPUMBState, esr)); 1478 break; 1479 case SR_FSR: 1480 tcg_gen_ld_i32(dest, tcg_env, offsetof(CPUMBState, fsr)); 1481 break; 1482 case SR_BTR: 1483 tcg_gen_ld_i32(dest, tcg_env, offsetof(CPUMBState, btr)); 1484 break; 1485 case SR_EDR: 1486 tcg_gen_ld_i32(dest, tcg_env, offsetof(CPUMBState, edr)); 1487 break; 1488 case 0x800: 1489 tcg_gen_ld_i32(dest, tcg_env, offsetof(CPUMBState, slr)); 1490 break; 1491 case 0x802: 1492 tcg_gen_ld_i32(dest, tcg_env, offsetof(CPUMBState, shr)); 1493 break; 1494 1495 #ifndef CONFIG_USER_ONLY 1496 case 0x1000: /* PID */ 1497 case 0x1001: /* ZPR */ 1498 case 0x1002: /* TLBX */ 1499 case 0x1003: /* TLBLO */ 1500 case 0x1004: /* TLBHI */ 1501 case 0x1005: /* TLBSX */ 1502 { 1503 TCGv_i32 tmp_ext = tcg_constant_i32(arg->e); 1504 TCGv_i32 tmp_reg = tcg_constant_i32(arg->rs & 7); 1505 1506 gen_helper_mmu_read(dest, tcg_env, tmp_ext, tmp_reg); 1507 } 1508 break; 1509 #endif 1510 1511 case 0x2000 ... 0x200c: 1512 tcg_gen_ld_i32(dest, tcg_env, 1513 offsetof(MicroBlazeCPU, cfg.pvr_regs[arg->rs - 0x2000]) 1514 - offsetof(MicroBlazeCPU, env)); 1515 break; 1516 default: 1517 qemu_log_mask(LOG_GUEST_ERROR, "Invalid mfs reg 0x%x\n", arg->rs); 1518 break; 1519 } 1520 return true; 1521 } 1522 1523 static void do_rti(DisasContext *dc) 1524 { 1525 TCGv_i32 tmp = tcg_temp_new_i32(); 1526 1527 tcg_gen_shri_i32(tmp, cpu_msr, 1); 1528 tcg_gen_ori_i32(cpu_msr, cpu_msr, MSR_IE); 1529 tcg_gen_andi_i32(tmp, tmp, MSR_VM | MSR_UM); 1530 tcg_gen_andi_i32(cpu_msr, cpu_msr, ~(MSR_VM | MSR_UM)); 1531 tcg_gen_or_i32(cpu_msr, cpu_msr, tmp); 1532 } 1533 1534 static void do_rtb(DisasContext *dc) 1535 { 1536 TCGv_i32 tmp = tcg_temp_new_i32(); 1537 1538 tcg_gen_shri_i32(tmp, cpu_msr, 1); 1539 tcg_gen_andi_i32(cpu_msr, cpu_msr, ~(MSR_VM | MSR_UM | MSR_BIP)); 1540 tcg_gen_andi_i32(tmp, tmp, (MSR_VM | MSR_UM)); 1541 tcg_gen_or_i32(cpu_msr, cpu_msr, tmp); 1542 } 1543 1544 static void do_rte(DisasContext *dc) 1545 { 1546 TCGv_i32 tmp = tcg_temp_new_i32(); 1547 1548 tcg_gen_shri_i32(tmp, cpu_msr, 1); 1549 tcg_gen_ori_i32(cpu_msr, cpu_msr, MSR_EE); 1550 tcg_gen_andi_i32(tmp, tmp, (MSR_VM | MSR_UM)); 1551 tcg_gen_andi_i32(cpu_msr, cpu_msr, ~(MSR_VM | MSR_UM | MSR_EIP)); 1552 tcg_gen_or_i32(cpu_msr, cpu_msr, tmp); 1553 } 1554 1555 /* Insns connected to FSL or AXI stream attached devices. */ 1556 static bool do_get(DisasContext *dc, int rd, int rb, int imm, int ctrl) 1557 { 1558 TCGv_i32 t_id, t_ctrl; 1559 1560 if (trap_userspace(dc, true)) { 1561 return true; 1562 } 1563 1564 t_id = tcg_temp_new_i32(); 1565 if (rb) { 1566 tcg_gen_andi_i32(t_id, cpu_R[rb], 0xf); 1567 } else { 1568 tcg_gen_movi_i32(t_id, imm); 1569 } 1570 1571 t_ctrl = tcg_constant_i32(ctrl); 1572 gen_helper_get(reg_for_write(dc, rd), t_id, t_ctrl); 1573 return true; 1574 } 1575 1576 static bool trans_get(DisasContext *dc, arg_get *arg) 1577 { 1578 return do_get(dc, arg->rd, 0, arg->imm, arg->ctrl); 1579 } 1580 1581 static bool trans_getd(DisasContext *dc, arg_getd *arg) 1582 { 1583 return do_get(dc, arg->rd, arg->rb, 0, arg->ctrl); 1584 } 1585 1586 static bool do_put(DisasContext *dc, int ra, int rb, int imm, int ctrl) 1587 { 1588 TCGv_i32 t_id, t_ctrl; 1589 1590 if (trap_userspace(dc, true)) { 1591 return true; 1592 } 1593 1594 t_id = tcg_temp_new_i32(); 1595 if (rb) { 1596 tcg_gen_andi_i32(t_id, cpu_R[rb], 0xf); 1597 } else { 1598 tcg_gen_movi_i32(t_id, imm); 1599 } 1600 1601 t_ctrl = tcg_constant_i32(ctrl); 1602 gen_helper_put(t_id, t_ctrl, reg_for_read(dc, ra)); 1603 return true; 1604 } 1605 1606 static bool trans_put(DisasContext *dc, arg_put *arg) 1607 { 1608 return do_put(dc, arg->ra, 0, arg->imm, arg->ctrl); 1609 } 1610 1611 static bool trans_putd(DisasContext *dc, arg_putd *arg) 1612 { 1613 return do_put(dc, arg->ra, arg->rb, 0, arg->ctrl); 1614 } 1615 1616 static void mb_tr_init_disas_context(DisasContextBase *dcb, CPUState *cs) 1617 { 1618 DisasContext *dc = container_of(dcb, DisasContext, base); 1619 MicroBlazeCPU *cpu = MICROBLAZE_CPU(cs); 1620 int bound; 1621 1622 dc->cfg = &cpu->cfg; 1623 dc->tb_flags = dc->base.tb->flags; 1624 dc->ext_imm = dc->base.tb->cs_base; 1625 dc->mem_index = cpu_mmu_index(cs, false); 1626 dc->jmp_cond = dc->tb_flags & D_FLAG ? TCG_COND_ALWAYS : TCG_COND_NEVER; 1627 dc->jmp_dest = -1; 1628 1629 bound = -(dc->base.pc_first | TARGET_PAGE_MASK) / 4; 1630 dc->base.max_insns = MIN(dc->base.max_insns, bound); 1631 } 1632 1633 static void mb_tr_tb_start(DisasContextBase *dcb, CPUState *cs) 1634 { 1635 } 1636 1637 static void mb_tr_insn_start(DisasContextBase *dcb, CPUState *cs) 1638 { 1639 DisasContext *dc = container_of(dcb, DisasContext, base); 1640 1641 tcg_gen_insn_start(dc->base.pc_next, dc->tb_flags & ~MSR_TB_MASK); 1642 } 1643 1644 static void mb_tr_translate_insn(DisasContextBase *dcb, CPUState *cs) 1645 { 1646 DisasContext *dc = container_of(dcb, DisasContext, base); 1647 uint32_t ir; 1648 1649 /* TODO: This should raise an exception, not terminate qemu. */ 1650 if (dc->base.pc_next & 3) { 1651 cpu_abort(cs, "Microblaze: unaligned PC=%x\n", 1652 (uint32_t)dc->base.pc_next); 1653 } 1654 1655 dc->tb_flags_to_set = 0; 1656 1657 ir = translator_ldl_swap(cpu_env(cs), &dc->base, dc->base.pc_next, 1658 mb_cpu_is_big_endian(cs) != TARGET_BIG_ENDIAN); 1659 if (!decode(dc, ir)) { 1660 trap_illegal(dc, true); 1661 } 1662 1663 /* Discard the imm global when its contents cannot be used. */ 1664 if ((dc->tb_flags & ~dc->tb_flags_to_set) & IMM_FLAG) { 1665 tcg_gen_discard_i32(cpu_imm); 1666 } 1667 1668 dc->tb_flags &= ~(IMM_FLAG | BIMM_FLAG | D_FLAG); 1669 dc->tb_flags |= dc->tb_flags_to_set; 1670 dc->base.pc_next += 4; 1671 1672 if (dc->jmp_cond != TCG_COND_NEVER && !(dc->tb_flags & D_FLAG)) { 1673 /* 1674 * Finish any return-from branch. 1675 */ 1676 uint32_t rt_ibe = dc->tb_flags & (DRTI_FLAG | DRTB_FLAG | DRTE_FLAG); 1677 if (unlikely(rt_ibe != 0)) { 1678 dc->tb_flags &= ~(DRTI_FLAG | DRTB_FLAG | DRTE_FLAG); 1679 if (rt_ibe & DRTI_FLAG) { 1680 do_rti(dc); 1681 } else if (rt_ibe & DRTB_FLAG) { 1682 do_rtb(dc); 1683 } else { 1684 do_rte(dc); 1685 } 1686 } 1687 1688 /* Complete the branch, ending the TB. */ 1689 switch (dc->base.is_jmp) { 1690 case DISAS_NORETURN: 1691 /* 1692 * E.g. illegal insn in a delay slot. We've already exited 1693 * and will handle D_FLAG in mb_cpu_do_interrupt. 1694 */ 1695 break; 1696 case DISAS_NEXT: 1697 /* 1698 * Normal insn a delay slot. 1699 * However, the return-from-exception type insns should 1700 * return to the main loop, as they have adjusted MSR. 1701 */ 1702 dc->base.is_jmp = (rt_ibe ? DISAS_EXIT_JUMP : DISAS_JUMP); 1703 break; 1704 case DISAS_EXIT_NEXT: 1705 /* 1706 * E.g. mts insn in a delay slot. Continue with btarget, 1707 * but still return to the main loop. 1708 */ 1709 dc->base.is_jmp = DISAS_EXIT_JUMP; 1710 break; 1711 default: 1712 g_assert_not_reached(); 1713 } 1714 } 1715 } 1716 1717 static void mb_tr_tb_stop(DisasContextBase *dcb, CPUState *cs) 1718 { 1719 DisasContext *dc = container_of(dcb, DisasContext, base); 1720 1721 if (dc->base.is_jmp == DISAS_NORETURN) { 1722 /* We have already exited the TB. */ 1723 return; 1724 } 1725 1726 t_sync_flags(dc); 1727 1728 switch (dc->base.is_jmp) { 1729 case DISAS_TOO_MANY: 1730 gen_goto_tb(dc, 0, dc->base.pc_next); 1731 return; 1732 1733 case DISAS_EXIT: 1734 break; 1735 case DISAS_EXIT_NEXT: 1736 tcg_gen_movi_i32(cpu_pc, dc->base.pc_next); 1737 break; 1738 case DISAS_EXIT_JUMP: 1739 tcg_gen_mov_i32(cpu_pc, cpu_btarget); 1740 tcg_gen_discard_i32(cpu_btarget); 1741 break; 1742 1743 case DISAS_JUMP: 1744 if (dc->jmp_dest != -1 && !(tb_cflags(dc->base.tb) & CF_NO_GOTO_TB)) { 1745 /* Direct jump. */ 1746 tcg_gen_discard_i32(cpu_btarget); 1747 1748 if (dc->jmp_cond != TCG_COND_ALWAYS) { 1749 /* Conditional direct jump. */ 1750 TCGLabel *taken = gen_new_label(); 1751 TCGv_i32 tmp = tcg_temp_new_i32(); 1752 1753 /* 1754 * Copy bvalue to a temp now, so we can discard bvalue. 1755 * This can avoid writing bvalue to memory when the 1756 * delay slot cannot raise an exception. 1757 */ 1758 tcg_gen_mov_i32(tmp, cpu_bvalue); 1759 tcg_gen_discard_i32(cpu_bvalue); 1760 1761 tcg_gen_brcondi_i32(dc->jmp_cond, tmp, 0, taken); 1762 gen_goto_tb(dc, 1, dc->base.pc_next); 1763 gen_set_label(taken); 1764 } 1765 gen_goto_tb(dc, 0, dc->jmp_dest); 1766 return; 1767 } 1768 1769 /* Indirect jump (or direct jump w/ goto_tb disabled) */ 1770 tcg_gen_mov_i32(cpu_pc, cpu_btarget); 1771 tcg_gen_discard_i32(cpu_btarget); 1772 tcg_gen_lookup_and_goto_ptr(); 1773 return; 1774 1775 default: 1776 g_assert_not_reached(); 1777 } 1778 1779 /* Finish DISAS_EXIT_* */ 1780 if (unlikely(cs->singlestep_enabled)) { 1781 gen_raise_exception(dc, EXCP_DEBUG); 1782 } else { 1783 tcg_gen_exit_tb(NULL, 0); 1784 } 1785 } 1786 1787 static const TranslatorOps mb_tr_ops = { 1788 .init_disas_context = mb_tr_init_disas_context, 1789 .tb_start = mb_tr_tb_start, 1790 .insn_start = mb_tr_insn_start, 1791 .translate_insn = mb_tr_translate_insn, 1792 .tb_stop = mb_tr_tb_stop, 1793 }; 1794 1795 void mb_translate_code(CPUState *cpu, TranslationBlock *tb, 1796 int *max_insns, vaddr pc, void *host_pc) 1797 { 1798 DisasContext dc; 1799 translator_loop(cpu, tb, max_insns, pc, host_pc, &mb_tr_ops, &dc.base); 1800 } 1801 1802 void mb_cpu_dump_state(CPUState *cs, FILE *f, int flags) 1803 { 1804 CPUMBState *env = cpu_env(cs); 1805 uint32_t iflags; 1806 int i; 1807 1808 qemu_fprintf(f, "pc=0x%08x msr=0x%05x mode=%s(saved=%s) eip=%d ie=%d\n", 1809 env->pc, env->msr, 1810 (env->msr & MSR_UM) ? "user" : "kernel", 1811 (env->msr & MSR_UMS) ? "user" : "kernel", 1812 (bool)(env->msr & MSR_EIP), 1813 (bool)(env->msr & MSR_IE)); 1814 1815 iflags = env->iflags; 1816 qemu_fprintf(f, "iflags: 0x%08x", iflags); 1817 if (iflags & IMM_FLAG) { 1818 qemu_fprintf(f, " IMM(0x%08x)", env->imm); 1819 } 1820 if (iflags & BIMM_FLAG) { 1821 qemu_fprintf(f, " BIMM"); 1822 } 1823 if (iflags & D_FLAG) { 1824 qemu_fprintf(f, " D(btarget=0x%08x)", env->btarget); 1825 } 1826 if (iflags & DRTI_FLAG) { 1827 qemu_fprintf(f, " DRTI"); 1828 } 1829 if (iflags & DRTE_FLAG) { 1830 qemu_fprintf(f, " DRTE"); 1831 } 1832 if (iflags & DRTB_FLAG) { 1833 qemu_fprintf(f, " DRTB"); 1834 } 1835 if (iflags & ESR_ESS_FLAG) { 1836 qemu_fprintf(f, " ESR_ESS(0x%04x)", iflags & ESR_ESS_MASK); 1837 } 1838 1839 qemu_fprintf(f, "\nesr=0x%04x fsr=0x%02x btr=0x%08x edr=0x%x\n" 1840 "ear=0x%" PRIx64 " slr=0x%x shr=0x%x\n", 1841 env->esr, env->fsr, env->btr, env->edr, 1842 env->ear, env->slr, env->shr); 1843 1844 for (i = 0; i < 32; i++) { 1845 qemu_fprintf(f, "r%2.2d=%08x%c", 1846 i, env->regs[i], i % 4 == 3 ? '\n' : ' '); 1847 } 1848 qemu_fprintf(f, "\n"); 1849 } 1850 1851 void mb_tcg_init(void) 1852 { 1853 #define R(X) { &cpu_R[X], offsetof(CPUMBState, regs[X]), "r" #X } 1854 #define SP(X) { &cpu_##X, offsetof(CPUMBState, X), #X } 1855 1856 static const struct { 1857 TCGv_i32 *var; int ofs; char name[8]; 1858 } i32s[] = { 1859 /* 1860 * Note that r0 is handled specially in reg_for_read 1861 * and reg_for_write. Nothing should touch cpu_R[0]. 1862 * Leave that element NULL, which will assert quickly 1863 * inside the tcg generator functions. 1864 */ 1865 R(1), R(2), R(3), R(4), R(5), R(6), R(7), 1866 R(8), R(9), R(10), R(11), R(12), R(13), R(14), R(15), 1867 R(16), R(17), R(18), R(19), R(20), R(21), R(22), R(23), 1868 R(24), R(25), R(26), R(27), R(28), R(29), R(30), R(31), 1869 1870 SP(pc), 1871 SP(msr), 1872 SP(msr_c), 1873 SP(imm), 1874 SP(iflags), 1875 SP(bvalue), 1876 SP(btarget), 1877 SP(res_val), 1878 }; 1879 1880 #undef R 1881 #undef SP 1882 1883 for (int i = 0; i < ARRAY_SIZE(i32s); ++i) { 1884 *i32s[i].var = 1885 tcg_global_mem_new_i32(tcg_env, i32s[i].ofs, i32s[i].name); 1886 } 1887 1888 cpu_res_addr = 1889 tcg_global_mem_new(tcg_env, offsetof(CPUMBState, res_addr), "res_addr"); 1890 } 1891