Signed-off-by: Yeqi Fu <fufuyqqq...@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