Loading target-microblaze/cpu.c +1 −0 Original line number Diff line number Diff line Loading @@ -39,6 +39,7 @@ static void mb_cpu_reset(CPUState *s) mcc->parent_reset(s); memset(env, 0, offsetof(CPUMBState, breakpoints)); env->res_addr = RES_ADDR_NONE; tlb_flush(env, 1); /* Disable stack protector. */ Loading target-microblaze/cpu.h +4 −0 Original line number Diff line number Diff line Loading @@ -243,6 +243,10 @@ struct CPUMBState { /* 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; /* Internal flags. */ #define IMM_FLAG 4 #define MSR_EE_FLAG (1 << 8) Loading target-microblaze/helper.c +2 −0 Original line number Diff line number Diff line Loading @@ -29,6 +29,7 @@ void do_interrupt (CPUMBState *env) { env->exception_index = -1; env->res_addr = RES_ADDR_NONE; env->regs[14] = env->sregs[SR_PC]; } Loading Loading @@ -116,6 +117,7 @@ void do_interrupt(CPUMBState *env) assert(!((env->iflags & D_FLAG) && (env->iflags & IMM_FLAG))); assert(!(env->iflags & (DRTI_FLAG | DRTE_FLAG | DRTB_FLAG))); /* assert(env->sregs[SR_MSR] & (MSR_EE)); Only for HW exceptions. */ env->res_addr = RES_ADDR_NONE; switch (env->exception_index) { case EXCP_HW_EXCP: if (!(env->pvr.regs[0] & PVR0_USE_EXC_MASK)) { Loading target-microblaze/translate.c +57 −5 Original line number Diff line number Diff line Loading @@ -162,6 +162,14 @@ static void write_carry(DisasContext *dc, TCGv v) tcg_temp_free(t0); } static void write_carryi(DisasContext *dc, int carry) { TCGv t0 = tcg_temp_new(); tcg_gen_movi_tl(t0, carry ? 1 : 0); write_carry(dc, t0); tcg_temp_free(t0); } /* True if ALU operand b is a small immediate that may deserve faster treatment. */ static inline int dec_alu_op_b_is_small_imm(DisasContext *dc) Loading Loading @@ -948,12 +956,13 @@ static inline void dec_byteswap(DisasContext *dc, TCGv dst, TCGv src, int size) static void dec_load(DisasContext *dc) { TCGv t, *addr; unsigned int size, rev = 0; unsigned int size, rev = 0, ex = 0; size = 1 << (dc->opcode & 3); if (!dc->type_b) { rev = (dc->ir >> 9) & 1; ex = (dc->ir >> 10) & 1; } if (size > 4 && (dc->tb_flags & MSR_EE_FLAG) Loading @@ -963,7 +972,8 @@ static void dec_load(DisasContext *dc) return; } LOG_DIS("l%d%s%s\n", size, dc->type_b ? "i" : "", rev ? "r" : ""); LOG_DIS("l%d%s%s%s\n", size, dc->type_b ? "i" : "", rev ? "r" : "", ex ? "x" : ""); t_sync_flags(dc); addr = compute_ldst_addr(dc, &t); Loading Loading @@ -1019,6 +1029,17 @@ 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); } /* If we get a fault on a dslot, the jmpstate better be in sync. */ sync_jmpstate(dc); Loading Loading @@ -1057,6 +1078,12 @@ static void dec_load(DisasContext *dc) } } if (ex) { /* lwx */ /* no support for for AXI exclusive so always clear C */ write_carryi(dc, 0); tcg_gen_st_tl(*addr, cpu_env, offsetof(CPUMBState, res_addr)); } if (addr == &t) tcg_temp_free(t); } Loading @@ -1078,12 +1105,14 @@ static void gen_store(DisasContext *dc, TCGv addr, TCGv val, static void dec_store(DisasContext *dc) { TCGv t, *addr; unsigned int size, rev = 0; TCGv t, *addr, swx_addr, r_check = 0; int swx_skip = 0; unsigned int size, rev = 0, ex = 0; size = 1 << (dc->opcode & 3); if (!dc->type_b) { rev = (dc->ir >> 9) & 1; ex = (dc->ir >> 10) & 1; } if (size > 4 && (dc->tb_flags & MSR_EE_FLAG) Loading @@ -1093,12 +1122,30 @@ static void dec_store(DisasContext *dc) return; } LOG_DIS("s%d%s%s\n", size, dc->type_b ? "i" : "", rev ? "r" : ""); LOG_DIS("s%d%s%s%s\n", size, dc->type_b ? "i" : "", rev ? "r" : "", ex ? "x" : ""); 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); if (ex) { /* swx */ r_check = tcg_temp_new(); swx_addr = tcg_temp_local_new(); /* 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_ld_tl(r_check, cpu_env, offsetof(CPUMBState, res_addr)); write_carryi(dc, 1); swx_skip = gen_new_label(); tcg_gen_brcond_tl(TCG_COND_NE, r_check, swx_addr, swx_skip); write_carryi(dc, 0); } if (rev && size != 4) { /* Endian reverse the address. t is addr. */ switch (size) { Loading Loading @@ -1174,6 +1221,11 @@ static void dec_store(DisasContext *dc) gen_helper_memalign(*addr, tcg_const_tl(dc->rd), tcg_const_tl(1), tcg_const_tl(size - 1)); } if (ex) { gen_set_label(swx_skip); tcg_temp_free(r_check); tcg_temp_free(swx_addr); } if (addr == &t) tcg_temp_free(t); Loading Loading
target-microblaze/cpu.c +1 −0 Original line number Diff line number Diff line Loading @@ -39,6 +39,7 @@ static void mb_cpu_reset(CPUState *s) mcc->parent_reset(s); memset(env, 0, offsetof(CPUMBState, breakpoints)); env->res_addr = RES_ADDR_NONE; tlb_flush(env, 1); /* Disable stack protector. */ Loading
target-microblaze/cpu.h +4 −0 Original line number Diff line number Diff line Loading @@ -243,6 +243,10 @@ struct CPUMBState { /* 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; /* Internal flags. */ #define IMM_FLAG 4 #define MSR_EE_FLAG (1 << 8) Loading
target-microblaze/helper.c +2 −0 Original line number Diff line number Diff line Loading @@ -29,6 +29,7 @@ void do_interrupt (CPUMBState *env) { env->exception_index = -1; env->res_addr = RES_ADDR_NONE; env->regs[14] = env->sregs[SR_PC]; } Loading Loading @@ -116,6 +117,7 @@ void do_interrupt(CPUMBState *env) assert(!((env->iflags & D_FLAG) && (env->iflags & IMM_FLAG))); assert(!(env->iflags & (DRTI_FLAG | DRTE_FLAG | DRTB_FLAG))); /* assert(env->sregs[SR_MSR] & (MSR_EE)); Only for HW exceptions. */ env->res_addr = RES_ADDR_NONE; switch (env->exception_index) { case EXCP_HW_EXCP: if (!(env->pvr.regs[0] & PVR0_USE_EXC_MASK)) { Loading
target-microblaze/translate.c +57 −5 Original line number Diff line number Diff line Loading @@ -162,6 +162,14 @@ static void write_carry(DisasContext *dc, TCGv v) tcg_temp_free(t0); } static void write_carryi(DisasContext *dc, int carry) { TCGv t0 = tcg_temp_new(); tcg_gen_movi_tl(t0, carry ? 1 : 0); write_carry(dc, t0); tcg_temp_free(t0); } /* True if ALU operand b is a small immediate that may deserve faster treatment. */ static inline int dec_alu_op_b_is_small_imm(DisasContext *dc) Loading Loading @@ -948,12 +956,13 @@ static inline void dec_byteswap(DisasContext *dc, TCGv dst, TCGv src, int size) static void dec_load(DisasContext *dc) { TCGv t, *addr; unsigned int size, rev = 0; unsigned int size, rev = 0, ex = 0; size = 1 << (dc->opcode & 3); if (!dc->type_b) { rev = (dc->ir >> 9) & 1; ex = (dc->ir >> 10) & 1; } if (size > 4 && (dc->tb_flags & MSR_EE_FLAG) Loading @@ -963,7 +972,8 @@ static void dec_load(DisasContext *dc) return; } LOG_DIS("l%d%s%s\n", size, dc->type_b ? "i" : "", rev ? "r" : ""); LOG_DIS("l%d%s%s%s\n", size, dc->type_b ? "i" : "", rev ? "r" : "", ex ? "x" : ""); t_sync_flags(dc); addr = compute_ldst_addr(dc, &t); Loading Loading @@ -1019,6 +1029,17 @@ 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); } /* If we get a fault on a dslot, the jmpstate better be in sync. */ sync_jmpstate(dc); Loading Loading @@ -1057,6 +1078,12 @@ static void dec_load(DisasContext *dc) } } if (ex) { /* lwx */ /* no support for for AXI exclusive so always clear C */ write_carryi(dc, 0); tcg_gen_st_tl(*addr, cpu_env, offsetof(CPUMBState, res_addr)); } if (addr == &t) tcg_temp_free(t); } Loading @@ -1078,12 +1105,14 @@ static void gen_store(DisasContext *dc, TCGv addr, TCGv val, static void dec_store(DisasContext *dc) { TCGv t, *addr; unsigned int size, rev = 0; TCGv t, *addr, swx_addr, r_check = 0; int swx_skip = 0; unsigned int size, rev = 0, ex = 0; size = 1 << (dc->opcode & 3); if (!dc->type_b) { rev = (dc->ir >> 9) & 1; ex = (dc->ir >> 10) & 1; } if (size > 4 && (dc->tb_flags & MSR_EE_FLAG) Loading @@ -1093,12 +1122,30 @@ static void dec_store(DisasContext *dc) return; } LOG_DIS("s%d%s%s\n", size, dc->type_b ? "i" : "", rev ? "r" : ""); LOG_DIS("s%d%s%s%s\n", size, dc->type_b ? "i" : "", rev ? "r" : "", ex ? "x" : ""); 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); if (ex) { /* swx */ r_check = tcg_temp_new(); swx_addr = tcg_temp_local_new(); /* 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_ld_tl(r_check, cpu_env, offsetof(CPUMBState, res_addr)); write_carryi(dc, 1); swx_skip = gen_new_label(); tcg_gen_brcond_tl(TCG_COND_NE, r_check, swx_addr, swx_skip); write_carryi(dc, 0); } if (rev && size != 4) { /* Endian reverse the address. t is addr. */ switch (size) { Loading Loading @@ -1174,6 +1221,11 @@ static void dec_store(DisasContext *dc) gen_helper_memalign(*addr, tcg_const_tl(dc->rd), tcg_const_tl(1), tcg_const_tl(size - 1)); } if (ex) { gen_set_label(swx_skip); tcg_temp_free(r_check); tcg_temp_free(swx_addr); } if (addr == &t) tcg_temp_free(t); Loading