diff options
author | Peter Maydell <peter.maydell@linaro.org> | 2018-05-29 13:01:11 +0100 |
---|---|---|
committer | Peter Maydell <peter.maydell@linaro.org> | 2018-05-29 13:01:11 +0100 |
commit | e609fa71e89c81fbe2670411be62da95dfb093e0 (patch) | |
tree | fc1b96d12b19dbe85aa270ecc56f9401b695ed99 | |
parent | dcd425608240ac6a5a223df2e8ce852b8fe1a661 (diff) | |
parent | d10367e035eab12c77b83b5985915ff7f003de1f (diff) | |
download | qemu-e609fa71e89c81fbe2670411be62da95dfb093e0.zip qemu-e609fa71e89c81fbe2670411be62da95dfb093e0.tar.gz qemu-e609fa71e89c81fbe2670411be62da95dfb093e0.tar.bz2 |
Merge remote-tracking branch 'remotes/edgar/tags/edgar/xilinx-next-2018-05-29-v1.for-upstream' into staging
Tag edgar/xilinx-next-2018-05-29-v1.for-upstream
# gpg: Signature made Tue 29 May 2018 09:58:30 BST
# gpg: using RSA key 29C596780F6BCA83
# gpg: Good signature from "Edgar E. Iglesias (Xilinx key) <edgar.iglesias@xilinx.com>"
# gpg: aka "Edgar E. Iglesias <edgar.iglesias@gmail.com>"
# Primary key fingerprint: AC44 FEDC 14F7 F1EB EDBF 4151 29C5 9678 0F6B CA83
* remotes/edgar/tags/edgar/xilinx-next-2018-05-29-v1.for-upstream: (38 commits)
target-microblaze: Consolidate MMU enabled checks
target-microblaze: cpu_mmu_index: Fixup indentation
target-microblaze: Use tcg_gen_movcond in eval_cond_jmp
target-microblaze: Convert env_btarget to i64
target-microblaze: Remove argument b in eval_cc()
target-microblaze: Use table based condition-codes conversion
target-microblaze: mmu: Cleanup debug log messages
target-microblaze: Simplify address computation using tcg_gen_addi_i32()
target-microblaze: Allow address sizes between 32 and 64 bits
target-microblaze: Add support for extended access to TLBLO
target-microblaze: dec_msr: Plug a temp leak
target-microblaze: mmu: Add a configurable output address mask
target-microblaze: mmu: Prepare for 64-bit addresses
target-microblaze: mmu: Remove unused register state
target-microblaze: mmu: Add R_TBLX_MISS macros
target-microblaze: Implement MFSE EAR
target-microblaze: Add Extended Addressing
target-microblaze: Setup for 64bit addressing
target-microblaze: Make special registers 64-bit
target-microblaze: dec_msr: Fix MTS to FSR
...
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
-rwxr-xr-x | configure | 1 | ||||
-rw-r--r-- | linux-user/microblaze/cpu_loop.c | 4 | ||||
-rw-r--r-- | target/microblaze/cpu.c | 30 | ||||
-rw-r--r-- | target/microblaze/cpu.h | 34 | ||||
-rw-r--r-- | target/microblaze/helper.c | 32 | ||||
-rw-r--r-- | target/microblaze/helper.h | 8 | ||||
-rw-r--r-- | target/microblaze/mmu.c | 81 | ||||
-rw-r--r-- | target/microblaze/mmu.h | 17 | ||||
-rw-r--r-- | target/microblaze/op_helper.c | 30 | ||||
-rw-r--r-- | target/microblaze/translate.c | 930 |
10 files changed, 598 insertions, 569 deletions
@@ -6844,6 +6844,7 @@ case "$target_name" in microblaze|microblazeel) TARGET_ARCH=microblaze bflt="yes" + echo "TARGET_ABI32=y" >> $config_target_mak ;; mips|mipsel) TARGET_ARCH=mips diff --git a/linux-user/microblaze/cpu_loop.c b/linux-user/microblaze/cpu_loop.c index 5ffb83d..5af12d5 100644 --- a/linux-user/microblaze/cpu_loop.c +++ b/linux-user/microblaze/cpu_loop.c @@ -105,8 +105,8 @@ void cpu_loop(CPUMBState *env) queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); break; default: - printf ("Unhandled hw-exception: 0x%x\n", - env->sregs[SR_ESR] & ESR_EC_MASK); + printf("Unhandled hw-exception: 0x%" PRIx64 "\n", + env->sregs[SR_ESR] & ESR_EC_MASK); cpu_dump_state(cs, stderr, fprintf, 0); exit(EXIT_FAILURE); break; diff --git a/target/microblaze/cpu.c b/target/microblaze/cpu.c index 4dc1404..9b546a2 100644 --- a/target/microblaze/cpu.c +++ b/target/microblaze/cpu.c @@ -72,6 +72,9 @@ static const struct { {NULL, 0}, }; +/* If no specific version gets selected, default to the following. */ +#define DEFAULT_CPU_VERSION "10.0" + static void mb_cpu_set_pc(CPUState *cs, vaddr value) { MicroBlazeCPU *cpu = MICROBLAZE_CPU(cs); @@ -125,6 +128,7 @@ static void mb_cpu_reset(CPUState *s) env->mmu.c_mmu = 3; env->mmu.c_mmu_tlb_access = 3; env->mmu.c_mmu_zones = 16; + env->mmu.c_addr_mask = MAKE_64BIT_MASK(0, cpu->cfg.addr_size); #endif } @@ -141,6 +145,7 @@ static void mb_cpu_realizefn(DeviceState *dev, Error **errp) MicroBlazeCPU *cpu = MICROBLAZE_CPU(cs); CPUMBState *env = &cpu->env; uint8_t version_code = 0; + const char *version; int i = 0; Error *local_err = NULL; @@ -150,6 +155,12 @@ static void mb_cpu_realizefn(DeviceState *dev, Error **errp) return; } + if (cpu->cfg.addr_size < 32 || cpu->cfg.addr_size > 64) { + error_setg(errp, "addr-size %d is out of range (32 - 64)", + cpu->cfg.addr_size); + return; + } + qemu_init_vcpu(cs); env->pvr.regs[0] = PVR0_USE_EXC_MASK \ @@ -162,8 +173,9 @@ static void mb_cpu_realizefn(DeviceState *dev, Error **errp) | PVR2_FPU_EXC_MASK \ | 0; - for (i = 0; mb_cpu_lookup[i].name && cpu->cfg.version; i++) { - if (strcmp(mb_cpu_lookup[i].name, cpu->cfg.version) == 0) { + version = cpu->cfg.version ? cpu->cfg.version : DEFAULT_CPU_VERSION; + for (i = 0; mb_cpu_lookup[i].name && version; i++) { + if (strcmp(mb_cpu_lookup[i].name, version) == 0) { version_code = mb_cpu_lookup[i].version_id; break; } @@ -195,8 +207,10 @@ static void mb_cpu_realizefn(DeviceState *dev, Error **errp) env->pvr.regs[5] |= cpu->cfg.dcache_writeback ? PVR5_DCACHE_WRITEBACK_MASK : 0; - env->pvr.regs[10] = 0x0c000000; /* Default to spartan 3a dsp family. */ - env->pvr.regs[11] = PVR11_USE_MMU | (16 << 17); + env->pvr.regs[10] = 0x0c000000 | /* Default to spartan 3a dsp family. */ + (cpu->cfg.addr_size - 32) << PVR10_ASIZE_SHIFT; + env->pvr.regs[11] = (cpu->cfg.use_mmu ? PVR11_USE_MMU : 0) | + 16 << 17; mcc->parent_realize(dev, errp); } @@ -226,6 +240,14 @@ static Property mb_properties[] = { DEFINE_PROP_UINT32("base-vectors", MicroBlazeCPU, cfg.base_vectors, 0), DEFINE_PROP_BOOL("use-stack-protection", MicroBlazeCPU, cfg.stackprot, false), + /* + * This is the C_ADDR_SIZE synth-time configuration option of the + * MicroBlaze cores. Supported values range between 32 and 64. + * + * When set to > 32, 32bit MicroBlaze can emit load/stores + * with extended addressing. + */ + DEFINE_PROP_UINT8("addr-size", MicroBlazeCPU, cfg.addr_size, 32), /* If use-fpu > 0 - FPU is enabled * If use-fpu = 2 - Floating point conversion and square root instructions * are enabled diff --git a/target/microblaze/cpu.h b/target/microblaze/cpu.h index 5be71bc..3c4e0ba 100644 --- a/target/microblaze/cpu.h +++ b/target/microblaze/cpu.h @@ -23,7 +23,7 @@ #include "qemu-common.h" #include "cpu-qom.h" -#define TARGET_LONG_BITS 32 +#define TARGET_LONG_BITS 64 #define CPUArchState struct CPUMBState @@ -203,6 +203,7 @@ typedef struct CPUMBState CPUMBState; /* Target family PVR mask */ #define PVR10_TARGET_FAMILY_MASK 0xFF000000 +#define PVR10_ASIZE_SHIFT 18 /* MMU descrtiption */ #define PVR11_USE_MMU 0xC0000000 @@ -238,19 +239,19 @@ typedef struct CPUMBState CPUMBState; struct CPUMBState { uint32_t debug; uint32_t btaken; - uint32_t btarget; + uint64_t btarget; uint32_t bimm; uint32_t imm; - uint32_t regs[33]; - uint32_t sregs[24]; + uint32_t regs[32]; + uint64_t sregs[14]; float_status fp_status; /* Stack protectors. Yes, it's a hw feature. */ uint32_t slr, shr; /* lwx/swx reserved address */ #define RES_ADDR_NONE 0xffffffff /* Use 0xffffffff to indicate no reservation */ - uint32_t res_addr; + target_ulong res_addr; uint32_t res_val; /* Internal flags. */ @@ -277,7 +278,7 @@ struct CPUMBState { /* These fields are preserved on reset. */ struct { - uint32_t regs[16]; + uint32_t regs[13]; } pvr; }; @@ -297,6 +298,7 @@ struct MicroBlazeCPU { struct { bool stackprot; uint32_t base_vectors; + uint8_t addr_size; uint8_t use_fpu; uint8_t use_hw_mul; bool use_barrel; @@ -340,8 +342,8 @@ int cpu_mb_signal_handler(int host_signum, void *pinfo, /* FIXME: MB uses variable pages down to 1K but linux only uses 4k. */ #define TARGET_PAGE_BITS 12 -#define TARGET_PHYS_ADDR_SPACE_BITS 32 -#define TARGET_VIRT_ADDR_SPACE_BITS 32 +#define TARGET_PHYS_ADDR_SPACE_BITS 64 +#define TARGET_VIRT_ADDR_SPACE_BITS 64 #define CPU_RESOLVING_TYPE TYPE_MICROBLAZE_CPU @@ -358,13 +360,17 @@ int cpu_mb_signal_handler(int host_signum, void *pinfo, static inline int cpu_mmu_index (CPUMBState *env, bool ifetch) { - /* Are we in nommu mode?. */ - if (!(env->sregs[SR_MSR] & MSR_VM)) - return MMU_NOMMU_IDX; + MicroBlazeCPU *cpu = mb_env_get_cpu(env); - if (env->sregs[SR_MSR] & MSR_UM) - return MMU_USER_IDX; - return MMU_KERNEL_IDX; + /* Are we in nommu mode?. */ + if (!(env->sregs[SR_MSR] & MSR_VM) || !cpu->cfg.use_mmu) { + return MMU_NOMMU_IDX; + } + + if (env->sregs[SR_MSR] & MSR_UM) { + return MMU_USER_IDX; + } + return MMU_KERNEL_IDX; } int mb_cpu_handle_mmu_fault(CPUState *cpu, vaddr address, int size, int rw, diff --git a/target/microblaze/helper.c b/target/microblaze/helper.c index fac6ee9..bc75379 100644 --- a/target/microblaze/helper.c +++ b/target/microblaze/helper.c @@ -54,22 +54,12 @@ int mb_cpu_handle_mmu_fault(CPUState *cs, vaddr address, int size, int rw, MicroBlazeCPU *cpu = MICROBLAZE_CPU(cs); CPUMBState *env = &cpu->env; unsigned int hit; - unsigned int mmu_available; int r = 1; int prot; - mmu_available = 0; - if (cpu->cfg.use_mmu) { - mmu_available = 1; - if ((cpu->cfg.pvr == C_PVR_FULL) && - (env->pvr.regs[11] & PVR11_USE_MMU) != PVR11_USE_MMU) { - mmu_available = 0; - } - } - /* Translate if the MMU is available and enabled. */ - if (mmu_available && (env->sregs[SR_MSR] & MSR_VM)) { - target_ulong vaddr, paddr; + if (mmu_idx != MMU_NOMMU_IDX) { + uint32_t vaddr, paddr; struct microblaze_mmu_lookup lu; hit = mmu_translate(&env->mmu, &lu, address, rw, mmu_idx); @@ -152,7 +142,8 @@ void mb_cpu_do_interrupt(CPUState *cs) env->sregs[SR_MSR] |= MSR_EIP; qemu_log_mask(CPU_LOG_INT, - "hw exception at pc=%x ear=%x esr=%x iflags=%x\n", + "hw exception at pc=%" PRIx64 " ear=%" PRIx64 " " + "esr=%" PRIx64 " iflags=%x\n", env->sregs[SR_PC], env->sregs[SR_EAR], env->sregs[SR_ESR], env->iflags); log_cpu_state_mask(CPU_LOG_INT, cs, 0); @@ -175,7 +166,8 @@ void mb_cpu_do_interrupt(CPUState *cs) /* was the branch immprefixed?. */ if (env->bimm) { qemu_log_mask(CPU_LOG_INT, - "bimm exception at pc=%x iflags=%x\n", + "bimm exception at pc=%" PRIx64 " " + "iflags=%x\n", env->sregs[SR_PC], env->iflags); env->regs[17] -= 4; log_cpu_state_mask(CPU_LOG_INT, cs, 0); @@ -193,7 +185,8 @@ void mb_cpu_do_interrupt(CPUState *cs) env->sregs[SR_MSR] |= MSR_EIP; qemu_log_mask(CPU_LOG_INT, - "exception at pc=%x ear=%x iflags=%x\n", + "exception at pc=%" PRIx64 " ear=%" PRIx64 " " + "iflags=%x\n", env->sregs[SR_PC], env->sregs[SR_EAR], env->iflags); log_cpu_state_mask(CPU_LOG_INT, cs, 0); env->iflags &= ~(IMM_FLAG | D_FLAG); @@ -230,7 +223,8 @@ void mb_cpu_do_interrupt(CPUState *cs) } #endif qemu_log_mask(CPU_LOG_INT, - "interrupt at pc=%x msr=%x %x iflags=%x\n", + "interrupt at pc=%" PRIx64 " msr=%" PRIx64 " %x " + "iflags=%x\n", env->sregs[SR_PC], env->sregs[SR_MSR], t, env->iflags); env->sregs[SR_MSR] &= ~(MSR_VMS | MSR_UMS | MSR_VM \ @@ -248,7 +242,8 @@ void mb_cpu_do_interrupt(CPUState *cs) assert(!(env->iflags & D_FLAG)); t = (env->sregs[SR_MSR] & (MSR_VM | MSR_UM)) << 1; qemu_log_mask(CPU_LOG_INT, - "break at pc=%x msr=%x %x iflags=%x\n", + "break at pc=%" PRIx64 " msr=%" PRIx64 " %x " + "iflags=%x\n", env->sregs[SR_PC], env->sregs[SR_MSR], t, env->iflags); log_cpu_state_mask(CPU_LOG_INT, cs, 0); env->sregs[SR_MSR] &= ~(MSR_VMS | MSR_UMS | MSR_VM | MSR_UM); @@ -274,9 +269,10 @@ hwaddr mb_cpu_get_phys_page_debug(CPUState *cs, vaddr addr) CPUMBState *env = &cpu->env; target_ulong vaddr, paddr = 0; struct microblaze_mmu_lookup lu; + int mmu_idx = cpu_mmu_index(env, false); unsigned int hit; - if (env->sregs[SR_MSR] & MSR_VM) { + if (mmu_idx != MMU_NOMMU_IDX) { hit = mmu_translate(&env->mmu, &lu, addr, 0, 0); if (hit) { vaddr = addr & TARGET_PAGE_MASK; diff --git a/target/microblaze/helper.h b/target/microblaze/helper.h index 71a6c08..2f8bdea 100644 --- a/target/microblaze/helper.h +++ b/target/microblaze/helper.h @@ -25,12 +25,12 @@ DEF_HELPER_3(fcmp_ge, i32, env, i32, i32) DEF_HELPER_FLAGS_2(pcmpbf, TCG_CALL_NO_RWG_SE, i32, i32, i32) #if !defined(CONFIG_USER_ONLY) -DEF_HELPER_2(mmu_read, i32, env, i32) -DEF_HELPER_3(mmu_write, void, env, i32, i32) +DEF_HELPER_3(mmu_read, i32, env, i32, i32) +DEF_HELPER_4(mmu_write, void, env, i32, i32, i32) #endif -DEF_HELPER_5(memalign, void, env, i32, i32, i32, i32) -DEF_HELPER_2(stackprot, void, env, i32) +DEF_HELPER_5(memalign, void, env, tl, i32, i32, i32) +DEF_HELPER_2(stackprot, void, env, tl) DEF_HELPER_2(get, i32, i32, i32) DEF_HELPER_3(put, void, i32, i32, i32) diff --git a/target/microblaze/mmu.c b/target/microblaze/mmu.c index 9d5e6aa..f4ceaea 100644 --- a/target/microblaze/mmu.c +++ b/target/microblaze/mmu.c @@ -22,8 +22,6 @@ #include "cpu.h" #include "exec/exec-all.h" -#define D(x) - static unsigned int tlb_decode_size(unsigned int f) { static const unsigned int sizes[] = { @@ -81,34 +79,29 @@ unsigned int mmu_translate(struct microblaze_mmu *mmu, { unsigned int i, hit = 0; unsigned int tlb_ex = 0, tlb_wr = 0, tlb_zsel; - unsigned int tlb_size; - uint32_t tlb_tag, tlb_rpn, mask, t0; + uint64_t tlb_tag, tlb_rpn, mask; + uint32_t tlb_size, t0; lu->err = ERR_MISS; for (i = 0; i < ARRAY_SIZE(mmu->rams[RAM_TAG]); i++) { - uint32_t t, d; + uint64_t t, d; /* Lookup and decode. */ t = mmu->rams[RAM_TAG][i]; - D(qemu_log("TLB %d valid=%d\n", i, t & TLB_VALID)); if (t & TLB_VALID) { tlb_size = tlb_decode_size((t & TLB_PAGESZ_MASK) >> 7); if (tlb_size < TARGET_PAGE_SIZE) { - qemu_log("%d pages not supported\n", tlb_size); + qemu_log_mask(LOG_UNIMP, "%d pages not supported\n", tlb_size); abort(); } - mask = ~(tlb_size - 1); + mask = ~((uint64_t)tlb_size - 1); tlb_tag = t & TLB_EPN_MASK; if ((vaddr & mask) != (tlb_tag & mask)) { - D(qemu_log("TLB %d vaddr=%x != tag=%x\n", - i, vaddr & mask, tlb_tag & mask)); continue; } if (mmu->tids[i] && ((mmu->regs[MMU_R_PID] & 0xff) != mmu->tids[i])) { - D(qemu_log("TLB %d pid=%x != tid=%x\n", - i, mmu->regs[MMU_R_PID], mmu->tids[i])); continue; } @@ -123,7 +116,8 @@ unsigned int mmu_translate(struct microblaze_mmu *mmu, t0 &= 0x3; if (tlb_zsel > mmu->c_mmu_zones) { - qemu_log_mask(LOG_GUEST_ERROR, "tlb zone select out of range! %d\n", tlb_zsel); + qemu_log_mask(LOG_GUEST_ERROR, + "tlb zone select out of range! %d\n", tlb_zsel); t0 = 1; /* Ignore. */ } @@ -164,6 +158,7 @@ unsigned int mmu_translate(struct microblaze_mmu *mmu, tlb_rpn = d & TLB_RPN_MASK; lu->vaddr = tlb_tag; + lu->paddr = tlb_rpn & mmu->c_addr_mask; lu->paddr = tlb_rpn; lu->size = tlb_size; lu->err = ERR_HIT; @@ -173,13 +168,14 @@ unsigned int mmu_translate(struct microblaze_mmu *mmu, } } done: - D(qemu_log("MMU vaddr=%x rw=%d tlb_wr=%d tlb_ex=%d hit=%d\n", - vaddr, rw, tlb_wr, tlb_ex, hit)); + qemu_log_mask(CPU_LOG_MMU, + "MMU vaddr=%" PRIx64 " rw=%d tlb_wr=%d tlb_ex=%d hit=%d\n", + vaddr, rw, tlb_wr, tlb_ex, hit); return hit; } /* Writes/reads to the MMU's special regs end up here. */ -uint32_t mmu_read(CPUMBState *env, uint32_t rn) +uint32_t mmu_read(CPUMBState *env, bool ext, uint32_t rn) { unsigned int i; uint32_t r = 0; @@ -188,50 +184,65 @@ uint32_t mmu_read(CPUMBState *env, uint32_t rn) qemu_log_mask(LOG_GUEST_ERROR, "MMU access on MMU-less system\n"); return 0; } + if (ext && rn != MMU_R_TLBLO) { + qemu_log_mask(LOG_GUEST_ERROR, "Extended access only to TLBLO.\n"); + return 0; + } switch (rn) { /* Reads to HI/LO trig reads from the mmu rams. */ case MMU_R_TLBLO: case MMU_R_TLBHI: if (!(env->mmu.c_mmu_tlb_access & 1)) { - qemu_log_mask(LOG_GUEST_ERROR, "Invalid access to MMU reg %d\n", rn); + qemu_log_mask(LOG_GUEST_ERROR, + "Invalid access to MMU reg %d\n", rn); return 0; } i = env->mmu.regs[MMU_R_TLBX] & 0xff; - r = env->mmu.rams[rn & 1][i]; + r = extract64(env->mmu.rams[rn & 1][i], ext * 32, 32); if (rn == MMU_R_TLBHI) env->mmu.regs[MMU_R_PID] = env->mmu.tids[i]; break; case MMU_R_PID: case MMU_R_ZPR: if (!(env->mmu.c_mmu_tlb_access & 1)) { - qemu_log_mask(LOG_GUEST_ERROR, "Invalid access to MMU reg %d\n", rn); + qemu_log_mask(LOG_GUEST_ERROR, + "Invalid access to MMU reg %d\n", rn); return 0; } r = env->mmu.regs[rn]; break; + case MMU_R_TLBX: + r = env->mmu.regs[rn]; + break; case MMU_R_TLBSX: qemu_log_mask(LOG_GUEST_ERROR, "TLBSX is write-only.\n"); break; default: - r = env->mmu.regs[rn]; + qemu_log_mask(LOG_GUEST_ERROR, "Invalid MMU register %d.\n", rn); break; } - D(qemu_log("%s rn=%d=%x\n", __func__, rn, r)); + qemu_log_mask(CPU_LOG_MMU, "%s rn=%d=%x\n", __func__, rn, r); return r; } -void mmu_write(CPUMBState *env, uint32_t rn, uint32_t v) +void mmu_write(CPUMBState *env, bool ext, uint32_t rn, uint32_t v) { MicroBlazeCPU *cpu = mb_env_get_cpu(env); + uint64_t tmp64; unsigned int i; - D(qemu_log("%s rn=%d=%x old=%x\n", __func__, rn, v, env->mmu.regs[rn])); + qemu_log_mask(CPU_LOG_MMU, + "%s rn=%d=%x old=%x\n", __func__, rn, v, env->mmu.regs[rn]); if (env->mmu.c_mmu < 2 || !env->mmu.c_mmu_tlb_access) { qemu_log_mask(LOG_GUEST_ERROR, "MMU access on MMU-less system\n"); return; } + if (ext && rn != MMU_R_TLBLO) { + qemu_log_mask(LOG_GUEST_ERROR, "Extended access only to TLBLO.\n"); + return; + } switch (rn) { /* Writes to HI/LO trig writes to the mmu rams. */ @@ -240,18 +251,19 @@ void mmu_write(CPUMBState *env, uint32_t rn, uint32_t v) i = env->mmu.regs[MMU_R_TLBX] & 0xff; if (rn == MMU_R_TLBHI) { if (i < 3 && !(v & TLB_VALID) && qemu_loglevel_mask(~0)) - qemu_log_mask(LOG_GUEST_ERROR, "invalidating index %x at pc=%x\n", + qemu_log_mask(LOG_GUEST_ERROR, + "invalidating index %x at pc=%" PRIx64 "\n", i, env->sregs[SR_PC]); env->mmu.tids[i] = env->mmu.regs[MMU_R_PID] & 0xff; mmu_flush_idx(env, i); } - env->mmu.rams[rn & 1][i] = v; - - D(qemu_log("%s ram[%d][%d]=%x\n", __func__, rn & 1, i, v)); + tmp64 = env->mmu.rams[rn & 1][i]; + env->mmu.rams[rn & 1][i] = deposit64(tmp64, ext * 32, 32, v); break; case MMU_R_ZPR: if (env->mmu.c_mmu_tlb_access <= 1) { - qemu_log_mask(LOG_GUEST_ERROR, "Invalid access to MMU reg %d\n", rn); + qemu_log_mask(LOG_GUEST_ERROR, + "Invalid access to MMU reg %d\n", rn); return; } @@ -264,7 +276,8 @@ void mmu_write(CPUMBState *env, uint32_t rn, uint32_t v) break; case MMU_R_PID: if (env->mmu.c_mmu_tlb_access <= 1) { - qemu_log_mask(LOG_GUEST_ERROR, "Invalid access to MMU reg %d\n", rn); + qemu_log_mask(LOG_GUEST_ERROR, + "Invalid access to MMU reg %d\n", rn); return; } @@ -283,7 +296,8 @@ void mmu_write(CPUMBState *env, uint32_t rn, uint32_t v) int hit; if (env->mmu.c_mmu_tlb_access <= 1) { - qemu_log_mask(LOG_GUEST_ERROR, "Invalid access to MMU reg %d\n", rn); + qemu_log_mask(LOG_GUEST_ERROR, + "Invalid access to MMU reg %d\n", rn); return; } @@ -291,12 +305,13 @@ void mmu_write(CPUMBState *env, uint32_t rn, uint32_t v) v & TLB_EPN_MASK, 0, cpu_mmu_index(env, false)); if (hit) { env->mmu.regs[MMU_R_TLBX] = lu.idx; - } else - env->mmu.regs[MMU_R_TLBX] |= 0x80000000; + } else { + env->mmu.regs[MMU_R_TLBX] |= R_TBLX_MISS_MASK; + } break; } default: - env->mmu.regs[rn] = v; + qemu_log_mask(LOG_GUEST_ERROR, "Invalid MMU register %d.\n", rn); break; } } diff --git a/target/microblaze/mmu.h b/target/microblaze/mmu.h index 3b7a998..a4272b6 100644 --- a/target/microblaze/mmu.h +++ b/target/microblaze/mmu.h @@ -28,7 +28,7 @@ #define RAM_TAG 0 /* Tag portion */ -#define TLB_EPN_MASK 0xFFFFFC00 /* Effective Page Number */ +#define TLB_EPN_MASK MAKE_64BIT_MASK(10, 64 - 10) #define TLB_PAGESZ_MASK 0x00000380 #define TLB_PAGESZ(x) (((x) & 0x7) << 7) #define PAGESZ_1K 0 @@ -42,7 +42,7 @@ #define TLB_VALID 0x00000040 /* Entry is valid */ /* Data portion */ -#define TLB_RPN_MASK 0xFFFFFC00 /* Real Page Number */ +#define TLB_RPN_MASK MAKE_64BIT_MASK(10, 64 - 10) #define TLB_PERM_MASK 0x00000300 #define TLB_EX 0x00000200 /* Instruction execution allowed */ #define TLB_WR 0x00000100 /* Writes permitted */ @@ -54,20 +54,25 @@ #define TLB_M 0x00000002 /* Memory is coherent */ #define TLB_G 0x00000001 /* Memory is guarded from prefetch */ +/* TLBX */ +#define R_TBLX_MISS_SHIFT 31 +#define R_TBLX_MISS_MASK (1U << R_TBLX_MISS_SHIFT) + #define TLB_ENTRIES 64 struct microblaze_mmu { /* Data and tag brams. */ - uint32_t rams[2][TLB_ENTRIES]; + uint64_t rams[2][TLB_ENTRIES]; /* We keep a separate ram for the tids to avoid the 48 bit tag width. */ uint8_t tids[TLB_ENTRIES]; /* Control flops. */ - uint32_t regs[8]; + uint32_t regs[3]; int c_mmu; int c_mmu_tlb_access; int c_mmu_zones; + uint64_t c_addr_mask; /* Mask to apply to physical addresses. */ }; struct microblaze_mmu_lookup @@ -85,6 +90,6 @@ struct microblaze_mmu_lookup unsigned int mmu_translate(struct microblaze_mmu *mmu, struct microblaze_mmu_lookup *lu, target_ulong vaddr, int rw, int mmu_idx); -uint32_t mmu_read(CPUMBState *env, uint32_t rn); -void mmu_write(CPUMBState *env, uint32_t rn, uint32_t v); +uint32_t mmu_read(CPUMBState *env, bool ea, uint32_t rn); +void mmu_write(CPUMBState *env, bool ea, uint32_t rn, uint32_t v); void mmu_init(struct microblaze_mmu *mmu); diff --git a/target/microblaze/op_helper.c b/target/microblaze/op_helper.c index 1b4fe79..7cdbbcc 100644 --- a/target/microblaze/op_helper.c +++ b/target/microblaze/op_helper.c @@ -94,16 +94,17 @@ void helper_debug(CPUMBState *env) { int i; - qemu_log("PC=%8.8x\n", env->sregs[SR_PC]); - qemu_log("rmsr=%x resr=%x rear=%x debug[%x] imm=%x iflags=%x\n", + qemu_log("PC=%" PRIx64 "\n", env->sregs[SR_PC]); + qemu_log("rmsr=%" PRIx64 " resr=%" PRIx64 " rear=%" PRIx64 " " + "debug[%x] imm=%x iflags=%x\n", env->sregs[SR_MSR], env->sregs[SR_ESR], env->sregs[SR_EAR], env->debug, env->imm, env->iflags); - qemu_log("btaken=%d btarget=%x mode=%s(saved=%s) eip=%d ie=%d\n", + qemu_log("btaken=%d btarget=%" PRIx64 " mode=%s(saved=%s) eip=%d ie=%d\n", env->btaken, env->btarget, (env->sregs[SR_MSR] & MSR_UM) ? "user" : "kernel", (env->sregs[SR_MSR] & MSR_UMS) ? "user" : "kernel", - (env->sregs[SR_MSR] & MSR_EIP), - (env->sregs[SR_MSR] & MSR_IE)); + (bool)(env->sregs[SR_MSR] & MSR_EIP), + (bool)(env->sregs[SR_MSR] & MSR_IE)); for (i = 0; i < 32; i++) { qemu_log("r%2.2d=%8.8x ", i, env->regs[i]); if ((i + 1) % 4 == 0) @@ -439,12 +440,14 @@ uint32_t helper_pcmpbf(uint32_t a, uint32_t b) return 0; } -void helper_memalign(CPUMBState *env, uint32_t addr, uint32_t dr, uint32_t wr, +void helper_memalign(CPUMBState *env, target_ulong addr, + uint32_t dr, uint32_t wr, uint32_t mask) { if (addr & mask) { qemu_log_mask(CPU_LOG_INT, - "unaligned access addr=%x mask=%x, wr=%d dr=r%d\n", + "unaligned access addr=" TARGET_FMT_lx + " mask=%x, wr=%d dr=r%d\n", addr, mask, wr, dr); env->sregs[SR_EAR] = addr; env->sregs[SR_ESR] = ESR_EC_UNALIGNED_DATA | (wr << 10) \ @@ -459,10 +462,11 @@ void helper_memalign(CPUMBState *env, uint32_t addr, uint32_t dr, uint32_t wr, } } -void helper_stackprot(CPUMBState *env, uint32_t addr) +void helper_stackprot(CPUMBState *env, target_ulong addr) { if (addr < env->slr || addr > env->shr) { - qemu_log_mask(CPU_LOG_INT, "Stack protector violation at %x %x %x\n", + qemu_log_mask(CPU_LOG_INT, "Stack protector violation at " + TARGET_FMT_lx " %x %x\n", addr, env->slr, env->shr); env->sregs[SR_EAR] = addr; env->sregs[SR_ESR] = ESR_EC_STACKPROT; @@ -472,14 +476,14 @@ void helper_stackprot(CPUMBState *env, uint32_t addr) #if !defined(CONFIG_USER_ONLY) /* Writes/reads to the MMU's special regs end up here. */ -uint32_t helper_mmu_read(CPUMBState *env, uint32_t rn) +uint32_t helper_mmu_read(CPUMBState *env, uint32_t ext, uint32_t rn) { - return mmu_read(env, rn); + return mmu_read(env, ext, rn); } -void helper_mmu_write(CPUMBState *env, uint32_t rn, uint32_t v) +void helper_mmu_write(CPUMBState *env, uint32_t ext, uint32_t rn, uint32_t v) { - mmu_write(env, rn, v); + mmu_write(env, ext, rn, v); } void mb_cpu_unassigned_access(CPUState *cs, hwaddr addr, diff --git a/target/microblaze/translate.c b/target/microblaze/translate.c index 0872dc9..b79600c 100644 --- a/target/microblaze/translate.c +++ b/target/microblaze/translate.c @@ -52,22 +52,22 @@ #define DISAS_UPDATE DISAS_TARGET_1 /* cpu state was modified dynamically */ #define DISAS_TB_JUMP DISAS_TARGET_2 /* only pc was modified statically */ -static TCGv env_debug; -static TCGv cpu_R[32]; -static TCGv cpu_SR[18]; -static TCGv env_imm; -static TCGv env_btaken; -static TCGv env_btarget; -static TCGv env_iflags; +static TCGv_i32 env_debug; +static TCGv_i32 cpu_R[32]; +static TCGv_i64 cpu_SR[14]; +static TCGv_i32 env_imm; +static TCGv_i32 env_btaken; +static TCGv_i64 env_btarget; +static TCGv_i32 env_iflags; static TCGv env_res_addr; -static TCGv env_res_val; +static TCGv_i32 env_res_val; #include "exec/gen-icount.h" /* This is the state at translation time. */ typedef struct DisasContext { MicroBlazeCPU *cpu; - target_ulong pc; + uint32_t pc; /* Decoder. */ int type_b; @@ -105,16 +105,15 @@ static const char *regnames[] = static const char *special_regnames[] = { - "rpc", "rmsr", "sr2", "sr3", "sr4", "sr5", "sr6", "sr7", - "sr8", "sr9", "sr10", "sr11", "sr12", "sr13", "sr14", "sr15", - "sr16", "sr17", "sr18" + "rpc", "rmsr", "sr2", "rear", "sr4", "resr", "sr6", "rfsr", + "sr8", "sr9", "sr10", "rbtr", "sr12", "redr" }; static inline void t_sync_flags(DisasContext *dc) { /* Synch the tb dependent flags between translator and runtime. */ if (dc->tb_flags != dc->synced_flags) { - tcg_gen_movi_tl(env_iflags, dc->tb_flags); + tcg_gen_movi_i32(env_iflags, dc->tb_flags); dc->synced_flags = dc->tb_flags; } } @@ -124,7 +123,7 @@ static inline void t_gen_raise_exception(DisasContext *dc, uint32_t index) TCGv_i32 tmp = tcg_const_i32(index); t_sync_flags(dc); - tcg_gen_movi_tl(cpu_SR[SR_PC], dc->pc); + tcg_gen_movi_i64(cpu_SR[SR_PC], dc->pc); gen_helper_raise_exception(cpu_env, tmp); tcg_temp_free_i32(tmp); dc->is_jmp = DISAS_UPDATE; @@ -143,41 +142,70 @@ static void gen_goto_tb(DisasContext *dc, int n, target_ulong dest) { if (use_goto_tb(dc, dest)) { tcg_gen_goto_tb(n); - tcg_gen_movi_tl(cpu_SR[SR_PC], dest); + tcg_gen_movi_i64(cpu_SR[SR_PC], dest); tcg_gen_exit_tb((uintptr_t)dc->tb + n); } else { - tcg_gen_movi_tl(cpu_SR[SR_PC], dest); + tcg_gen_movi_i64(cpu_SR[SR_PC], dest); tcg_gen_exit_tb(0); } } -static void read_carry(DisasContext *dc, TCGv d) +static void read_carry(DisasContext *dc, TCGv_i32 d) { - tcg_gen_shri_tl(d, cpu_SR[SR_MSR], 31); + tcg_gen_extrl_i64_i32(d, cpu_SR[SR_MSR]); + tcg_gen_shri_i32(d, d, 31); } /* * write_carry sets the carry bits in MSR based on bit 0 of v. * v[31:1] are ignored. */ -static void write_carry(DisasContext *dc, TCGv v) +static void write_carry(DisasContext *dc, TCGv_i32 v) { - TCGv t0 = tcg_temp_new(); - tcg_gen_shli_tl(t0, v, 31); - tcg_gen_sari_tl(t0, t0, 31); - tcg_gen_andi_tl(t0, t0, (MSR_C | MSR_CC)); - tcg_gen_andi_tl(cpu_SR[SR_MSR], cpu_SR[SR_MSR], - ~(MSR_C | MSR_CC)); - tcg_gen_or_tl(cpu_SR[SR_MSR], cpu_SR[SR_MSR], t0); - tcg_temp_free(t0); + TCGv_i64 t0 = tcg_temp_new_i64(); + tcg_gen_extu_i32_i64(t0, v); + /* Deposit bit 0 into MSR_C and the alias MSR_CC. */ + tcg_gen_deposit_i64(cpu_SR[SR_MSR], cpu_SR[SR_MSR], t0, 2, 1); + tcg_gen_deposit_i64(cpu_SR[SR_MSR], cpu_SR[SR_MSR], t0, 31, 1); + tcg_temp_free_i64(t0); } static void write_carryi(DisasContext *dc, bool carry) { - TCGv t0 = tcg_temp_new(); - tcg_gen_movi_tl(t0, carry); + TCGv_i32 t0 = tcg_temp_new_i32(); + tcg_gen_movi_i32(t0, carry); write_carry(dc, t0); - tcg_temp_free(t0); + tcg_temp_free_i32(t0); +} + +/* + * Returns true if the insn an illegal operation. + * If exceptions are enabled, an exception is raised. + */ +static bool trap_illegal(DisasContext *dc, bool cond) +{ + if (cond && (dc->tb_flags & MSR_EE_FLAG) + && (dc->cpu->env.pvr.regs[2] & PVR2_ILL_OPCODE_EXC_MASK)) { + tcg_gen_movi_i64(cpu_SR[SR_ESR], ESR_EC_ILLEGAL_OP); + t_gen_raise_exception(dc, EXCP_HW_EXCP); + } + return cond; +} + +/* + * Returns true if the insn is illegal in userspace. + * If exceptions are enabled, an exception is raised. + */ +static bool trap_userspace(DisasContext *dc, bool cond) +{ + int mem_index = cpu_mmu_index(&dc->cpu->env, false); + bool cond_user = cond && mem_index == MMU_USER_IDX; + + if (cond_user && (dc->tb_flags & MSR_EE_FLAG)) { + tcg_gen_movi_i64(cpu_SR[SR_ESR], ESR_EC_PRIVINSN); + t_gen_raise_exception(dc, EXCP_HW_EXCP); + } + return cond_user; } /* True if ALU operand b is a small immediate that may deserve @@ -188,13 +216,13 @@ static inline int dec_alu_op_b_is_small_imm(DisasContext *dc) return dc->type_b && !(dc->tb_flags & IMM_FLAG); } -static inline TCGv *dec_alu_op_b(DisasContext *dc) +static inline TCGv_i32 *dec_alu_op_b(DisasContext *dc) { if (dc->type_b) { if (dc->tb_flags & IMM_FLAG) - tcg_gen_ori_tl(env_imm, env_imm, dc->imm); + tcg_gen_ori_i32(env_imm, env_imm, dc->imm); else - tcg_gen_movi_tl(env_imm, (int32_t)((int16_t)dc->imm)); + tcg_gen_movi_i32(env_imm, (int32_t)((int16_t)dc->imm)); return &env_imm; } else return &cpu_R[dc->rb]; @@ -203,7 +231,7 @@ static inline TCGv *dec_alu_op_b(DisasContext *dc) static void dec_add(DisasContext *dc) { unsigned int k, c; - TCGv cf; + TCGv_i32 cf; k = dc->opcode & 4; c = dc->opcode & 2; @@ -217,15 +245,15 @@ static void dec_add(DisasContext *dc) /* k - keep carry, no need to update MSR. */ /* If rd == r0, it's a nop. */ if (dc->rd) { - tcg_gen_add_tl(cpu_R[dc->rd], cpu_R[dc->ra], *(dec_alu_op_b(dc))); + tcg_gen_add_i32(cpu_R[dc->rd], cpu_R[dc->ra], *(dec_alu_op_b(dc))); if (c) { /* c - Add carry into the result. */ - cf = tcg_temp_new(); + cf = tcg_temp_new_i32(); read_carry(dc, cf); - tcg_gen_add_tl(cpu_R[dc->rd], cpu_R[dc->rd], cf); - tcg_temp_free(cf); + tcg_gen_add_i32(cpu_R[dc->rd], cpu_R[dc->rd], cf); + tcg_temp_free_i32(cf); } } return; @@ -233,31 +261,31 @@ static void dec_add(DisasContext *dc) /* From now on, we can assume k is zero. So we need to update MSR. */ /* Extract carry. */ - cf = tcg_temp_new(); + cf = tcg_temp_new_i32(); if (c) { read_carry(dc, cf); } else { - tcg_gen_movi_tl(cf, 0); + tcg_gen_movi_i32(cf, 0); } if (dc->rd) { - TCGv ncf = tcg_temp_new(); + TCGv_i32 ncf = tcg_temp_new_i32(); gen_helper_carry(ncf, cpu_R[dc->ra], *(dec_alu_op_b(dc)), cf); - tcg_gen_add_tl(cpu_R[dc->rd], cpu_R[dc->ra], *(dec_alu_op_b(dc))); - tcg_gen_add_tl(cpu_R[dc->rd], cpu_R[dc->rd], cf); + tcg_gen_add_i32(cpu_R[dc->rd], cpu_R[dc->ra], *(dec_alu_op_b(dc))); + tcg_gen_add_i32(cpu_R[dc->rd], cpu_R[dc->rd], cf); write_carry(dc, ncf); - tcg_temp_free(ncf); + tcg_temp_free_i32(ncf); } else { gen_helper_carry(cf, cpu_R[dc->ra], *(dec_alu_op_b(dc)), cf); write_carry(dc, cf); } - tcg_temp_free(cf); + tcg_temp_free_i32(cf); } static void dec_sub(DisasContext *dc) { unsigned int u, cmp, k, c; - TCGv cf, na; + TCGv_i32 cf, na; u = dc->imm & 2; k = dc->opcode & 4; @@ -283,15 +311,15 @@ static void dec_sub(DisasContext *dc) /* k - keep carry, no need to update MSR. */ /* If rd == r0, it's a nop. */ if (dc->rd) { - tcg_gen_sub_tl(cpu_R[dc->rd], *(dec_alu_op_b(dc)), cpu_R[dc->ra]); + tcg_gen_sub_i32(cpu_R[dc->rd], *(dec_alu_op_b(dc)), cpu_R[dc->ra]); if (c) { /* c - Add carry into the result. */ - cf = tcg_temp_new(); + cf = tcg_temp_new_i32(); read_carry(dc, cf); - tcg_gen_add_tl(cpu_R[dc->rd], cpu_R[dc->rd], cf); - tcg_temp_free(cf); + tcg_gen_add_i32(cpu_R[dc->rd], cpu_R[dc->rd], cf); + tcg_temp_free_i32(cf); } } return; @@ -299,41 +327,38 @@ static void dec_sub(DisasContext *dc) /* From now on, we can assume k is zero. So we need to update MSR. */ /* Extract carry. And complement a into na. */ - cf = tcg_temp_new(); - na = tcg_temp_new(); + cf = tcg_temp_new_i32(); + na = tcg_temp_new_i32(); if (c) { read_carry(dc, cf); } else { - tcg_gen_movi_tl(cf, 1); + tcg_gen_movi_i32(cf, 1); } /* d = b + ~a + c. carry defaults to 1. */ - tcg_gen_not_tl(na, cpu_R[dc->ra]); + tcg_gen_not_i32(na, cpu_R[dc->ra]); if (dc->rd) { - TCGv ncf = tcg_temp_new(); + TCGv_i32 ncf = tcg_temp_new_i32(); gen_helper_carry(ncf, na, *(dec_alu_op_b(dc)), cf); - tcg_gen_add_tl(cpu_R[dc->rd], na, *(dec_alu_op_b(dc))); - tcg_gen_add_tl(cpu_R[dc->rd], cpu_R[dc->rd], cf); + tcg_gen_add_i32(cpu_R[dc->rd], na, *(dec_alu_op_b(dc))); + tcg_gen_add_i32(cpu_R[dc->rd], cpu_R[dc->rd], cf); write_carry(dc, ncf); - tcg_temp_free(ncf); + tcg_temp_free_i32(ncf); } else { gen_helper_carry(cf, na, *(dec_alu_op_b(dc)), cf); write_carry(dc, cf); } - tcg_temp_free(cf); - tcg_temp_free(na); + tcg_temp_free_i32(cf); + tcg_temp_free_i32(na); } static void dec_pattern(DisasContext *dc) { unsigned int mode; - if ((dc->tb_flags & MSR_EE_FLAG) - && (dc->cpu->env.pvr.regs[2] & PVR2_ILL_OPCODE_EXC_MASK) - && !dc->cpu->cfg.use_pcmp_instr) { - tcg_gen_movi_tl(cpu_SR[SR_ESR], ESR_EC_ILLEGAL_OP); - t_gen_raise_exception(dc, EXCP_HW_EXCP); + if (trap_illegal(dc, !dc->cpu->cfg.use_pcmp_instr)) { + return; } mode = dc->opcode & 3; @@ -347,14 +372,14 @@ static void dec_pattern(DisasContext *dc) case 2: LOG_DIS("pcmpeq r%d r%d r%d\n", dc->rd, dc->ra, dc->rb); if (dc->rd) { - tcg_gen_setcond_tl(TCG_COND_EQ, cpu_R[dc->rd], + tcg_gen_setcond_i32(TCG_COND_EQ, cpu_R[dc->rd], cpu_R[dc->ra], cpu_R[dc->rb]); } break; case 3: LOG_DIS("pcmpne r%d r%d r%d\n", dc->rd, dc->ra, dc->rb); if (dc->rd) { - tcg_gen_setcond_tl(TCG_COND_NE, cpu_R[dc->rd], + tcg_gen_setcond_i32(TCG_COND_NE, cpu_R[dc->rd], cpu_R[dc->ra], cpu_R[dc->rb]); } break; @@ -381,9 +406,9 @@ static void dec_and(DisasContext *dc) return; if (not) { - tcg_gen_andc_tl(cpu_R[dc->rd], cpu_R[dc->ra], *(dec_alu_op_b(dc))); + tcg_gen_andc_i32(cpu_R[dc->rd], cpu_R[dc->ra], *(dec_alu_op_b(dc))); } else - tcg_gen_and_tl(cpu_R[dc->rd], cpu_R[dc->ra], *(dec_alu_op_b(dc))); + tcg_gen_and_i32(cpu_R[dc->rd], cpu_R[dc->ra], *(dec_alu_op_b(dc))); } static void dec_or(DisasContext *dc) @@ -395,7 +420,7 @@ static void dec_or(DisasContext *dc) LOG_DIS("or r%d r%d r%d imm=%x\n", dc->rd, dc->ra, dc->rb, dc->imm); if (dc->rd) - tcg_gen_or_tl(cpu_R[dc->rd], cpu_R[dc->ra], *(dec_alu_op_b(dc))); + tcg_gen_or_i32(cpu_R[dc->rd], cpu_R[dc->ra], *(dec_alu_op_b(dc))); } static void dec_xor(DisasContext *dc) @@ -407,43 +432,54 @@ static void dec_xor(DisasContext *dc) LOG_DIS("xor r%d\n", dc->rd); if (dc->rd) - tcg_gen_xor_tl(cpu_R[dc->rd], cpu_R[dc->ra], *(dec_alu_op_b(dc))); + tcg_gen_xor_i32(cpu_R[dc->rd], cpu_R[dc->ra], *(dec_alu_op_b(dc))); } -static inline void msr_read(DisasContext *dc, TCGv d) +static inline void msr_read(DisasContext *dc, TCGv_i32 d) { - tcg_gen_mov_tl(d, cpu_SR[SR_MSR]); + tcg_gen_extrl_i64_i32(d, cpu_SR[SR_MSR]); } -static inline void msr_write(DisasContext *dc, TCGv v) +static inline void msr_write(DisasContext *dc, TCGv_i32 v) { - TCGv t; + TCGv_i64 t; - t = tcg_temp_new(); + t = tcg_temp_new_i64(); dc->cpustate_changed = 1; /* PVR bit is not writable. */ - tcg_gen_andi_tl(t, v, ~MSR_PVR); - tcg_gen_andi_tl(cpu_SR[SR_MSR], cpu_SR[SR_MSR], MSR_PVR); - tcg_gen_or_tl(cpu_SR[SR_MSR], cpu_SR[SR_MSR], t); - tcg_temp_free(t); + tcg_gen_extu_i32_i64(t, v); + tcg_gen_andi_i64(t, t, ~MSR_PVR); + tcg_gen_andi_i64(cpu_SR[SR_MSR], cpu_SR[SR_MSR], MSR_PVR); + tcg_gen_or_i64(cpu_SR[SR_MSR], cpu_SR[SR_MSR], t); + tcg_temp_free_i64(t); } static void dec_msr(DisasContext *dc) { CPUState *cs = CPU(dc->cpu); - TCGv t0, t1; - unsigned int sr, to, rn; - int mem_index = cpu_mmu_index(&dc->cpu->env, false); + TCGv_i32 t0, t1; + unsigned int sr, rn; + bool to, clrset, extended = false; - sr = dc->imm & ((1 << 14) - 1); - to = dc->imm & (1 << 14); + sr = extract32(dc->imm, 0, 14); + to = extract32(dc->imm, 14, 1); + clrset = extract32(dc->imm, 15, 1) == 0; dc->type_b = 1; - if (to) + if (to) { dc->cpustate_changed = 1; + } + + /* Extended MSRs are only available if addr_size > 32. */ + if (dc->cpu->cfg.addr_size > 32) { + /* The E-bit is encoded differently for To/From MSR. */ + static const unsigned int e_bit[] = { 19, 24 }; + + extended = extract32(dc->imm, e_bit[to], 1); + } /* msrclr and msrset. */ - if (!(dc->imm & (1 << 15))) { - unsigned int clr = dc->ir & (1 << 16); + if (clrset) { + bool clr = extract32(dc->ir, 16, 1); LOG_DIS("msr%s r%d imm=%x\n", clr ? "clr" : "set", dc->rd, dc->imm); @@ -453,52 +489,51 @@ static void dec_msr(DisasContext *dc) return; } - if ((dc->tb_flags & MSR_EE_FLAG) - && mem_index == MMU_USER_IDX && (dc->imm != 4 && dc->imm != 0)) { - tcg_gen_movi_tl(cpu_SR[SR_ESR], ESR_EC_PRIVINSN); - t_gen_raise_exception(dc, EXCP_HW_EXCP); + if (trap_userspace(dc, dc->imm != 4 && dc->imm != 0)) { return; } if (dc->rd) msr_read(dc, cpu_R[dc->rd]); - t0 = tcg_temp_new(); - t1 = tcg_temp_new(); + t0 = tcg_temp_new_i32(); + t1 = tcg_temp_new_i32(); msr_read(dc, t0); - tcg_gen_mov_tl(t1, *(dec_alu_op_b(dc))); + tcg_gen_mov_i32(t1, *(dec_alu_op_b(dc))); if (clr) { - tcg_gen_not_tl(t1, t1); - tcg_gen_and_tl(t0, t0, t1); + tcg_gen_not_i32(t1, t1); + tcg_gen_and_i32(t0, t0, t1); } else - tcg_gen_or_tl(t0, t0, t1); + tcg_gen_or_i32(t0, t0, t1); msr_write(dc, t0); - tcg_temp_free(t0); - tcg_temp_free(t1); - tcg_gen_movi_tl(cpu_SR[SR_PC], dc->pc + 4); + tcg_temp_free_i32(t0); + tcg_temp_free_i32(t1); + tcg_gen_movi_i64(cpu_SR[SR_PC], dc->pc + 4); dc->is_jmp = DISAS_UPDATE; return; } - if (to) { - if ((dc->tb_flags & MSR_EE_FLAG) - && mem_index == MMU_USER_IDX) { - tcg_gen_movi_tl(cpu_SR[SR_ESR], ESR_EC_PRIVINSN); - t_gen_raise_exception(dc, EXCP_HW_EXCP); - return; - } + if (trap_userspace(dc, to)) { + return; } #if !defined(CONFIG_USER_ONLY) /* Catch read/writes to the mmu block. */ if ((sr & ~0xff) == 0x1000) { + TCGv_i32 tmp_ext = tcg_const_i32(extended); + TCGv_i32 tmp_sr; + sr &= 7; + tmp_sr = tcg_const_i32(sr); LOG_DIS("m%ss sr%d r%d imm=%x\n", to ? "t" : "f", sr, dc->ra, dc->imm); - if (to) - gen_helper_mmu_write(cpu_env, tcg_const_tl(sr), cpu_R[dc->ra]); - else - gen_helper_mmu_read(cpu_R[dc->rd], cpu_env, tcg_const_tl(sr)); + if (to) { + gen_helper_mmu_write(cpu_env, tmp_ext, tmp_sr, cpu_R[dc->ra]); + } else { + gen_helper_mmu_read(cpu_R[dc->rd], cpu_env, tmp_ext, tmp_sr); + } + tcg_temp_free_i32(tmp_sr); + tcg_temp_free_i32(tmp_ext); return; } #endif @@ -511,20 +546,18 @@ static void dec_msr(DisasContext *dc) case 1: msr_write(dc, cpu_R[dc->ra]); break; - case 0x3: - tcg_gen_mov_tl(cpu_SR[SR_EAR], cpu_R[dc->ra]); - break; - case 0x5: - tcg_gen_mov_tl(cpu_SR[SR_ESR], cpu_R[dc->ra]); - break; - case 0x7: - tcg_gen_andi_tl(cpu_SR[SR_FSR], cpu_R[dc->ra], 31); + case SR_EAR: + case SR_ESR: + case SR_FSR: + tcg_gen_extu_i32_i64(cpu_SR[sr], cpu_R[dc->ra]); break; case 0x800: - tcg_gen_st_tl(cpu_R[dc->ra], cpu_env, offsetof(CPUMBState, slr)); + tcg_gen_st_i32(cpu_R[dc->ra], + cpu_env, offsetof(CPUMBState, slr)); break; case 0x802: - tcg_gen_st_tl(cpu_R[dc->ra], cpu_env, offsetof(CPUMBState, shr)); + tcg_gen_st_i32(cpu_R[dc->ra], + cpu_env, offsetof(CPUMBState, shr)); break; default: cpu_abort(CPU(dc->cpu), "unknown mts reg %x\n", sr); @@ -535,44 +568,32 @@ static void dec_msr(DisasContext *dc) switch (sr) { case 0: - tcg_gen_movi_tl(cpu_R[dc->rd], dc->pc); + tcg_gen_movi_i32(cpu_R[dc->rd], dc->pc); break; case 1: msr_read(dc, cpu_R[dc->rd]); break; - case 0x3: - tcg_gen_mov_tl(cpu_R[dc->rd], cpu_SR[SR_EAR]); - break; - case 0x5: - tcg_gen_mov_tl(cpu_R[dc->rd], cpu_SR[SR_ESR]); - break; - case 0x7: - tcg_gen_mov_tl(cpu_R[dc->rd], cpu_SR[SR_FSR]); - break; - case 0xb: - tcg_gen_mov_tl(cpu_R[dc->rd], cpu_SR[SR_BTR]); + case SR_EAR: + if (extended) { + tcg_gen_extrh_i64_i32(cpu_R[dc->rd], cpu_SR[sr]); + break; + } + case SR_ESR: + case SR_FSR: + case SR_BTR: + tcg_gen_extrl_i64_i32(cpu_R[dc->rd], cpu_SR[sr]); break; case 0x800: - tcg_gen_ld_tl(cpu_R[dc->rd], cpu_env, offsetof(CPUMBState, slr)); + tcg_gen_ld_i32(cpu_R[dc->rd], + cpu_env, offsetof(CPUMBState, slr)); break; case 0x802: - tcg_gen_ld_tl(cpu_R[dc->rd], cpu_env, offsetof(CPUMBState, shr)); + tcg_gen_ld_i32(cpu_R[dc->rd], + cpu_env, offsetof(CPUMBState, shr)); break; - case 0x2000: - case 0x2001: - case 0x2002: - case 0x2003: - case 0x2004: - case 0x2005: - case 0x2006: - case 0x2007: - case 0x2008: - case 0x2009: - case 0x200a: - case 0x200b: - case 0x200c: + case 0x2000 ... 0x200c: rn = sr & 0xf; - tcg_gen_ld_tl(cpu_R[dc->rd], + tcg_gen_ld_i32(cpu_R[dc->rd], cpu_env, offsetof(CPUMBState, pvr.regs[rn])); break; default: @@ -582,21 +603,17 @@ static void dec_msr(DisasContext *dc) } if (dc->rd == 0) { - tcg_gen_movi_tl(cpu_R[0], 0); + tcg_gen_movi_i32(cpu_R[0], 0); } } /* Multiplier unit. */ static void dec_mul(DisasContext *dc) { - TCGv tmp; + TCGv_i32 tmp; unsigned int subcode; - if ((dc->tb_flags & MSR_EE_FLAG) - && (dc->cpu->env.pvr.regs[2] & PVR2_ILL_OPCODE_EXC_MASK) - && !dc->cpu->cfg.use_hw_mul) { - tcg_gen_movi_tl(cpu_SR[SR_ESR], ESR_EC_ILLEGAL_OP); - t_gen_raise_exception(dc, EXCP_HW_EXCP); + if (trap_illegal(dc, !dc->cpu->cfg.use_hw_mul)) { return; } @@ -604,7 +621,7 @@ static void dec_mul(DisasContext *dc) if (dc->type_b) { LOG_DIS("muli r%d r%d %x\n", dc->rd, dc->ra, dc->imm); - tcg_gen_mul_tl(cpu_R[dc->rd], cpu_R[dc->ra], *(dec_alu_op_b(dc))); + tcg_gen_mul_i32(cpu_R[dc->rd], cpu_R[dc->ra], *(dec_alu_op_b(dc))); return; } @@ -613,29 +630,31 @@ static void dec_mul(DisasContext *dc) /* nop??? */ } - tmp = tcg_temp_new(); + tmp = tcg_temp_new_i32(); switch (subcode) { case 0: LOG_DIS("mul r%d r%d r%d\n", dc->rd, dc->ra, dc->rb); - tcg_gen_mul_tl(cpu_R[dc->rd], cpu_R[dc->ra], cpu_R[dc->rb]); + tcg_gen_mul_i32(cpu_R[dc->rd], cpu_R[dc->ra], cpu_R[dc->rb]); break; case 1: LOG_DIS("mulh r%d r%d r%d\n", dc->rd, dc->ra, dc->rb); - tcg_gen_muls2_tl(tmp, cpu_R[dc->rd], cpu_R[dc->ra], cpu_R[dc->rb]); + tcg_gen_muls2_i32(tmp, cpu_R[dc->rd], + cpu_R[dc->ra], cpu_R[dc->rb]); break; case 2: LOG_DIS("mulhsu r%d r%d r%d\n", dc->rd, dc->ra, dc->rb); - tcg_gen_mulsu2_tl(tmp, cpu_R[dc->rd], cpu_R[dc->ra], cpu_R[dc->rb]); + tcg_gen_mulsu2_i32(tmp, cpu_R[dc->rd], + cpu_R[dc->ra], cpu_R[dc->rb]); break; case 3: LOG_DIS("mulhu r%d r%d r%d\n", dc->rd, dc->ra, dc->rb); - tcg_gen_mulu2_tl(tmp, cpu_R[dc->rd], cpu_R[dc->ra], cpu_R[dc->rb]); + tcg_gen_mulu2_i32(tmp, cpu_R[dc->rd], cpu_R[dc->ra], cpu_R[dc->rb]); break; default: cpu_abort(CPU(dc->cpu), "unknown MUL insn %x\n", subcode); break; } - tcg_temp_free(tmp); + tcg_temp_free_i32(tmp); } /* Div unit. */ @@ -646,10 +665,8 @@ static void dec_div(DisasContext *dc) u = dc->imm & 2; LOG_DIS("div\n"); - if ((dc->cpu->env.pvr.regs[2] & PVR2_ILL_OPCODE_EXC_MASK) - && !dc->cpu->cfg.use_div) { - tcg_gen_movi_tl(cpu_SR[SR_ESR], ESR_EC_ILLEGAL_OP); - t_gen_raise_exception(dc, EXCP_HW_EXCP); + if (trap_illegal(dc, !dc->cpu->cfg.use_div)) { + return; } if (u) @@ -659,20 +676,16 @@ static void dec_div(DisasContext *dc) gen_helper_divs(cpu_R[dc->rd], cpu_env, *(dec_alu_op_b(dc)), cpu_R[dc->ra]); if (!dc->rd) - tcg_gen_movi_tl(cpu_R[dc->rd], 0); + tcg_gen_movi_i32(cpu_R[dc->rd], 0); } static void dec_barrel(DisasContext *dc) { - TCGv t0; + TCGv_i32 t0; unsigned int imm_w, imm_s; bool s, t, e = false, i = false; - if ((dc->tb_flags & MSR_EE_FLAG) - && (dc->cpu->env.pvr.regs[2] & PVR2_ILL_OPCODE_EXC_MASK) - && !dc->cpu->cfg.use_barrel) { - tcg_gen_movi_tl(cpu_SR[SR_ESR], ESR_EC_ILLEGAL_OP); - t_gen_raise_exception(dc, EXCP_HW_EXCP); + if (trap_illegal(dc, !dc->cpu->cfg.use_barrel)) { return; } @@ -710,45 +723,45 @@ static void dec_barrel(DisasContext *dc) imm_s, width); } } else { - t0 = tcg_temp_new(); + t0 = tcg_temp_new_i32(); - tcg_gen_mov_tl(t0, *(dec_alu_op_b(dc))); - tcg_gen_andi_tl(t0, t0, 31); + tcg_gen_mov_i32(t0, *(dec_alu_op_b(dc))); + tcg_gen_andi_i32(t0, t0, 31); if (s) { - tcg_gen_shl_tl(cpu_R[dc->rd], cpu_R[dc->ra], t0); + tcg_gen_shl_i32(cpu_R[dc->rd], cpu_R[dc->ra], t0); } else { if (t) { - tcg_gen_sar_tl(cpu_R[dc->rd], cpu_R[dc->ra], t0); + tcg_gen_sar_i32(cpu_R[dc->rd], cpu_R[dc->ra], t0); } else { - tcg_gen_shr_tl(cpu_R[dc->rd], cpu_R[dc->ra], t0); + tcg_gen_shr_i32(cpu_R[dc->rd], cpu_R[dc->ra], t0); } } - tcg_temp_free(t0); + tcg_temp_free_i32(t0); } } static void dec_bit(DisasContext *dc) { CPUState *cs = CPU(dc->cpu); - TCGv t0; + TCGv_i32 t0; unsigned int op; - int mem_index = cpu_mmu_index(&dc->cpu->env, false); op = dc->ir & ((1 << 9) - 1); switch (op) { case 0x21: /* src. */ - t0 = tcg_temp_new(); + t0 = tcg_temp_new_i32(); LOG_DIS("src r%d r%d\n", dc->rd, dc->ra); - tcg_gen_andi_tl(t0, cpu_SR[SR_MSR], MSR_CC); + tcg_gen_extrl_i64_i32(t0, cpu_SR[SR_MSR]); + tcg_gen_andi_i32(t0, t0, MSR_CC); write_carry(dc, cpu_R[dc->ra]); if (dc->rd) { - tcg_gen_shri_tl(cpu_R[dc->rd], cpu_R[dc->ra], 1); - tcg_gen_or_tl(cpu_R[dc->rd], cpu_R[dc->rd], t0); + tcg_gen_shri_i32(cpu_R[dc->rd], cpu_R[dc->ra], 1); + tcg_gen_or_i32(cpu_R[dc->rd], cpu_R[dc->rd], t0); } - tcg_temp_free(t0); + tcg_temp_free_i32(t0); break; case 0x1: @@ -760,9 +773,9 @@ static void dec_bit(DisasContext *dc) write_carry(dc, cpu_R[dc->ra]); if (dc->rd) { if (op == 0x41) - tcg_gen_shri_tl(cpu_R[dc->rd], cpu_R[dc->ra], 1); + tcg_gen_shri_i32(cpu_R[dc->rd], cpu_R[dc->ra], 1); else - tcg_gen_sari_tl(cpu_R[dc->rd], cpu_R[dc->ra], 1); + tcg_gen_sari_i32(cpu_R[dc->rd], cpu_R[dc->ra], 1); } break; case 0x60: @@ -779,29 +792,16 @@ static void dec_bit(DisasContext *dc) case 0x76: /* wdc. */ LOG_DIS("wdc r%d\n", dc->ra); - if ((dc->tb_flags & MSR_EE_FLAG) - && mem_index == MMU_USER_IDX) { - tcg_gen_movi_tl(cpu_SR[SR_ESR], ESR_EC_PRIVINSN); - t_gen_raise_exception(dc, EXCP_HW_EXCP); - return; - } + trap_userspace(dc, true); break; case 0x68: /* wic. */ LOG_DIS("wic r%d\n", dc->ra); - if ((dc->tb_flags & MSR_EE_FLAG) - && mem_index == MMU_USER_IDX) { - tcg_gen_movi_tl(cpu_SR[SR_ESR], ESR_EC_PRIVINSN); - t_gen_raise_exception(dc, EXCP_HW_EXCP); - return; - } + trap_userspace(dc, true); break; case 0xe0: - if ((dc->tb_flags & MSR_EE_FLAG) - && (dc->cpu->env.pvr.regs[2] & PVR2_ILL_OPCODE_EXC_MASK) - && !dc->cpu->cfg.use_pcmp_instr) { - tcg_gen_movi_tl(cpu_SR[SR_ESR], ESR_EC_ILLEGAL_OP); - t_gen_raise_exception(dc, EXCP_HW_EXCP); + if (trap_illegal(dc, !dc->cpu->cfg.use_pcmp_instr)) { + return; } if (dc->cpu->cfg.use_pcmp_instr) { tcg_gen_clzi_i32(cpu_R[dc->rd], cpu_R[dc->ra], 32); @@ -828,101 +828,128 @@ static inline void sync_jmpstate(DisasContext *dc) { if (dc->jmp == JMP_DIRECT || dc->jmp == JMP_DIRECT_CC) { if (dc->jmp == JMP_DIRECT) { - tcg_gen_movi_tl(env_btaken, 1); + tcg_gen_movi_i32(env_btaken, 1); } dc->jmp = JMP_INDIRECT; - tcg_gen_movi_tl(env_btarget, dc->jmp_pc); + tcg_gen_movi_i64(env_btarget, dc->jmp_pc); } } static void dec_imm(DisasContext *dc) { LOG_DIS("imm %x\n", dc->imm << 16); - tcg_gen_movi_tl(env_imm, (dc->imm << 16)); + tcg_gen_movi_i32(env_imm, (dc->imm << 16)); dc->tb_flags |= IMM_FLAG; dc->clear_imm = 0; } -static inline TCGv *compute_ldst_addr(DisasContext *dc, TCGv *t) +static inline void compute_ldst_addr(DisasContext *dc, bool ea, TCGv t) { - unsigned int extimm = dc->tb_flags & IMM_FLAG; - /* Should be set to one if r1 is used by loadstores. */ - int stackprot = 0; + bool extimm = dc->tb_flags & IMM_FLAG; + /* Should be set to true if r1 is used by loadstores. */ + bool stackprot = false; + TCGv_i32 t32; /* All load/stores use ra. */ if (dc->ra == 1 && dc->cpu->cfg.stackprot) { - stackprot = 1; + stackprot = true; } /* Treat the common cases first. */ if (!dc->type_b) { - /* If any of the regs is r0, return a ptr to the other. */ + if (ea) { + int addr_size = dc->cpu->cfg.addr_size; + + if (addr_size == 32) { + tcg_gen_extu_i32_tl(t, cpu_R[dc->rb]); + return; + } + + tcg_gen_concat_i32_i64(t, cpu_R[dc->rb], cpu_R[dc->ra]); + if (addr_size < 64) { + /* Mask off out of range bits. */ + tcg_gen_andi_i64(t, t, MAKE_64BIT_MASK(0, addr_size)); + } + return; + } + + /* If any of the regs is r0, set t to the value of the other reg. */ if (dc->ra == 0) { - return &cpu_R[dc->rb]; + tcg_gen_extu_i32_tl(t, cpu_R[dc->rb]); + return; } else if (dc->rb == 0) { - return &cpu_R[dc->ra]; + tcg_gen_extu_i32_tl(t, cpu_R[dc->ra]); + return; } if (dc->rb == 1 && dc->cpu->cfg.stackprot) { - stackprot = 1; + stackprot = true; } - *t = tcg_temp_new(); - tcg_gen_add_tl(*t, cpu_R[dc->ra], cpu_R[dc->rb]); + t32 = tcg_temp_new_i32(); + tcg_gen_add_i32(t32, cpu_R[dc->ra], cpu_R[dc->rb]); + tcg_gen_extu_i32_tl(t, t32); + tcg_temp_free_i32(t32); if (stackprot) { - gen_helper_stackprot(cpu_env, *t); + gen_helper_stackprot(cpu_env, t); } - return t; + return; } /* Immediate. */ + t32 = tcg_temp_new_i32(); if (!extimm) { - if (dc->imm == 0) { - return &cpu_R[dc->ra]; - } - *t = tcg_temp_new(); - tcg_gen_movi_tl(*t, (int32_t)((int16_t)dc->imm)); - tcg_gen_add_tl(*t, cpu_R[dc->ra], *t); + tcg_gen_addi_i32(t32, cpu_R[dc->ra], (int16_t)dc->imm); } else { - *t = tcg_temp_new(); - tcg_gen_add_tl(*t, cpu_R[dc->ra], *(dec_alu_op_b(dc))); + tcg_gen_add_i32(t32, cpu_R[dc->ra], *(dec_alu_op_b(dc))); } + tcg_gen_extu_i32_tl(t, t32); + tcg_temp_free_i32(t32); if (stackprot) { - gen_helper_stackprot(cpu_env, *t); + gen_helper_stackprot(cpu_env, t); } - return t; + return; } static void dec_load(DisasContext *dc) { - TCGv t, v, *addr; - unsigned int size, rev = 0, ex = 0; + TCGv_i32 v; + TCGv addr; + unsigned int size; + bool rev = false, ex = false, ea = false; + int mem_index = cpu_mmu_index(&dc->cpu->env, false); TCGMemOp mop; mop = dc->opcode & 3; size = 1 << mop; if (!dc->type_b) { - rev = (dc->ir >> 9) & 1; - ex = (dc->ir >> 10) & 1; + ea = extract32(dc->ir, 7, 1); + rev = extract32(dc->ir, 9, 1); + ex = extract32(dc->ir, 10, 1); } mop |= MO_TE; if (rev) { mop ^= MO_BSWAP; } - if (size > 4 && (dc->tb_flags & MSR_EE_FLAG) - && (dc->cpu->env.pvr.regs[2] & PVR2_ILL_OPCODE_EXC_MASK)) { - tcg_gen_movi_tl(cpu_SR[SR_ESR], ESR_EC_ILLEGAL_OP); - t_gen_raise_exception(dc, EXCP_HW_EXCP); + if (trap_illegal(dc, size > 4)) { return; } - LOG_DIS("l%d%s%s%s\n", size, dc->type_b ? "i" : "", rev ? "r" : "", - ex ? "x" : ""); + if (trap_userspace(dc, ea)) { + return; + } + + LOG_DIS("l%d%s%s%s%s\n", size, dc->type_b ? "i" : "", rev ? "r" : "", + ex ? "x" : "", + ea ? "ea" : ""); t_sync_flags(dc); - addr = compute_ldst_addr(dc, &t); + addr = tcg_temp_new(); + compute_ldst_addr(dc, ea, addr); + /* Extended addressing bypasses the MMU. */ + mem_index = ea ? MMU_NOMMU_IDX : mem_index; /* * When doing reverse accesses we need to do two things. @@ -941,17 +968,10 @@ static void dec_load(DisasContext *dc) 11 -> 00 */ TCGv low = tcg_temp_new(); - /* Force addr into the temp. */ - if (addr != &t) { - t = tcg_temp_new(); - tcg_gen_mov_tl(t, *addr); - addr = &t; - } - - tcg_gen_andi_tl(low, t, 3); + tcg_gen_andi_tl(low, addr, 3); tcg_gen_sub_tl(low, tcg_const_tl(3), low); - tcg_gen_andi_tl(t, t, ~3); - tcg_gen_or_tl(t, t, low); + tcg_gen_andi_tl(addr, addr, ~3); + tcg_gen_or_tl(addr, addr, low); tcg_temp_free(low); break; } @@ -959,14 +979,7 @@ static void dec_load(DisasContext *dc) case 2: /* 00 -> 10 10 -> 00. */ - /* Force addr into the temp. */ - if (addr != &t) { - t = tcg_temp_new(); - tcg_gen_xori_tl(t, *addr, 2); - addr = &t; - } else { - tcg_gen_xori_tl(t, t, 2); - } + tcg_gen_xori_tl(addr, addr, 2); break; default: cpu_abort(CPU(dc->cpu), "Invalid reverse size\n"); @@ -976,13 +989,7 @@ static void dec_load(DisasContext *dc) /* lwx does not throw unaligned access errors, so force alignment */ if (ex) { - /* Force addr into the temp. */ - if (addr != &t) { - t = tcg_temp_new(); - tcg_gen_mov_tl(t, *addr); - addr = &t; - } - tcg_gen_andi_tl(t, t, ~3); + tcg_gen_andi_tl(addr, addr, ~3); } /* If we get a fault on a dslot, the jmpstate better be in sync. */ @@ -995,90 +1002,92 @@ static void dec_load(DisasContext *dc) * into v. If the load succeeds, we verify alignment of the * address and if that succeeds we write into the destination reg. */ - v = tcg_temp_new(); - tcg_gen_qemu_ld_tl(v, *addr, cpu_mmu_index(&dc->cpu->env, false), mop); + v = tcg_temp_new_i32(); + tcg_gen_qemu_ld_i32(v, addr, mem_index, mop); if ((dc->cpu->env.pvr.regs[2] & PVR2_UNALIGNED_EXC_MASK) && size > 1) { - tcg_gen_movi_tl(cpu_SR[SR_PC], dc->pc); - gen_helper_memalign(cpu_env, *addr, tcg_const_tl(dc->rd), - tcg_const_tl(0), tcg_const_tl(size - 1)); + tcg_gen_movi_i64(cpu_SR[SR_PC], dc->pc); + gen_helper_memalign(cpu_env, addr, tcg_const_i32(dc->rd), + tcg_const_i32(0), tcg_const_i32(size - 1)); } if (ex) { - tcg_gen_mov_tl(env_res_addr, *addr); - tcg_gen_mov_tl(env_res_val, v); + tcg_gen_mov_tl(env_res_addr, addr); + tcg_gen_mov_i32(env_res_val, v); } if (dc->rd) { - tcg_gen_mov_tl(cpu_R[dc->rd], v); + tcg_gen_mov_i32(cpu_R[dc->rd], v); } - tcg_temp_free(v); + tcg_temp_free_i32(v); if (ex) { /* lwx */ /* no support for AXI exclusive so always clear C */ write_carryi(dc, 0); } - if (addr == &t) - tcg_temp_free(t); + tcg_temp_free(addr); } static void dec_store(DisasContext *dc) { - TCGv t, *addr, swx_addr; + TCGv addr; TCGLabel *swx_skip = NULL; - unsigned int size, rev = 0, ex = 0; + unsigned int size; + bool rev = false, ex = false, ea = false; + int mem_index = cpu_mmu_index(&dc->cpu->env, false); TCGMemOp mop; mop = dc->opcode & 3; size = 1 << mop; if (!dc->type_b) { - rev = (dc->ir >> 9) & 1; - ex = (dc->ir >> 10) & 1; + ea = extract32(dc->ir, 7, 1); + rev = extract32(dc->ir, 9, 1); + ex = extract32(dc->ir, 10, 1); } mop |= MO_TE; if (rev) { mop ^= MO_BSWAP; } - if (size > 4 && (dc->tb_flags & MSR_EE_FLAG) - && (dc->cpu->env.pvr.regs[2] & PVR2_ILL_OPCODE_EXC_MASK)) { - tcg_gen_movi_tl(cpu_SR[SR_ESR], ESR_EC_ILLEGAL_OP); - t_gen_raise_exception(dc, EXCP_HW_EXCP); + if (trap_illegal(dc, size > 4)) { return; } - LOG_DIS("s%d%s%s%s\n", size, dc->type_b ? "i" : "", rev ? "r" : "", - ex ? "x" : ""); + trap_userspace(dc, ea); + + LOG_DIS("s%d%s%s%s%s\n", size, dc->type_b ? "i" : "", rev ? "r" : "", + ex ? "x" : "", + ea ? "ea" : ""); t_sync_flags(dc); /* If we get a fault on a dslot, the jmpstate better be in sync. */ sync_jmpstate(dc); - addr = compute_ldst_addr(dc, &t); + /* SWX needs a temp_local. */ + addr = ex ? tcg_temp_local_new() : tcg_temp_new(); + compute_ldst_addr(dc, ea, addr); + /* Extended addressing bypasses the MMU. */ + mem_index = ea ? MMU_NOMMU_IDX : mem_index; - swx_addr = tcg_temp_local_new(); if (ex) { /* swx */ - TCGv tval; + TCGv_i32 tval; - /* Force addr into the swx_addr. */ - tcg_gen_mov_tl(swx_addr, *addr); - addr = &swx_addr; /* swx does not throw unaligned access errors, so force alignment */ - tcg_gen_andi_tl(swx_addr, swx_addr, ~3); + tcg_gen_andi_tl(addr, addr, ~3); write_carryi(dc, 1); swx_skip = gen_new_label(); - tcg_gen_brcond_tl(TCG_COND_NE, env_res_addr, swx_addr, swx_skip); + tcg_gen_brcond_tl(TCG_COND_NE, env_res_addr, addr, swx_skip); /* Compare the value loaded at lwx with current contents of the reserved location. FIXME: This only works for system emulation where we can expect this compare and the following write to be atomic. For user emulation we need to add atomicity between threads. */ - tval = tcg_temp_new(); - tcg_gen_qemu_ld_tl(tval, swx_addr, cpu_mmu_index(&dc->cpu->env, false), - MO_TEUL); - tcg_gen_brcond_tl(TCG_COND_NE, env_res_val, tval, swx_skip); + tval = tcg_temp_new_i32(); + tcg_gen_qemu_ld_i32(tval, addr, cpu_mmu_index(&dc->cpu->env, false), + MO_TEUL); + tcg_gen_brcond_i32(TCG_COND_NE, env_res_val, tval, swx_skip); write_carryi(dc, 0); - tcg_temp_free(tval); + tcg_temp_free_i32(tval); } if (rev && size != 4) { @@ -1092,17 +1101,10 @@ static void dec_store(DisasContext *dc) 11 -> 00 */ TCGv low = tcg_temp_new(); - /* Force addr into the temp. */ - if (addr != &t) { - t = tcg_temp_new(); - tcg_gen_mov_tl(t, *addr); - addr = &t; - } - - tcg_gen_andi_tl(low, t, 3); + tcg_gen_andi_tl(low, addr, 3); tcg_gen_sub_tl(low, tcg_const_tl(3), low); - tcg_gen_andi_tl(t, t, ~3); - tcg_gen_or_tl(t, t, low); + tcg_gen_andi_tl(addr, addr, ~3); + tcg_gen_or_tl(addr, addr, low); tcg_temp_free(low); break; } @@ -1111,79 +1113,74 @@ static void dec_store(DisasContext *dc) /* 00 -> 10 10 -> 00. */ /* Force addr into the temp. */ - if (addr != &t) { - t = tcg_temp_new(); - tcg_gen_xori_tl(t, *addr, 2); - addr = &t; - } else { - tcg_gen_xori_tl(t, t, 2); - } + tcg_gen_xori_tl(addr, addr, 2); break; default: cpu_abort(CPU(dc->cpu), "Invalid reverse size\n"); break; } } - tcg_gen_qemu_st_tl(cpu_R[dc->rd], *addr, cpu_mmu_index(&dc->cpu->env, false), mop); + tcg_gen_qemu_st_i32(cpu_R[dc->rd], addr, mem_index, mop); /* Verify alignment if needed. */ if ((dc->cpu->env.pvr.regs[2] & PVR2_UNALIGNED_EXC_MASK) && size > 1) { - tcg_gen_movi_tl(cpu_SR[SR_PC], dc->pc); + tcg_gen_movi_i64(cpu_SR[SR_PC], dc->pc); /* FIXME: if the alignment is wrong, we should restore the value * in memory. One possible way to achieve this is to probe * the MMU prior to the memaccess, thay way we could put * the alignment checks in between the probe and the mem * access. */ - gen_helper_memalign(cpu_env, *addr, tcg_const_tl(dc->rd), - tcg_const_tl(1), tcg_const_tl(size - 1)); + gen_helper_memalign(cpu_env, addr, tcg_const_i32(dc->rd), + tcg_const_i32(1), tcg_const_i32(size - 1)); } if (ex) { gen_set_label(swx_skip); } - tcg_temp_free(swx_addr); - if (addr == &t) - tcg_temp_free(t); + tcg_temp_free(addr); } static inline void eval_cc(DisasContext *dc, unsigned int cc, - TCGv d, TCGv a, TCGv b) + TCGv_i32 d, TCGv_i32 a) { + static const int mb_to_tcg_cc[] = { + [CC_EQ] = TCG_COND_EQ, + [CC_NE] = TCG_COND_NE, + [CC_LT] = TCG_COND_LT, + [CC_LE] = TCG_COND_LE, + [CC_GE] = TCG_COND_GE, + [CC_GT] = TCG_COND_GT, + }; + switch (cc) { - case CC_EQ: - tcg_gen_setcond_tl(TCG_COND_EQ, d, a, b); - break; - case CC_NE: - tcg_gen_setcond_tl(TCG_COND_NE, d, a, b); - break; - case CC_LT: - tcg_gen_setcond_tl(TCG_COND_LT, d, a, b); - break; - case CC_LE: - tcg_gen_setcond_tl(TCG_COND_LE, d, a, b); - break; - case CC_GE: - tcg_gen_setcond_tl(TCG_COND_GE, d, a, b); - break; - case CC_GT: - tcg_gen_setcond_tl(TCG_COND_GT, d, a, b); - break; - default: - cpu_abort(CPU(dc->cpu), "Unknown condition code %x.\n", cc); - break; + case CC_EQ: + case CC_NE: + case CC_LT: + case CC_LE: + case CC_GE: + case CC_GT: + tcg_gen_setcondi_i32(mb_to_tcg_cc[cc], d, a, 0); + break; + default: + cpu_abort(CPU(dc->cpu), "Unknown condition code %x.\n", cc); + break; } } -static void eval_cond_jmp(DisasContext *dc, TCGv pc_true, TCGv pc_false) +static void eval_cond_jmp(DisasContext *dc, TCGv_i64 pc_true, TCGv_i64 pc_false) { - TCGLabel *l1 = gen_new_label(); - /* Conditional jmp. */ - tcg_gen_mov_tl(cpu_SR[SR_PC], pc_false); - tcg_gen_brcondi_tl(TCG_COND_EQ, env_btaken, 0, l1); - tcg_gen_mov_tl(cpu_SR[SR_PC], pc_true); - gen_set_label(l1); + TCGv_i64 tmp_btaken = tcg_temp_new_i64(); + TCGv_i64 tmp_zero = tcg_const_i64(0); + + tcg_gen_extu_i32_i64(tmp_btaken, env_btaken); + tcg_gen_movcond_i64(TCG_COND_NE, cpu_SR[SR_PC], + tmp_btaken, tmp_zero, + pc_true, pc_false); + + tcg_temp_free_i64(tmp_btaken); + tcg_temp_free_i64(tmp_zero); } static void dec_bcc(DisasContext *dc) @@ -1199,28 +1196,28 @@ static void dec_bcc(DisasContext *dc) if (dslot) { dc->delayed_branch = 2; dc->tb_flags |= D_FLAG; - tcg_gen_st_tl(tcg_const_tl(dc->type_b && (dc->tb_flags & IMM_FLAG)), + tcg_gen_st_i32(tcg_const_i32(dc->type_b && (dc->tb_flags & IMM_FLAG)), cpu_env, offsetof(CPUMBState, bimm)); } if (dec_alu_op_b_is_small_imm(dc)) { int32_t offset = (int32_t)((int16_t)dc->imm); /* sign-extend. */ - tcg_gen_movi_tl(env_btarget, dc->pc + offset); + tcg_gen_movi_i64(env_btarget, dc->pc + offset); dc->jmp = JMP_DIRECT_CC; dc->jmp_pc = dc->pc + offset; } else { dc->jmp = JMP_INDIRECT; - tcg_gen_movi_tl(env_btarget, dc->pc); - tcg_gen_add_tl(env_btarget, env_btarget, *(dec_alu_op_b(dc))); + tcg_gen_extu_i32_i64(env_btarget, *(dec_alu_op_b(dc))); + tcg_gen_addi_i64(env_btarget, env_btarget, dc->pc); + tcg_gen_andi_i64(env_btarget, env_btarget, UINT32_MAX); } - eval_cc(dc, cc, env_btaken, cpu_R[dc->ra], tcg_const_tl(0)); + eval_cc(dc, cc, env_btaken, cpu_R[dc->ra]); } static void dec_br(DisasContext *dc) { unsigned int dslot, link, abs, mbar; - int mem_index = cpu_mmu_index(&dc->cpu->env, false); dslot = dc->ir & (1 << 20); abs = dc->ir & (1 << 19); @@ -1240,7 +1237,7 @@ static void dec_br(DisasContext *dc) tcg_gen_st_i32(tmp_1, cpu_env, -offsetof(MicroBlazeCPU, env) +offsetof(CPUState, halted)); - tcg_gen_movi_tl(cpu_SR[SR_PC], dc->pc + 4); + tcg_gen_movi_i64(cpu_SR[SR_PC], dc->pc + 4); gen_helper_raise_exception(cpu_env, tmp_hlt); tcg_temp_free_i32(tmp_hlt); tcg_temp_free_i32(tmp_1); @@ -1261,23 +1258,21 @@ static void dec_br(DisasContext *dc) if (dslot) { dc->delayed_branch = 2; dc->tb_flags |= D_FLAG; - tcg_gen_st_tl(tcg_const_tl(dc->type_b && (dc->tb_flags & IMM_FLAG)), + tcg_gen_st_i32(tcg_const_i32(dc->type_b && (dc->tb_flags & IMM_FLAG)), cpu_env, offsetof(CPUMBState, bimm)); } if (link && dc->rd) - tcg_gen_movi_tl(cpu_R[dc->rd], dc->pc); + tcg_gen_movi_i32(cpu_R[dc->rd], dc->pc); dc->jmp = JMP_INDIRECT; if (abs) { - tcg_gen_movi_tl(env_btaken, 1); - tcg_gen_mov_tl(env_btarget, *(dec_alu_op_b(dc))); + tcg_gen_movi_i32(env_btaken, 1); + tcg_gen_extu_i32_i64(env_btarget, *(dec_alu_op_b(dc))); if (link && !dslot) { if (!(dc->tb_flags & IMM_FLAG) && (dc->imm == 8 || dc->imm == 0x18)) t_gen_raise_exception(dc, EXCP_BREAK); if (dc->imm == 0) { - if ((dc->tb_flags & MSR_EE_FLAG) && mem_index == MMU_USER_IDX) { - tcg_gen_movi_tl(cpu_SR[SR_ESR], ESR_EC_PRIVINSN); - t_gen_raise_exception(dc, EXCP_HW_EXCP); + if (trap_userspace(dc, true)) { return; } @@ -1289,116 +1284,115 @@ static void dec_br(DisasContext *dc) dc->jmp = JMP_DIRECT; dc->jmp_pc = dc->pc + (int32_t)((int16_t)dc->imm); } else { - tcg_gen_movi_tl(env_btaken, 1); - tcg_gen_movi_tl(env_btarget, dc->pc); - tcg_gen_add_tl(env_btarget, env_btarget, *(dec_alu_op_b(dc))); + tcg_gen_movi_i32(env_btaken, 1); + tcg_gen_extu_i32_i64(env_btarget, *(dec_alu_op_b(dc))); + tcg_gen_addi_i64(env_btarget, env_btarget, dc->pc); + tcg_gen_andi_i64(env_btarget, env_btarget, UINT32_MAX); } } } static inline void do_rti(DisasContext *dc) { - TCGv t0, t1; - t0 = tcg_temp_new(); - t1 = tcg_temp_new(); - tcg_gen_shri_tl(t0, cpu_SR[SR_MSR], 1); - tcg_gen_ori_tl(t1, cpu_SR[SR_MSR], MSR_IE); - tcg_gen_andi_tl(t0, t0, (MSR_VM | MSR_UM)); - - tcg_gen_andi_tl(t1, t1, ~(MSR_VM | MSR_UM)); - tcg_gen_or_tl(t1, t1, t0); + TCGv_i32 t0, t1; + t0 = tcg_temp_new_i32(); + t1 = tcg_temp_new_i32(); + tcg_gen_extrl_i64_i32(t1, cpu_SR[SR_MSR]); + tcg_gen_shri_i32(t0, t1, 1); + tcg_gen_ori_i32(t1, t1, MSR_IE); + tcg_gen_andi_i32(t0, t0, (MSR_VM | MSR_UM)); + + tcg_gen_andi_i32(t1, t1, ~(MSR_VM | MSR_UM)); + tcg_gen_or_i32(t1, t1, t0); msr_write(dc, t1); - tcg_temp_free(t1); - tcg_temp_free(t0); + tcg_temp_free_i32(t1); + tcg_temp_free_i32(t0); dc->tb_flags &= ~DRTI_FLAG; } static inline void do_rtb(DisasContext *dc) { - TCGv t0, t1; - t0 = tcg_temp_new(); - t1 = tcg_temp_new(); - tcg_gen_andi_tl(t1, cpu_SR[SR_MSR], ~MSR_BIP); - tcg_gen_shri_tl(t0, t1, 1); - tcg_gen_andi_tl(t0, t0, (MSR_VM | MSR_UM)); - - tcg_gen_andi_tl(t1, t1, ~(MSR_VM | MSR_UM)); - tcg_gen_or_tl(t1, t1, t0); + TCGv_i32 t0, t1; + t0 = tcg_temp_new_i32(); + t1 = tcg_temp_new_i32(); + tcg_gen_extrl_i64_i32(t1, cpu_SR[SR_MSR]); + tcg_gen_andi_i32(t1, t1, ~MSR_BIP); + tcg_gen_shri_i32(t0, t1, 1); + tcg_gen_andi_i32(t0, t0, (MSR_VM | MSR_UM)); + + tcg_gen_andi_i32(t1, t1, ~(MSR_VM | MSR_UM)); + tcg_gen_or_i32(t1, t1, t0); msr_write(dc, t1); - tcg_temp_free(t1); - tcg_temp_free(t0); + tcg_temp_free_i32(t1); + tcg_temp_free_i32(t0); dc->tb_flags &= ~DRTB_FLAG; } static inline void do_rte(DisasContext *dc) { - TCGv t0, t1; - t0 = tcg_temp_new(); - t1 = tcg_temp_new(); - - tcg_gen_ori_tl(t1, cpu_SR[SR_MSR], MSR_EE); - tcg_gen_andi_tl(t1, t1, ~MSR_EIP); - tcg_gen_shri_tl(t0, t1, 1); - tcg_gen_andi_tl(t0, t0, (MSR_VM | MSR_UM)); - - tcg_gen_andi_tl(t1, t1, ~(MSR_VM | MSR_UM)); - tcg_gen_or_tl(t1, t1, t0); + TCGv_i32 t0, t1; + t0 = tcg_temp_new_i32(); + t1 = tcg_temp_new_i32(); + + tcg_gen_extrl_i64_i32(t1, cpu_SR[SR_MSR]); + tcg_gen_ori_i32(t1, t1, MSR_EE); + tcg_gen_andi_i32(t1, t1, ~MSR_EIP); + tcg_gen_shri_i32(t0, t1, 1); + tcg_gen_andi_i32(t0, t0, (MSR_VM | MSR_UM)); + + tcg_gen_andi_i32(t1, t1, ~(MSR_VM | MSR_UM)); + tcg_gen_or_i32(t1, t1, t0); msr_write(dc, t1); - tcg_temp_free(t1); - tcg_temp_free(t0); + tcg_temp_free_i32(t1); + tcg_temp_free_i32(t0); dc->tb_flags &= ~DRTE_FLAG; } static void dec_rts(DisasContext *dc) { unsigned int b_bit, i_bit, e_bit; - int mem_index = cpu_mmu_index(&dc->cpu->env, false); + TCGv_i64 tmp64; i_bit = dc->ir & (1 << 21); b_bit = dc->ir & (1 << 22); e_bit = dc->ir & (1 << 23); + if (trap_userspace(dc, i_bit || b_bit || e_bit)) { + return; + } + dc->delayed_branch = 2; dc->tb_flags |= D_FLAG; - tcg_gen_st_tl(tcg_const_tl(dc->type_b && (dc->tb_flags & IMM_FLAG)), + tcg_gen_st_i32(tcg_const_i32(dc->type_b && (dc->tb_flags & IMM_FLAG)), cpu_env, offsetof(CPUMBState, bimm)); if (i_bit) { LOG_DIS("rtid ir=%x\n", dc->ir); - if ((dc->tb_flags & MSR_EE_FLAG) - && mem_index == MMU_USER_IDX) { - tcg_gen_movi_tl(cpu_SR[SR_ESR], ESR_EC_PRIVINSN); - t_gen_raise_exception(dc, EXCP_HW_EXCP); - } dc->tb_flags |= DRTI_FLAG; } else if (b_bit) { LOG_DIS("rtbd ir=%x\n", dc->ir); - if ((dc->tb_flags & MSR_EE_FLAG) - && mem_index == MMU_USER_IDX) { - tcg_gen_movi_tl(cpu_SR[SR_ESR], ESR_EC_PRIVINSN); - t_gen_raise_exception(dc, EXCP_HW_EXCP); - } dc->tb_flags |= DRTB_FLAG; } else if (e_bit) { LOG_DIS("rted ir=%x\n", dc->ir); - if ((dc->tb_flags & MSR_EE_FLAG) - && mem_index == MMU_USER_IDX) { - tcg_gen_movi_tl(cpu_SR[SR_ESR], ESR_EC_PRIVINSN); - t_gen_raise_exception(dc, EXCP_HW_EXCP); - } dc->tb_flags |= DRTE_FLAG; } else LOG_DIS("rts ir=%x\n", dc->ir); dc->jmp = JMP_INDIRECT; - tcg_gen_movi_tl(env_btaken, 1); - tcg_gen_add_tl(env_btarget, cpu_R[dc->ra], *(dec_alu_op_b(dc))); + tcg_gen_movi_i32(env_btaken, 1); + + tmp64 = tcg_temp_new_i64(); + tcg_gen_extu_i32_i64(env_btarget, *(dec_alu_op_b(dc))); + tcg_gen_extu_i32_i64(tmp64, cpu_R[dc->ra]); + tcg_gen_add_i64(env_btarget, env_btarget, tmp64); + tcg_gen_andi_i64(env_btarget, env_btarget, UINT32_MAX); + tcg_temp_free_i64(tmp64); } static int dec_check_fpuv2(DisasContext *dc) { if ((dc->cpu->cfg.use_fpu != 2) && (dc->tb_flags & MSR_EE_FLAG)) { - tcg_gen_movi_tl(cpu_SR[SR_ESR], ESR_EC_FPU); + tcg_gen_movi_i64(cpu_SR[SR_ESR], ESR_EC_FPU); t_gen_raise_exception(dc, EXCP_HW_EXCP); } return (dc->cpu->cfg.use_fpu == 2) ? 0 : PVR2_USE_FPU2_MASK; @@ -1408,11 +1402,7 @@ static void dec_fpu(DisasContext *dc) { unsigned int fpu_insn; - if ((dc->tb_flags & MSR_EE_FLAG) - && (dc->cpu->env.pvr.regs[2] & PVR2_ILL_OPCODE_EXC_MASK) - && !dc->cpu->cfg.use_fpu) { - tcg_gen_movi_tl(cpu_SR[SR_ESR], ESR_EC_ILLEGAL_OP); - t_gen_raise_exception(dc, EXCP_HW_EXCP); + if (trap_illegal(dc, !dc->cpu->cfg.use_fpu)) { return; } @@ -1511,10 +1501,7 @@ static void dec_fpu(DisasContext *dc) static void dec_null(DisasContext *dc) { - if ((dc->tb_flags & MSR_EE_FLAG) - && (dc->cpu->env.pvr.regs[2] & PVR2_ILL_OPCODE_EXC_MASK)) { - tcg_gen_movi_tl(cpu_SR[SR_ESR], ESR_EC_ILLEGAL_OP); - t_gen_raise_exception(dc, EXCP_HW_EXCP); + if (trap_illegal(dc, true)) { return; } qemu_log_mask(LOG_GUEST_ERROR, "unknown insn pc=%x opc=%x\n", dc->pc, dc->opcode); @@ -1524,37 +1511,34 @@ static void dec_null(DisasContext *dc) /* Insns connected to FSL or AXI stream attached devices. */ static void dec_stream(DisasContext *dc) { - int mem_index = cpu_mmu_index(&dc->cpu->env, false); TCGv_i32 t_id, t_ctrl; int ctrl; LOG_DIS("%s%s imm=%x\n", dc->rd ? "get" : "put", dc->type_b ? "" : "d", dc->imm); - if ((dc->tb_flags & MSR_EE_FLAG) && (mem_index == MMU_USER_IDX)) { - tcg_gen_movi_tl(cpu_SR[SR_ESR], ESR_EC_PRIVINSN); - t_gen_raise_exception(dc, EXCP_HW_EXCP); + if (trap_userspace(dc, true)) { return; } - t_id = tcg_temp_new(); + t_id = tcg_temp_new_i32(); if (dc->type_b) { - tcg_gen_movi_tl(t_id, dc->imm & 0xf); + tcg_gen_movi_i32(t_id, dc->imm & 0xf); ctrl = dc->imm >> 10; } else { - tcg_gen_andi_tl(t_id, cpu_R[dc->rb], 0xf); + tcg_gen_andi_i32(t_id, cpu_R[dc->rb], 0xf); ctrl = dc->imm >> 5; } - t_ctrl = tcg_const_tl(ctrl); + t_ctrl = tcg_const_i32(ctrl); if (dc->rd == 0) { gen_helper_put(t_id, t_ctrl, cpu_R[dc->ra]); } else { gen_helper_get(cpu_R[dc->rd], t_id, t_ctrl); } - tcg_temp_free(t_id); - tcg_temp_free(t_ctrl); + tcg_temp_free_i32(t_id); + tcg_temp_free_i32(t_ctrl); } static struct decoder_info { @@ -1595,13 +1579,7 @@ static inline void decode(DisasContext *dc, uint32_t ir) if (dc->ir) dc->nr_nops = 0; else { - if ((dc->tb_flags & MSR_EE_FLAG) - && (dc->cpu->env.pvr.regs[2] & PVR2_ILL_OPCODE_EXC_MASK) - && (dc->cpu->env.pvr.regs[2] & PVR2_OPCODE_0x0_ILL_MASK)) { - tcg_gen_movi_tl(cpu_SR[SR_ESR], ESR_EC_ILLEGAL_OP); - t_gen_raise_exception(dc, EXCP_HW_EXCP); - return; - } + trap_illegal(dc, dc->cpu->env.pvr.regs[2] & PVR2_OPCODE_0x0_ILL_MASK); LOG_DIS("nr_nops=%d\t", dc->nr_nops); dc->nr_nops++; @@ -1636,7 +1614,7 @@ void gen_intermediate_code(CPUState *cs, struct TranslationBlock *tb) struct DisasContext ctx; struct DisasContext *dc = &ctx; uint32_t page_start, org_flags; - target_ulong npc; + uint32_t npc; int num_insns; int max_insns; @@ -1679,7 +1657,7 @@ void gen_intermediate_code(CPUState *cs, struct TranslationBlock *tb) #if SIM_COMPAT if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) { - tcg_gen_movi_tl(cpu_SR[SR_PC], dc->pc); + tcg_gen_movi_i64(cpu_SR[SR_PC], dc->pc); gen_helper_debug(); } #endif @@ -1721,7 +1699,7 @@ void gen_intermediate_code(CPUState *cs, struct TranslationBlock *tb) dc->tb_flags &= ~D_FLAG; /* If it is a direct jump, try direct chaining. */ if (dc->jmp == JMP_INDIRECT) { - eval_cond_jmp(dc, env_btarget, tcg_const_tl(dc->pc)); + eval_cond_jmp(dc, env_btarget, tcg_const_i64(dc->pc)); dc->is_jmp = DISAS_JUMP; } else if (dc->jmp == JMP_DIRECT) { t_sync_flags(dc); @@ -1731,7 +1709,7 @@ void gen_intermediate_code(CPUState *cs, struct TranslationBlock *tb) TCGLabel *l1 = gen_new_label(); t_sync_flags(dc); /* Conditional jmp. */ - tcg_gen_brcondi_tl(TCG_COND_NE, env_btaken, 0, l1); + tcg_gen_brcondi_i32(TCG_COND_NE, env_btaken, 0, l1); gen_goto_tb(dc, 1, dc->pc); gen_set_label(l1); gen_goto_tb(dc, 0, dc->jmp_pc); @@ -1754,7 +1732,7 @@ void gen_intermediate_code(CPUState *cs, struct TranslationBlock *tb) if (dc->jmp == JMP_DIRECT || dc->jmp == JMP_DIRECT_CC) { if (dc->tb_flags & D_FLAG) { dc->is_jmp = DISAS_UPDATE; - tcg_gen_movi_tl(cpu_SR[SR_PC], npc); + tcg_gen_movi_i64(cpu_SR[SR_PC], npc); sync_jmpstate(dc); } else npc = dc->jmp_pc; @@ -1766,7 +1744,7 @@ void gen_intermediate_code(CPUState *cs, struct TranslationBlock *tb) if (dc->is_jmp == DISAS_NEXT && (dc->cpustate_changed || org_flags != dc->tb_flags)) { dc->is_jmp = DISAS_UPDATE; - tcg_gen_movi_tl(cpu_SR[SR_PC], npc); + tcg_gen_movi_i64(cpu_SR[SR_PC], npc); } t_sync_flags(dc); @@ -1774,7 +1752,7 @@ void gen_intermediate_code(CPUState *cs, struct TranslationBlock *tb) TCGv_i32 tmp = tcg_const_i32(EXCP_DEBUG); if (dc->is_jmp != DISAS_JUMP) { - tcg_gen_movi_tl(cpu_SR[SR_PC], npc); + tcg_gen_movi_i64(cpu_SR[SR_PC], npc); } gen_helper_raise_exception(cpu_env, tmp); tcg_temp_free_i32(tmp); @@ -1824,17 +1802,19 @@ void mb_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf, if (!env || !f) return; - cpu_fprintf(f, "IN: PC=%x %s\n", + cpu_fprintf(f, "IN: PC=%" PRIx64 " %s\n", env->sregs[SR_PC], lookup_symbol(env->sregs[SR_PC])); - cpu_fprintf(f, "rmsr=%x resr=%x rear=%x debug=%x imm=%x iflags=%x fsr=%x\n", + cpu_fprintf(f, "rmsr=%" PRIx64 " resr=%" PRIx64 " rear=%" PRIx64 " " + "debug=%x imm=%x iflags=%x fsr=%" PRIx64 "\n", env->sregs[SR_MSR], env->sregs[SR_ESR], env->sregs[SR_EAR], env->debug, env->imm, env->iflags, env->sregs[SR_FSR]); - cpu_fprintf(f, "btaken=%d btarget=%x mode=%s(saved=%s) eip=%d ie=%d\n", + cpu_fprintf(f, "btaken=%d btarget=%" PRIx64 " mode=%s(saved=%s) " + "eip=%d ie=%d\n", env->btaken, env->btarget, (env->sregs[SR_MSR] & MSR_UM) ? "user" : "kernel", (env->sregs[SR_MSR] & MSR_UMS) ? "user" : "kernel", - (env->sregs[SR_MSR] & MSR_EIP), - (env->sregs[SR_MSR] & MSR_IE)); + (bool)(env->sregs[SR_MSR] & MSR_EIP), + (bool)(env->sregs[SR_MSR] & MSR_IE)); for (i = 0; i < 32; i++) { cpu_fprintf(f, "r%2.2d=%8.8x ", i, env->regs[i]); @@ -1848,34 +1828,34 @@ void mb_tcg_init(void) { int i; - env_debug = tcg_global_mem_new(cpu_env, + env_debug = tcg_global_mem_new_i32(cpu_env, offsetof(CPUMBState, debug), "debug0"); - env_iflags = tcg_global_mem_new(cpu_env, + env_iflags = tcg_global_mem_new_i32(cpu_env, offsetof(CPUMBState, iflags), "iflags"); - env_imm = tcg_global_mem_new(cpu_env, + env_imm = tcg_global_mem_new_i32(cpu_env, offsetof(CPUMBState, imm), "imm"); - env_btarget = tcg_global_mem_new(cpu_env, + env_btarget = tcg_global_mem_new_i64(cpu_env, offsetof(CPUMBState, btarget), "btarget"); - env_btaken = tcg_global_mem_new(cpu_env, + env_btaken = tcg_global_mem_new_i32(cpu_env, offsetof(CPUMBState, btaken), "btaken"); env_res_addr = tcg_global_mem_new(cpu_env, offsetof(CPUMBState, res_addr), "res_addr"); - env_res_val = tcg_global_mem_new(cpu_env, + env_res_val = tcg_global_mem_new_i32(cpu_env, offsetof(CPUMBState, res_val), "res_val"); for (i = 0; i < ARRAY_SIZE(cpu_R); i++) { - cpu_R[i] = tcg_global_mem_new(cpu_env, + cpu_R[i] = tcg_global_mem_new_i32(cpu_env, offsetof(CPUMBState, regs[i]), regnames[i]); } for (i = 0; i < ARRAY_SIZE(cpu_SR); i++) { - cpu_SR[i] = tcg_global_mem_new(cpu_env, + cpu_SR[i] = tcg_global_mem_new_i64(cpu_env, offsetof(CPUMBState, sregs[i]), special_regnames[i]); } |