diff options
-rw-r--r-- | target-microblaze/microblaze-decode.h | 1 | ||||
-rw-r--r-- | target-microblaze/translate.c | 111 |
2 files changed, 111 insertions, 1 deletions
diff --git a/target-microblaze/microblaze-decode.h b/target-microblaze/microblaze-decode.h index 2c975d6677..602027dbfb 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 9c8631dc21..16b282f577 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; |