This patch only adds the helpers. Functions to invoke the helpers from translated code are generated in subsequent patches.
Signed-off-by: Emilio G. Cota <c...@braap.org> --- target-i386/helper.h | 34 ++++++++++++++++++++++++++++++++++ target-i386/mem_helper.c | 38 ++++++++++++++++++++++++++++++++++++++ target-i386/translate.c | 45 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 117 insertions(+) diff --git a/target-i386/helper.h b/target-i386/helper.h index 2bb0d1f..df68204 100644 --- a/target-i386/helper.h +++ b/target-i386/helper.h @@ -84,6 +84,40 @@ DEF_HELPER_4(cmpxchgq, tl, env, tl, tl, tl) DEF_HELPER_2(cmpxchg16b, void, env, tl) DEF_HELPER_2(cmpxchg16b_unlocked, void, env, tl) #endif + +/* + * Use glue(foo, glue(bar, baz)) instead of glue(glue(foo, bar), baz), otherwise + * some gcc's (e.g. v4.6.3) can get confused with the surrounding DEF_HELPER. + */ +#ifndef TARGET_X86_64 +#define DEF_ATOMIC_ALL(NAME) \ + DEF_HELPER_3(glue(atomic_, glue(NAME, b)), tl, env, tl, tl) \ + DEF_HELPER_3(glue(atomic_, glue(NAME, w)), tl, env, tl, tl) \ + DEF_HELPER_3(glue(atomic_, glue(NAME, l)), tl, env, tl, tl) +#else /* 64-bit */ +#define DEF_ATOMIC_ALL(NAME) \ + DEF_HELPER_3(glue(atomic_, glue(NAME, b)), tl, env, tl, tl) \ + DEF_HELPER_3(glue(atomic_, glue(NAME, w)), tl, env, tl, tl) \ + DEF_HELPER_3(glue(atomic_, glue(NAME, l)), tl, env, tl, tl) \ + DEF_HELPER_3(glue(atomic_, glue(NAME, q)), tl, env, tl, tl) +#endif + +DEF_ATOMIC_ALL(fetch_add) +DEF_ATOMIC_ALL(fetch_and) +DEF_ATOMIC_ALL(fetch_or) +DEF_ATOMIC_ALL(fetch_sub) +DEF_ATOMIC_ALL(fetch_xor) + +DEF_ATOMIC_ALL(add_fetch) +DEF_ATOMIC_ALL(and_fetch) +DEF_ATOMIC_ALL(or_fetch) +DEF_ATOMIC_ALL(sub_fetch) +DEF_ATOMIC_ALL(xor_fetch) + +DEF_ATOMIC_ALL(xchg) + +#undef DEF_ATOMIC_ALL + DEF_HELPER_1(single_step, void, env) DEF_HELPER_1(cpuid, void, env) DEF_HELPER_1(rdtsc, void, env) diff --git a/target-i386/mem_helper.c b/target-i386/mem_helper.c index b002aba..13f4f3b 100644 --- a/target-i386/mem_helper.c +++ b/target-i386/mem_helper.c @@ -170,6 +170,44 @@ void helper_cmpxchg16b(CPUX86State *env, target_ulong a0) } #endif +#define GEN_ATOMIC_HELPER(NAME) \ +target_ulong \ +glue(helper_atomic_, \ + NAME)(CPUArchState *env, target_ulong addr, target_ulong val) \ +{ \ + return glue(glue(cpu_atomic_, NAME), _data_ra)(env, addr, val, GETPC()); \ +} + +#ifndef TARGET_X86_64 +#define GEN_ATOMIC_HELPER_ALL(NAME) \ + GEN_ATOMIC_HELPER(glue(NAME, b)) \ + GEN_ATOMIC_HELPER(glue(NAME, w)) \ + GEN_ATOMIC_HELPER(glue(NAME, l)) +#else /* 64-bit */ +#define GEN_ATOMIC_HELPER_ALL(NAME) \ + GEN_ATOMIC_HELPER(glue(NAME, b)) \ + GEN_ATOMIC_HELPER(glue(NAME, w)) \ + GEN_ATOMIC_HELPER(glue(NAME, l)) \ + GEN_ATOMIC_HELPER(glue(NAME, q)) +#endif /* TARGET_X86_64 */ + +GEN_ATOMIC_HELPER_ALL(fetch_add) +GEN_ATOMIC_HELPER_ALL(fetch_and) +GEN_ATOMIC_HELPER_ALL(fetch_or) +GEN_ATOMIC_HELPER_ALL(fetch_sub) +GEN_ATOMIC_HELPER_ALL(fetch_xor) + +GEN_ATOMIC_HELPER_ALL(add_fetch) +GEN_ATOMIC_HELPER_ALL(and_fetch) +GEN_ATOMIC_HELPER_ALL(or_fetch) +GEN_ATOMIC_HELPER_ALL(sub_fetch) +GEN_ATOMIC_HELPER_ALL(xor_fetch) + +GEN_ATOMIC_HELPER_ALL(xchg) + +#undef GEN_ATOMIC_HELPER +#undef GEN_ATOMIC_HELPER_ALL + void helper_boundw(CPUX86State *env, target_ulong a0, int v) { int low, high; diff --git a/target-i386/translate.c b/target-i386/translate.c index 9abd82f..eead9d7 100644 --- a/target-i386/translate.c +++ b/target-i386/translate.c @@ -1271,6 +1271,51 @@ static void gen_cmpxchg(TCGv ret, TCGv addr, TCGv old, TCGv new, TCGMemOp ot) } } +#ifndef TARGET_X86_64 +#define GEN_ATOMIC_HELPER(NAME) \ +static void \ +glue(gen_atomic_, NAME)(TCGv ret, TCGv addr, TCGv reg, TCGMemOp ot) \ +{ \ + switch (ot & 3) { \ + case 0: \ + glue(glue(gen_helper_atomic_, NAME), b)(ret, cpu_env, addr, reg); \ + break; \ + case 1: \ + glue(glue(gen_helper_atomic_, NAME), w)(ret, cpu_env, addr, reg); \ + break; \ + case 2: \ + glue(glue(gen_helper_atomic_, NAME), l)(ret, cpu_env, addr, reg); \ + break; \ + default: \ + tcg_abort(); \ + } \ +} +#else /* 64-bit */ +#define GEN_ATOMIC_HELPER(NAME) \ +static void \ +glue(gen_atomic_, NAME)(TCGv ret, TCGv addr, TCGv reg, TCGMemOp ot) \ +{ \ + switch (ot & 3) { \ + case 0: \ + glue(glue(gen_helper_atomic_, NAME), b)(ret, cpu_env, addr, reg); \ + break; \ + case 1: \ + glue(glue(gen_helper_atomic_, NAME), w)(ret, cpu_env, addr, reg); \ + break; \ + case 2: \ + glue(glue(gen_helper_atomic_, NAME), l)(ret, cpu_env, addr, reg); \ + break; \ + case 3: \ + glue(glue(gen_helper_atomic_, NAME), q)(ret, cpu_env, addr, reg); \ + break; \ + default: \ + tcg_abort(); \ + } \ +} +#endif /* TARGET_X86_64 */ + +#undef GEN_ATOMIC_HELPER + /* if d == OR_TMP0, it means memory operand (address in A0) */ static void gen_op(DisasContext *s1, int op, TCGMemOp ot, int d) { -- 2.5.0