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