aboutsummaryrefslogtreecommitdiff
path: root/target/arm/translate.c
diff options
context:
space:
mode:
Diffstat (limited to 'target/arm/translate.c')
-rw-r--r--target/arm/translate.c73
1 files changed, 48 insertions, 25 deletions
diff --git a/target/arm/translate.c b/target/arm/translate.c
index 7c4675ffd8..66cf28c8cb 100644
--- a/target/arm/translate.c
+++ b/target/arm/translate.c
@@ -9733,6 +9733,8 @@ static void disas_arm_insn(DisasContext *s, unsigned int insn)
rd = (insn >> 12) & 0xf;
if (insn & (1 << 23)) {
/* load/store exclusive */
+ bool is_ld = extract32(insn, 20, 1);
+ bool is_lasr = !extract32(insn, 8, 1);
int op2 = (insn >> 8) & 3;
op1 = (insn >> 21) & 0x3;
@@ -9760,11 +9762,12 @@ static void disas_arm_insn(DisasContext *s, unsigned int insn)
addr = tcg_temp_local_new_i32();
load_reg_var(s, addr, rn);
- /* Since the emulation does not have barriers,
- the acquire/release semantics need no special
- handling */
+ if (is_lasr && !is_ld) {
+ tcg_gen_mb(TCG_MO_ALL | TCG_BAR_STRL);
+ }
+
if (op2 == 0) {
- if (insn & (1 << 20)) {
+ if (is_ld) {
tmp = tcg_temp_new_i32();
switch (op1) {
case 0: /* lda */
@@ -9810,7 +9813,7 @@ static void disas_arm_insn(DisasContext *s, unsigned int insn)
}
tcg_temp_free_i32(tmp);
}
- } else if (insn & (1 << 20)) {
+ } else if (is_ld) {
switch (op1) {
case 0: /* ldrex */
gen_load_exclusive(s, rd, 15, addr, 2);
@@ -9847,6 +9850,10 @@ static void disas_arm_insn(DisasContext *s, unsigned int insn)
}
}
tcg_temp_free_i32(addr);
+
+ if (is_lasr && is_ld) {
+ tcg_gen_mb(TCG_MO_ALL | TCG_BAR_LDAQ);
+ }
} else if ((insn & 0x00300f00) == 0) {
/* 0bcccc_0001_0x00_xxxx_xxxx_0000_1001_xxxx
* - SWP, SWPB
@@ -10862,6 +10869,8 @@ static void disas_thumb2_insn(DisasContext *s, uint32_t insn)
tcg_gen_addi_i32(tmp, tmp, s->pc);
store_reg(s, 15, tmp);
} else {
+ bool is_lasr = false;
+ bool is_ld = extract32(insn, 20, 1);
int op2 = (insn >> 6) & 0x3;
op = (insn >> 4) & 0x3;
switch (op2) {
@@ -10883,12 +10892,18 @@ static void disas_thumb2_insn(DisasContext *s, uint32_t insn)
case 3:
/* Load-acquire/store-release exclusive */
ARCH(8);
+ is_lasr = true;
break;
}
+
+ if (is_lasr && !is_ld) {
+ tcg_gen_mb(TCG_MO_ALL | TCG_BAR_STRL);
+ }
+
addr = tcg_temp_local_new_i32();
load_reg_var(s, addr, rn);
if (!(op2 & 1)) {
- if (insn & (1 << 20)) {
+ if (is_ld) {
tmp = tcg_temp_new_i32();
switch (op) {
case 0: /* ldab */
@@ -10927,12 +10942,16 @@ static void disas_thumb2_insn(DisasContext *s, uint32_t insn)
}
tcg_temp_free_i32(tmp);
}
- } else if (insn & (1 << 20)) {
+ } else if (is_ld) {
gen_load_exclusive(s, rs, rd, addr, op);
} else {
gen_store_exclusive(s, rm, rs, rd, addr, op);
}
tcg_temp_free_i32(addr);
+
+ if (is_lasr && is_ld) {
+ tcg_gen_mb(TCG_MO_ALL | TCG_BAR_LDAQ);
+ }
}
} else {
/* Load/store multiple, RFE, SRS. */
@@ -13021,6 +13040,8 @@ static void arm_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
DisasContext *dc = container_of(dcbase, DisasContext, base);
CPUARMState *env = cs->env_ptr;
ARMCPU *cpu = arm_env_get_cpu(env);
+ uint32_t tb_flags = dc->base.tb->flags;
+ uint32_t condexec, core_mmu_idx;
dc->isar = &cpu->isar;
dc->pc = dc->base.pc_first;
@@ -13032,26 +13053,28 @@ static void arm_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
*/
dc->secure_routed_to_el3 = arm_feature(env, ARM_FEATURE_EL3) &&
!arm_el_is_aa64(env, 3);
- dc->thumb = ARM_TBFLAG_THUMB(dc->base.tb->flags);
- dc->sctlr_b = ARM_TBFLAG_SCTLR_B(dc->base.tb->flags);
- dc->be_data = ARM_TBFLAG_BE_DATA(dc->base.tb->flags) ? MO_BE : MO_LE;
- dc->condexec_mask = (ARM_TBFLAG_CONDEXEC(dc->base.tb->flags) & 0xf) << 1;
- dc->condexec_cond = ARM_TBFLAG_CONDEXEC(dc->base.tb->flags) >> 4;
- dc->mmu_idx = core_to_arm_mmu_idx(env, ARM_TBFLAG_MMUIDX(dc->base.tb->flags));
+ dc->thumb = FIELD_EX32(tb_flags, TBFLAG_A32, THUMB);
+ dc->sctlr_b = FIELD_EX32(tb_flags, TBFLAG_A32, SCTLR_B);
+ dc->be_data = FIELD_EX32(tb_flags, TBFLAG_ANY, BE_DATA) ? MO_BE : MO_LE;
+ condexec = FIELD_EX32(tb_flags, TBFLAG_A32, CONDEXEC);
+ dc->condexec_mask = (condexec & 0xf) << 1;
+ dc->condexec_cond = condexec >> 4;
+ core_mmu_idx = FIELD_EX32(tb_flags, TBFLAG_ANY, MMUIDX);
+ dc->mmu_idx = core_to_arm_mmu_idx(env, core_mmu_idx);
dc->current_el = arm_mmu_idx_to_el(dc->mmu_idx);
#if !defined(CONFIG_USER_ONLY)
dc->user = (dc->current_el == 0);
#endif
- dc->ns = ARM_TBFLAG_NS(dc->base.tb->flags);
- dc->fp_excp_el = ARM_TBFLAG_FPEXC_EL(dc->base.tb->flags);
- dc->vfp_enabled = ARM_TBFLAG_VFPEN(dc->base.tb->flags);
- dc->vec_len = ARM_TBFLAG_VECLEN(dc->base.tb->flags);
- dc->vec_stride = ARM_TBFLAG_VECSTRIDE(dc->base.tb->flags);
- dc->c15_cpar = ARM_TBFLAG_XSCALE_CPAR(dc->base.tb->flags);
- dc->v7m_handler_mode = ARM_TBFLAG_HANDLER(dc->base.tb->flags);
+ dc->ns = FIELD_EX32(tb_flags, TBFLAG_A32, NS);
+ dc->fp_excp_el = FIELD_EX32(tb_flags, TBFLAG_ANY, FPEXC_EL);
+ dc->vfp_enabled = FIELD_EX32(tb_flags, TBFLAG_A32, VFPEN);
+ dc->vec_len = FIELD_EX32(tb_flags, TBFLAG_A32, VECLEN);
+ dc->vec_stride = FIELD_EX32(tb_flags, TBFLAG_A32, VECSTRIDE);
+ dc->c15_cpar = FIELD_EX32(tb_flags, TBFLAG_A32, XSCALE_CPAR);
+ dc->v7m_handler_mode = FIELD_EX32(tb_flags, TBFLAG_A32, HANDLER);
dc->v8m_secure = arm_feature(env, ARM_FEATURE_M_SECURITY) &&
regime_is_secure(env, dc->mmu_idx);
- dc->v8m_stackcheck = ARM_TBFLAG_STACKCHECK(dc->base.tb->flags);
+ dc->v8m_stackcheck = FIELD_EX32(tb_flags, TBFLAG_A32, STACKCHECK);
dc->cp_regs = cpu->cp_regs;
dc->features = env->features;
@@ -13070,8 +13093,8 @@ static void arm_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
* emit code to generate a software step exception
* end the TB
*/
- dc->ss_active = ARM_TBFLAG_SS_ACTIVE(dc->base.tb->flags);
- dc->pstate_ss = ARM_TBFLAG_PSTATE_SS(dc->base.tb->flags);
+ dc->ss_active = FIELD_EX32(tb_flags, TBFLAG_ANY, SS_ACTIVE);
+ dc->pstate_ss = FIELD_EX32(tb_flags, TBFLAG_ANY, PSTATE_SS);
dc->is_ldex = false;
dc->ss_same_el = false; /* Can't be true since EL_d must be AArch64 */
@@ -13516,11 +13539,11 @@ void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb)
DisasContext dc;
const TranslatorOps *ops = &arm_translator_ops;
- if (ARM_TBFLAG_THUMB(tb->flags)) {
+ if (FIELD_EX32(tb->flags, TBFLAG_A32, THUMB)) {
ops = &thumb_translator_ops;
}
#ifdef TARGET_AARCH64
- if (ARM_TBFLAG_AARCH64_STATE(tb->flags)) {
+ if (FIELD_EX32(tb->flags, TBFLAG_ANY, AARCH64_STATE)) {
ops = &aarch64_translator_ops;
}
#endif