[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[RFC v2 3/6] target/i386: Add native library calls
From: |
Yeqi Fu |
Subject: |
[RFC v2 3/6] target/i386: Add native library calls |
Date: |
Thu, 8 Jun 2023 00:47:47 +0800 |
Signed-off-by: Yeqi Fu <fufuyqqqqqq@gmail.com>
---
target/i386/helper.h | 6 +++
target/i386/tcg/translate.c | 20 +++++++++
target/i386/tcg/user/meson.build | 1 +
target/i386/tcg/user/native_helper.c | 65 ++++++++++++++++++++++++++++
4 files changed, 92 insertions(+)
create mode 100644 target/i386/tcg/user/native_helper.c
diff --git a/target/i386/helper.h b/target/i386/helper.h
index e627a93107..6c91655887 100644
--- a/target/i386/helper.h
+++ b/target/i386/helper.h
@@ -221,3 +221,9 @@ DEF_HELPER_3(rcrq, tl, env, tl, tl)
#endif
DEF_HELPER_1(rdrand, tl, env)
+
+#if defined(CONFIG_USER_ONLY) && defined(CONFIG_USER_NATIVE_CALL)
+DEF_HELPER_1(native_memcpy, void, env)
+DEF_HELPER_1(native_memcmp, void, env)
+DEF_HELPER_1(native_memset, void, env)
+#endif
diff --git a/target/i386/tcg/translate.c b/target/i386/tcg/translate.c
index 91c9c0c478..eb0c1e9566 100644
--- a/target/i386/tcg/translate.c
+++ b/target/i386/tcg/translate.c
@@ -33,6 +33,7 @@
#include "helper-tcg.h"
#include "exec/log.h"
+#include "native/native-func.h"
#define PREFIX_REPZ 0x01
#define PREFIX_REPNZ 0x02
@@ -6806,6 +6807,25 @@ static bool disas_insn(DisasContext *s, CPUState *cpu)
case 0x1d0 ... 0x1fe:
disas_insn_new(s, cpu, b);
break;
+ /* One unknown opcode for native call */
+#if defined(CONFIG_USER_ONLY) && defined(CONFIG_USER_NATIVE_CALL)
+ case 0x1ff:
+ uint16_t sig = x86_lduw_code(env, s);
+ switch (sig) {
+ case NATIVE_MEMCPY:
+ gen_helper_native_memcpy(cpu_env);
+ break;
+ case NATIVE_MEMSET:
+ gen_helper_native_memset(cpu_env);
+ break;
+ case NATIVE_MEMCMP:
+ gen_helper_native_memcmp(cpu_env);
+ break;
+ default:
+ goto unknown_op;
+ }
+ break;
+#endif
default:
goto unknown_op;
}
diff --git a/target/i386/tcg/user/meson.build b/target/i386/tcg/user/meson.build
index 1df6bc4343..490808bd65 100644
--- a/target/i386/tcg/user/meson.build
+++ b/target/i386/tcg/user/meson.build
@@ -1,4 +1,5 @@
i386_user_ss.add(when: ['CONFIG_TCG', 'CONFIG_USER_ONLY'], if_true: files(
'excp_helper.c',
'seg_helper.c',
+ 'native_helper.c',
))
diff --git a/target/i386/tcg/user/native_helper.c
b/target/i386/tcg/user/native_helper.c
new file mode 100644
index 0000000000..4a9b98eee2
--- /dev/null
+++ b/target/i386/tcg/user/native_helper.c
@@ -0,0 +1,65 @@
+/*
+ * native function call helpers
+ */
+
+#include "qemu/osdep.h"
+#include "cpu.h"
+#include "exec/helper-proto.h"
+#include "exec/exec-all.h"
+#include "exec/cpu_ldst.h"
+#include "tcg/helper-tcg.h"
+#include "tcg/seg_helper.h"
+
+#ifdef TARGET_X86_64
+#define NATIVE_FN_W_3W() \
+ target_ulong arg0, arg1, arg2; \
+ arg0 = env->regs[R_EDI]; \
+ arg1 = env->regs[R_ESI]; \
+ arg2 = env->regs[R_EDX];
+#else
+/*
+ * linux x86 has several calling conventions. The following implementation
+ * is for the most commonly used cdecl calling convention.
+ */
+#define NATIVE_FN_W_3W() \
+ target_ulong arg0, arg1, arg2; \
+ arg0 = *(target_ulong *)g2h(cs, env->regs[R_ESP] + 4); \
+ arg1 = *(target_ulong *)g2h(cs, env->regs[R_ESP] + 8); \
+ arg2 = *(target_ulong *)g2h(cs, env->regs[R_ESP] + 12);
+#endif
+
+void helper_native_memcpy(CPUX86State *env)
+{
+ CPUState *cs = env_cpu(env);
+ NATIVE_FN_W_3W();
+ void *ret;
+ void *dest = g2h(cs, arg0);
+ void *src = g2h(cs, arg1);
+ size_t n = (size_t)arg2;
+ ret = memcpy(dest, src, n);
+ env->regs[R_EAX] = (target_ulong)h2g(ret);
+}
+
+void helper_native_memcmp(CPUX86State *env)
+{
+ CPUState *cs = env_cpu(env);
+ NATIVE_FN_W_3W();
+ int ret;
+ void *s1 = g2h(cs, arg0);
+ void *s2 = g2h(cs, arg1);
+ size_t n = (size_t)arg2;
+ ret = memcmp(s1, s2, n);
+ env->regs[R_EAX] = ret;
+}
+
+void helper_native_memset(CPUX86State *env)
+{
+ CPUState *cs = env_cpu(env);
+ NATIVE_FN_W_3W();
+ void *ret;
+ void *s = g2h(cs, arg0);
+ int c = (int)arg1;
+ size_t n = (size_t)arg2;
+ ret = memset(s, c, n);
+ env->regs[R_EAX] = (target_ulong)h2g(ret);
+}
--
2.34.1