diff options
author | Peter Maydell <peter.maydell@linaro.org> | 2017-07-04 13:05:30 +0100 |
---|---|---|
committer | Peter Maydell <peter.maydell@linaro.org> | 2017-07-04 13:05:30 +0100 |
commit | 2185c93ba80f81bfa27ce6f259c7f2ef4f08b668 (patch) | |
tree | f2bfba6f066e0f5da675ad95bf1cb2df4921a5c0 /target | |
parent | 0c7a8b9baa744ae4323bb46cb4fe942355beaa85 (diff) | |
parent | 31cf950ea2a010c33e5384aaba91f01dc27c1599 (diff) |
Merge remote-tracking branch 'remotes/edgar/tags/edgar/xilinx-next.for-upstream' into staging
edgar/xilinx-next.for-upstream
# gpg: Signature made Tue 04 Jul 2017 10:00:47 BST
# gpg: using RSA key 0x29C596780F6BCA83
# 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.for-upstream:
xilinx-dp: Add support for the yuy2 video format
target-microblaze: Add CPU version 10.0
target-microblaze: dec_barrel: Add BSIFI
target-microblaze: dec_barrel: Add BSEFI
target-microblaze: dec_barrel: Plug TCG temp leak
target-microblaze: dec_barrel: Add braces around if-statements
target-microblaze: dec_barrel: Use extract32
target-microblaze: dec_barrel: Use bool instead of unsigned int
target-microblaze: Introduce a use-pcmp-instr property
target-microblaze: Introduce a use-msr-instr property
target-microblaze: Introduce a use-hw-mul property
target-microblaze: Introduce a use-div property
target-microblaze: Introduce a use-barrel property
target-microblaze: Add CPU versions 9.4, 9.5 and 9.6
target-microblaze: Don't hard code 0xb as initial MB version
target-microblaze: Correct bit shift for the PVR0 version field
disas/microblaze: Add missing 'const' attributes
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'target')
-rw-r--r-- | target/microblaze/cpu.c | 39 | ||||
-rw-r--r-- | target/microblaze/cpu.h | 7 | ||||
-rw-r--r-- | target/microblaze/translate.c | 77 |
3 files changed, 86 insertions, 37 deletions
diff --git a/target/microblaze/cpu.c b/target/microblaze/cpu.c index 3d58869716..f85ff01b39 100644 --- a/target/microblaze/cpu.c +++ b/target/microblaze/cpu.c @@ -64,6 +64,10 @@ static const struct { {"9.1", 0x1D}, {"9.2", 0x1F}, {"9.3", 0x20}, + {"9.4", 0x21}, + {"9.5", 0x22}, + {"9.6", 0x23}, + {"10.0", 0x24}, {NULL, 0}, }; @@ -147,23 +151,13 @@ static void mb_cpu_realizefn(DeviceState *dev, Error **errp) qemu_init_vcpu(cs); - env->pvr.regs[0] = PVR0_USE_BARREL_MASK \ - | PVR0_USE_DIV_MASK \ - | PVR0_USE_HW_MUL_MASK \ - | PVR0_USE_EXC_MASK \ + env->pvr.regs[0] = PVR0_USE_EXC_MASK \ | PVR0_USE_ICACHE_MASK \ - | PVR0_USE_DCACHE_MASK \ - | (0xb << 8); + | PVR0_USE_DCACHE_MASK; env->pvr.regs[2] = PVR2_D_OPB_MASK \ | PVR2_D_LMB_MASK \ | PVR2_I_OPB_MASK \ | PVR2_I_LMB_MASK \ - | PVR2_USE_MSR_INSTR \ - | PVR2_USE_PCMP_INSTR \ - | PVR2_USE_BARREL_MASK \ - | PVR2_USE_DIV_MASK \ - | PVR2_USE_HW_MUL_MASK \ - | PVR2_USE_MUL64_MASK \ | PVR2_FPU_EXC_MASK \ | 0; @@ -180,13 +174,22 @@ static void mb_cpu_realizefn(DeviceState *dev, Error **errp) env->pvr.regs[0] |= (cpu->cfg.stackprot ? PVR0_SPROT_MASK : 0) | (cpu->cfg.use_fpu ? PVR0_USE_FPU_MASK : 0) | + (cpu->cfg.use_hw_mul ? PVR0_USE_HW_MUL_MASK : 0) | + (cpu->cfg.use_barrel ? PVR0_USE_BARREL_MASK : 0) | + (cpu->cfg.use_div ? PVR0_USE_DIV_MASK : 0) | (cpu->cfg.use_mmu ? PVR0_USE_MMU_MASK : 0) | (cpu->cfg.endi ? PVR0_ENDI_MASK : 0) | - (version_code << 16) | + (version_code << PVR0_VERSION_SHIFT) | (cpu->cfg.pvr == C_PVR_FULL ? PVR0_PVR_FULL_MASK : 0); env->pvr.regs[2] |= (cpu->cfg.use_fpu ? PVR2_USE_FPU_MASK : 0) | - (cpu->cfg.use_fpu > 1 ? PVR2_USE_FPU2_MASK : 0); + (cpu->cfg.use_fpu > 1 ? PVR2_USE_FPU2_MASK : 0) | + (cpu->cfg.use_hw_mul ? PVR2_USE_HW_MUL_MASK : 0) | + (cpu->cfg.use_hw_mul > 1 ? PVR2_USE_MUL64_MASK : 0) | + (cpu->cfg.use_barrel ? PVR2_USE_BARREL_MASK : 0) | + (cpu->cfg.use_div ? PVR2_USE_DIV_MASK : 0) | + (cpu->cfg.use_msr_instr ? PVR2_USE_MSR_INSTR : 0) | + (cpu->cfg.use_pcmp_instr ? PVR2_USE_PCMP_INSTR : 0); env->pvr.regs[5] |= cpu->cfg.dcache_writeback ? PVR5_DCACHE_WRITEBACK_MASK : 0; @@ -233,6 +236,14 @@ static Property mb_properties[] = { * are enabled */ DEFINE_PROP_UINT8("use-fpu", MicroBlazeCPU, cfg.use_fpu, 2), + /* If use-hw-mul > 0 - Multiplier is enabled + * If use-hw-mul = 2 - 64-bit multiplier is enabled + */ + DEFINE_PROP_UINT8("use-hw-mul", MicroBlazeCPU, cfg.use_hw_mul, 2), + DEFINE_PROP_BOOL("use-barrel", MicroBlazeCPU, cfg.use_barrel, true), + DEFINE_PROP_BOOL("use-div", MicroBlazeCPU, cfg.use_div, true), + DEFINE_PROP_BOOL("use-msr-instr", MicroBlazeCPU, cfg.use_msr_instr, true), + DEFINE_PROP_BOOL("use-pcmp-instr", MicroBlazeCPU, cfg.use_pcmp_instr, true), DEFINE_PROP_BOOL("use-mmu", MicroBlazeCPU, cfg.use_mmu, true), DEFINE_PROP_BOOL("dcache-writeback", MicroBlazeCPU, cfg.dcache_writeback, false), diff --git a/target/microblaze/cpu.h b/target/microblaze/cpu.h index bf6963bcb7..5ce4c82657 100644 --- a/target/microblaze/cpu.h +++ b/target/microblaze/cpu.h @@ -129,6 +129,8 @@ typedef struct CPUMBState CPUMBState; #define PVR0_USER1_MASK 0x000000FF #define PVR0_SPROT_MASK 0x00000001 +#define PVR0_VERSION_SHIFT 8 + /* User 2 PVR mask */ #define PVR1_USER2_MASK 0xFFFFFFFF @@ -296,6 +298,11 @@ struct MicroBlazeCPU { bool stackprot; uint32_t base_vectors; uint8_t use_fpu; + uint8_t use_hw_mul; + bool use_barrel; + bool use_div; + bool use_msr_instr; + bool use_pcmp_instr; bool use_mmu; bool dcache_writeback; bool endi; diff --git a/target/microblaze/translate.c b/target/microblaze/translate.c index 0bb609513c..cb65d1e129 100644 --- a/target/microblaze/translate.c +++ b/target/microblaze/translate.c @@ -326,7 +326,7 @@ static void dec_pattern(DisasContext *dc) 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_USE_PCMP_INSTR))) { + && !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); } @@ -443,7 +443,7 @@ static void dec_msr(DisasContext *dc) LOG_DIS("msr%s r%d imm=%x\n", clr ? "clr" : "set", dc->rd, dc->imm); - if (!(dc->cpu->env.pvr.regs[2] & PVR2_USE_MSR_INSTR)) { + if (!dc->cpu->cfg.use_msr_instr) { /* nop??? */ return; } @@ -589,7 +589,7 @@ static void dec_mul(DisasContext *dc) if ((dc->tb_flags & MSR_EE_FLAG) && (dc->cpu->env.pvr.regs[2] & PVR2_ILL_OPCODE_EXC_MASK) - && !(dc->cpu->env.pvr.regs[0] & PVR0_USE_HW_MUL_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); return; @@ -604,8 +604,7 @@ static void dec_mul(DisasContext *dc) } /* mulh, mulhsu and mulhu are not available if C_USE_HW_MUL is < 2. */ - if (subcode >= 1 && subcode <= 3 - && !((dc->cpu->env.pvr.regs[2] & PVR2_USE_MUL64_MASK))) { + if (subcode >= 1 && subcode <= 3 && dc->cpu->cfg.use_hw_mul < 2) { /* nop??? */ } @@ -643,7 +642,7 @@ static void dec_div(DisasContext *dc) LOG_DIS("div\n"); if ((dc->cpu->env.pvr.regs[2] & PVR2_ILL_OPCODE_EXC_MASK) - && !((dc->cpu->env.pvr.regs[0] & PVR0_USE_DIV_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); } @@ -661,34 +660,66 @@ static void dec_div(DisasContext *dc) static void dec_barrel(DisasContext *dc) { TCGv t0; - unsigned int s, t; + 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->env.pvr.regs[0] & PVR0_USE_BARREL_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); return; } - s = dc->imm & (1 << 10); - t = dc->imm & (1 << 9); + if (dc->type_b) { + /* Insert and extract are only available in immediate mode. */ + i = extract32(dc->imm, 15, 1); + e = extract32(dc->imm, 14, 1); + } + s = extract32(dc->imm, 10, 1); + t = extract32(dc->imm, 9, 1); + imm_w = extract32(dc->imm, 6, 5); + imm_s = extract32(dc->imm, 0, 5); - LOG_DIS("bs%s%s r%d r%d r%d\n", + LOG_DIS("bs%s%s%s r%d r%d r%d\n", + e ? "e" : "", s ? "l" : "r", t ? "a" : "l", dc->rd, dc->ra, dc->rb); - t0 = tcg_temp_new(); + if (e) { + if (imm_w + imm_s > 32 || imm_w == 0) { + /* These inputs have an undefined behavior. */ + qemu_log_mask(LOG_GUEST_ERROR, "bsefi: Bad input w=%d s=%d\n", + imm_w, imm_s); + } else { + tcg_gen_extract_i32(cpu_R[dc->rd], cpu_R[dc->ra], imm_s, imm_w); + } + } else if (i) { + int width = imm_w - imm_s + 1; + + if (imm_w < imm_s) { + /* These inputs have an undefined behavior. */ + qemu_log_mask(LOG_GUEST_ERROR, "bsifi: Bad input w=%d s=%d\n", + imm_w, imm_s); + } else { + tcg_gen_deposit_i32(cpu_R[dc->rd], cpu_R[dc->rd], cpu_R[dc->ra], + imm_s, width); + } + } else { + t0 = tcg_temp_new(); - tcg_gen_mov_tl(t0, *(dec_alu_op_b(dc))); - tcg_gen_andi_tl(t0, t0, 31); + tcg_gen_mov_tl(t0, *(dec_alu_op_b(dc))); + tcg_gen_andi_tl(t0, t0, 31); - if (s) - tcg_gen_shl_tl(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); - else - tcg_gen_shr_tl(cpu_R[dc->rd], cpu_R[dc->ra], t0); + if (s) { + tcg_gen_shl_tl(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); + } else { + tcg_gen_shr_tl(cpu_R[dc->rd], cpu_R[dc->ra], t0); + } + } + tcg_temp_free(t0); } } @@ -763,11 +794,11 @@ static void dec_bit(DisasContext *dc) case 0xe0: 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_USE_PCMP_INSTR))) { + && !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 (dc->cpu->env.pvr.regs[2] & PVR2_USE_PCMP_INSTR) { + if (dc->cpu->cfg.use_pcmp_instr) { tcg_gen_clzi_i32(cpu_R[dc->rd], cpu_R[dc->ra], 32); } break; |