aboutsummaryrefslogtreecommitdiff
path: root/target
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2017-07-04 13:05:30 +0100
committerPeter Maydell <peter.maydell@linaro.org>2017-07-04 13:05:30 +0100
commit2185c93ba80f81bfa27ce6f259c7f2ef4f08b668 (patch)
treef2bfba6f066e0f5da675ad95bf1cb2df4921a5c0 /target
parent0c7a8b9baa744ae4323bb46cb4fe942355beaa85 (diff)
parent31cf950ea2a010c33e5384aaba91f01dc27c1599 (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.c39
-rw-r--r--target/microblaze/cpu.h7
-rw-r--r--target/microblaze/translate.c77
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;