[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH 03/11] target/arm: Introduce read_pc
From: |
Richard Henderson |
Subject: |
[Qemu-devel] [PATCH 03/11] target/arm: Introduce read_pc |
Date: |
Tue, 6 Aug 2019 21:53:27 -0700 |
We currently have 3 different ways of computing the architectural
value of "PC" as seen in the ARM ARM.
The value of s->pc has been incremented past the current insn,
but that is all. Thus for a32, PC = s->pc + 4; for t32, PC = s->pc;
for t16, PC = s->pc + 2. These differing computations make it
impossible at present to unify the various code paths.
With the newly introduced s->pc_curr, we can compute the correct
value for all cases, using the formula given in the ARM ARM.
Signed-off-by: Richard Henderson <address@hidden>
---
target/arm/translate.c | 59 ++++++++++++++++--------------------------
1 file changed, 23 insertions(+), 36 deletions(-)
diff --git a/target/arm/translate.c b/target/arm/translate.c
index 59e35aafbf..61933865d5 100644
--- a/target/arm/translate.c
+++ b/target/arm/translate.c
@@ -196,17 +196,17 @@ static inline void store_cpu_offset(TCGv_i32 var, int
offset)
#define store_cpu_field(var, name) \
store_cpu_offset(var, offsetof(CPUARMState, name))
+/* The architectural value of PC. */
+static uint32_t read_pc(DisasContext *s)
+{
+ return s->pc_curr + (s->thumb ? 4 : 8);
+}
+
/* Set a variable to the value of a CPU register. */
static void load_reg_var(DisasContext *s, TCGv_i32 var, int reg)
{
if (reg == 15) {
- uint32_t addr;
- /* normally, since we updated PC, we need only to add one insn */
- if (s->thumb)
- addr = (long)s->pc + 2;
- else
- addr = (long)s->pc + 4;
- tcg_gen_movi_i32(var, addr);
+ tcg_gen_movi_i32(var, read_pc(s));
} else {
tcg_gen_mov_i32(var, cpu_R[reg]);
}
@@ -7868,16 +7868,14 @@ static void disas_arm_insn(DisasContext *s, unsigned
int insn)
/* branch link and change to thumb (blx <offset>) */
int32_t offset;
- val = (uint32_t)s->pc;
tmp = tcg_temp_new_i32();
- tcg_gen_movi_i32(tmp, val);
+ tcg_gen_movi_i32(tmp, s->pc);
store_reg(s, 14, tmp);
/* Sign-extend the 24-bit offset */
offset = (((int32_t)insn) << 8) >> 8;
+ val = read_pc(s);
/* offset * 4 + bit24 * 2 + (thumb bit) */
val += (offset << 2) | ((insn >> 23) & 2) | 1;
- /* pipeline offset */
- val += 4;
/* protected by ARCH(5); above, near the start of uncond block */
gen_bx_im(s, val);
return;
@@ -9153,10 +9151,8 @@ static void disas_arm_insn(DisasContext *s, unsigned int
insn)
} else {
/* store */
if (i == 15) {
- /* special case: r15 = PC + 8 */
- val = (long)s->pc + 4;
tmp = tcg_temp_new_i32();
- tcg_gen_movi_i32(tmp, val);
+ tcg_gen_movi_i32(tmp, read_pc(s));
} else if (user) {
tmp = tcg_temp_new_i32();
tmp2 = tcg_const_i32(i);
@@ -9222,15 +9218,13 @@ static void disas_arm_insn(DisasContext *s, unsigned
int insn)
int32_t offset;
/* branch (and link) */
- val = (int32_t)s->pc;
if (insn & (1 << 24)) {
tmp = tcg_temp_new_i32();
- tcg_gen_movi_i32(tmp, val);
+ tcg_gen_movi_i32(tmp, s->pc);
store_reg(s, 14, tmp);
}
offset = sextract32(insn << 2, 0, 26);
- val += offset + 4;
- gen_jmp(s, val);
+ gen_jmp(s, read_pc(s) + offset);
}
break;
case 0xc:
@@ -9588,12 +9582,7 @@ static void disas_thumb2_insn(DisasContext *s, uint32_t
insn)
tcg_temp_free_i32(addr);
} else if ((insn & (7 << 5)) == 0) {
/* Table Branch. */
- if (rn == 15) {
- addr = tcg_temp_new_i32();
- tcg_gen_movi_i32(addr, s->pc);
- } else {
- addr = load_reg(s, rn);
- }
+ addr = load_reg(s, rn);
tmp = load_reg(s, rm);
tcg_gen_add_i32(addr, addr, tmp);
if (insn & (1 << 4)) {
@@ -9609,7 +9598,7 @@ static void disas_thumb2_insn(DisasContext *s, uint32_t
insn)
}
tcg_temp_free_i32(addr);
tcg_gen_shli_i32(tmp, tmp, 1);
- tcg_gen_addi_i32(tmp, tmp, s->pc);
+ tcg_gen_addi_i32(tmp, tmp, read_pc(s));
store_reg(s, 15, tmp);
} else {
bool is_lasr = false;
@@ -10342,7 +10331,7 @@ static void disas_thumb2_insn(DisasContext *s, uint32_t
insn)
tcg_gen_movi_i32(cpu_R[14], s->pc | 1);
}
- offset += s->pc;
+ offset += read_pc(s);
if (insn & (1 << 12)) {
/* b/bl */
gen_jmp(s, offset);
@@ -10583,7 +10572,7 @@ static void disas_thumb2_insn(DisasContext *s, uint32_t
insn)
offset |= (insn & (1 << 11)) << 8;
/* jump to the offset */
- gen_jmp(s, s->pc + offset);
+ gen_jmp(s, read_pc(s) + offset);
}
} else {
/*
@@ -11077,7 +11066,7 @@ static void disas_thumb_insn(DisasContext *s, uint32_t
insn)
if (insn & (1 << 11)) {
rd = (insn >> 8) & 7;
/* load pc-relative. Bit 1 of PC is ignored. */
- val = s->pc + 2 + ((insn & 0xff) * 4);
+ val = read_pc(s) + ((insn & 0xff) * 4);
val &= ~(uint32_t)2;
addr = tcg_temp_new_i32();
tcg_gen_movi_i32(addr, val);
@@ -11464,7 +11453,7 @@ static void disas_thumb_insn(DisasContext *s, uint32_t
insn)
} else {
/* PC. bit 1 is ignored. */
tmp = tcg_temp_new_i32();
- tcg_gen_movi_i32(tmp, (s->pc + 2) & ~(uint32_t)2);
+ tcg_gen_movi_i32(tmp, read_pc(s) & ~(uint32_t)2);
}
val = (insn & 0xff) * 4;
tcg_gen_addi_i32(tmp, tmp, val);
@@ -11584,9 +11573,7 @@ static void disas_thumb_insn(DisasContext *s, uint32_t
insn)
tcg_gen_brcondi_i32(TCG_COND_NE, tmp, 0, s->condlabel);
tcg_temp_free_i32(tmp);
offset = ((insn & 0xf8) >> 2) | (insn & 0x200) >> 3;
- val = (uint32_t)s->pc + 2;
- val += offset;
- gen_jmp(s, val);
+ gen_jmp(s, read_pc(s) + offset);
break;
case 15: /* IT, nop-hint. */
@@ -11750,7 +11737,7 @@ static void disas_thumb_insn(DisasContext *s, uint32_t
insn)
arm_skip_unless(s, cond);
/* jump to the offset */
- val = (uint32_t)s->pc + 2;
+ val = read_pc(s);
offset = ((int32_t)insn << 24) >> 24;
val += offset << 1;
gen_jmp(s, val);
@@ -11776,9 +11763,9 @@ static void disas_thumb_insn(DisasContext *s, uint32_t
insn)
break;
}
/* unconditional branch */
- val = (uint32_t)s->pc;
+ val = read_pc(s);
offset = ((int32_t)insn << 21) >> 21;
- val += (offset << 1) + 2;
+ val += offset << 1;
gen_jmp(s, val);
break;
@@ -11802,7 +11789,7 @@ static void disas_thumb_insn(DisasContext *s, uint32_t
insn)
/* 0b1111_0xxx_xxxx_xxxx : BL/BLX prefix */
uint32_t uoffset = ((int32_t)insn << 21) >> 9;
- tcg_gen_movi_i32(cpu_R[14], s->pc + 2 + uoffset);
+ tcg_gen_movi_i32(cpu_R[14], read_pc(s) + uoffset);
}
break;
}
--
2.17.1
[Qemu-devel] [PATCH 05/11] target/arm: Remove redundant s->pc & ~1, Richard Henderson, 2019/08/07
[Qemu-devel] [PATCH 04/11] target/arm: Introduce add_reg_for_lit, Richard Henderson, 2019/08/07
[Qemu-devel] [PATCH 07/11] target/arm: Replace offset with pc in gen_exception_insn, Richard Henderson, 2019/08/07
[Qemu-devel] [PATCH 08/11] target/arm: Replace offset with pc in gen_exception_internal_insn, Richard Henderson, 2019/08/07
[Qemu-devel] [PATCH 09/11] target/arm: Remove offset argument to gen_exception_bkpt_insn, Richard Henderson, 2019/08/07