target/arm/common-semi-target.c | 72 +++++++++++++++++++++++++++------
target/arm/cpu.c | 4 ++
target/arm/internals.h | 2 +
3 files changed, 65 insertions(+), 13 deletions(-)
diff --git a/target/arm/common-semi-target.c b/target/arm/common-semi-target.c
index 38d52deb3d6..5263c0435a8 100644
--- a/target/arm/common-semi-target.c
+++ b/target/arm/common-semi-target.c
@@ -10,9 +10,10 @@
#include "qemu/osdep.h"
#include "cpu.h"
#include "semihosting/common-semi.h"
+#include "internals.h"
#include "target/arm/cpu-qom.h"
-uint64_t common_semi_arg(CPUState *cs, int argno)
+static uint64_t arm_semi_arg(CPUState *cs, int argno)
{
ARMCPU *cpu = ARM_CPU(cs);
CPUARMState *env = &cpu->env;
@@ -23,7 +24,7 @@ uint64_t common_semi_arg(CPUState *cs, int argno)
}
}
-void common_semi_set_ret(CPUState *cs, uint64_t ret)
+static void arm_semi_set_ret(CPUState *cs, uint64_t ret)
{
ARMCPU *cpu = ARM_CPU(cs);
CPUARMState *env = &cpu->env;
@@ -34,29 +35,74 @@ void common_semi_set_ret(CPUState *cs, uint64_t ret)
}
}
+static void arm_semi_set_err(CPUState *cs, int err)
+{
+}
+
+static bool arm_semi_is_64bit(CPUState *cs)
+{
+ return is_a64(cpu_env(cs));
+}
+
+static bool arm_semi_sys_exit_is_extended(CPUState *cs)
+{
+ return is_a64(cpu_env(cs));
+}
+
+static uint64_t arm_semi_stack_bottom(CPUState *cs)
+{
+ ARMCPU *cpu = ARM_CPU(cs);
+ CPUARMState *env = &cpu->env;
+ return is_a64(env) ? env->xregs[31] : env->regs[13];
+}
+
+static bool arm_semi_has_synccache(CPUState *cs)
+{
+ /* Ok for A64, invalid for A32/T32 */
+ return is_a64(cpu_env(cs));
+}
+
+const SemihostingCPUOps arm_semihosting_ops = {
+ .arg = arm_semi_arg,
+ .set_ret = arm_semi_set_ret,
+ .set_err = arm_semi_set_err,
+ .is_64bit = arm_semi_is_64bit,
+ .sys_exit_is_extended = arm_semi_sys_exit_is_extended,
+ .stack_bottom = arm_semi_stack_bottom,
+ .has_synccache = arm_semi_has_synccache,
+};
+
+uint64_t common_semi_arg(CPUState *cs, int argno)
+{
+ return arm_semi_arg(cs, argno);
+}
+
+void common_semi_set_ret(CPUState *cs, uint64_t ret)
+{
+ arm_semi_set_ret(cs, ret);
+}
+
void common_semi_set_err(CPUState *cs, int err)
{
-}
-
-bool common_semi_sys_exit_is_extended(CPUState *cs)
-{
- return is_a64(cpu_env(cs));
+ arm_semi_set_err(cs, err);
}
bool is_64bit_semihosting(CPUArchState *env)
{
- return is_a64(env);
+ return arm_semi_is_64bit(env_cpu(env));
+}
+
+bool common_semi_sys_exit_is_extended(CPUState *cs)
+{
+ return arm_semi_sys_exit_is_extended(cs);
}
uint64_t common_semi_stack_bottom(CPUState *cs)
{
- ARMCPU *cpu = ARM_CPU(cs);
- CPUARMState *env = &cpu->env;
- return is_a64(env) ? env->xregs[31] : env->regs[13];
+ return arm_semi_stack_bottom(cs);
}
bool common_semi_has_synccache(CPUArchState *env)
{
- /* Ok for A64, invalid for A32/T32 */
- return is_a64(env);
+ return arm_semi_has_synccache(env_cpu(env));
}
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
index 10ac6c98318..81ec1ce21c6 100644
--- a/target/arm/cpu.c
+++ b/target/arm/cpu.c
@@ -2663,6 +2663,10 @@ static void arm_cpu_class_init(ObjectClass *oc, const
void *data)
#ifdef CONFIG_TCG
cc->tcg_ops = &arm_tcg_ops;
+#if !defined(CONFIG_USER_ONLY) || defined(CONFIG_LINUX)
+ /* semihosting is not supported for bsd-user */
+ cc->semi_ops = &arm_semihosting_ops;
+#endif
#endif /* CONFIG_TCG */
}
diff --git a/target/arm/internals.h b/target/arm/internals.h
index c41fa5225c7..e849e357cfe 100644
--- a/target/arm/internals.h
+++ b/target/arm/internals.h
@@ -437,6 +437,8 @@ bool arm_cpu_exec_halt(CPUState *cs);
int arm_cpu_mmu_index(CPUState *cs, bool ifetch);
#endif /* CONFIG_TCG */
+extern const struct SemihostingCPUOps arm_semihosting_ops;
+
typedef enum ARMFPRounding {
FPROUNDING_TIEEVEN,
FPROUNDING_POSINF,