Rather than re-reading the insn during syscall processing to
find the immediate, store it in CPUARMState during translate.
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
target/arm/cpu.h | 1 +
linux-user/arm/cpu_loop.c | 13 ++++---------
target/arm/tcg/translate.c | 19 +++++++++++++++++--
3 files changed, 22 insertions(+), 11 deletions(-)
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
index b11a31c807..5b564c7113 100644
--- a/target/arm/cpu.h
+++ b/target/arm/cpu.h
@@ -817,6 +817,7 @@ typedef struct CPUArchState {
bool tagged_addr_enable;
#else
/* For usermode syscall translation. */
+ uint32_t syscall_info;
bool eabi;
#endif /* !CONFIG_USER_ONLY */
} CPUARMState;
diff --git a/linux-user/arm/cpu_loop.c b/linux-user/arm/cpu_loop.c
index 19874f4c72..86f13ad83a 100644
--- a/linux-user/arm/cpu_loop.c
+++ b/linux-user/arm/cpu_loop.c
@@ -271,7 +271,6 @@ void cpu_loop(CPUARMState *env)
{
CPUState *cs = env_cpu(env);
int trapnr, si_signo, si_code;
- unsigned int n, insn;
abi_ulong ret;
for(;;) {
@@ -312,20 +311,16 @@ void cpu_loop(CPUARMState *env)
break;
case EXCP_SWI:
{
+ unsigned int n;
+
env->eabi = true;
/* system call */
if (env->thumb) {
/* Thumb is always EABI style with syscall number in r7 */
n = env->regs[7];
} else {
- /*
- * Equivalent of kernel CONFIG_OABI_COMPAT: read the
- * Arm SVC insn to extract the immediate, which is the
- * syscall number in OABI.
- */
- /* FIXME - what to do if get_user() fails? */
- get_user_code_u32(insn, env->regs[15] - 4, env);
- n = insn & 0xffffff;
+ /* The 24-bit SVC immediate is stored during translate. */
+ n = env->syscall_info;
if (n == 0) {
/* zero immediate: EABI, syscall number in r7 */
n = env->regs[7];
diff --git a/target/arm/tcg/translate.c b/target/arm/tcg/translate.c
index ce427c5a3c..ec21e33a06 100644
--- a/target/arm/tcg/translate.c
+++ b/target/arm/tcg/translate.c
@@ -1158,6 +1158,21 @@ void unallocated_encoding(DisasContext *s)
gen_exception_insn(s, 0, EXCP_UDEF, syn_uncategorized());
}
+static void gen_exception_swi(DisasContext *s)
+{
+#ifdef CONFIG_USER_ONLY
+# ifndef TARGET_AARCH64
+ /*
+ * Only 16-bits of the immediate are recorded in the syndrome,
+ * so store the entire 24-bit immediate for cpu_loop().
+ */
+ tcg_gen_st_i32(tcg_constant_i32(s->svc_imm), tcg_env,
+ offsetof(CPUARMState, syscall_info));
+# endif
+#endif
+ gen_exception(EXCP_SWI, syn_aa32_svc(s->svc_imm, s->thumb));
+}
+
/* Force a TB lookup after an instruction that changes the CPU state. */
void gen_lookup_tb(DisasContext *s)
{
@@ -6781,7 +6796,7 @@ static void arm_tr_tb_stop(DisasContextBase *dcbase, CPUState *cpu)
switch (dc->base.is_jmp) {
case DISAS_SWI:
gen_ss_advance(dc);
- gen_exception(EXCP_SWI, syn_aa32_svc(dc->svc_imm, dc->thumb));
+ gen_exception_swi(dc);
break;
case DISAS_HVC:
gen_ss_advance(dc);
@@ -6854,7 +6869,7 @@ static void arm_tr_tb_stop(DisasContextBase *dcbase, CPUState *cpu)
gen_helper_yield(tcg_env);
break;
case DISAS_SWI:
- gen_exception(EXCP_SWI, syn_aa32_svc(dc->svc_imm, dc->thumb));
+ gen_exception_swi(dc);
break;
case DISAS_HVC:
gen_exception_el(EXCP_HVC, syn_aa32_hvc(dc->svc_imm), 2);
--
2.43.0