tcg/tcg-op: Perform comparison pass with qemu

This commit is contained in:
Lioncash 2018-03-15 21:31:37 -04:00
parent a132b1723c
commit 2e5cfbcfbf
No known key found for this signature in database
GPG key ID: 4E3C3CC1031BA9C7

View file

@ -53,8 +53,7 @@ void tcg_gen_op2(TCGContext *ctx, TCGOpcode opc, TCGArg a1, TCGArg a2)
op->args[1] = a2; op->args[1] = a2;
} }
void tcg_gen_op3(TCGContext *ctx, TCGOpcode opc, TCGArg a1, void tcg_gen_op3(TCGContext *ctx, TCGOpcode opc, TCGArg a1, TCGArg a2, TCGArg a3)
TCGArg a2, TCGArg a3)
{ {
TCGOp *op = tcg_emit_op(ctx, opc); TCGOp *op = tcg_emit_op(ctx, opc);
op->args[0] = a1; op->args[0] = a1;
@ -62,8 +61,7 @@ void tcg_gen_op3(TCGContext *ctx, TCGOpcode opc, TCGArg a1,
op->args[2] = a3; op->args[2] = a3;
} }
void tcg_gen_op4(TCGContext *ctx, TCGOpcode opc, TCGArg a1, void tcg_gen_op4(TCGContext *ctx, TCGOpcode opc, TCGArg a1, TCGArg a2, TCGArg a3, TCGArg a4)
TCGArg a2, TCGArg a3, TCGArg a4)
{ {
TCGOp *op = tcg_emit_op(ctx, opc); TCGOp *op = tcg_emit_op(ctx, opc);
op->args[0] = a1; op->args[0] = a1;
@ -72,8 +70,8 @@ void tcg_gen_op4(TCGContext *ctx, TCGOpcode opc, TCGArg a1,
op->args[3] = a4; op->args[3] = a4;
} }
void tcg_gen_op5(TCGContext *ctx, TCGOpcode opc, TCGArg a1, void tcg_gen_op5(TCGContext *ctx, TCGOpcode opc, TCGArg a1, TCGArg a2, TCGArg a3,
TCGArg a2, TCGArg a3, TCGArg a4, TCGArg a5) TCGArg a4, TCGArg a5)
{ {
TCGOp *op = tcg_emit_op(ctx, opc); TCGOp *op = tcg_emit_op(ctx, opc);
op->args[0] = a1; op->args[0] = a1;
@ -83,8 +81,8 @@ void tcg_gen_op5(TCGContext *ctx, TCGOpcode opc, TCGArg a1,
op->args[4] = a5; op->args[4] = a5;
} }
void tcg_gen_op6(TCGContext *ctx, TCGOpcode opc, TCGArg a1, TCGArg a2, void tcg_gen_op6(TCGContext *ctx, TCGOpcode opc, TCGArg a1, TCGArg a2, TCGArg a3,
TCGArg a3, TCGArg a4, TCGArg a5, TCGArg a6) TCGArg a4, TCGArg a5, TCGArg a6)
{ {
TCGOp *op = tcg_emit_op(ctx, opc); TCGOp *op = tcg_emit_op(ctx, opc);
op->args[0] = a1; op->args[0] = a1;
@ -1097,7 +1095,7 @@ void tcg_gen_ld_i64(TCGContext *s, TCGv_i64 ret, TCGv_ptr arg2, tcg_target_long
{ {
/* Since arg2 and ret have different types, /* Since arg2 and ret have different types,
they cannot be the same temporary */ they cannot be the same temporary */
#ifdef TCG_TARGET_WORDS_BIGENDIAN #ifdef HOST_WORDS_BIGENDIAN
tcg_gen_ld_i32(s, TCGV_HIGH(s, ret), arg2, offset); tcg_gen_ld_i32(s, TCGV_HIGH(s, ret), arg2, offset);
tcg_gen_ld_i32(s, TCGV_LOW(s, ret), arg2, offset + 4); tcg_gen_ld_i32(s, TCGV_LOW(s, ret), arg2, offset + 4);
#else #else
@ -1108,7 +1106,7 @@ void tcg_gen_ld_i64(TCGContext *s, TCGv_i64 ret, TCGv_ptr arg2, tcg_target_long
void tcg_gen_st_i64(TCGContext *s, TCGv_i64 arg1, TCGv_ptr arg2, tcg_target_long offset) void tcg_gen_st_i64(TCGContext *s, TCGv_i64 arg1, TCGv_ptr arg2, tcg_target_long offset)
{ {
#ifdef TCG_TARGET_WORDS_BIGENDIAN #ifdef HOST_WORDS_BIGENDIAN
tcg_gen_st_i32(s, TCGV_HIGH(s, arg1), arg2, offset); tcg_gen_st_i32(s, TCGV_HIGH(s, arg1), arg2, offset);
tcg_gen_st_i32(s, TCGV_LOW(s, arg1), arg2, offset + 4); tcg_gen_st_i32(s, TCGV_LOW(s, arg1), arg2, offset + 4);
#else #else
@ -1239,7 +1237,7 @@ void tcg_gen_andi_i64(TCGContext *s, TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2)
return; return;
} }
break; break;
case 0xffffffff: case 0xffffffffu:
if (TCG_TARGET_HAS_ext32u_i64) { if (TCG_TARGET_HAS_ext32u_i64) {
tcg_gen_op2_i64(s, INDEX_op_ext32u_i64, ret, arg1); tcg_gen_op2_i64(s, INDEX_op_ext32u_i64, ret, arg1);
return; return;
@ -2778,64 +2776,42 @@ typedef void (*gen_atomic_op_i64)(TCGContext *, TCGv_i64, TCGv_env, TCGv, TCGv_i
#ifdef CONFIG_ATOMIC64 #ifdef CONFIG_ATOMIC64
# define WITH_ATOMIC64(X) X, # define WITH_ATOMIC64(X) X,
#else #else
# define WITH_ATOMIC64(X) NULL, # define WITH_ATOMIC64(X)
#endif #endif
#ifdef HOST_WORDS_BIGENDIAN
static void * const table_cmpxchg[16] = { static void * const table_cmpxchg[16] = {
gen_helper_atomic_cmpxchgb, [MO_8] = gen_helper_atomic_cmpxchgb,
gen_helper_atomic_cmpxchgw_be, [MO_16 | MO_LE] = gen_helper_atomic_cmpxchgw_le,
gen_helper_atomic_cmpxchgl_be, [MO_16 | MO_BE] = gen_helper_atomic_cmpxchgw_be,
WITH_ATOMIC64(gen_helper_atomic_cmpxchgq_be) [MO_32 | MO_LE] = gen_helper_atomic_cmpxchgl_le,
NULL, [MO_32 | MO_BE] = gen_helper_atomic_cmpxchgl_be,
NULL, WITH_ATOMIC64([MO_64 | MO_LE] = gen_helper_atomic_cmpxchgq_le)
NULL, WITH_ATOMIC64([MO_64 | MO_BE] = gen_helper_atomic_cmpxchgq_be)
NULL,
NULL,
gen_helper_atomic_cmpxchgw_le,
gen_helper_atomic_cmpxchgl_le,
WITH_ATOMIC64(gen_helper_atomic_cmpxchgq_le)
}
#else
static void * const table_cmpxchg[16] = {
gen_helper_atomic_cmpxchgb,
gen_helper_atomic_cmpxchgw_le,
gen_helper_atomic_cmpxchgl_le,
WITH_ATOMIC64(gen_helper_atomic_cmpxchgq_le)
NULL,
NULL,
NULL,
NULL,
NULL,
gen_helper_atomic_cmpxchgw_be,
gen_helper_atomic_cmpxchgl_be,
WITH_ATOMIC64(gen_helper_atomic_cmpxchgq_be)
}; };
#endif
void tcg_gen_atomic_cmpxchg_i32(TCGContext *s, void tcg_gen_atomic_cmpxchg_i32(TCGContext *tcg_ctx,
TCGv_i32 retv, TCGv addr, TCGv_i32 cmpv, TCGv_i32 retv, TCGv addr, TCGv_i32 cmpv,
TCGv_i32 newv, TCGArg idx, TCGMemOp memop) TCGv_i32 newv, TCGArg idx, TCGMemOp memop)
{ {
memop = tcg_canonicalize_memop(memop, 0, 0); memop = tcg_canonicalize_memop(memop, 0, 0);
if (!(s->tb_cflags & CF_PARALLEL)) { if (!(tcg_ctx->tb_cflags & CF_PARALLEL)) {
TCGv_i32 t1 = tcg_temp_new_i32(s); TCGv_i32 t1 = tcg_temp_new_i32(tcg_ctx);
TCGv_i32 t2 = tcg_temp_new_i32(s); TCGv_i32 t2 = tcg_temp_new_i32(tcg_ctx);
tcg_gen_ext_i32(s, t2, cmpv, memop & MO_SIZE); tcg_gen_ext_i32(tcg_ctx, t2, cmpv, memop & MO_SIZE);
tcg_gen_qemu_ld_i32(s->uc, t1, addr, idx, memop & ~MO_SIGN); tcg_gen_qemu_ld_i32(tcg_ctx->uc, t1, addr, idx, memop & ~MO_SIGN);
tcg_gen_movcond_i32(s, TCG_COND_EQ, t2, t1, t2, newv, t1); tcg_gen_movcond_i32(tcg_ctx, TCG_COND_EQ, t2, t1, t2, newv, t1);
tcg_gen_qemu_st_i32(s->uc, t2, addr, idx, memop); tcg_gen_qemu_st_i32(tcg_ctx->uc, t2, addr, idx, memop);
tcg_temp_free_i32(s, t2); tcg_temp_free_i32(tcg_ctx, t2);
if (memop & MO_SIGN) { if (memop & MO_SIGN) {
tcg_gen_ext_i32(s, retv, t1, memop); tcg_gen_ext_i32(tcg_ctx, retv, t1, memop);
} else { } else {
tcg_gen_mov_i32(s, retv, t1); tcg_gen_mov_i32(tcg_ctx, retv, t1);
} }
tcg_temp_free_i32(s, t1); tcg_temp_free_i32(tcg_ctx, t1);
} else { } else {
gen_atomic_cx_i32 gen; gen_atomic_cx_i32 gen;
@ -2844,43 +2820,43 @@ void tcg_gen_atomic_cmpxchg_i32(TCGContext *s,
#ifdef CONFIG_SOFTMMU #ifdef CONFIG_SOFTMMU
{ {
TCGv_i32 oi = tcg_const_i32(s, make_memop_idx(memop & ~MO_SIGN, idx)); TCGv_i32 oi = tcg_const_i32(tcg_ctx, make_memop_idx(memop & ~MO_SIGN, idx));
gen(s, retv, s->uc->cpu_env, addr, cmpv, newv, oi); gen(tcg_ctx, retv, tcg_ctx->uc->cpu_env, addr, cmpv, newv, oi);
tcg_temp_free_i32(s, oi); tcg_temp_free_i32(tcg_ctx, oi);
} }
#else #else
gen(s, retv, s->uc->cpu_env, addr, cmpv, newv); gen(tcg_ctx, retv, tcg_ctx->uc->cpu_env, addr, cmpv, newv);
#endif #endif
if (memop & MO_SIGN) { if (memop & MO_SIGN) {
tcg_gen_ext_i32(s, retv, retv, memop); tcg_gen_ext_i32(tcg_ctx, retv, retv, memop);
} }
} }
} }
void tcg_gen_atomic_cmpxchg_i64(TCGContext *s, void tcg_gen_atomic_cmpxchg_i64(TCGContext *tcg_ctx,
TCGv_i64 retv, TCGv addr, TCGv_i64 cmpv, TCGv_i64 retv, TCGv addr, TCGv_i64 cmpv,
TCGv_i64 newv, TCGArg idx, TCGMemOp memop) TCGv_i64 newv, TCGArg idx, TCGMemOp memop)
{ {
memop = tcg_canonicalize_memop(memop, 1, 0); memop = tcg_canonicalize_memop(memop, 1, 0);
if (!(s->tb_cflags & CF_PARALLEL)) { if (!(tcg_ctx->tb_cflags & CF_PARALLEL)) {
TCGv_i64 t1 = tcg_temp_new_i64(s); TCGv_i64 t1 = tcg_temp_new_i64(tcg_ctx);
TCGv_i64 t2 = tcg_temp_new_i64(s); TCGv_i64 t2 = tcg_temp_new_i64(tcg_ctx);
tcg_gen_ext_i64(s, t2, cmpv, memop & MO_SIZE); tcg_gen_ext_i64(tcg_ctx, t2, cmpv, memop & MO_SIZE);
tcg_gen_qemu_ld_i64(s->uc, t1, addr, idx, memop & ~MO_SIGN); tcg_gen_qemu_ld_i64(tcg_ctx->uc, t1, addr, idx, memop & ~MO_SIGN);
tcg_gen_movcond_i64(s, TCG_COND_EQ, t2, t1, t2, newv, t1); tcg_gen_movcond_i64(tcg_ctx, TCG_COND_EQ, t2, t1, t2, newv, t1);
tcg_gen_qemu_st_i64(s->uc, t2, addr, idx, memop); tcg_gen_qemu_st_i64(tcg_ctx->uc, t2, addr, idx, memop);
tcg_temp_free_i64(s, t2); tcg_temp_free_i64(tcg_ctx, t2);
if (memop & MO_SIGN) { if (memop & MO_SIGN) {
tcg_gen_ext_i64(s, retv, t1, memop); tcg_gen_ext_i64(tcg_ctx, retv, t1, memop);
} else { } else {
tcg_gen_mov_i64(s, retv, t1); tcg_gen_mov_i64(tcg_ctx, retv, t1);
} }
tcg_temp_free_i64(s, t1); tcg_temp_free_i64(tcg_ctx, t1);
} else if ((memop & MO_SIZE) == MO_64) { } else if ((memop & MO_SIZE) == MO_64) {
#ifdef CONFIG_ATOMIC64 #ifdef CONFIG_ATOMIC64
gen_atomic_cx_i64 gen; gen_atomic_cx_i64 gen;
@ -2890,35 +2866,35 @@ void tcg_gen_atomic_cmpxchg_i64(TCGContext *s,
#ifdef CONFIG_SOFTMMU #ifdef CONFIG_SOFTMMU
{ {
TCGv_i32 oi = tcg_const_i32(s, make_memop_idx(memop, idx)); TCGv_i32 oi = tcg_const_i32(tcg_ctx, make_memop_idx(memop, idx));
gen(s, retv, s->uc->cpu_env, addr, cmpv, newv, oi); gen(tcg_ctx, retv, tcg_ctx->uc->cpu_env, addr, cmpv, newv, oi);
tcg_temp_free_i32(s, oi); tcg_temp_free_i32(tcg_ctx, oi);
} }
#else #else
gen(s, retv, s->uc->cpu_env, addr, cmpv, newv); gen(s, retv, s->uc->cpu_env, addr, cmpv, newv);
#endif #endif
#else #else
gen_helper_exit_atomic(s, s->uc->cpu_env); gen_helper_exit_atomic(tcg_ctx, tcg_ctx->uc->cpu_env);
/* Produce a result, so that we have a well-formed opcode stream /* Produce a result, so that we have a well-formed opcode stream
with respect to uses of the result in the (dead) code following. */ with respect to uses of the result in the (dead) code following. */
tcg_gen_movi_i64(s, retv, 0); tcg_gen_movi_i64(tcg_ctx, retv, 0);
#endif /* CONFIG_ATOMIC64 */ #endif /* CONFIG_ATOMIC64 */
} else { } else {
TCGv_i32 c32 = tcg_temp_new_i32(s); TCGv_i32 c32 = tcg_temp_new_i32(tcg_ctx);
TCGv_i32 n32 = tcg_temp_new_i32(s); TCGv_i32 n32 = tcg_temp_new_i32(tcg_ctx);
TCGv_i32 r32 = tcg_temp_new_i32(s); TCGv_i32 r32 = tcg_temp_new_i32(tcg_ctx);
tcg_gen_extrl_i64_i32(s, c32, cmpv); tcg_gen_extrl_i64_i32(tcg_ctx, c32, cmpv);
tcg_gen_extrl_i64_i32(s, n32, newv); tcg_gen_extrl_i64_i32(tcg_ctx, n32, newv);
tcg_gen_atomic_cmpxchg_i32(s, r32, addr, c32, n32, idx, memop & ~MO_SIGN); tcg_gen_atomic_cmpxchg_i32(tcg_ctx, r32, addr, c32, n32, idx, memop & ~MO_SIGN);
tcg_temp_free_i32(s, c32); tcg_temp_free_i32(tcg_ctx, c32);
tcg_temp_free_i32(s, n32); tcg_temp_free_i32(tcg_ctx, n32);
tcg_gen_extu_i32_i64(s, retv, r32); tcg_gen_extu_i32_i64(tcg_ctx, retv, r32);
tcg_temp_free_i32(s, r32); tcg_temp_free_i32(tcg_ctx, r32);
if (memop & MO_SIGN) { if (memop & MO_SIGN) {
tcg_gen_ext_i64(s, retv, retv, memop); tcg_gen_ext_i64(tcg_ctx, retv, retv, memop);
} }
} }
} }
@ -3032,59 +3008,33 @@ static void do_atomic_op_i64(TCGContext *s,
} }
} }
#ifdef HOST_WORDS_BIGENDIAN
#define GEN_ATOMIC_TABLE(NAME) \
static void * const table_##NAME[16] = { \
gen_helper_atomic_##NAME##b, \
gen_helper_atomic_##NAME##w_be, \
gen_helper_atomic_##NAME##l_be, \
gen_helper_atomic_##NAME##q_be, \
NULL, \
NULL, \
NULL, \
NULL, \
NULL, \
gen_helper_atomic_##NAME##w_le, \
gen_helper_atomic_##NAME##l_le, \
gen_helper_atomic_##NAME##q_le, \
};
#else
#define GEN_ATOMIC_TABLE(NAME) \
static void * const table_##NAME[16] = { \
gen_helper_atomic_##NAME##b, \
gen_helper_atomic_##NAME##w_le, \
gen_helper_atomic_##NAME##w_be, \
gen_helper_atomic_##NAME##l_le, \
NULL, \
NULL, \
NULL, \
NULL, \
NULL, \
gen_helper_atomic_##NAME##l_be, \
gen_helper_atomic_##NAME##q_le, \
gen_helper_atomic_##NAME##q_be, \
};
#endif
#define GEN_ATOMIC_HELPER(NAME, OP, NEW) \ #define GEN_ATOMIC_HELPER(NAME, OP, NEW) \
GEN_ATOMIC_TABLE(NAME) \ static void * const table_##NAME[16] = { \
[MO_8] = gen_helper_atomic_##NAME##b, \
[MO_16 | MO_LE] = gen_helper_atomic_##NAME##w_le, \
[MO_16 | MO_BE] = gen_helper_atomic_##NAME##w_be, \
[MO_32 | MO_LE] = gen_helper_atomic_##NAME##l_le, \
[MO_32 | MO_BE] = gen_helper_atomic_##NAME##l_be, \
WITH_ATOMIC64([MO_64 | MO_LE] = gen_helper_atomic_##NAME##q_le) \
WITH_ATOMIC64([MO_64 | MO_BE] = gen_helper_atomic_##NAME##q_be) \
}; \
void tcg_gen_atomic_##NAME##_i32 \ void tcg_gen_atomic_##NAME##_i32 \
(TCGContext *s, TCGv_i32 ret, TCGv addr, TCGv_i32 val, TCGArg idx, TCGMemOp memop) \ (TCGContext *tcg_ctx, TCGv_i32 ret, TCGv addr, TCGv_i32 val, TCGArg idx, TCGMemOp memop) \
{ \ { \
if (s->tb_cflags & CF_PARALLEL) { \ if (tcg_ctx->tb_cflags & CF_PARALLEL) { \
do_atomic_op_i32(s, ret, addr, val, idx, memop, table_##NAME); \ do_atomic_op_i32(tcg_ctx, ret, addr, val, idx, memop, table_##NAME); \
} else { \ } else { \
do_nonatomic_op_i32(s, ret, addr, val, idx, memop, NEW, \ do_nonatomic_op_i32(tcg_ctx, ret, addr, val, idx, memop, NEW, \
tcg_gen_##OP##_i32); \ tcg_gen_##OP##_i32); \
} \ } \
} \ } \
void tcg_gen_atomic_##NAME##_i64 \ void tcg_gen_atomic_##NAME##_i64 \
(TCGContext *s, TCGv_i64 ret, TCGv addr, TCGv_i64 val, TCGArg idx, TCGMemOp memop) \ (TCGContext *tcg_ctx, TCGv_i64 ret, TCGv addr, TCGv_i64 val, TCGArg idx, TCGMemOp memop) \
{ \ { \
if (s->tb_cflags & CF_PARALLEL) { \ if (tcg_ctx->tb_cflags & CF_PARALLEL) { \
do_atomic_op_i64(s, ret, addr, val, idx, memop, table_##NAME); \ do_atomic_op_i64(tcg_ctx, ret, addr, val, idx, memop, table_##NAME); \
} else { \ } else { \
do_nonatomic_op_i64(s, ret, addr, val, idx, memop, NEW, \ do_nonatomic_op_i64(tcg_ctx, ret, addr, val, idx, memop, NEW, \
tcg_gen_##OP##_i64); \ tcg_gen_##OP##_i64); \
} \ } \
} }
@ -3111,6 +3061,4 @@ static void tcg_gen_mov2_i64(TCGContext *s, TCGv_i64 r, TCGv_i64 a, TCGv_i64 b)
GEN_ATOMIC_HELPER(xchg, mov2, 0) GEN_ATOMIC_HELPER(xchg, mov2, 0)
#undef GEN_ATOMIC_TABLE
#undef GEN_ATOMIC_HELPER #undef GEN_ATOMIC_HELPER