mirror of
https://github.com/xemu-project/xemu.git
synced 2024-11-23 11:39:53 +00:00
target/arm: Introduce gen_pc_plus_diff for aarch32
In preparation for TARGET_TB_PCREL, reduce reliance on absolute values. Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org> Signed-off-by: Richard Henderson <richard.henderson@linaro.org> Message-id: 20221020030641.2066807-9-richard.henderson@linaro.org Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
parent
19f6b76baa
commit
35dbeb8177
@ -260,23 +260,22 @@ static inline int get_a32_user_mem_index(DisasContext *s)
|
||||
}
|
||||
}
|
||||
|
||||
/* The architectural value of PC. */
|
||||
static uint32_t read_pc(DisasContext *s)
|
||||
{
|
||||
return s->pc_curr + (s->thumb ? 4 : 8);
|
||||
}
|
||||
|
||||
/* The pc_curr difference for an architectural jump. */
|
||||
static target_long jmp_diff(DisasContext *s, target_long diff)
|
||||
{
|
||||
return diff + (s->thumb ? 4 : 8);
|
||||
}
|
||||
|
||||
static void gen_pc_plus_diff(DisasContext *s, TCGv_i32 var, target_long diff)
|
||||
{
|
||||
tcg_gen_movi_i32(var, s->pc_curr + diff);
|
||||
}
|
||||
|
||||
/* Set a variable to the value of a CPU register. */
|
||||
void load_reg_var(DisasContext *s, TCGv_i32 var, int reg)
|
||||
{
|
||||
if (reg == 15) {
|
||||
tcg_gen_movi_i32(var, read_pc(s));
|
||||
gen_pc_plus_diff(s, var, jmp_diff(s, 0));
|
||||
} else {
|
||||
tcg_gen_mov_i32(var, cpu_R[reg]);
|
||||
}
|
||||
@ -292,7 +291,11 @@ TCGv_i32 add_reg_for_lit(DisasContext *s, int reg, int ofs)
|
||||
TCGv_i32 tmp = tcg_temp_new_i32();
|
||||
|
||||
if (reg == 15) {
|
||||
tcg_gen_movi_i32(tmp, (read_pc(s) & ~3) + ofs);
|
||||
/*
|
||||
* This address is computed from an aligned PC:
|
||||
* subtract off the low bits.
|
||||
*/
|
||||
gen_pc_plus_diff(s, tmp, jmp_diff(s, ofs - (s->pc_curr & 3)));
|
||||
} else {
|
||||
tcg_gen_addi_i32(tmp, cpu_R[reg], ofs);
|
||||
}
|
||||
@ -1155,7 +1158,7 @@ void unallocated_encoding(DisasContext *s)
|
||||
/* Force a TB lookup after an instruction that changes the CPU state. */
|
||||
void gen_lookup_tb(DisasContext *s)
|
||||
{
|
||||
tcg_gen_movi_i32(cpu_R[15], s->base.pc_next);
|
||||
gen_pc_plus_diff(s, cpu_R[15], curr_insn_len(s));
|
||||
s->base.is_jmp = DISAS_EXIT;
|
||||
}
|
||||
|
||||
@ -6479,7 +6482,7 @@ static bool trans_BLX_r(DisasContext *s, arg_BLX_r *a)
|
||||
return false;
|
||||
}
|
||||
tmp = load_reg(s, a->rm);
|
||||
tcg_gen_movi_i32(cpu_R[14], s->base.pc_next | s->thumb);
|
||||
gen_pc_plus_diff(s, cpu_R[14], curr_insn_len(s) | s->thumb);
|
||||
gen_bx(s, tmp);
|
||||
return true;
|
||||
}
|
||||
@ -8347,7 +8350,7 @@ static bool trans_B_cond_thumb(DisasContext *s, arg_ci *a)
|
||||
|
||||
static bool trans_BL(DisasContext *s, arg_i *a)
|
||||
{
|
||||
tcg_gen_movi_i32(cpu_R[14], s->base.pc_next | s->thumb);
|
||||
gen_pc_plus_diff(s, cpu_R[14], curr_insn_len(s) | s->thumb);
|
||||
gen_jmp(s, jmp_diff(s, a->imm));
|
||||
return true;
|
||||
}
|
||||
@ -8366,7 +8369,7 @@ static bool trans_BLX_i(DisasContext *s, arg_BLX_i *a)
|
||||
if (s->thumb && (a->imm & 2)) {
|
||||
return false;
|
||||
}
|
||||
tcg_gen_movi_i32(cpu_R[14], s->base.pc_next | s->thumb);
|
||||
gen_pc_plus_diff(s, cpu_R[14], curr_insn_len(s) | s->thumb);
|
||||
store_cpu_field_constant(!s->thumb, thumb);
|
||||
/* This jump is computed from an aligned PC: subtract off the low bits. */
|
||||
gen_jmp(s, jmp_diff(s, a->imm - (s->pc_curr & 3)));
|
||||
@ -8376,7 +8379,7 @@ static bool trans_BLX_i(DisasContext *s, arg_BLX_i *a)
|
||||
static bool trans_BL_BLX_prefix(DisasContext *s, arg_BL_BLX_prefix *a)
|
||||
{
|
||||
assert(!arm_dc_feature(s, ARM_FEATURE_THUMB2));
|
||||
tcg_gen_movi_i32(cpu_R[14], read_pc(s) + (a->imm << 12));
|
||||
gen_pc_plus_diff(s, cpu_R[14], jmp_diff(s, a->imm << 12));
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -8386,7 +8389,7 @@ static bool trans_BL_suffix(DisasContext *s, arg_BL_suffix *a)
|
||||
|
||||
assert(!arm_dc_feature(s, ARM_FEATURE_THUMB2));
|
||||
tcg_gen_addi_i32(tmp, cpu_R[14], (a->imm << 1) | 1);
|
||||
tcg_gen_movi_i32(cpu_R[14], s->base.pc_next | 1);
|
||||
gen_pc_plus_diff(s, cpu_R[14], curr_insn_len(s) | 1);
|
||||
gen_bx(s, tmp);
|
||||
return true;
|
||||
}
|
||||
@ -8402,7 +8405,7 @@ static bool trans_BLX_suffix(DisasContext *s, arg_BLX_suffix *a)
|
||||
tmp = tcg_temp_new_i32();
|
||||
tcg_gen_addi_i32(tmp, cpu_R[14], a->imm << 1);
|
||||
tcg_gen_andi_i32(tmp, tmp, 0xfffffffc);
|
||||
tcg_gen_movi_i32(cpu_R[14], s->base.pc_next | 1);
|
||||
gen_pc_plus_diff(s, cpu_R[14], curr_insn_len(s) | 1);
|
||||
gen_bx(s, tmp);
|
||||
return true;
|
||||
}
|
||||
@ -8725,10 +8728,11 @@ static bool op_tbranch(DisasContext *s, arg_tbranch *a, bool half)
|
||||
tcg_gen_add_i32(addr, addr, tmp);
|
||||
|
||||
gen_aa32_ld_i32(s, tmp, addr, get_mem_index(s), half ? MO_UW : MO_UB);
|
||||
tcg_temp_free_i32(addr);
|
||||
|
||||
tcg_gen_add_i32(tmp, tmp, tmp);
|
||||
tcg_gen_addi_i32(tmp, tmp, read_pc(s));
|
||||
gen_pc_plus_diff(s, addr, jmp_diff(s, 0));
|
||||
tcg_gen_add_i32(tmp, tmp, addr);
|
||||
tcg_temp_free_i32(addr);
|
||||
store_reg(s, 15, tmp);
|
||||
return true;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user