aboutsummaryrefslogtreecommitdiff
path: root/target-microblaze
diff options
context:
space:
mode:
Diffstat (limited to 'target-microblaze')
-rw-r--r--target-microblaze/microblaze-decode.h1
-rw-r--r--target-microblaze/translate.c111
2 files changed, 111 insertions, 1 deletions
diff --git a/target-microblaze/microblaze-decode.h b/target-microblaze/microblaze-decode.h
index 2c975d6..602027d 100644
--- a/target-microblaze/microblaze-decode.h
+++ b/target-microblaze/microblaze-decode.h
@@ -41,6 +41,7 @@
#define DEC_BARREL {B8(00010001), B8(00110111)}
#define DEC_MUL {B8(00010000), B8(00110111)}
#define DEC_DIV {B8(00010010), B8(00110111)}
+#define DEC_FPU {B8(00111111), B8(00010110)}
#define DEC_LD {B8(00110000), B8(00110100)}
#define DEC_ST {B8(00110100), B8(00110100)}
diff --git a/target-microblaze/translate.c b/target-microblaze/translate.c
index 9c8631d..16b282f 100644
--- a/target-microblaze/translate.c
+++ b/target-microblaze/translate.c
@@ -231,6 +231,13 @@ static void dec_pattern(DisasContext *dc)
unsigned int mode;
int l1;
+ if ((dc->tb_flags & MSR_EE_FLAG)
+ && !(dc->env->pvr.regs[2] & PVR2_ILL_OPCODE_EXC_MASK)
+ && !((dc->env->pvr.regs[2] & PVR2_USE_PCMP_INSTR))) {
+ tcg_gen_movi_tl(cpu_SR[SR_ESR], ESR_EC_ILLEGAL_OP);
+ t_gen_raise_exception(dc, EXCP_HW_EXCP);
+ }
+
mode = dc->opcode & 3;
switch (mode) {
case 0:
@@ -358,6 +365,7 @@ static void dec_msr(DisasContext *dc)
{
TCGv t0, t1;
unsigned int sr, to, rn;
+ int mem_index = cpu_mmu_index(dc->env);
sr = dc->imm & ((1 << 14) - 1);
to = dc->imm & (1 << 14);
@@ -371,6 +379,19 @@ static void dec_msr(DisasContext *dc)
LOG_DIS("msr%s r%d imm=%x\n", clr ? "clr" : "set",
dc->rd, dc->imm);
+
+ if (!(dc->env->pvr.regs[2] & PVR2_USE_MSR_INSTR)) {
+ /* nop??? */
+ 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);
+ return;
+ }
+
if (dc->rd)
msr_read(dc, cpu_R[dc->rd]);
@@ -392,6 +413,15 @@ static void dec_msr(DisasContext *dc)
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 !defined(CONFIG_USER_ONLY)
/* Catch read/writes to the mmu block. */
if ((sr & ~0xff) == 0x1000) {
@@ -518,6 +548,14 @@ static void dec_mul(DisasContext *dc)
TCGv d[2];
unsigned int subcode;
+ if ((dc->tb_flags & MSR_EE_FLAG)
+ && !(dc->env->pvr.regs[2] & PVR2_ILL_OPCODE_EXC_MASK)
+ && !(dc->env->pvr.regs[0] & PVR0_USE_HW_MUL_MASK)) {
+ tcg_gen_movi_tl(cpu_SR[SR_ESR], ESR_EC_ILLEGAL_OP);
+ t_gen_raise_exception(dc, EXCP_HW_EXCP);
+ return;
+ }
+
subcode = dc->imm & 3;
d[0] = tcg_temp_new();
d[1] = tcg_temp_new();
@@ -528,6 +566,12 @@ static void dec_mul(DisasContext *dc)
goto done;
}
+ /* mulh, mulhsu and mulhu are not available if C_USE_HW_MUL is < 2. */
+ if (subcode >= 1 && subcode <= 3
+ && !((dc->env->pvr.regs[2] & PVR2_USE_MUL64_MASK))) {
+ /* nop??? */
+ }
+
switch (subcode) {
case 0:
LOG_DIS("mul r%d r%d r%d\n", dc->rd, dc->ra, dc->rb);
@@ -562,6 +606,12 @@ static void dec_div(DisasContext *dc)
u = dc->imm & 2;
LOG_DIS("div\n");
+ if (!(dc->env->pvr.regs[2] & PVR2_ILL_OPCODE_EXC_MASK)
+ && !((dc->env->pvr.regs[0] & PVR0_USE_DIV_MASK))) {
+ tcg_gen_movi_tl(cpu_SR[SR_ESR], ESR_EC_ILLEGAL_OP);
+ t_gen_raise_exception(dc, EXCP_HW_EXCP);
+ }
+
/* FIXME: support div by zero exceptions. */
if (u)
gen_helper_divu(cpu_R[dc->rd], *(dec_alu_op_b(dc)), cpu_R[dc->ra]);
@@ -576,6 +626,14 @@ static void dec_barrel(DisasContext *dc)
TCGv t0;
unsigned int s, t;
+ if ((dc->tb_flags & MSR_EE_FLAG)
+ && !(dc->env->pvr.regs[2] & PVR2_ILL_OPCODE_EXC_MASK)
+ && !(dc->env->pvr.regs[0] & PVR0_USE_BARREL_MASK)) {
+ 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);
@@ -601,6 +659,7 @@ static void dec_bit(DisasContext *dc)
{
TCGv t0, t1;
unsigned int op;
+ int mem_index = cpu_mmu_index(dc->env);
op = dc->ir & ((1 << 8) - 1);
switch (op) {
@@ -653,10 +712,22 @@ static void dec_bit(DisasContext *dc)
case 0x64:
/* 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;
+ }
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;
+ }
break;
default:
cpu_abort(dc->env, "unknown bit oc=%x op=%x rd=%d ra=%d rb=%d\n",
@@ -966,6 +1037,7 @@ static inline void do_rte(DisasContext *dc)
static void dec_rts(DisasContext *dc)
{
unsigned int b_bit, i_bit, e_bit;
+ int mem_index = cpu_mmu_index(dc->env);
i_bit = dc->ir & (1 << 21);
b_bit = dc->ir & (1 << 22);
@@ -978,12 +1050,27 @@ static void dec_rts(DisasContext *dc)
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);
@@ -992,6 +1079,20 @@ static void dec_rts(DisasContext *dc)
tcg_gen_add_tl(env_btarget, cpu_R[dc->ra], *(dec_alu_op_b(dc)));
}
+static void dec_fpu(DisasContext *dc)
+{
+ if ((dc->tb_flags & MSR_EE_FLAG)
+ && !(dc->env->pvr.regs[2] & PVR2_ILL_OPCODE_EXC_MASK)
+ && !((dc->env->pvr.regs[2] & PVR2_USE_FPU_MASK))) {
+ tcg_gen_movi_tl(cpu_SR[SR_ESR], ESR_EC_ILLEGAL_OP);
+ t_gen_raise_exception(dc, EXCP_HW_EXCP);
+ return;
+ }
+
+ qemu_log ("unimplemented FPU insn pc=%x opc=%x\n", dc->pc, dc->opcode);
+ dc->abort_at_next_insn = 1;
+}
+
static void dec_null(DisasContext *dc)
{
qemu_log ("unknown insn pc=%x opc=%x\n", dc->pc, dc->opcode);
@@ -1018,6 +1119,7 @@ static struct decoder_info {
{DEC_BR, dec_br},
{DEC_BCC, dec_bcc},
{DEC_RTS, dec_rts},
+ {DEC_FPU, dec_fpu},
{DEC_MUL, dec_mul},
{DEC_DIV, dec_div},
{DEC_MSR, dec_msr},
@@ -1038,6 +1140,14 @@ static inline void decode(DisasContext *dc)
if (dc->ir)
dc->nr_nops = 0;
else {
+ if ((dc->tb_flags & MSR_EE_FLAG)
+ && !(dc->env->pvr.regs[2] & PVR2_ILL_OPCODE_EXC_MASK)
+ && !(dc->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;
+ }
+
LOG_DIS("nr_nops=%d\t", dc->nr_nops);
dc->nr_nops++;
if (dc->nr_nops > 4)
@@ -1061,7 +1171,6 @@ static inline void decode(DisasContext *dc)
}
}
-
static void check_breakpoint(CPUState *env, DisasContext *dc)
{
CPUBreakpoint *bp;