tcg cleanups:
- Remove tcg_abort() - Split out extensions as known backend interfaces - Put the separate extensions together as tcg_out_movext - Introduce tcg_out_xchg as a backend interface - Clear TCGLabelQemuLdst on allocation - Avoid redundant extensions for riscv -----BEGIN PGP SIGNATURE----- iQFRBAABCgA7FiEEekgeeIaLTbaoWgXAZN846K9+IV8FAmRE69sdHHJpY2hhcmQu aGVuZGVyc29uQGxpbmFyby5vcmcACgkQZN846K9+IV/6jQf6Al9cgeJ6guVMpoRS +sXaTs5U2yaqRvz5gGn2ANFuFgD2QanbWHjS5guTnhbsvq3icyOCpIXIPg/Z04LB fTgAUCF5ut8U8C12HyGq/p4BFoTTWnCGPwY+PB9pMb5LiEcmaSUUz+fSA8xMX1b6 EylI8YNd74A9j5PBNbGIXooj8llM71p9YztwQ9V7sPH3ZON4qbPRDgrJsb5TngMa daTpGoW+A9UyG7z0Ie6UuiOyYAzeQqm64WmMlc7UYeb9lL+yxvCq4+MXH2V/SKqg GLOF95DCdqj1EeZCOt0aN1ybZPcYFFkmpXrD1iLu0Mhy7Qo/vghX/eFoFnLleD+Y yM+LTg== =d2hZ -----END PGP SIGNATURE----- Merge tag 'pull-tcg-20230423' of https://gitlab.com/rth7680/qemu into staging tcg cleanups: - Remove tcg_abort() - Split out extensions as known backend interfaces - Put the separate extensions together as tcg_out_movext - Introduce tcg_out_xchg as a backend interface - Clear TCGLabelQemuLdst on allocation - Avoid redundant extensions for riscv # -----BEGIN PGP SIGNATURE----- # # iQFRBAABCgA7FiEEekgeeIaLTbaoWgXAZN846K9+IV8FAmRE69sdHHJpY2hhcmQu # aGVuZGVyc29uQGxpbmFyby5vcmcACgkQZN846K9+IV/6jQf6Al9cgeJ6guVMpoRS # +sXaTs5U2yaqRvz5gGn2ANFuFgD2QanbWHjS5guTnhbsvq3icyOCpIXIPg/Z04LB # fTgAUCF5ut8U8C12HyGq/p4BFoTTWnCGPwY+PB9pMb5LiEcmaSUUz+fSA8xMX1b6 # EylI8YNd74A9j5PBNbGIXooj8llM71p9YztwQ9V7sPH3ZON4qbPRDgrJsb5TngMa # daTpGoW+A9UyG7z0Ie6UuiOyYAzeQqm64WmMlc7UYeb9lL+yxvCq4+MXH2V/SKqg # GLOF95DCdqj1EeZCOt0aN1ybZPcYFFkmpXrD1iLu0Mhy7Qo/vghX/eFoFnLleD+Y # yM+LTg== # =d2hZ # -----END PGP SIGNATURE----- # gpg: Signature made Sun 23 Apr 2023 09:27:07 AM BST # gpg: using RSA key 7A481E78868B4DB6A85A05C064DF38E8AF7E215F # gpg: issuer "richard.henderson@linaro.org" # gpg: Good signature from "Richard Henderson <richard.henderson@linaro.org>" [ultimate] * tag 'pull-tcg-20230423' of https://gitlab.com/rth7680/qemu: tcg/riscv: Conditionalize tcg_out_exts_i32_i64 tcg: Clear TCGLabelQemuLdst on allocation tcg: Introduce tcg_out_xchg tcg: Introduce tcg_out_movext tcg: Split out tcg_out_extrl_i64_i32 tcg: Split out tcg_out_extu_i32_i64 tcg: Split out tcg_out_exts_i32_i64 tcg: Split out tcg_out_ext32u tcg: Split out tcg_out_ext32s tcg: Split out tcg_out_ext16u tcg: Split out tcg_out_ext16s tcg: Split out tcg_out_ext8u tcg: Split out tcg_out_ext8s tcg: Replace tcg_abort with g_assert_not_reached tcg: Replace if + tcg_abort with tcg_debug_assert Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
This commit is contained in:
commit
327ec8d6c2
@ -967,12 +967,6 @@ typedef struct TCGTargetOpDef {
|
|||||||
const char *args_ct_str[TCG_MAX_OP_ARGS];
|
const char *args_ct_str[TCG_MAX_OP_ARGS];
|
||||||
} TCGTargetOpDef;
|
} TCGTargetOpDef;
|
||||||
|
|
||||||
#define tcg_abort() \
|
|
||||||
do {\
|
|
||||||
fprintf(stderr, "%s:%d: tcg fatal error\n", __FILE__, __LINE__);\
|
|
||||||
abort();\
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
bool tcg_op_supported(TCGOpcode op);
|
bool tcg_op_supported(TCGOpcode op);
|
||||||
|
|
||||||
void tcg_gen_callN(void *func, TCGTemp *ret, int nargs, TCGTemp **args);
|
void tcg_gen_callN(void *func, TCGTemp *ret, int nargs, TCGTemp **args);
|
||||||
|
@ -476,7 +476,7 @@ static TCGv gen_op_deposit_reg_v(DisasContext *s, MemOp ot, int reg, TCGv dest,
|
|||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
default:
|
default:
|
||||||
tcg_abort();
|
g_assert_not_reached();
|
||||||
}
|
}
|
||||||
return cpu_regs[reg];
|
return cpu_regs[reg];
|
||||||
}
|
}
|
||||||
@ -660,7 +660,7 @@ static void gen_lea_v_seg(DisasContext *s, MemOp aflag, TCGv a0,
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
tcg_abort();
|
g_assert_not_reached();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ovr_seg >= 0) {
|
if (ovr_seg >= 0) {
|
||||||
@ -765,7 +765,7 @@ static void gen_helper_in_func(MemOp ot, TCGv v, TCGv_i32 n)
|
|||||||
gen_helper_inl(v, cpu_env, n);
|
gen_helper_inl(v, cpu_env, n);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
tcg_abort();
|
g_assert_not_reached();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -782,7 +782,7 @@ static void gen_helper_out_func(MemOp ot, TCGv_i32 v, TCGv_i32 n)
|
|||||||
gen_helper_outl(cpu_env, v, n);
|
gen_helper_outl(cpu_env, v, n);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
tcg_abort();
|
g_assert_not_reached();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1932,7 +1932,7 @@ static void gen_rotc_rm_T1(DisasContext *s, MemOp ot, int op1,
|
|||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
default:
|
default:
|
||||||
tcg_abort();
|
g_assert_not_reached();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
switch (ot) {
|
switch (ot) {
|
||||||
@ -1951,7 +1951,7 @@ static void gen_rotc_rm_T1(DisasContext *s, MemOp ot, int op1,
|
|||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
default:
|
default:
|
||||||
tcg_abort();
|
g_assert_not_reached();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* store */
|
/* store */
|
||||||
@ -2282,7 +2282,7 @@ static AddressParts gen_lea_modrm_0(CPUX86State *env, DisasContext *s,
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
tcg_abort();
|
g_assert_not_reached();
|
||||||
}
|
}
|
||||||
|
|
||||||
done:
|
done:
|
||||||
@ -2434,7 +2434,7 @@ static inline uint32_t insn_get(CPUX86State *env, DisasContext *s, MemOp ot)
|
|||||||
ret = x86_ldl_code(env, s);
|
ret = x86_ldl_code(env, s);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
tcg_abort();
|
g_assert_not_reached();
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -3723,7 +3723,7 @@ static bool disas_insn(DisasContext *s, CPUState *cpu)
|
|||||||
gen_op_mov_reg_v(s, MO_16, R_EAX, s->T0);
|
gen_op_mov_reg_v(s, MO_16, R_EAX, s->T0);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
tcg_abort();
|
g_assert_not_reached();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 0x99: /* CDQ/CWD */
|
case 0x99: /* CDQ/CWD */
|
||||||
@ -3748,7 +3748,7 @@ static bool disas_insn(DisasContext *s, CPUState *cpu)
|
|||||||
gen_op_mov_reg_v(s, MO_16, R_EDX, s->T0);
|
gen_op_mov_reg_v(s, MO_16, R_EDX, s->T0);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
tcg_abort();
|
g_assert_not_reached();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 0x1af: /* imul Gv, Ev */
|
case 0x1af: /* imul Gv, Ev */
|
||||||
|
@ -418,7 +418,7 @@ static int get_mem_index(DisasContext *s)
|
|||||||
case PSW_ASC_HOME >> FLAG_MASK_PSW_SHIFT:
|
case PSW_ASC_HOME >> FLAG_MASK_PSW_SHIFT:
|
||||||
return MMU_HOME_IDX;
|
return MMU_HOME_IDX;
|
||||||
default:
|
default:
|
||||||
tcg_abort();
|
g_assert_not_reached();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -652,7 +652,7 @@ static void gen_op_calc_cc(DisasContext *s)
|
|||||||
gen_helper_calc_cc(cc_op, cpu_env, cc_op, cc_src, cc_dst, cc_vr);
|
gen_helper_calc_cc(cc_op, cpu_env, cc_op, cc_src, cc_dst, cc_vr);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
tcg_abort();
|
g_assert_not_reached();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* We now have cc in cc_op as constant */
|
/* We now have cc in cc_op as constant */
|
||||||
|
@ -1106,6 +1106,11 @@ static void tcg_out_movi(TCGContext *s, TCGType type, TCGReg rd,
|
|||||||
tcg_out_insn(s, 3305, LDR, 0, rd);
|
tcg_out_insn(s, 3305, LDR, 0, rd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool tcg_out_xchg(TCGContext *s, TCGType type, TCGReg r1, TCGReg r2)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
static void tcg_out_addi_ptr(TCGContext *s, TCGReg rd, TCGReg rs,
|
static void tcg_out_addi_ptr(TCGContext *s, TCGReg rd, TCGReg rs,
|
||||||
tcg_target_long imm)
|
tcg_target_long imm)
|
||||||
{
|
{
|
||||||
@ -1419,6 +1424,26 @@ static inline void tcg_out_sxt(TCGContext *s, TCGType ext, MemOp s_bits,
|
|||||||
tcg_out_sbfm(s, ext, rd, rn, 0, bits);
|
tcg_out_sbfm(s, ext, rd, rn, 0, bits);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void tcg_out_ext8s(TCGContext *s, TCGType type, TCGReg rd, TCGReg rn)
|
||||||
|
{
|
||||||
|
tcg_out_sxt(s, type, MO_8, rd, rn);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void tcg_out_ext16s(TCGContext *s, TCGType type, TCGReg rd, TCGReg rn)
|
||||||
|
{
|
||||||
|
tcg_out_sxt(s, type, MO_16, rd, rn);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void tcg_out_ext32s(TCGContext *s, TCGReg rd, TCGReg rn)
|
||||||
|
{
|
||||||
|
tcg_out_sxt(s, TCG_TYPE_I64, MO_32, rd, rn);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void tcg_out_exts_i32_i64(TCGContext *s, TCGReg rd, TCGReg rn)
|
||||||
|
{
|
||||||
|
tcg_out_ext32s(s, rd, rn);
|
||||||
|
}
|
||||||
|
|
||||||
static inline void tcg_out_uxt(TCGContext *s, MemOp s_bits,
|
static inline void tcg_out_uxt(TCGContext *s, MemOp s_bits,
|
||||||
TCGReg rd, TCGReg rn)
|
TCGReg rd, TCGReg rn)
|
||||||
{
|
{
|
||||||
@ -1427,6 +1452,31 @@ static inline void tcg_out_uxt(TCGContext *s, MemOp s_bits,
|
|||||||
tcg_out_ubfm(s, 0, rd, rn, 0, bits);
|
tcg_out_ubfm(s, 0, rd, rn, 0, bits);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void tcg_out_ext8u(TCGContext *s, TCGReg rd, TCGReg rn)
|
||||||
|
{
|
||||||
|
tcg_out_uxt(s, MO_8, rd, rn);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void tcg_out_ext16u(TCGContext *s, TCGReg rd, TCGReg rn)
|
||||||
|
{
|
||||||
|
tcg_out_uxt(s, MO_16, rd, rn);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void tcg_out_ext32u(TCGContext *s, TCGReg rd, TCGReg rn)
|
||||||
|
{
|
||||||
|
tcg_out_movr(s, TCG_TYPE_I32, rd, rn);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void tcg_out_extu_i32_i64(TCGContext *s, TCGReg rd, TCGReg rn)
|
||||||
|
{
|
||||||
|
tcg_out_ext32u(s, rd, rn);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void tcg_out_extrl_i64_i32(TCGContext *s, TCGReg rd, TCGReg rn)
|
||||||
|
{
|
||||||
|
tcg_out_mov(s, TCG_TYPE_I32, rd, rn);
|
||||||
|
}
|
||||||
|
|
||||||
static void tcg_out_addsubi(TCGContext *s, int ext, TCGReg rd,
|
static void tcg_out_addsubi(TCGContext *s, int ext, TCGReg rd,
|
||||||
TCGReg rn, int64_t aimm)
|
TCGReg rn, int64_t aimm)
|
||||||
{
|
{
|
||||||
@ -1575,7 +1625,6 @@ static bool tcg_out_qemu_ld_slow_path(TCGContext *s, TCGLabelQemuLdst *lb)
|
|||||||
{
|
{
|
||||||
MemOpIdx oi = lb->oi;
|
MemOpIdx oi = lb->oi;
|
||||||
MemOp opc = get_memop(oi);
|
MemOp opc = get_memop(oi);
|
||||||
MemOp size = opc & MO_SIZE;
|
|
||||||
|
|
||||||
if (!reloc_pc19(lb->label_ptr[0], tcg_splitwx_to_rx(s->code_ptr))) {
|
if (!reloc_pc19(lb->label_ptr[0], tcg_splitwx_to_rx(s->code_ptr))) {
|
||||||
return false;
|
return false;
|
||||||
@ -1586,12 +1635,9 @@ static bool tcg_out_qemu_ld_slow_path(TCGContext *s, TCGLabelQemuLdst *lb)
|
|||||||
tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_X2, oi);
|
tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_X2, oi);
|
||||||
tcg_out_adr(s, TCG_REG_X3, lb->raddr);
|
tcg_out_adr(s, TCG_REG_X3, lb->raddr);
|
||||||
tcg_out_call_int(s, qemu_ld_helpers[opc & MO_SIZE]);
|
tcg_out_call_int(s, qemu_ld_helpers[opc & MO_SIZE]);
|
||||||
if (opc & MO_SIGN) {
|
|
||||||
tcg_out_sxt(s, lb->type, size, lb->datalo_reg, TCG_REG_X0);
|
|
||||||
} else {
|
|
||||||
tcg_out_mov(s, size == MO_64, lb->datalo_reg, TCG_REG_X0);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
tcg_out_movext(s, lb->type, lb->datalo_reg,
|
||||||
|
TCG_TYPE_REG, opc & MO_SSIZE, TCG_REG_X0);
|
||||||
tcg_out_goto(s, lb->raddr);
|
tcg_out_goto(s, lb->raddr);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -1778,7 +1824,7 @@ static void tcg_out_qemu_ld_direct(TCGContext *s, MemOp memop, TCGType ext,
|
|||||||
tcg_out_ldst_r(s, I3312_LDRX, data_r, addr_r, otype, off_r);
|
tcg_out_ldst_r(s, I3312_LDRX, data_r, addr_r, otype, off_r);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
tcg_abort();
|
g_assert_not_reached();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1800,7 +1846,7 @@ static void tcg_out_qemu_st_direct(TCGContext *s, MemOp memop,
|
|||||||
tcg_out_ldst_r(s, I3312_STRX, data_r, addr_r, otype, off_r);
|
tcg_out_ldst_r(s, I3312_STRX, data_r, addr_r, otype, off_r);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
tcg_abort();
|
g_assert_not_reached();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2212,7 +2258,7 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc,
|
|||||||
case INDEX_op_bswap32_i64:
|
case INDEX_op_bswap32_i64:
|
||||||
tcg_out_rev(s, TCG_TYPE_I32, MO_32, a0, a1);
|
tcg_out_rev(s, TCG_TYPE_I32, MO_32, a0, a1);
|
||||||
if (a2 & TCG_BSWAP_OS) {
|
if (a2 & TCG_BSWAP_OS) {
|
||||||
tcg_out_sxt(s, TCG_TYPE_I64, MO_32, a0, a0);
|
tcg_out_ext32s(s, a0, a0);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case INDEX_op_bswap32_i32:
|
case INDEX_op_bswap32_i32:
|
||||||
@ -2223,38 +2269,13 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc,
|
|||||||
tcg_out_rev(s, TCG_TYPE_I32, MO_16, a0, a1);
|
tcg_out_rev(s, TCG_TYPE_I32, MO_16, a0, a1);
|
||||||
if (a2 & TCG_BSWAP_OS) {
|
if (a2 & TCG_BSWAP_OS) {
|
||||||
/* Output must be sign-extended. */
|
/* Output must be sign-extended. */
|
||||||
tcg_out_sxt(s, ext, MO_16, a0, a0);
|
tcg_out_ext16s(s, ext, a0, a0);
|
||||||
} else if ((a2 & (TCG_BSWAP_IZ | TCG_BSWAP_OZ)) == TCG_BSWAP_OZ) {
|
} else if ((a2 & (TCG_BSWAP_IZ | TCG_BSWAP_OZ)) == TCG_BSWAP_OZ) {
|
||||||
/* Output must be zero-extended, but input isn't. */
|
/* Output must be zero-extended, but input isn't. */
|
||||||
tcg_out_uxt(s, MO_16, a0, a0);
|
tcg_out_ext16u(s, a0, a0);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case INDEX_op_ext8s_i64:
|
|
||||||
case INDEX_op_ext8s_i32:
|
|
||||||
tcg_out_sxt(s, ext, MO_8, a0, a1);
|
|
||||||
break;
|
|
||||||
case INDEX_op_ext16s_i64:
|
|
||||||
case INDEX_op_ext16s_i32:
|
|
||||||
tcg_out_sxt(s, ext, MO_16, a0, a1);
|
|
||||||
break;
|
|
||||||
case INDEX_op_ext_i32_i64:
|
|
||||||
case INDEX_op_ext32s_i64:
|
|
||||||
tcg_out_sxt(s, TCG_TYPE_I64, MO_32, a0, a1);
|
|
||||||
break;
|
|
||||||
case INDEX_op_ext8u_i64:
|
|
||||||
case INDEX_op_ext8u_i32:
|
|
||||||
tcg_out_uxt(s, MO_8, a0, a1);
|
|
||||||
break;
|
|
||||||
case INDEX_op_ext16u_i64:
|
|
||||||
case INDEX_op_ext16u_i32:
|
|
||||||
tcg_out_uxt(s, MO_16, a0, a1);
|
|
||||||
break;
|
|
||||||
case INDEX_op_extu_i32_i64:
|
|
||||||
case INDEX_op_ext32u_i64:
|
|
||||||
tcg_out_movr(s, TCG_TYPE_I32, a0, a1);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case INDEX_op_deposit_i64:
|
case INDEX_op_deposit_i64:
|
||||||
case INDEX_op_deposit_i32:
|
case INDEX_op_deposit_i32:
|
||||||
tcg_out_dep(s, ext, a0, REG0(2), args[3], args[4]);
|
tcg_out_dep(s, ext, a0, REG0(2), args[3], args[4]);
|
||||||
@ -2310,6 +2331,19 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc,
|
|||||||
case INDEX_op_call: /* Always emitted via tcg_out_call. */
|
case INDEX_op_call: /* Always emitted via tcg_out_call. */
|
||||||
case INDEX_op_exit_tb: /* Always emitted via tcg_out_exit_tb. */
|
case INDEX_op_exit_tb: /* Always emitted via tcg_out_exit_tb. */
|
||||||
case INDEX_op_goto_tb: /* Always emitted via tcg_out_goto_tb. */
|
case INDEX_op_goto_tb: /* Always emitted via tcg_out_goto_tb. */
|
||||||
|
case INDEX_op_ext8s_i32: /* Always emitted via tcg_reg_alloc_op. */
|
||||||
|
case INDEX_op_ext8s_i64:
|
||||||
|
case INDEX_op_ext8u_i32:
|
||||||
|
case INDEX_op_ext8u_i64:
|
||||||
|
case INDEX_op_ext16s_i64:
|
||||||
|
case INDEX_op_ext16s_i32:
|
||||||
|
case INDEX_op_ext16u_i64:
|
||||||
|
case INDEX_op_ext16u_i32:
|
||||||
|
case INDEX_op_ext32s_i64:
|
||||||
|
case INDEX_op_ext32u_i64:
|
||||||
|
case INDEX_op_ext_i32_i64:
|
||||||
|
case INDEX_op_extu_i32_i64:
|
||||||
|
case INDEX_op_extrl_i64_i32:
|
||||||
default:
|
default:
|
||||||
g_assert_not_reached();
|
g_assert_not_reached();
|
||||||
}
|
}
|
||||||
|
@ -958,30 +958,66 @@ static void tcg_out_udiv(TCGContext *s, ARMCond cond,
|
|||||||
tcg_out32(s, 0x0730f010 | (cond << 28) | (rd << 16) | rn | (rm << 8));
|
tcg_out32(s, 0x0730f010 | (cond << 28) | (rd << 16) | rn | (rm << 8));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void tcg_out_ext8s(TCGContext *s, ARMCond cond, TCGReg rd, TCGReg rn)
|
static void tcg_out_ext8s(TCGContext *s, TCGType t, TCGReg rd, TCGReg rn)
|
||||||
{
|
{
|
||||||
/* sxtb */
|
/* sxtb */
|
||||||
tcg_out32(s, 0x06af0070 | (cond << 28) | (rd << 12) | rn);
|
tcg_out32(s, 0x06af0070 | (COND_AL << 28) | (rd << 12) | rn);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void tcg_out_ext8u(TCGContext *s, TCGReg rd, TCGReg rn)
|
||||||
|
{
|
||||||
|
tcg_out_dat_imm(s, COND_AL, ARITH_AND, rd, rn, 0xff);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void __attribute__((unused))
|
static void __attribute__((unused))
|
||||||
tcg_out_ext8u(TCGContext *s, ARMCond cond, TCGReg rd, TCGReg rn)
|
tcg_out_ext8u_cond(TCGContext *s, ARMCond cond, TCGReg rd, TCGReg rn)
|
||||||
{
|
{
|
||||||
tcg_out_dat_imm(s, cond, ARITH_AND, rd, rn, 0xff);
|
tcg_out_dat_imm(s, cond, ARITH_AND, rd, rn, 0xff);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void tcg_out_ext16s(TCGContext *s, ARMCond cond, TCGReg rd, TCGReg rn)
|
static void tcg_out_ext16s(TCGContext *s, TCGType t, TCGReg rd, TCGReg rn)
|
||||||
{
|
{
|
||||||
/* sxth */
|
/* sxth */
|
||||||
tcg_out32(s, 0x06bf0070 | (cond << 28) | (rd << 12) | rn);
|
tcg_out32(s, 0x06bf0070 | (COND_AL << 28) | (rd << 12) | rn);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void tcg_out_ext16u(TCGContext *s, ARMCond cond, TCGReg rd, TCGReg rn)
|
static void tcg_out_ext16u_cond(TCGContext *s, ARMCond cond,
|
||||||
|
TCGReg rd, TCGReg rn)
|
||||||
{
|
{
|
||||||
/* uxth */
|
/* uxth */
|
||||||
tcg_out32(s, 0x06ff0070 | (cond << 28) | (rd << 12) | rn);
|
tcg_out32(s, 0x06ff0070 | (cond << 28) | (rd << 12) | rn);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void tcg_out_ext16u(TCGContext *s, TCGReg rd, TCGReg rn)
|
||||||
|
{
|
||||||
|
tcg_out_ext16u_cond(s, COND_AL, rd, rn);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void tcg_out_ext32s(TCGContext *s, TCGReg rd, TCGReg rn)
|
||||||
|
{
|
||||||
|
g_assert_not_reached();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void tcg_out_ext32u(TCGContext *s, TCGReg rd, TCGReg rn)
|
||||||
|
{
|
||||||
|
g_assert_not_reached();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void tcg_out_exts_i32_i64(TCGContext *s, TCGReg rd, TCGReg rn)
|
||||||
|
{
|
||||||
|
g_assert_not_reached();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void tcg_out_extu_i32_i64(TCGContext *s, TCGReg rd, TCGReg rn)
|
||||||
|
{
|
||||||
|
g_assert_not_reached();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void tcg_out_extrl_i64_i32(TCGContext *s, TCGReg rd, TCGReg rn)
|
||||||
|
{
|
||||||
|
g_assert_not_reached();
|
||||||
|
}
|
||||||
|
|
||||||
static void tcg_out_bswap16(TCGContext *s, ARMCond cond,
|
static void tcg_out_bswap16(TCGContext *s, ARMCond cond,
|
||||||
TCGReg rd, TCGReg rn, int flags)
|
TCGReg rd, TCGReg rn, int flags)
|
||||||
{
|
{
|
||||||
@ -1365,10 +1401,10 @@ static TCGReg NAME(TCGContext *s, TCGReg argreg, ARGTYPE arg) \
|
|||||||
|
|
||||||
DEFINE_TCG_OUT_ARG(tcg_out_arg_imm32, uint32_t, tcg_out_movi32,
|
DEFINE_TCG_OUT_ARG(tcg_out_arg_imm32, uint32_t, tcg_out_movi32,
|
||||||
(tcg_out_movi32(s, COND_AL, TCG_REG_TMP, arg), arg = TCG_REG_TMP))
|
(tcg_out_movi32(s, COND_AL, TCG_REG_TMP, arg), arg = TCG_REG_TMP))
|
||||||
DEFINE_TCG_OUT_ARG(tcg_out_arg_reg8, TCGReg, tcg_out_ext8u,
|
DEFINE_TCG_OUT_ARG(tcg_out_arg_reg8, TCGReg, tcg_out_ext8u_cond,
|
||||||
(tcg_out_ext8u(s, COND_AL, TCG_REG_TMP, arg), arg = TCG_REG_TMP))
|
(tcg_out_ext8u_cond(s, COND_AL, TCG_REG_TMP, arg), arg = TCG_REG_TMP))
|
||||||
DEFINE_TCG_OUT_ARG(tcg_out_arg_reg16, TCGReg, tcg_out_ext16u,
|
DEFINE_TCG_OUT_ARG(tcg_out_arg_reg16, TCGReg, tcg_out_ext16u_cond,
|
||||||
(tcg_out_ext16u(s, COND_AL, TCG_REG_TMP, arg), arg = TCG_REG_TMP))
|
(tcg_out_ext16u_cond(s, COND_AL, TCG_REG_TMP, arg), arg = TCG_REG_TMP))
|
||||||
DEFINE_TCG_OUT_ARG(tcg_out_arg_reg32, TCGReg, tcg_out_mov_reg, )
|
DEFINE_TCG_OUT_ARG(tcg_out_arg_reg32, TCGReg, tcg_out_mov_reg, )
|
||||||
|
|
||||||
static TCGReg tcg_out_arg_reg64(TCGContext *s, TCGReg argreg,
|
static TCGReg tcg_out_arg_reg64(TCGContext *s, TCGReg argreg,
|
||||||
@ -1531,17 +1567,7 @@ static bool tcg_out_qemu_ld_slow_path(TCGContext *s, TCGLabelQemuLdst *lb)
|
|||||||
|
|
||||||
datalo = lb->datalo_reg;
|
datalo = lb->datalo_reg;
|
||||||
datahi = lb->datahi_reg;
|
datahi = lb->datahi_reg;
|
||||||
switch (opc & MO_SSIZE) {
|
if ((opc & MO_SIZE) == MO_64) {
|
||||||
case MO_SB:
|
|
||||||
tcg_out_ext8s(s, COND_AL, datalo, TCG_REG_R0);
|
|
||||||
break;
|
|
||||||
case MO_SW:
|
|
||||||
tcg_out_ext16s(s, COND_AL, datalo, TCG_REG_R0);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
tcg_out_mov_reg(s, COND_AL, datalo, TCG_REG_R0);
|
|
||||||
break;
|
|
||||||
case MO_UQ:
|
|
||||||
if (datalo != TCG_REG_R1) {
|
if (datalo != TCG_REG_R1) {
|
||||||
tcg_out_mov_reg(s, COND_AL, datalo, TCG_REG_R0);
|
tcg_out_mov_reg(s, COND_AL, datalo, TCG_REG_R0);
|
||||||
tcg_out_mov_reg(s, COND_AL, datahi, TCG_REG_R1);
|
tcg_out_mov_reg(s, COND_AL, datahi, TCG_REG_R1);
|
||||||
@ -1553,7 +1579,9 @@ static bool tcg_out_qemu_ld_slow_path(TCGContext *s, TCGLabelQemuLdst *lb)
|
|||||||
tcg_out_mov_reg(s, COND_AL, datahi, TCG_REG_R1);
|
tcg_out_mov_reg(s, COND_AL, datahi, TCG_REG_R1);
|
||||||
tcg_out_mov_reg(s, COND_AL, datalo, TCG_REG_TMP);
|
tcg_out_mov_reg(s, COND_AL, datalo, TCG_REG_TMP);
|
||||||
}
|
}
|
||||||
break;
|
} else {
|
||||||
|
tcg_out_movext(s, TCG_TYPE_I32, datalo,
|
||||||
|
TCG_TYPE_I32, opc & MO_SSIZE, TCG_REG_R0);
|
||||||
}
|
}
|
||||||
|
|
||||||
tcg_out_goto(s, COND_AL, lb->raddr);
|
tcg_out_goto(s, COND_AL, lb->raddr);
|
||||||
@ -2244,16 +2272,6 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc,
|
|||||||
tcg_out_bswap32(s, COND_AL, args[0], args[1]);
|
tcg_out_bswap32(s, COND_AL, args[0], args[1]);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case INDEX_op_ext8s_i32:
|
|
||||||
tcg_out_ext8s(s, COND_AL, args[0], args[1]);
|
|
||||||
break;
|
|
||||||
case INDEX_op_ext16s_i32:
|
|
||||||
tcg_out_ext16s(s, COND_AL, args[0], args[1]);
|
|
||||||
break;
|
|
||||||
case INDEX_op_ext16u_i32:
|
|
||||||
tcg_out_ext16u(s, COND_AL, args[0], args[1]);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case INDEX_op_deposit_i32:
|
case INDEX_op_deposit_i32:
|
||||||
tcg_out_deposit(s, COND_AL, args[0], args[2],
|
tcg_out_deposit(s, COND_AL, args[0], args[2],
|
||||||
args[3], args[4], const_args[2]);
|
args[3], args[4], const_args[2]);
|
||||||
@ -2301,8 +2319,12 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc,
|
|||||||
case INDEX_op_call: /* Always emitted via tcg_out_call. */
|
case INDEX_op_call: /* Always emitted via tcg_out_call. */
|
||||||
case INDEX_op_exit_tb: /* Always emitted via tcg_out_exit_tb. */
|
case INDEX_op_exit_tb: /* Always emitted via tcg_out_exit_tb. */
|
||||||
case INDEX_op_goto_tb: /* Always emitted via tcg_out_goto_tb. */
|
case INDEX_op_goto_tb: /* Always emitted via tcg_out_goto_tb. */
|
||||||
|
case INDEX_op_ext8s_i32: /* Always emitted via tcg_reg_alloc_op. */
|
||||||
|
case INDEX_op_ext8u_i32:
|
||||||
|
case INDEX_op_ext16s_i32:
|
||||||
|
case INDEX_op_ext16u_i32:
|
||||||
default:
|
default:
|
||||||
tcg_abort();
|
g_assert_not_reached();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2585,6 +2607,11 @@ static void tcg_out_movi(TCGContext *s, TCGType type,
|
|||||||
tcg_out_movi32(s, COND_AL, ret, arg);
|
tcg_out_movi32(s, COND_AL, ret, arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool tcg_out_xchg(TCGContext *s, TCGType type, TCGReg r1, TCGReg r2)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
static void tcg_out_addi_ptr(TCGContext *s, TCGReg rd, TCGReg rs,
|
static void tcg_out_addi_ptr(TCGContext *s, TCGReg rd, TCGReg rs,
|
||||||
tcg_target_long imm)
|
tcg_target_long imm)
|
||||||
{
|
{
|
||||||
|
@ -218,7 +218,7 @@ static bool patch_reloc(tcg_insn_unit *code_ptr, int type,
|
|||||||
tcg_patch8(code_ptr, value);
|
tcg_patch8(code_ptr, value);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
tcg_abort();
|
g_assert_not_reached();
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -460,6 +460,7 @@ static bool tcg_target_const_match(int64_t val, TCGType type, int ct)
|
|||||||
#define OPC_VPTERNLOGQ (0x25 | P_EXT3A | P_DATA16 | P_VEXW | P_EVEX)
|
#define OPC_VPTERNLOGQ (0x25 | P_EXT3A | P_DATA16 | P_VEXW | P_EVEX)
|
||||||
#define OPC_VZEROUPPER (0x77 | P_EXT)
|
#define OPC_VZEROUPPER (0x77 | P_EXT)
|
||||||
#define OPC_XCHG_ax_r32 (0x90)
|
#define OPC_XCHG_ax_r32 (0x90)
|
||||||
|
#define OPC_XCHG_EvGv (0x87)
|
||||||
|
|
||||||
#define OPC_GRP3_Eb (0xf6)
|
#define OPC_GRP3_Eb (0xf6)
|
||||||
#define OPC_GRP3_Ev (0xf7)
|
#define OPC_GRP3_Ev (0xf7)
|
||||||
@ -1078,6 +1079,13 @@ static void tcg_out_movi(TCGContext *s, TCGType type,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool tcg_out_xchg(TCGContext *s, TCGType type, TCGReg r1, TCGReg r2)
|
||||||
|
{
|
||||||
|
int rexw = type == TCG_TYPE_I32 ? 0 : P_REXW;
|
||||||
|
tcg_out_modrm(s, OPC_XCHG_EvGv + rexw, r1, r2);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
static void tcg_out_addi_ptr(TCGContext *s, TCGReg rd, TCGReg rs,
|
static void tcg_out_addi_ptr(TCGContext *s, TCGReg rd, TCGReg rs,
|
||||||
tcg_target_long imm)
|
tcg_target_long imm)
|
||||||
{
|
{
|
||||||
@ -1095,7 +1103,7 @@ static inline void tcg_out_pushi(TCGContext *s, tcg_target_long val)
|
|||||||
tcg_out_opc(s, OPC_PUSH_Iv, 0, 0, 0);
|
tcg_out_opc(s, OPC_PUSH_Iv, 0, 0, 0);
|
||||||
tcg_out32(s, val);
|
tcg_out32(s, val);
|
||||||
} else {
|
} else {
|
||||||
tcg_abort();
|
g_assert_not_reached();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1259,43 +1267,61 @@ static inline void tcg_out_rolw_8(TCGContext *s, int reg)
|
|||||||
tcg_out_shifti(s, SHIFT_ROL + P_DATA16, reg, 8);
|
tcg_out_shifti(s, SHIFT_ROL + P_DATA16, reg, 8);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void tcg_out_ext8u(TCGContext *s, int dest, int src)
|
static void tcg_out_ext8u(TCGContext *s, TCGReg dest, TCGReg src)
|
||||||
{
|
{
|
||||||
/* movzbl */
|
/* movzbl */
|
||||||
tcg_debug_assert(src < 4 || TCG_TARGET_REG_BITS == 64);
|
tcg_debug_assert(src < 4 || TCG_TARGET_REG_BITS == 64);
|
||||||
tcg_out_modrm(s, OPC_MOVZBL + P_REXB_RM, dest, src);
|
tcg_out_modrm(s, OPC_MOVZBL + P_REXB_RM, dest, src);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void tcg_out_ext8s(TCGContext *s, int dest, int src, int rexw)
|
static void tcg_out_ext8s(TCGContext *s, TCGType type, TCGReg dest, TCGReg src)
|
||||||
{
|
{
|
||||||
|
int rexw = type == TCG_TYPE_I32 ? 0 : P_REXW;
|
||||||
/* movsbl */
|
/* movsbl */
|
||||||
tcg_debug_assert(src < 4 || TCG_TARGET_REG_BITS == 64);
|
tcg_debug_assert(src < 4 || TCG_TARGET_REG_BITS == 64);
|
||||||
tcg_out_modrm(s, OPC_MOVSBL + P_REXB_RM + rexw, dest, src);
|
tcg_out_modrm(s, OPC_MOVSBL + P_REXB_RM + rexw, dest, src);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void tcg_out_ext16u(TCGContext *s, int dest, int src)
|
static void tcg_out_ext16u(TCGContext *s, TCGReg dest, TCGReg src)
|
||||||
{
|
{
|
||||||
/* movzwl */
|
/* movzwl */
|
||||||
tcg_out_modrm(s, OPC_MOVZWL, dest, src);
|
tcg_out_modrm(s, OPC_MOVZWL, dest, src);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void tcg_out_ext16s(TCGContext *s, int dest, int src, int rexw)
|
static void tcg_out_ext16s(TCGContext *s, TCGType type, TCGReg dest, TCGReg src)
|
||||||
{
|
{
|
||||||
|
int rexw = type == TCG_TYPE_I32 ? 0 : P_REXW;
|
||||||
/* movsw[lq] */
|
/* movsw[lq] */
|
||||||
tcg_out_modrm(s, OPC_MOVSWL + rexw, dest, src);
|
tcg_out_modrm(s, OPC_MOVSWL + rexw, dest, src);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void tcg_out_ext32u(TCGContext *s, int dest, int src)
|
static void tcg_out_ext32u(TCGContext *s, TCGReg dest, TCGReg src)
|
||||||
{
|
{
|
||||||
/* 32-bit mov zero extends. */
|
/* 32-bit mov zero extends. */
|
||||||
tcg_out_modrm(s, OPC_MOVL_GvEv, dest, src);
|
tcg_out_modrm(s, OPC_MOVL_GvEv, dest, src);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void tcg_out_ext32s(TCGContext *s, int dest, int src)
|
static void tcg_out_ext32s(TCGContext *s, TCGReg dest, TCGReg src)
|
||||||
{
|
{
|
||||||
|
tcg_debug_assert(TCG_TARGET_REG_BITS == 64);
|
||||||
tcg_out_modrm(s, OPC_MOVSLQ, dest, src);
|
tcg_out_modrm(s, OPC_MOVSLQ, dest, src);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void tcg_out_exts_i32_i64(TCGContext *s, TCGReg dest, TCGReg src)
|
||||||
|
{
|
||||||
|
tcg_out_ext32s(s, dest, src);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void tcg_out_extu_i32_i64(TCGContext *s, TCGReg dest, TCGReg src)
|
||||||
|
{
|
||||||
|
tcg_out_ext32u(s, dest, src);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void tcg_out_extrl_i64_i32(TCGContext *s, TCGReg dest, TCGReg src)
|
||||||
|
{
|
||||||
|
tcg_out_ext32u(s, dest, src);
|
||||||
|
}
|
||||||
|
|
||||||
static inline void tcg_out_bswap64(TCGContext *s, int reg)
|
static inline void tcg_out_bswap64(TCGContext *s, int reg)
|
||||||
{
|
{
|
||||||
tcg_out_opc(s, OPC_BSWAP + P_REXW + LOWREGMASK(reg), 0, reg, 0);
|
tcg_out_opc(s, OPC_BSWAP + P_REXW + LOWREGMASK(reg), 0, reg, 0);
|
||||||
@ -1359,7 +1385,7 @@ static void tgen_arithi(TCGContext *s, int c, int r0,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
tcg_abort();
|
g_assert_not_reached();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void tcg_out_addi(TCGContext *s, int reg, tcg_target_long val)
|
static void tcg_out_addi(TCGContext *s, int reg, tcg_target_long val)
|
||||||
@ -1369,8 +1395,8 @@ static void tcg_out_addi(TCGContext *s, int reg, tcg_target_long val)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Use SMALL != 0 to force a short forward branch. */
|
/* Set SMALL to force a short forward branch. */
|
||||||
static void tcg_out_jxx(TCGContext *s, int opc, TCGLabel *l, int small)
|
static void tcg_out_jxx(TCGContext *s, int opc, TCGLabel *l, bool small)
|
||||||
{
|
{
|
||||||
int32_t val, val1;
|
int32_t val, val1;
|
||||||
|
|
||||||
@ -1385,9 +1411,7 @@ static void tcg_out_jxx(TCGContext *s, int opc, TCGLabel *l, int small)
|
|||||||
}
|
}
|
||||||
tcg_out8(s, val1);
|
tcg_out8(s, val1);
|
||||||
} else {
|
} else {
|
||||||
if (small) {
|
tcg_debug_assert(!small);
|
||||||
tcg_abort();
|
|
||||||
}
|
|
||||||
if (opc == -1) {
|
if (opc == -1) {
|
||||||
tcg_out8(s, OPC_JMP_long);
|
tcg_out8(s, OPC_JMP_long);
|
||||||
tcg_out32(s, val - 5);
|
tcg_out32(s, val - 5);
|
||||||
@ -1525,7 +1549,7 @@ static void tcg_out_brcond2(TCGContext *s, const TCGArg *args,
|
|||||||
label_this, small);
|
label_this, small);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
tcg_abort();
|
g_assert_not_reached();
|
||||||
}
|
}
|
||||||
tcg_out_label(s, label_next);
|
tcg_out_label(s, label_next);
|
||||||
}
|
}
|
||||||
@ -1892,7 +1916,6 @@ static bool tcg_out_qemu_ld_slow_path(TCGContext *s, TCGLabelQemuLdst *l)
|
|||||||
MemOp opc = get_memop(oi);
|
MemOp opc = get_memop(oi);
|
||||||
TCGReg data_reg;
|
TCGReg data_reg;
|
||||||
tcg_insn_unit **label_ptr = &l->label_ptr[0];
|
tcg_insn_unit **label_ptr = &l->label_ptr[0];
|
||||||
int rexw = (l->type == TCG_TYPE_I64 ? P_REXW : 0);
|
|
||||||
|
|
||||||
/* resolve label address */
|
/* resolve label address */
|
||||||
tcg_patch32(label_ptr[0], s->code_ptr - label_ptr[0] - 4);
|
tcg_patch32(label_ptr[0], s->code_ptr - label_ptr[0] - 4);
|
||||||
@ -1929,28 +1952,8 @@ static bool tcg_out_qemu_ld_slow_path(TCGContext *s, TCGLabelQemuLdst *l)
|
|||||||
tcg_out_branch(s, 1, qemu_ld_helpers[opc & (MO_BSWAP | MO_SIZE)]);
|
tcg_out_branch(s, 1, qemu_ld_helpers[opc & (MO_BSWAP | MO_SIZE)]);
|
||||||
|
|
||||||
data_reg = l->datalo_reg;
|
data_reg = l->datalo_reg;
|
||||||
switch (opc & MO_SSIZE) {
|
if (TCG_TARGET_REG_BITS == 32 && (opc & MO_SIZE) == MO_64) {
|
||||||
case MO_SB:
|
if (data_reg == TCG_REG_EDX) {
|
||||||
tcg_out_ext8s(s, data_reg, TCG_REG_EAX, rexw);
|
|
||||||
break;
|
|
||||||
case MO_SW:
|
|
||||||
tcg_out_ext16s(s, data_reg, TCG_REG_EAX, rexw);
|
|
||||||
break;
|
|
||||||
#if TCG_TARGET_REG_BITS == 64
|
|
||||||
case MO_SL:
|
|
||||||
tcg_out_ext32s(s, data_reg, TCG_REG_EAX);
|
|
||||||
break;
|
|
||||||
#endif
|
|
||||||
case MO_UB:
|
|
||||||
case MO_UW:
|
|
||||||
/* Note that the helpers have zero-extended to tcg_target_long. */
|
|
||||||
case MO_UL:
|
|
||||||
tcg_out_mov(s, TCG_TYPE_I32, data_reg, TCG_REG_EAX);
|
|
||||||
break;
|
|
||||||
case MO_UQ:
|
|
||||||
if (TCG_TARGET_REG_BITS == 64) {
|
|
||||||
tcg_out_mov(s, TCG_TYPE_I64, data_reg, TCG_REG_RAX);
|
|
||||||
} else if (data_reg == TCG_REG_EDX) {
|
|
||||||
/* xchg %edx, %eax */
|
/* xchg %edx, %eax */
|
||||||
tcg_out_opc(s, OPC_XCHG_ax_r32 + TCG_REG_EDX, 0, 0, 0);
|
tcg_out_opc(s, OPC_XCHG_ax_r32 + TCG_REG_EDX, 0, 0, 0);
|
||||||
tcg_out_mov(s, TCG_TYPE_I32, l->datahi_reg, TCG_REG_EAX);
|
tcg_out_mov(s, TCG_TYPE_I32, l->datahi_reg, TCG_REG_EAX);
|
||||||
@ -1958,9 +1961,9 @@ static bool tcg_out_qemu_ld_slow_path(TCGContext *s, TCGLabelQemuLdst *l)
|
|||||||
tcg_out_mov(s, TCG_TYPE_I32, data_reg, TCG_REG_EAX);
|
tcg_out_mov(s, TCG_TYPE_I32, data_reg, TCG_REG_EAX);
|
||||||
tcg_out_mov(s, TCG_TYPE_I32, l->datahi_reg, TCG_REG_EDX);
|
tcg_out_mov(s, TCG_TYPE_I32, l->datahi_reg, TCG_REG_EDX);
|
||||||
}
|
}
|
||||||
break;
|
} else {
|
||||||
default:
|
tcg_out_movext(s, l->type, data_reg,
|
||||||
tcg_abort();
|
TCG_TYPE_REG, opc & MO_SSIZE, TCG_REG_EAX);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Jump to the code corresponding to next IR of qemu_st */
|
/* Jump to the code corresponding to next IR of qemu_st */
|
||||||
@ -2154,6 +2157,7 @@ static void tcg_out_qemu_ld_direct(TCGContext *s, TCGReg datalo, TCGReg datahi,
|
|||||||
TCGReg base, int index, intptr_t ofs,
|
TCGReg base, int index, intptr_t ofs,
|
||||||
int seg, bool is64, MemOp memop)
|
int seg, bool is64, MemOp memop)
|
||||||
{
|
{
|
||||||
|
TCGType type = is64 ? TCG_TYPE_I64 : TCG_TYPE_I32;
|
||||||
bool use_movbe = false;
|
bool use_movbe = false;
|
||||||
int rexw = is64 * P_REXW;
|
int rexw = is64 * P_REXW;
|
||||||
int movop = OPC_MOVL_GvEv;
|
int movop = OPC_MOVL_GvEv;
|
||||||
@ -2196,7 +2200,7 @@ static void tcg_out_qemu_ld_direct(TCGContext *s, TCGReg datalo, TCGReg datahi,
|
|||||||
if (use_movbe) {
|
if (use_movbe) {
|
||||||
tcg_out_modrm_sib_offset(s, OPC_MOVBE_GyMy + P_DATA16 + seg,
|
tcg_out_modrm_sib_offset(s, OPC_MOVBE_GyMy + P_DATA16 + seg,
|
||||||
datalo, base, index, 0, ofs);
|
datalo, base, index, 0, ofs);
|
||||||
tcg_out_ext16s(s, datalo, datalo, rexw);
|
tcg_out_ext16s(s, type, datalo, datalo);
|
||||||
} else {
|
} else {
|
||||||
tcg_out_modrm_sib_offset(s, OPC_MOVSWL + rexw + seg,
|
tcg_out_modrm_sib_offset(s, OPC_MOVSWL + rexw + seg,
|
||||||
datalo, base, index, 0, ofs);
|
datalo, base, index, 0, ofs);
|
||||||
@ -2671,19 +2675,6 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
|
|||||||
tcg_out_modrm(s, OPC_GRP3_Ev + rexw, EXT3_NOT, a0);
|
tcg_out_modrm(s, OPC_GRP3_Ev + rexw, EXT3_NOT, a0);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
OP_32_64(ext8s):
|
|
||||||
tcg_out_ext8s(s, a0, a1, rexw);
|
|
||||||
break;
|
|
||||||
OP_32_64(ext16s):
|
|
||||||
tcg_out_ext16s(s, a0, a1, rexw);
|
|
||||||
break;
|
|
||||||
OP_32_64(ext8u):
|
|
||||||
tcg_out_ext8u(s, a0, a1);
|
|
||||||
break;
|
|
||||||
OP_32_64(ext16u):
|
|
||||||
tcg_out_ext16u(s, a0, a1);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case INDEX_op_qemu_ld_i32:
|
case INDEX_op_qemu_ld_i32:
|
||||||
tcg_out_qemu_ld(s, args, 0);
|
tcg_out_qemu_ld(s, args, 0);
|
||||||
break;
|
break;
|
||||||
@ -2765,15 +2756,6 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
|
|||||||
case INDEX_op_bswap64_i64:
|
case INDEX_op_bswap64_i64:
|
||||||
tcg_out_bswap64(s, a0);
|
tcg_out_bswap64(s, a0);
|
||||||
break;
|
break;
|
||||||
case INDEX_op_extu_i32_i64:
|
|
||||||
case INDEX_op_ext32u_i64:
|
|
||||||
case INDEX_op_extrl_i64_i32:
|
|
||||||
tcg_out_ext32u(s, a0, a1);
|
|
||||||
break;
|
|
||||||
case INDEX_op_ext_i32_i64:
|
|
||||||
case INDEX_op_ext32s_i64:
|
|
||||||
tcg_out_ext32s(s, a0, a1);
|
|
||||||
break;
|
|
||||||
case INDEX_op_extrh_i64_i32:
|
case INDEX_op_extrh_i64_i32:
|
||||||
tcg_out_shifti(s, SHIFT_SHR + P_REXW, a0, 32);
|
tcg_out_shifti(s, SHIFT_SHR + P_REXW, a0, 32);
|
||||||
break;
|
break;
|
||||||
@ -2790,7 +2772,7 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
|
|||||||
/* load bits 0..15 */
|
/* load bits 0..15 */
|
||||||
tcg_out_modrm(s, OPC_MOVL_EvGv | P_DATA16, a2, a0);
|
tcg_out_modrm(s, OPC_MOVL_EvGv | P_DATA16, a2, a0);
|
||||||
} else {
|
} else {
|
||||||
tcg_abort();
|
g_assert_not_reached();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -2823,7 +2805,7 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
|
|||||||
if (a1 < 4 && a0 < 8) {
|
if (a1 < 4 && a0 < 8) {
|
||||||
tcg_out_modrm(s, OPC_MOVSBL, a0, a1 + 4);
|
tcg_out_modrm(s, OPC_MOVSBL, a0, a1 + 4);
|
||||||
} else {
|
} else {
|
||||||
tcg_out_ext16s(s, a0, a1, 0);
|
tcg_out_ext16s(s, TCG_TYPE_I32, a0, a1);
|
||||||
tcg_out_shifti(s, SHIFT_SAR, a0, 8);
|
tcg_out_shifti(s, SHIFT_SAR, a0, 8);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -2842,8 +2824,21 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
|
|||||||
case INDEX_op_call: /* Always emitted via tcg_out_call. */
|
case INDEX_op_call: /* Always emitted via tcg_out_call. */
|
||||||
case INDEX_op_exit_tb: /* Always emitted via tcg_out_exit_tb. */
|
case INDEX_op_exit_tb: /* Always emitted via tcg_out_exit_tb. */
|
||||||
case INDEX_op_goto_tb: /* Always emitted via tcg_out_goto_tb. */
|
case INDEX_op_goto_tb: /* Always emitted via tcg_out_goto_tb. */
|
||||||
|
case INDEX_op_ext8s_i32: /* Always emitted via tcg_reg_alloc_op. */
|
||||||
|
case INDEX_op_ext8s_i64:
|
||||||
|
case INDEX_op_ext8u_i32:
|
||||||
|
case INDEX_op_ext8u_i64:
|
||||||
|
case INDEX_op_ext16s_i32:
|
||||||
|
case INDEX_op_ext16s_i64:
|
||||||
|
case INDEX_op_ext16u_i32:
|
||||||
|
case INDEX_op_ext16u_i64:
|
||||||
|
case INDEX_op_ext32s_i64:
|
||||||
|
case INDEX_op_ext32u_i64:
|
||||||
|
case INDEX_op_ext_i32_i64:
|
||||||
|
case INDEX_op_extu_i32_i64:
|
||||||
|
case INDEX_op_extrl_i64_i32:
|
||||||
default:
|
default:
|
||||||
tcg_abort();
|
g_assert_not_reached();
|
||||||
}
|
}
|
||||||
|
|
||||||
#undef OP_32_64
|
#undef OP_32_64
|
||||||
|
@ -419,6 +419,11 @@ static void tcg_out_addi(TCGContext *s, TCGType type, TCGReg rd,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool tcg_out_xchg(TCGContext *s, TCGType type, TCGReg r1, TCGReg r2)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
static void tcg_out_addi_ptr(TCGContext *s, TCGReg rd, TCGReg rs,
|
static void tcg_out_addi_ptr(TCGContext *s, TCGReg rd, TCGReg rs,
|
||||||
tcg_target_long imm)
|
tcg_target_long imm)
|
||||||
{
|
{
|
||||||
@ -441,12 +446,12 @@ static void tcg_out_ext32u(TCGContext *s, TCGReg ret, TCGReg arg)
|
|||||||
tcg_out_opc_bstrpick_d(s, ret, arg, 0, 31);
|
tcg_out_opc_bstrpick_d(s, ret, arg, 0, 31);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void tcg_out_ext8s(TCGContext *s, TCGReg ret, TCGReg arg)
|
static void tcg_out_ext8s(TCGContext *s, TCGType type, TCGReg ret, TCGReg arg)
|
||||||
{
|
{
|
||||||
tcg_out_opc_sext_b(s, ret, arg);
|
tcg_out_opc_sext_b(s, ret, arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void tcg_out_ext16s(TCGContext *s, TCGReg ret, TCGReg arg)
|
static void tcg_out_ext16s(TCGContext *s, TCGType type, TCGReg ret, TCGReg arg)
|
||||||
{
|
{
|
||||||
tcg_out_opc_sext_h(s, ret, arg);
|
tcg_out_opc_sext_h(s, ret, arg);
|
||||||
}
|
}
|
||||||
@ -456,6 +461,21 @@ static void tcg_out_ext32s(TCGContext *s, TCGReg ret, TCGReg arg)
|
|||||||
tcg_out_opc_addi_w(s, ret, arg, 0);
|
tcg_out_opc_addi_w(s, ret, arg, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void tcg_out_exts_i32_i64(TCGContext *s, TCGReg ret, TCGReg arg)
|
||||||
|
{
|
||||||
|
tcg_out_ext32s(s, ret, arg);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void tcg_out_extu_i32_i64(TCGContext *s, TCGReg ret, TCGReg arg)
|
||||||
|
{
|
||||||
|
tcg_out_ext32u(s, ret, arg);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void tcg_out_extrl_i64_i32(TCGContext *s, TCGReg ret, TCGReg arg)
|
||||||
|
{
|
||||||
|
tcg_out_ext32s(s, ret, arg);
|
||||||
|
}
|
||||||
|
|
||||||
static void tcg_out_clzctz(TCGContext *s, LoongArchInsn opc,
|
static void tcg_out_clzctz(TCGContext *s, LoongArchInsn opc,
|
||||||
TCGReg a0, TCGReg a1, TCGReg a2,
|
TCGReg a0, TCGReg a1, TCGReg a2,
|
||||||
bool c2, bool is_32bit)
|
bool c2, bool is_32bit)
|
||||||
@ -876,7 +896,6 @@ static bool tcg_out_qemu_ld_slow_path(TCGContext *s, TCGLabelQemuLdst *l)
|
|||||||
MemOpIdx oi = l->oi;
|
MemOpIdx oi = l->oi;
|
||||||
MemOp opc = get_memop(oi);
|
MemOp opc = get_memop(oi);
|
||||||
MemOp size = opc & MO_SIZE;
|
MemOp size = opc & MO_SIZE;
|
||||||
TCGType type = l->type;
|
|
||||||
|
|
||||||
/* resolve label address */
|
/* resolve label address */
|
||||||
if (!reloc_br_sk16(l->label_ptr[0], tcg_splitwx_to_rx(s->code_ptr))) {
|
if (!reloc_br_sk16(l->label_ptr[0], tcg_splitwx_to_rx(s->code_ptr))) {
|
||||||
@ -891,28 +910,8 @@ static bool tcg_out_qemu_ld_slow_path(TCGContext *s, TCGLabelQemuLdst *l)
|
|||||||
|
|
||||||
tcg_out_call_int(s, qemu_ld_helpers[size], false);
|
tcg_out_call_int(s, qemu_ld_helpers[size], false);
|
||||||
|
|
||||||
switch (opc & MO_SSIZE) {
|
tcg_out_movext(s, l->type, l->datalo_reg,
|
||||||
case MO_SB:
|
TCG_TYPE_REG, opc & MO_SSIZE, TCG_REG_A0);
|
||||||
tcg_out_ext8s(s, l->datalo_reg, TCG_REG_A0);
|
|
||||||
break;
|
|
||||||
case MO_SW:
|
|
||||||
tcg_out_ext16s(s, l->datalo_reg, TCG_REG_A0);
|
|
||||||
break;
|
|
||||||
case MO_SL:
|
|
||||||
tcg_out_ext32s(s, l->datalo_reg, TCG_REG_A0);
|
|
||||||
break;
|
|
||||||
case MO_UL:
|
|
||||||
if (type == TCG_TYPE_I32) {
|
|
||||||
/* MO_UL loads of i32 should be sign-extended too */
|
|
||||||
tcg_out_ext32s(s, l->datalo_reg, TCG_REG_A0);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
/* fallthrough */
|
|
||||||
default:
|
|
||||||
tcg_out_mov(s, type, l->datalo_reg, TCG_REG_A0);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return tcg_out_goto(s, l->raddr);
|
return tcg_out_goto(s, l->raddr);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -930,23 +929,8 @@ static bool tcg_out_qemu_st_slow_path(TCGContext *s, TCGLabelQemuLdst *l)
|
|||||||
/* call store helper */
|
/* call store helper */
|
||||||
tcg_out_mov(s, TCG_TYPE_PTR, TCG_REG_A0, TCG_AREG0);
|
tcg_out_mov(s, TCG_TYPE_PTR, TCG_REG_A0, TCG_AREG0);
|
||||||
tcg_out_mov(s, TCG_TYPE_PTR, TCG_REG_A1, l->addrlo_reg);
|
tcg_out_mov(s, TCG_TYPE_PTR, TCG_REG_A1, l->addrlo_reg);
|
||||||
switch (size) {
|
tcg_out_movext(s, size == MO_64 ? TCG_TYPE_I32 : TCG_TYPE_I32, TCG_REG_A2,
|
||||||
case MO_8:
|
l->type, size, l->datalo_reg);
|
||||||
tcg_out_ext8u(s, TCG_REG_A2, l->datalo_reg);
|
|
||||||
break;
|
|
||||||
case MO_16:
|
|
||||||
tcg_out_ext16u(s, TCG_REG_A2, l->datalo_reg);
|
|
||||||
break;
|
|
||||||
case MO_32:
|
|
||||||
tcg_out_ext32u(s, TCG_REG_A2, l->datalo_reg);
|
|
||||||
break;
|
|
||||||
case MO_64:
|
|
||||||
tcg_out_mov(s, TCG_TYPE_I64, TCG_REG_A2, l->datalo_reg);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
g_assert_not_reached();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_A3, oi);
|
tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_A3, oi);
|
||||||
tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_A4, (tcg_target_long)l->raddr);
|
tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_A4, (tcg_target_long)l->raddr);
|
||||||
|
|
||||||
@ -1123,7 +1107,7 @@ static void tcg_out_qemu_st_indexed(TCGContext *s, TCGReg data,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args)
|
static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, TCGType type)
|
||||||
{
|
{
|
||||||
TCGReg addr_regl;
|
TCGReg addr_regl;
|
||||||
TCGReg data_regl;
|
TCGReg data_regl;
|
||||||
@ -1145,8 +1129,7 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args)
|
|||||||
tcg_out_tlb_load(s, addr_regl, oi, label_ptr, 0);
|
tcg_out_tlb_load(s, addr_regl, oi, label_ptr, 0);
|
||||||
base = tcg_out_zext_addr_if_32_bit(s, addr_regl, TCG_REG_TMP0);
|
base = tcg_out_zext_addr_if_32_bit(s, addr_regl, TCG_REG_TMP0);
|
||||||
tcg_out_qemu_st_indexed(s, data_regl, base, TCG_REG_TMP2, opc);
|
tcg_out_qemu_st_indexed(s, data_regl, base, TCG_REG_TMP2, opc);
|
||||||
add_qemu_ldst_label(s, 0, oi,
|
add_qemu_ldst_label(s, 0, oi, type,
|
||||||
0, /* type param is unused for stores */
|
|
||||||
data_regl, addr_regl,
|
data_regl, addr_regl,
|
||||||
s->code_ptr, label_ptr);
|
s->code_ptr, label_ptr);
|
||||||
#else
|
#else
|
||||||
@ -1246,37 +1229,6 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc,
|
|||||||
tcg_out_brcond(s, a2, a0, a1, arg_label(args[3]));
|
tcg_out_brcond(s, a2, a0, a1, arg_label(args[3]));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case INDEX_op_ext8s_i32:
|
|
||||||
case INDEX_op_ext8s_i64:
|
|
||||||
tcg_out_ext8s(s, a0, a1);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case INDEX_op_ext8u_i32:
|
|
||||||
case INDEX_op_ext8u_i64:
|
|
||||||
tcg_out_ext8u(s, a0, a1);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case INDEX_op_ext16s_i32:
|
|
||||||
case INDEX_op_ext16s_i64:
|
|
||||||
tcg_out_ext16s(s, a0, a1);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case INDEX_op_ext16u_i32:
|
|
||||||
case INDEX_op_ext16u_i64:
|
|
||||||
tcg_out_ext16u(s, a0, a1);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case INDEX_op_ext32u_i64:
|
|
||||||
case INDEX_op_extu_i32_i64:
|
|
||||||
tcg_out_ext32u(s, a0, a1);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case INDEX_op_ext32s_i64:
|
|
||||||
case INDEX_op_extrl_i64_i32:
|
|
||||||
case INDEX_op_ext_i32_i64:
|
|
||||||
tcg_out_ext32s(s, a0, a1);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case INDEX_op_extrh_i64_i32:
|
case INDEX_op_extrh_i64_i32:
|
||||||
tcg_out_opc_srai_d(s, a0, a1, 32);
|
tcg_out_opc_srai_d(s, a0, a1, 32);
|
||||||
break;
|
break;
|
||||||
@ -1361,7 +1313,7 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc,
|
|||||||
case INDEX_op_bswap16_i64:
|
case INDEX_op_bswap16_i64:
|
||||||
tcg_out_opc_revb_2h(s, a0, a1);
|
tcg_out_opc_revb_2h(s, a0, a1);
|
||||||
if (a2 & TCG_BSWAP_OS) {
|
if (a2 & TCG_BSWAP_OS) {
|
||||||
tcg_out_ext16s(s, a0, a0);
|
tcg_out_ext16s(s, TCG_TYPE_REG, a0, a0);
|
||||||
} else if ((a2 & (TCG_BSWAP_IZ | TCG_BSWAP_OZ)) == TCG_BSWAP_OZ) {
|
} else if ((a2 & (TCG_BSWAP_IZ | TCG_BSWAP_OZ)) == TCG_BSWAP_OZ) {
|
||||||
tcg_out_ext16u(s, a0, a0);
|
tcg_out_ext16u(s, a0, a0);
|
||||||
}
|
}
|
||||||
@ -1616,10 +1568,10 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc,
|
|||||||
tcg_out_qemu_ld(s, args, TCG_TYPE_I64);
|
tcg_out_qemu_ld(s, args, TCG_TYPE_I64);
|
||||||
break;
|
break;
|
||||||
case INDEX_op_qemu_st_i32:
|
case INDEX_op_qemu_st_i32:
|
||||||
tcg_out_qemu_st(s, args);
|
tcg_out_qemu_st(s, args, TCG_TYPE_I32);
|
||||||
break;
|
break;
|
||||||
case INDEX_op_qemu_st_i64:
|
case INDEX_op_qemu_st_i64:
|
||||||
tcg_out_qemu_st(s, args);
|
tcg_out_qemu_st(s, args, TCG_TYPE_I64);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case INDEX_op_mov_i32: /* Always emitted via tcg_out_mov. */
|
case INDEX_op_mov_i32: /* Always emitted via tcg_out_mov. */
|
||||||
@ -1627,6 +1579,19 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc,
|
|||||||
case INDEX_op_call: /* Always emitted via tcg_out_call. */
|
case INDEX_op_call: /* Always emitted via tcg_out_call. */
|
||||||
case INDEX_op_exit_tb: /* Always emitted via tcg_out_exit_tb. */
|
case INDEX_op_exit_tb: /* Always emitted via tcg_out_exit_tb. */
|
||||||
case INDEX_op_goto_tb: /* Always emitted via tcg_out_goto_tb. */
|
case INDEX_op_goto_tb: /* Always emitted via tcg_out_goto_tb. */
|
||||||
|
case INDEX_op_ext8s_i32: /* Always emitted via tcg_reg_alloc_op. */
|
||||||
|
case INDEX_op_ext8s_i64:
|
||||||
|
case INDEX_op_ext8u_i32:
|
||||||
|
case INDEX_op_ext8u_i64:
|
||||||
|
case INDEX_op_ext16s_i32:
|
||||||
|
case INDEX_op_ext16s_i64:
|
||||||
|
case INDEX_op_ext16u_i32:
|
||||||
|
case INDEX_op_ext16u_i64:
|
||||||
|
case INDEX_op_ext32s_i64:
|
||||||
|
case INDEX_op_ext32u_i64:
|
||||||
|
case INDEX_op_ext_i32_i64:
|
||||||
|
case INDEX_op_extu_i32_i64:
|
||||||
|
case INDEX_op_extrl_i64_i32:
|
||||||
default:
|
default:
|
||||||
g_assert_not_reached();
|
g_assert_not_reached();
|
||||||
}
|
}
|
||||||
|
@ -552,6 +552,54 @@ static void tcg_out_movi(TCGContext *s, TCGType type,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void tcg_out_ext8s(TCGContext *s, TCGType type, TCGReg rd, TCGReg rs)
|
||||||
|
{
|
||||||
|
tcg_debug_assert(TCG_TARGET_HAS_ext8s_i32);
|
||||||
|
tcg_out_opc_reg(s, OPC_SEB, rd, TCG_REG_ZERO, rs);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void tcg_out_ext8u(TCGContext *s, TCGReg rd, TCGReg rs)
|
||||||
|
{
|
||||||
|
tcg_out_opc_imm(s, OPC_ANDI, rd, rs, 0xff);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void tcg_out_ext16s(TCGContext *s, TCGType type, TCGReg rd, TCGReg rs)
|
||||||
|
{
|
||||||
|
tcg_debug_assert(TCG_TARGET_HAS_ext16s_i32);
|
||||||
|
tcg_out_opc_reg(s, OPC_SEH, rd, TCG_REG_ZERO, rs);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void tcg_out_ext16u(TCGContext *s, TCGReg rd, TCGReg rs)
|
||||||
|
{
|
||||||
|
tcg_out_opc_imm(s, OPC_ANDI, rd, rs, 0xffff);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void tcg_out_ext32s(TCGContext *s, TCGReg rd, TCGReg rs)
|
||||||
|
{
|
||||||
|
tcg_debug_assert(TCG_TARGET_REG_BITS == 64);
|
||||||
|
tcg_out_opc_sa(s, OPC_SLL, rd, rs, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void tcg_out_exts_i32_i64(TCGContext *s, TCGReg rd, TCGReg rs)
|
||||||
|
{
|
||||||
|
tcg_out_ext32s(s, rd, rs);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void tcg_out_extu_i32_i64(TCGContext *s, TCGReg rd, TCGReg rs)
|
||||||
|
{
|
||||||
|
tcg_out_ext32u(s, rd, rs);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void tcg_out_extrl_i64_i32(TCGContext *s, TCGReg rd, TCGReg rs)
|
||||||
|
{
|
||||||
|
tcg_out_ext32s(s, rd, rs);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool tcg_out_xchg(TCGContext *s, TCGType type, TCGReg r1, TCGReg r2)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
static void tcg_out_addi_ptr(TCGContext *s, TCGReg rd, TCGReg rs,
|
static void tcg_out_addi_ptr(TCGContext *s, TCGReg rd, TCGReg rs,
|
||||||
tcg_target_long imm)
|
tcg_target_long imm)
|
||||||
{
|
{
|
||||||
@ -635,6 +683,7 @@ static void tcg_out_bswap64(TCGContext *s, TCGReg ret, TCGReg arg)
|
|||||||
|
|
||||||
static void tcg_out_ext32u(TCGContext *s, TCGReg ret, TCGReg arg)
|
static void tcg_out_ext32u(TCGContext *s, TCGReg ret, TCGReg arg)
|
||||||
{
|
{
|
||||||
|
tcg_debug_assert(TCG_TARGET_REG_BITS == 64);
|
||||||
if (use_mips32r2_instructions) {
|
if (use_mips32r2_instructions) {
|
||||||
tcg_out_opc_bf(s, OPC_DEXT, ret, arg, 31, 0);
|
tcg_out_opc_bf(s, OPC_DEXT, ret, arg, 31, 0);
|
||||||
} else {
|
} else {
|
||||||
@ -798,7 +847,7 @@ static void tcg_out_setcond(TCGContext *s, TCGCond cond, TCGReg ret,
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
tcg_abort();
|
g_assert_not_reached();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -855,7 +904,7 @@ static void tcg_out_brcond(TCGContext *s, TCGCond cond, TCGReg arg1,
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
tcg_abort();
|
g_assert_not_reached();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1093,7 +1142,7 @@ static int tcg_out_call_iarg_reg8(TCGContext *s, int i, TCGReg arg)
|
|||||||
if (i < ARRAY_SIZE(tcg_target_call_iarg_regs)) {
|
if (i < ARRAY_SIZE(tcg_target_call_iarg_regs)) {
|
||||||
tmp = tcg_target_call_iarg_regs[i];
|
tmp = tcg_target_call_iarg_regs[i];
|
||||||
}
|
}
|
||||||
tcg_out_opc_imm(s, OPC_ANDI, tmp, arg, 0xff);
|
tcg_out_ext8u(s, tmp, arg);
|
||||||
return tcg_out_call_iarg_reg(s, i, tmp);
|
return tcg_out_call_iarg_reg(s, i, tmp);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1291,7 +1340,7 @@ static bool tcg_out_qemu_ld_slow_path(TCGContext *s, TCGLabelQemuLdst *l)
|
|||||||
/* delay slot */
|
/* delay slot */
|
||||||
if (TCG_TARGET_REG_BITS == 64 && l->type == TCG_TYPE_I32) {
|
if (TCG_TARGET_REG_BITS == 64 && l->type == TCG_TYPE_I32) {
|
||||||
/* we always sign-extend 32-bit loads */
|
/* we always sign-extend 32-bit loads */
|
||||||
tcg_out_opc_sa(s, OPC_SLL, v0, TCG_REG_V0, 0);
|
tcg_out_ext32s(s, v0, TCG_REG_V0);
|
||||||
} else {
|
} else {
|
||||||
tcg_out_opc_reg(s, OPC_OR, v0, TCG_REG_V0, TCG_REG_ZERO);
|
tcg_out_opc_reg(s, OPC_OR, v0, TCG_REG_V0, TCG_REG_ZERO);
|
||||||
}
|
}
|
||||||
@ -1337,7 +1386,7 @@ static bool tcg_out_qemu_st_slow_path(TCGContext *s, TCGLabelQemuLdst *l)
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
tcg_abort();
|
g_assert_not_reached();
|
||||||
}
|
}
|
||||||
i = tcg_out_call_iarg_imm(s, i, oi);
|
i = tcg_out_call_iarg_imm(s, i, oi);
|
||||||
|
|
||||||
@ -1527,7 +1576,7 @@ static void tcg_out_qemu_ld_direct(TCGContext *s, TCGReg lo, TCGReg hi,
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
tcg_abort();
|
g_assert_not_reached();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1775,7 +1824,7 @@ static void tcg_out_qemu_st_direct(TCGContext *s, TCGReg lo, TCGReg hi,
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
tcg_abort();
|
g_assert_not_reached();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1848,7 +1897,7 @@ static void tcg_out_qemu_st_unalign(TCGContext *s, TCGReg lo, TCGReg hi,
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
tcg_abort();
|
g_assert_not_reached();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, bool is_64)
|
static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, bool is_64)
|
||||||
@ -2245,13 +2294,6 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc,
|
|||||||
case INDEX_op_not_i64:
|
case INDEX_op_not_i64:
|
||||||
i1 = OPC_NOR;
|
i1 = OPC_NOR;
|
||||||
goto do_unary;
|
goto do_unary;
|
||||||
case INDEX_op_ext8s_i32:
|
|
||||||
case INDEX_op_ext8s_i64:
|
|
||||||
i1 = OPC_SEB;
|
|
||||||
goto do_unary;
|
|
||||||
case INDEX_op_ext16s_i32:
|
|
||||||
case INDEX_op_ext16s_i64:
|
|
||||||
i1 = OPC_SEH;
|
|
||||||
do_unary:
|
do_unary:
|
||||||
tcg_out_opc_reg(s, i1, a0, TCG_REG_ZERO, a1);
|
tcg_out_opc_reg(s, i1, a0, TCG_REG_ZERO, a1);
|
||||||
break;
|
break;
|
||||||
@ -2272,15 +2314,6 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc,
|
|||||||
case INDEX_op_extrh_i64_i32:
|
case INDEX_op_extrh_i64_i32:
|
||||||
tcg_out_dsra(s, a0, a1, 32);
|
tcg_out_dsra(s, a0, a1, 32);
|
||||||
break;
|
break;
|
||||||
case INDEX_op_ext32s_i64:
|
|
||||||
case INDEX_op_ext_i32_i64:
|
|
||||||
case INDEX_op_extrl_i64_i32:
|
|
||||||
tcg_out_opc_sa(s, OPC_SLL, a0, a1, 0);
|
|
||||||
break;
|
|
||||||
case INDEX_op_ext32u_i64:
|
|
||||||
case INDEX_op_extu_i32_i64:
|
|
||||||
tcg_out_ext32u(s, a0, a1);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case INDEX_op_sar_i32:
|
case INDEX_op_sar_i32:
|
||||||
i1 = OPC_SRAV, i2 = OPC_SRA;
|
i1 = OPC_SRAV, i2 = OPC_SRA;
|
||||||
@ -2419,8 +2452,19 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc,
|
|||||||
case INDEX_op_call: /* Always emitted via tcg_out_call. */
|
case INDEX_op_call: /* Always emitted via tcg_out_call. */
|
||||||
case INDEX_op_exit_tb: /* Always emitted via tcg_out_exit_tb. */
|
case INDEX_op_exit_tb: /* Always emitted via tcg_out_exit_tb. */
|
||||||
case INDEX_op_goto_tb: /* Always emitted via tcg_out_goto_tb. */
|
case INDEX_op_goto_tb: /* Always emitted via tcg_out_goto_tb. */
|
||||||
|
case INDEX_op_ext8s_i32: /* Always emitted via tcg_reg_alloc_op. */
|
||||||
|
case INDEX_op_ext8s_i64:
|
||||||
|
case INDEX_op_ext8u_i32:
|
||||||
|
case INDEX_op_ext8u_i64:
|
||||||
|
case INDEX_op_ext16s_i32:
|
||||||
|
case INDEX_op_ext16s_i64:
|
||||||
|
case INDEX_op_ext32s_i64:
|
||||||
|
case INDEX_op_ext32u_i64:
|
||||||
|
case INDEX_op_ext_i32_i64:
|
||||||
|
case INDEX_op_extu_i32_i64:
|
||||||
|
case INDEX_op_extrl_i64_i32:
|
||||||
default:
|
default:
|
||||||
tcg_abort();
|
g_assert_not_reached();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -453,9 +453,7 @@ static uint64_t do_constant_folding_2(TCGOpcode op, uint64_t x, uint64_t y)
|
|||||||
return (uint64_t)x % ((uint64_t)y ? : 1);
|
return (uint64_t)x % ((uint64_t)y ? : 1);
|
||||||
|
|
||||||
default:
|
default:
|
||||||
fprintf(stderr,
|
g_assert_not_reached();
|
||||||
"Unrecognized operation %d in do_constant_folding.\n", op);
|
|
||||||
tcg_abort();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -493,7 +491,7 @@ static bool do_constant_folding_cond_32(uint32_t x, uint32_t y, TCGCond c)
|
|||||||
case TCG_COND_GTU:
|
case TCG_COND_GTU:
|
||||||
return x > y;
|
return x > y;
|
||||||
default:
|
default:
|
||||||
tcg_abort();
|
g_assert_not_reached();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -521,7 +519,7 @@ static bool do_constant_folding_cond_64(uint64_t x, uint64_t y, TCGCond c)
|
|||||||
case TCG_COND_GTU:
|
case TCG_COND_GTU:
|
||||||
return x > y;
|
return x > y;
|
||||||
default:
|
default:
|
||||||
tcg_abort();
|
g_assert_not_reached();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -541,7 +539,7 @@ static bool do_constant_folding_cond_eq(TCGCond c)
|
|||||||
case TCG_COND_EQ:
|
case TCG_COND_EQ:
|
||||||
return 1;
|
return 1;
|
||||||
default:
|
default:
|
||||||
tcg_abort();
|
g_assert_not_reached();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -775,31 +775,54 @@ static inline void tcg_out_rlw(TCGContext *s, int op, TCGReg ra, TCGReg rs,
|
|||||||
tcg_out32(s, op | RA(ra) | RS(rs) | SH(sh) | MB(mb) | ME(me));
|
tcg_out32(s, op | RA(ra) | RS(rs) | SH(sh) | MB(mb) | ME(me));
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void tcg_out_ext8s(TCGContext *s, TCGReg dst, TCGReg src)
|
static void tcg_out_ext8s(TCGContext *s, TCGType type, TCGReg dst, TCGReg src)
|
||||||
{
|
{
|
||||||
tcg_out32(s, EXTSB | RA(dst) | RS(src));
|
tcg_out32(s, EXTSB | RA(dst) | RS(src));
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void tcg_out_ext16s(TCGContext *s, TCGReg dst, TCGReg src)
|
static void tcg_out_ext8u(TCGContext *s, TCGReg dst, TCGReg src)
|
||||||
|
{
|
||||||
|
tcg_out32(s, ANDI | SAI(src, dst, 0xff));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void tcg_out_ext16s(TCGContext *s, TCGType type, TCGReg dst, TCGReg src)
|
||||||
{
|
{
|
||||||
tcg_out32(s, EXTSH | RA(dst) | RS(src));
|
tcg_out32(s, EXTSH | RA(dst) | RS(src));
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void tcg_out_ext16u(TCGContext *s, TCGReg dst, TCGReg src)
|
static void tcg_out_ext16u(TCGContext *s, TCGReg dst, TCGReg src)
|
||||||
{
|
{
|
||||||
tcg_out32(s, ANDI | SAI(src, dst, 0xffff));
|
tcg_out32(s, ANDI | SAI(src, dst, 0xffff));
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void tcg_out_ext32s(TCGContext *s, TCGReg dst, TCGReg src)
|
static void tcg_out_ext32s(TCGContext *s, TCGReg dst, TCGReg src)
|
||||||
{
|
{
|
||||||
|
tcg_debug_assert(TCG_TARGET_REG_BITS == 64);
|
||||||
tcg_out32(s, EXTSW | RA(dst) | RS(src));
|
tcg_out32(s, EXTSW | RA(dst) | RS(src));
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void tcg_out_ext32u(TCGContext *s, TCGReg dst, TCGReg src)
|
static void tcg_out_ext32u(TCGContext *s, TCGReg dst, TCGReg src)
|
||||||
{
|
{
|
||||||
|
tcg_debug_assert(TCG_TARGET_REG_BITS == 64);
|
||||||
tcg_out_rld(s, RLDICL, dst, src, 0, 32);
|
tcg_out_rld(s, RLDICL, dst, src, 0, 32);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void tcg_out_exts_i32_i64(TCGContext *s, TCGReg dst, TCGReg src)
|
||||||
|
{
|
||||||
|
tcg_out_ext32s(s, dst, src);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void tcg_out_extu_i32_i64(TCGContext *s, TCGReg dst, TCGReg src)
|
||||||
|
{
|
||||||
|
tcg_out_ext32u(s, dst, src);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void tcg_out_extrl_i64_i32(TCGContext *s, TCGReg rd, TCGReg rn)
|
||||||
|
{
|
||||||
|
tcg_debug_assert(TCG_TARGET_REG_BITS == 64);
|
||||||
|
tcg_out_mov(s, TCG_TYPE_I32, rd, rn);
|
||||||
|
}
|
||||||
|
|
||||||
static inline void tcg_out_shli32(TCGContext *s, TCGReg dst, TCGReg src, int c)
|
static inline void tcg_out_shli32(TCGContext *s, TCGReg dst, TCGReg src, int c)
|
||||||
{
|
{
|
||||||
tcg_out_rlw(s, RLWINM, dst, src, c, 0, 31 - c);
|
tcg_out_rlw(s, RLWINM, dst, src, c, 0, 31 - c);
|
||||||
@ -838,7 +861,7 @@ static void tcg_out_bswap16(TCGContext *s, TCGReg dst, TCGReg src, int flags)
|
|||||||
if (have_isa_3_10) {
|
if (have_isa_3_10) {
|
||||||
tcg_out32(s, BRH | RA(dst) | RS(src));
|
tcg_out32(s, BRH | RA(dst) | RS(src));
|
||||||
if (flags & TCG_BSWAP_OS) {
|
if (flags & TCG_BSWAP_OS) {
|
||||||
tcg_out_ext16s(s, dst, dst);
|
tcg_out_ext16s(s, TCG_TYPE_REG, dst, dst);
|
||||||
} else if ((flags & (TCG_BSWAP_IZ | TCG_BSWAP_OZ)) == TCG_BSWAP_OZ) {
|
} else if ((flags & (TCG_BSWAP_IZ | TCG_BSWAP_OZ)) == TCG_BSWAP_OZ) {
|
||||||
tcg_out_ext16u(s, dst, dst);
|
tcg_out_ext16u(s, dst, dst);
|
||||||
}
|
}
|
||||||
@ -857,7 +880,7 @@ static void tcg_out_bswap16(TCGContext *s, TCGReg dst, TCGReg src, int flags)
|
|||||||
tcg_out_rlw(s, RLWIMI, tmp, src, 8, 16, 23);
|
tcg_out_rlw(s, RLWIMI, tmp, src, 8, 16, 23);
|
||||||
|
|
||||||
if (flags & TCG_BSWAP_OS) {
|
if (flags & TCG_BSWAP_OS) {
|
||||||
tcg_out_ext16s(s, dst, tmp);
|
tcg_out_ext16s(s, TCG_TYPE_REG, dst, tmp);
|
||||||
} else {
|
} else {
|
||||||
tcg_out_mov(s, TCG_TYPE_REG, dst, tmp);
|
tcg_out_mov(s, TCG_TYPE_REG, dst, tmp);
|
||||||
}
|
}
|
||||||
@ -1131,6 +1154,11 @@ static void tcg_out_movi(TCGContext *s, TCGType type, TCGReg ret,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool tcg_out_xchg(TCGContext *s, TCGType type, TCGReg r1, TCGReg r2)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
static void tcg_out_addi_ptr(TCGContext *s, TCGReg rd, TCGReg rs,
|
static void tcg_out_addi_ptr(TCGContext *s, TCGReg rd, TCGReg rs,
|
||||||
tcg_target_long imm)
|
tcg_target_long imm)
|
||||||
{
|
{
|
||||||
@ -1510,7 +1538,7 @@ static void tcg_out_cmp(TCGContext *s, int cond, TCGArg arg1, TCGArg arg2,
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
tcg_abort();
|
g_assert_not_reached();
|
||||||
}
|
}
|
||||||
op |= BF(cr) | ((type == TCG_TYPE_I64) << 21);
|
op |= BF(cr) | ((type == TCG_TYPE_I64) << 21);
|
||||||
|
|
||||||
@ -1681,7 +1709,7 @@ static void tcg_out_setcond(TCGContext *s, TCGType type, TCGCond cond,
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
tcg_abort();
|
g_assert_not_reached();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1835,7 +1863,7 @@ static void tcg_out_cmp2(TCGContext *s, const TCGArg *args,
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
tcg_abort();
|
g_assert_not_reached();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1948,10 +1976,6 @@ static const uint32_t qemu_stx_opc[(MO_SIZE + MO_BSWAP) + 1] = {
|
|||||||
[MO_BSWAP | MO_UQ] = STDBRX,
|
[MO_BSWAP | MO_UQ] = STDBRX,
|
||||||
};
|
};
|
||||||
|
|
||||||
static const uint32_t qemu_exts_opc[4] = {
|
|
||||||
EXTSB, EXTSH, EXTSW, 0
|
|
||||||
};
|
|
||||||
|
|
||||||
#if defined (CONFIG_SOFTMMU)
|
#if defined (CONFIG_SOFTMMU)
|
||||||
/* helper signature: helper_ld_mmu(CPUState *env, target_ulong addr,
|
/* helper signature: helper_ld_mmu(CPUState *env, target_ulong addr,
|
||||||
* int mmu_idx, uintptr_t ra)
|
* int mmu_idx, uintptr_t ra)
|
||||||
@ -2145,11 +2169,9 @@ static bool tcg_out_qemu_ld_slow_path(TCGContext *s, TCGLabelQemuLdst *lb)
|
|||||||
if (TCG_TARGET_REG_BITS == 32 && (opc & MO_SIZE) == MO_64) {
|
if (TCG_TARGET_REG_BITS == 32 && (opc & MO_SIZE) == MO_64) {
|
||||||
tcg_out_mov(s, TCG_TYPE_I32, lo, TCG_REG_R4);
|
tcg_out_mov(s, TCG_TYPE_I32, lo, TCG_REG_R4);
|
||||||
tcg_out_mov(s, TCG_TYPE_I32, hi, TCG_REG_R3);
|
tcg_out_mov(s, TCG_TYPE_I32, hi, TCG_REG_R3);
|
||||||
} else if (opc & MO_SIGN) {
|
|
||||||
uint32_t insn = qemu_exts_opc[opc & MO_SIZE];
|
|
||||||
tcg_out32(s, insn | RA(lo) | RS(TCG_REG_R3));
|
|
||||||
} else {
|
} else {
|
||||||
tcg_out_mov(s, TCG_TYPE_REG, lo, TCG_REG_R3);
|
tcg_out_movext(s, lb->type, lo,
|
||||||
|
TCG_TYPE_REG, opc & MO_SSIZE, TCG_REG_R3);
|
||||||
}
|
}
|
||||||
|
|
||||||
tcg_out_b(s, 0, lb->raddr);
|
tcg_out_b(s, 0, lb->raddr);
|
||||||
@ -2183,25 +2205,13 @@ static bool tcg_out_qemu_st_slow_path(TCGContext *s, TCGLabelQemuLdst *lb)
|
|||||||
|
|
||||||
lo = lb->datalo_reg;
|
lo = lb->datalo_reg;
|
||||||
hi = lb->datahi_reg;
|
hi = lb->datahi_reg;
|
||||||
if (TCG_TARGET_REG_BITS == 32) {
|
if (TCG_TARGET_REG_BITS == 32 && s_bits == MO_64) {
|
||||||
switch (s_bits) {
|
|
||||||
case MO_64:
|
|
||||||
arg |= (TCG_TARGET_CALL_ARG_I64 == TCG_CALL_ARG_EVEN);
|
arg |= (TCG_TARGET_CALL_ARG_I64 == TCG_CALL_ARG_EVEN);
|
||||||
tcg_out_mov(s, TCG_TYPE_I32, arg++, hi);
|
tcg_out_mov(s, TCG_TYPE_I32, arg++, hi);
|
||||||
/* FALLTHRU */
|
|
||||||
case MO_32:
|
|
||||||
tcg_out_mov(s, TCG_TYPE_I32, arg++, lo);
|
tcg_out_mov(s, TCG_TYPE_I32, arg++, lo);
|
||||||
break;
|
|
||||||
default:
|
|
||||||
tcg_out_rlw(s, RLWINM, arg++, lo, 0, 32 - (8 << s_bits), 31);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
if (s_bits == MO_64) {
|
tcg_out_movext(s, s_bits == MO_64 ? TCG_TYPE_I64 : TCG_TYPE_I32,
|
||||||
tcg_out_mov(s, TCG_TYPE_I64, arg++, lo);
|
arg++, lb->type, s_bits, lo);
|
||||||
} else {
|
|
||||||
tcg_out_rld(s, RLDICL, arg++, lo, 0, 64 - (8 << s_bits));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
tcg_out_movi(s, TCG_TYPE_I32, arg++, oi);
|
tcg_out_movi(s, TCG_TYPE_I32, arg++, oi);
|
||||||
@ -2348,8 +2358,8 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, bool is_64)
|
|||||||
} else {
|
} else {
|
||||||
insn = qemu_ldx_opc[opc & (MO_SIZE | MO_BSWAP)];
|
insn = qemu_ldx_opc[opc & (MO_SIZE | MO_BSWAP)];
|
||||||
tcg_out32(s, insn | TAB(datalo, rbase, addrlo));
|
tcg_out32(s, insn | TAB(datalo, rbase, addrlo));
|
||||||
insn = qemu_exts_opc[s_bits];
|
tcg_out_movext(s, TCG_TYPE_REG, datalo,
|
||||||
tcg_out32(s, insn | RA(datalo) | RS(datalo));
|
TCG_TYPE_REG, opc & MO_SSIZE, datalo);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2626,7 +2636,7 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc,
|
|||||||
case INDEX_op_ld8s_i32:
|
case INDEX_op_ld8s_i32:
|
||||||
case INDEX_op_ld8s_i64:
|
case INDEX_op_ld8s_i64:
|
||||||
tcg_out_mem_long(s, LBZ, LBZX, args[0], args[1], args[2]);
|
tcg_out_mem_long(s, LBZ, LBZX, args[0], args[1], args[2]);
|
||||||
tcg_out_ext8s(s, args[0], args[0]);
|
tcg_out_ext8s(s, TCG_TYPE_REG, args[0], args[0]);
|
||||||
break;
|
break;
|
||||||
case INDEX_op_ld16u_i32:
|
case INDEX_op_ld16u_i32:
|
||||||
case INDEX_op_ld16u_i64:
|
case INDEX_op_ld16u_i64:
|
||||||
@ -2974,22 +2984,6 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc,
|
|||||||
tcg_out_qemu_st(s, args, true);
|
tcg_out_qemu_st(s, args, true);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case INDEX_op_ext8s_i32:
|
|
||||||
case INDEX_op_ext8s_i64:
|
|
||||||
tcg_out_ext8s(s, args[0], args[1]);
|
|
||||||
break;
|
|
||||||
case INDEX_op_ext16s_i32:
|
|
||||||
case INDEX_op_ext16s_i64:
|
|
||||||
tcg_out_ext16s(s, args[0], args[1]);
|
|
||||||
break;
|
|
||||||
case INDEX_op_ext_i32_i64:
|
|
||||||
case INDEX_op_ext32s_i64:
|
|
||||||
tcg_out_ext32s(s, args[0], args[1]);
|
|
||||||
break;
|
|
||||||
case INDEX_op_extu_i32_i64:
|
|
||||||
tcg_out_ext32u(s, args[0], args[1]);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case INDEX_op_setcond_i32:
|
case INDEX_op_setcond_i32:
|
||||||
tcg_out_setcond(s, TCG_TYPE_I32, args[3], args[0], args[1], args[2],
|
tcg_out_setcond(s, TCG_TYPE_I32, args[3], args[0], args[1], args[2],
|
||||||
const_args[2]);
|
const_args[2]);
|
||||||
@ -3125,8 +3119,21 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc,
|
|||||||
case INDEX_op_call: /* Always emitted via tcg_out_call. */
|
case INDEX_op_call: /* Always emitted via tcg_out_call. */
|
||||||
case INDEX_op_exit_tb: /* Always emitted via tcg_out_exit_tb. */
|
case INDEX_op_exit_tb: /* Always emitted via tcg_out_exit_tb. */
|
||||||
case INDEX_op_goto_tb: /* Always emitted via tcg_out_goto_tb. */
|
case INDEX_op_goto_tb: /* Always emitted via tcg_out_goto_tb. */
|
||||||
|
case INDEX_op_ext8s_i32: /* Always emitted via tcg_reg_alloc_op. */
|
||||||
|
case INDEX_op_ext8s_i64:
|
||||||
|
case INDEX_op_ext8u_i32:
|
||||||
|
case INDEX_op_ext8u_i64:
|
||||||
|
case INDEX_op_ext16s_i32:
|
||||||
|
case INDEX_op_ext16s_i64:
|
||||||
|
case INDEX_op_ext16u_i32:
|
||||||
|
case INDEX_op_ext16u_i64:
|
||||||
|
case INDEX_op_ext32s_i64:
|
||||||
|
case INDEX_op_ext32u_i64:
|
||||||
|
case INDEX_op_ext_i32_i64:
|
||||||
|
case INDEX_op_extu_i32_i64:
|
||||||
|
case INDEX_op_extrl_i64_i32:
|
||||||
default:
|
default:
|
||||||
tcg_abort();
|
g_assert_not_reached();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -561,6 +561,11 @@ static void tcg_out_movi(TCGContext *s, TCGType type, TCGReg rd,
|
|||||||
tcg_out_opc_imm(s, OPC_LD, rd, rd, 0);
|
tcg_out_opc_imm(s, OPC_LD, rd, rd, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool tcg_out_xchg(TCGContext *s, TCGType type, TCGReg r1, TCGReg r2)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
static void tcg_out_addi_ptr(TCGContext *s, TCGReg rd, TCGReg rs,
|
static void tcg_out_addi_ptr(TCGContext *s, TCGReg rd, TCGReg rs,
|
||||||
tcg_target_long imm)
|
tcg_target_long imm)
|
||||||
{
|
{
|
||||||
@ -585,13 +590,13 @@ static void tcg_out_ext32u(TCGContext *s, TCGReg ret, TCGReg arg)
|
|||||||
tcg_out_opc_imm(s, OPC_SRLI, ret, ret, 32);
|
tcg_out_opc_imm(s, OPC_SRLI, ret, ret, 32);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void tcg_out_ext8s(TCGContext *s, TCGReg ret, TCGReg arg)
|
static void tcg_out_ext8s(TCGContext *s, TCGType type, TCGReg ret, TCGReg arg)
|
||||||
{
|
{
|
||||||
tcg_out_opc_imm(s, OPC_SLLIW, ret, arg, 24);
|
tcg_out_opc_imm(s, OPC_SLLIW, ret, arg, 24);
|
||||||
tcg_out_opc_imm(s, OPC_SRAIW, ret, ret, 24);
|
tcg_out_opc_imm(s, OPC_SRAIW, ret, ret, 24);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void tcg_out_ext16s(TCGContext *s, TCGReg ret, TCGReg arg)
|
static void tcg_out_ext16s(TCGContext *s, TCGType type, TCGReg ret, TCGReg arg)
|
||||||
{
|
{
|
||||||
tcg_out_opc_imm(s, OPC_SLLIW, ret, arg, 16);
|
tcg_out_opc_imm(s, OPC_SLLIW, ret, arg, 16);
|
||||||
tcg_out_opc_imm(s, OPC_SRAIW, ret, ret, 16);
|
tcg_out_opc_imm(s, OPC_SRAIW, ret, ret, 16);
|
||||||
@ -602,6 +607,23 @@ static void tcg_out_ext32s(TCGContext *s, TCGReg ret, TCGReg arg)
|
|||||||
tcg_out_opc_imm(s, OPC_ADDIW, ret, arg, 0);
|
tcg_out_opc_imm(s, OPC_ADDIW, ret, arg, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void tcg_out_exts_i32_i64(TCGContext *s, TCGReg ret, TCGReg arg)
|
||||||
|
{
|
||||||
|
if (ret != arg) {
|
||||||
|
tcg_out_ext32s(s, ret, arg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void tcg_out_extu_i32_i64(TCGContext *s, TCGReg ret, TCGReg arg)
|
||||||
|
{
|
||||||
|
tcg_out_ext32u(s, ret, arg);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void tcg_out_extrl_i64_i32(TCGContext *s, TCGReg ret, TCGReg arg)
|
||||||
|
{
|
||||||
|
tcg_out_ext32s(s, ret, arg);
|
||||||
|
}
|
||||||
|
|
||||||
static void tcg_out_ldst(TCGContext *s, RISCVInsn opc, TCGReg data,
|
static void tcg_out_ldst(TCGContext *s, RISCVInsn opc, TCGReg data,
|
||||||
TCGReg addr, intptr_t offset)
|
TCGReg addr, intptr_t offset)
|
||||||
{
|
{
|
||||||
@ -1064,17 +1086,8 @@ static bool tcg_out_qemu_st_slow_path(TCGContext *s, TCGLabelQemuLdst *l)
|
|||||||
/* call store helper */
|
/* call store helper */
|
||||||
tcg_out_mov(s, TCG_TYPE_PTR, a0, TCG_AREG0);
|
tcg_out_mov(s, TCG_TYPE_PTR, a0, TCG_AREG0);
|
||||||
tcg_out_mov(s, TCG_TYPE_PTR, a1, l->addrlo_reg);
|
tcg_out_mov(s, TCG_TYPE_PTR, a1, l->addrlo_reg);
|
||||||
tcg_out_mov(s, TCG_TYPE_PTR, a2, l->datalo_reg);
|
tcg_out_movext(s, s_bits == MO_64 ? TCG_TYPE_I64 : TCG_TYPE_I32, a2,
|
||||||
switch (s_bits) {
|
l->type, s_bits, l->datalo_reg);
|
||||||
case MO_8:
|
|
||||||
tcg_out_ext8u(s, a2, a2);
|
|
||||||
break;
|
|
||||||
case MO_16:
|
|
||||||
tcg_out_ext16u(s, a2, a2);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
tcg_out_movi(s, TCG_TYPE_PTR, a3, oi);
|
tcg_out_movi(s, TCG_TYPE_PTR, a3, oi);
|
||||||
tcg_out_movi(s, TCG_TYPE_PTR, a4, (tcg_target_long)l->raddr);
|
tcg_out_movi(s, TCG_TYPE_PTR, a4, (tcg_target_long)l->raddr);
|
||||||
|
|
||||||
@ -1597,37 +1610,6 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc,
|
|||||||
tcg_out_qemu_st(s, args, true);
|
tcg_out_qemu_st(s, args, true);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case INDEX_op_ext8u_i32:
|
|
||||||
case INDEX_op_ext8u_i64:
|
|
||||||
tcg_out_ext8u(s, a0, a1);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case INDEX_op_ext16u_i32:
|
|
||||||
case INDEX_op_ext16u_i64:
|
|
||||||
tcg_out_ext16u(s, a0, a1);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case INDEX_op_ext32u_i64:
|
|
||||||
case INDEX_op_extu_i32_i64:
|
|
||||||
tcg_out_ext32u(s, a0, a1);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case INDEX_op_ext8s_i32:
|
|
||||||
case INDEX_op_ext8s_i64:
|
|
||||||
tcg_out_ext8s(s, a0, a1);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case INDEX_op_ext16s_i32:
|
|
||||||
case INDEX_op_ext16s_i64:
|
|
||||||
tcg_out_ext16s(s, a0, a1);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case INDEX_op_ext32s_i64:
|
|
||||||
case INDEX_op_extrl_i64_i32:
|
|
||||||
case INDEX_op_ext_i32_i64:
|
|
||||||
tcg_out_ext32s(s, a0, a1);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case INDEX_op_extrh_i64_i32:
|
case INDEX_op_extrh_i64_i32:
|
||||||
tcg_out_opc_imm(s, OPC_SRAI, a0, a1, 32);
|
tcg_out_opc_imm(s, OPC_SRAI, a0, a1, 32);
|
||||||
break;
|
break;
|
||||||
@ -1651,6 +1633,19 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc,
|
|||||||
case INDEX_op_call: /* Always emitted via tcg_out_call. */
|
case INDEX_op_call: /* Always emitted via tcg_out_call. */
|
||||||
case INDEX_op_exit_tb: /* Always emitted via tcg_out_exit_tb. */
|
case INDEX_op_exit_tb: /* Always emitted via tcg_out_exit_tb. */
|
||||||
case INDEX_op_goto_tb: /* Always emitted via tcg_out_goto_tb. */
|
case INDEX_op_goto_tb: /* Always emitted via tcg_out_goto_tb. */
|
||||||
|
case INDEX_op_ext8s_i32: /* Always emitted via tcg_reg_alloc_op. */
|
||||||
|
case INDEX_op_ext8s_i64:
|
||||||
|
case INDEX_op_ext8u_i32:
|
||||||
|
case INDEX_op_ext8u_i64:
|
||||||
|
case INDEX_op_ext16s_i32:
|
||||||
|
case INDEX_op_ext16s_i64:
|
||||||
|
case INDEX_op_ext16u_i32:
|
||||||
|
case INDEX_op_ext16u_i64:
|
||||||
|
case INDEX_op_ext32s_i64:
|
||||||
|
case INDEX_op_ext32u_i64:
|
||||||
|
case INDEX_op_ext_i32_i64:
|
||||||
|
case INDEX_op_extu_i32_i64:
|
||||||
|
case INDEX_op_extrl_i64_i32:
|
||||||
default:
|
default:
|
||||||
g_assert_not_reached();
|
g_assert_not_reached();
|
||||||
}
|
}
|
||||||
|
@ -1076,6 +1076,11 @@ static inline bool tcg_out_sti(TCGContext *s, TCGType type, TCGArg val,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool tcg_out_xchg(TCGContext *s, TCGType type, TCGReg r1, TCGReg r2)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
static void tcg_out_addi_ptr(TCGContext *s, TCGReg rd, TCGReg rs,
|
static void tcg_out_addi_ptr(TCGContext *s, TCGReg rd, TCGReg rs,
|
||||||
tcg_target_long imm)
|
tcg_target_long imm)
|
||||||
{
|
{
|
||||||
@ -1092,36 +1097,51 @@ static inline void tcg_out_risbg(TCGContext *s, TCGReg dest, TCGReg src,
|
|||||||
tcg_out16(s, (ofs << 8) | (RIEf_RISBG & 0xff));
|
tcg_out16(s, (ofs << 8) | (RIEf_RISBG & 0xff));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void tgen_ext8s(TCGContext *s, TCGType type, TCGReg dest, TCGReg src)
|
static void tcg_out_ext8s(TCGContext *s, TCGType type, TCGReg dest, TCGReg src)
|
||||||
{
|
{
|
||||||
tcg_out_insn(s, RRE, LGBR, dest, src);
|
tcg_out_insn(s, RRE, LGBR, dest, src);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void tgen_ext8u(TCGContext *s, TCGType type, TCGReg dest, TCGReg src)
|
static void tcg_out_ext8u(TCGContext *s, TCGReg dest, TCGReg src)
|
||||||
{
|
{
|
||||||
tcg_out_insn(s, RRE, LLGCR, dest, src);
|
tcg_out_insn(s, RRE, LLGCR, dest, src);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void tgen_ext16s(TCGContext *s, TCGType type, TCGReg dest, TCGReg src)
|
static void tcg_out_ext16s(TCGContext *s, TCGType type, TCGReg dest, TCGReg src)
|
||||||
{
|
{
|
||||||
tcg_out_insn(s, RRE, LGHR, dest, src);
|
tcg_out_insn(s, RRE, LGHR, dest, src);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void tgen_ext16u(TCGContext *s, TCGType type, TCGReg dest, TCGReg src)
|
static void tcg_out_ext16u(TCGContext *s, TCGReg dest, TCGReg src)
|
||||||
{
|
{
|
||||||
tcg_out_insn(s, RRE, LLGHR, dest, src);
|
tcg_out_insn(s, RRE, LLGHR, dest, src);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void tgen_ext32s(TCGContext *s, TCGReg dest, TCGReg src)
|
static void tcg_out_ext32s(TCGContext *s, TCGReg dest, TCGReg src)
|
||||||
{
|
{
|
||||||
tcg_out_insn(s, RRE, LGFR, dest, src);
|
tcg_out_insn(s, RRE, LGFR, dest, src);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void tgen_ext32u(TCGContext *s, TCGReg dest, TCGReg src)
|
static void tcg_out_ext32u(TCGContext *s, TCGReg dest, TCGReg src)
|
||||||
{
|
{
|
||||||
tcg_out_insn(s, RRE, LLGFR, dest, src);
|
tcg_out_insn(s, RRE, LLGFR, dest, src);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void tcg_out_exts_i32_i64(TCGContext *s, TCGReg dest, TCGReg src)
|
||||||
|
{
|
||||||
|
tcg_out_ext32s(s, dest, src);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void tcg_out_extu_i32_i64(TCGContext *s, TCGReg dest, TCGReg src)
|
||||||
|
{
|
||||||
|
tcg_out_ext32u(s, dest, src);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void tcg_out_extrl_i64_i32(TCGContext *s, TCGReg dest, TCGReg src)
|
||||||
|
{
|
||||||
|
tcg_out_mov(s, TCG_TYPE_I32, dest, src);
|
||||||
|
}
|
||||||
|
|
||||||
static void tgen_andi_risbg(TCGContext *s, TCGReg out, TCGReg in, uint64_t val)
|
static void tgen_andi_risbg(TCGContext *s, TCGReg out, TCGReg in, uint64_t val)
|
||||||
{
|
{
|
||||||
int msb, lsb;
|
int msb, lsb;
|
||||||
@ -1149,15 +1169,15 @@ static void tgen_andi(TCGContext *s, TCGType type, TCGReg dest, uint64_t val)
|
|||||||
|
|
||||||
/* Look for the zero-extensions. */
|
/* Look for the zero-extensions. */
|
||||||
if ((val & valid) == 0xffffffff) {
|
if ((val & valid) == 0xffffffff) {
|
||||||
tgen_ext32u(s, dest, dest);
|
tcg_out_ext32u(s, dest, dest);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if ((val & valid) == 0xff) {
|
if ((val & valid) == 0xff) {
|
||||||
tgen_ext8u(s, TCG_TYPE_I64, dest, dest);
|
tcg_out_ext8u(s, dest, dest);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if ((val & valid) == 0xffff) {
|
if ((val & valid) == 0xffff) {
|
||||||
tgen_ext16u(s, TCG_TYPE_I64, dest, dest);
|
tcg_out_ext16u(s, dest, dest);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1440,7 +1460,7 @@ static void tgen_ctpop(TCGContext *s, TCGType type, TCGReg dest, TCGReg src)
|
|||||||
/* With MIE3, and bit 0 of m4 set, we get the complete result. */
|
/* With MIE3, and bit 0 of m4 set, we get the complete result. */
|
||||||
if (HAVE_FACILITY(MISC_INSN_EXT3)) {
|
if (HAVE_FACILITY(MISC_INSN_EXT3)) {
|
||||||
if (type == TCG_TYPE_I32) {
|
if (type == TCG_TYPE_I32) {
|
||||||
tgen_ext32u(s, dest, src);
|
tcg_out_ext32u(s, dest, src);
|
||||||
src = dest;
|
src = dest;
|
||||||
}
|
}
|
||||||
tcg_out_insn(s, RRFc, POPCNT, dest, src, 8);
|
tcg_out_insn(s, RRFc, POPCNT, dest, src, 8);
|
||||||
@ -1600,7 +1620,7 @@ static void tcg_out_qemu_ld_direct(TCGContext *s, MemOp opc, TCGReg data,
|
|||||||
case MO_UW | MO_BSWAP:
|
case MO_UW | MO_BSWAP:
|
||||||
/* swapped unsigned halfword load with upper bits zeroed */
|
/* swapped unsigned halfword load with upper bits zeroed */
|
||||||
tcg_out_insn(s, RXY, LRVH, data, base, index, disp);
|
tcg_out_insn(s, RXY, LRVH, data, base, index, disp);
|
||||||
tgen_ext16u(s, TCG_TYPE_I64, data, data);
|
tcg_out_ext16u(s, data, data);
|
||||||
break;
|
break;
|
||||||
case MO_UW:
|
case MO_UW:
|
||||||
tcg_out_insn(s, RXY, LLGH, data, base, index, disp);
|
tcg_out_insn(s, RXY, LLGH, data, base, index, disp);
|
||||||
@ -1609,7 +1629,7 @@ static void tcg_out_qemu_ld_direct(TCGContext *s, MemOp opc, TCGReg data,
|
|||||||
case MO_SW | MO_BSWAP:
|
case MO_SW | MO_BSWAP:
|
||||||
/* swapped sign-extended halfword load */
|
/* swapped sign-extended halfword load */
|
||||||
tcg_out_insn(s, RXY, LRVH, data, base, index, disp);
|
tcg_out_insn(s, RXY, LRVH, data, base, index, disp);
|
||||||
tgen_ext16s(s, TCG_TYPE_I64, data, data);
|
tcg_out_ext16s(s, TCG_TYPE_REG, data, data);
|
||||||
break;
|
break;
|
||||||
case MO_SW:
|
case MO_SW:
|
||||||
tcg_out_insn(s, RXY, LGH, data, base, index, disp);
|
tcg_out_insn(s, RXY, LGH, data, base, index, disp);
|
||||||
@ -1618,7 +1638,7 @@ static void tcg_out_qemu_ld_direct(TCGContext *s, MemOp opc, TCGReg data,
|
|||||||
case MO_UL | MO_BSWAP:
|
case MO_UL | MO_BSWAP:
|
||||||
/* swapped unsigned int load with upper bits zeroed */
|
/* swapped unsigned int load with upper bits zeroed */
|
||||||
tcg_out_insn(s, RXY, LRV, data, base, index, disp);
|
tcg_out_insn(s, RXY, LRV, data, base, index, disp);
|
||||||
tgen_ext32u(s, data, data);
|
tcg_out_ext32u(s, data, data);
|
||||||
break;
|
break;
|
||||||
case MO_UL:
|
case MO_UL:
|
||||||
tcg_out_insn(s, RXY, LLGF, data, base, index, disp);
|
tcg_out_insn(s, RXY, LLGF, data, base, index, disp);
|
||||||
@ -1627,7 +1647,7 @@ static void tcg_out_qemu_ld_direct(TCGContext *s, MemOp opc, TCGReg data,
|
|||||||
case MO_SL | MO_BSWAP:
|
case MO_SL | MO_BSWAP:
|
||||||
/* swapped sign-extended int load */
|
/* swapped sign-extended int load */
|
||||||
tcg_out_insn(s, RXY, LRV, data, base, index, disp);
|
tcg_out_insn(s, RXY, LRV, data, base, index, disp);
|
||||||
tgen_ext32s(s, data, data);
|
tcg_out_ext32s(s, data, data);
|
||||||
break;
|
break;
|
||||||
case MO_SL:
|
case MO_SL:
|
||||||
tcg_out_insn(s, RXY, LGF, data, base, index, disp);
|
tcg_out_insn(s, RXY, LGF, data, base, index, disp);
|
||||||
@ -1641,7 +1661,7 @@ static void tcg_out_qemu_ld_direct(TCGContext *s, MemOp opc, TCGReg data,
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
tcg_abort();
|
g_assert_not_reached();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1687,7 +1707,7 @@ static void tcg_out_qemu_st_direct(TCGContext *s, MemOp opc, TCGReg data,
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
tcg_abort();
|
g_assert_not_reached();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1743,7 +1763,7 @@ static TCGReg tcg_out_tlb_read(TCGContext *s, TCGReg addr_reg, MemOp opc,
|
|||||||
offsetof(CPUTLBEntry, addend));
|
offsetof(CPUTLBEntry, addend));
|
||||||
|
|
||||||
if (TARGET_LONG_BITS == 32) {
|
if (TARGET_LONG_BITS == 32) {
|
||||||
tgen_ext32u(s, TCG_REG_R3, addr_reg);
|
tcg_out_ext32u(s, TCG_REG_R3, addr_reg);
|
||||||
return TCG_REG_R3;
|
return TCG_REG_R3;
|
||||||
}
|
}
|
||||||
return addr_reg;
|
return addr_reg;
|
||||||
@ -1794,6 +1814,7 @@ static bool tcg_out_qemu_st_slow_path(TCGContext *s, TCGLabelQemuLdst *lb)
|
|||||||
TCGReg data_reg = lb->datalo_reg;
|
TCGReg data_reg = lb->datalo_reg;
|
||||||
MemOpIdx oi = lb->oi;
|
MemOpIdx oi = lb->oi;
|
||||||
MemOp opc = get_memop(oi);
|
MemOp opc = get_memop(oi);
|
||||||
|
MemOp size = opc & MO_SIZE;
|
||||||
|
|
||||||
if (!patch_reloc(lb->label_ptr[0], R_390_PC16DBL,
|
if (!patch_reloc(lb->label_ptr[0], R_390_PC16DBL,
|
||||||
(intptr_t)tcg_splitwx_to_rx(s->code_ptr), 2)) {
|
(intptr_t)tcg_splitwx_to_rx(s->code_ptr), 2)) {
|
||||||
@ -1804,22 +1825,8 @@ static bool tcg_out_qemu_st_slow_path(TCGContext *s, TCGLabelQemuLdst *lb)
|
|||||||
if (TARGET_LONG_BITS == 64) {
|
if (TARGET_LONG_BITS == 64) {
|
||||||
tcg_out_mov(s, TCG_TYPE_I64, TCG_REG_R3, addr_reg);
|
tcg_out_mov(s, TCG_TYPE_I64, TCG_REG_R3, addr_reg);
|
||||||
}
|
}
|
||||||
switch (opc & MO_SIZE) {
|
tcg_out_movext(s, size == MO_64 ? TCG_TYPE_I64 : TCG_TYPE_I32,
|
||||||
case MO_UB:
|
TCG_REG_R4, lb->type, size, data_reg);
|
||||||
tgen_ext8u(s, TCG_TYPE_I64, TCG_REG_R4, data_reg);
|
|
||||||
break;
|
|
||||||
case MO_UW:
|
|
||||||
tgen_ext16u(s, TCG_TYPE_I64, TCG_REG_R4, data_reg);
|
|
||||||
break;
|
|
||||||
case MO_UL:
|
|
||||||
tgen_ext32u(s, TCG_REG_R4, data_reg);
|
|
||||||
break;
|
|
||||||
case MO_UQ:
|
|
||||||
tcg_out_mov(s, TCG_TYPE_I64, TCG_REG_R4, data_reg);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
tcg_abort();
|
|
||||||
}
|
|
||||||
tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_R5, oi);
|
tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_R5, oi);
|
||||||
tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_R6, (uintptr_t)lb->raddr);
|
tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_R6, (uintptr_t)lb->raddr);
|
||||||
tcg_out_call_int(s, qemu_st_helpers[opc & (MO_BSWAP | MO_SIZE)]);
|
tcg_out_call_int(s, qemu_st_helpers[opc & (MO_BSWAP | MO_SIZE)]);
|
||||||
@ -1879,7 +1886,7 @@ static void tcg_prepare_user_ldst(TCGContext *s, TCGReg *addr_reg,
|
|||||||
TCGReg *index_reg, tcg_target_long *disp)
|
TCGReg *index_reg, tcg_target_long *disp)
|
||||||
{
|
{
|
||||||
if (TARGET_LONG_BITS == 32) {
|
if (TARGET_LONG_BITS == 32) {
|
||||||
tgen_ext32u(s, TCG_TMP0, *addr_reg);
|
tcg_out_ext32u(s, TCG_TMP0, *addr_reg);
|
||||||
*addr_reg = TCG_TMP0;
|
*addr_reg = TCG_TMP0;
|
||||||
}
|
}
|
||||||
if (guest_base < 0x80000) {
|
if (guest_base < 0x80000) {
|
||||||
@ -2233,19 +2240,6 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case INDEX_op_ext8s_i32:
|
|
||||||
tgen_ext8s(s, TCG_TYPE_I32, args[0], args[1]);
|
|
||||||
break;
|
|
||||||
case INDEX_op_ext16s_i32:
|
|
||||||
tgen_ext16s(s, TCG_TYPE_I32, args[0], args[1]);
|
|
||||||
break;
|
|
||||||
case INDEX_op_ext8u_i32:
|
|
||||||
tgen_ext8u(s, TCG_TYPE_I32, args[0], args[1]);
|
|
||||||
break;
|
|
||||||
case INDEX_op_ext16u_i32:
|
|
||||||
tgen_ext16u(s, TCG_TYPE_I32, args[0], args[1]);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case INDEX_op_bswap16_i32:
|
case INDEX_op_bswap16_i32:
|
||||||
a0 = args[0], a1 = args[1], a2 = args[2];
|
a0 = args[0], a1 = args[1], a2 = args[2];
|
||||||
tcg_out_insn(s, RRE, LRVR, a0, a1);
|
tcg_out_insn(s, RRE, LRVR, a0, a1);
|
||||||
@ -2272,9 +2266,9 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
|
|||||||
a0 = args[0], a1 = args[1], a2 = args[2];
|
a0 = args[0], a1 = args[1], a2 = args[2];
|
||||||
tcg_out_insn(s, RRE, LRVR, a0, a1);
|
tcg_out_insn(s, RRE, LRVR, a0, a1);
|
||||||
if (a2 & TCG_BSWAP_OS) {
|
if (a2 & TCG_BSWAP_OS) {
|
||||||
tgen_ext32s(s, a0, a0);
|
tcg_out_ext32s(s, a0, a0);
|
||||||
} else if ((a2 & (TCG_BSWAP_IZ | TCG_BSWAP_OZ)) == TCG_BSWAP_OZ) {
|
} else if ((a2 & (TCG_BSWAP_IZ | TCG_BSWAP_OZ)) == TCG_BSWAP_OZ) {
|
||||||
tgen_ext32u(s, a0, a0);
|
tcg_out_ext32u(s, a0, a0);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -2537,27 +2531,6 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case INDEX_op_ext8s_i64:
|
|
||||||
tgen_ext8s(s, TCG_TYPE_I64, args[0], args[1]);
|
|
||||||
break;
|
|
||||||
case INDEX_op_ext16s_i64:
|
|
||||||
tgen_ext16s(s, TCG_TYPE_I64, args[0], args[1]);
|
|
||||||
break;
|
|
||||||
case INDEX_op_ext_i32_i64:
|
|
||||||
case INDEX_op_ext32s_i64:
|
|
||||||
tgen_ext32s(s, args[0], args[1]);
|
|
||||||
break;
|
|
||||||
case INDEX_op_ext8u_i64:
|
|
||||||
tgen_ext8u(s, TCG_TYPE_I64, args[0], args[1]);
|
|
||||||
break;
|
|
||||||
case INDEX_op_ext16u_i64:
|
|
||||||
tgen_ext16u(s, TCG_TYPE_I64, args[0], args[1]);
|
|
||||||
break;
|
|
||||||
case INDEX_op_extu_i32_i64:
|
|
||||||
case INDEX_op_ext32u_i64:
|
|
||||||
tgen_ext32u(s, args[0], args[1]);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case INDEX_op_add2_i64:
|
case INDEX_op_add2_i64:
|
||||||
if (const_args[4]) {
|
if (const_args[4]) {
|
||||||
if ((int64_t)args[4] >= 0) {
|
if ((int64_t)args[4] >= 0) {
|
||||||
@ -2644,8 +2617,21 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
|
|||||||
case INDEX_op_call: /* Always emitted via tcg_out_call. */
|
case INDEX_op_call: /* Always emitted via tcg_out_call. */
|
||||||
case INDEX_op_exit_tb: /* Always emitted via tcg_out_exit_tb. */
|
case INDEX_op_exit_tb: /* Always emitted via tcg_out_exit_tb. */
|
||||||
case INDEX_op_goto_tb: /* Always emitted via tcg_out_goto_tb. */
|
case INDEX_op_goto_tb: /* Always emitted via tcg_out_goto_tb. */
|
||||||
|
case INDEX_op_ext8s_i32: /* Always emitted via tcg_reg_alloc_op. */
|
||||||
|
case INDEX_op_ext8s_i64:
|
||||||
|
case INDEX_op_ext8u_i32:
|
||||||
|
case INDEX_op_ext8u_i64:
|
||||||
|
case INDEX_op_ext16s_i32:
|
||||||
|
case INDEX_op_ext16s_i64:
|
||||||
|
case INDEX_op_ext16u_i32:
|
||||||
|
case INDEX_op_ext16u_i64:
|
||||||
|
case INDEX_op_ext32s_i64:
|
||||||
|
case INDEX_op_ext32u_i64:
|
||||||
|
case INDEX_op_ext_i32_i64:
|
||||||
|
case INDEX_op_extu_i32_i64:
|
||||||
|
case INDEX_op_extrl_i64_i32:
|
||||||
default:
|
default:
|
||||||
tcg_abort();
|
g_assert_not_reached();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -496,6 +496,57 @@ static void tcg_out_movi(TCGContext *s, TCGType type,
|
|||||||
tcg_out_movi_int(s, type, ret, arg, false, TCG_REG_T2);
|
tcg_out_movi_int(s, type, ret, arg, false, TCG_REG_T2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void tcg_out_ext8s(TCGContext *s, TCGType type, TCGReg rd, TCGReg rs)
|
||||||
|
{
|
||||||
|
g_assert_not_reached();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void tcg_out_ext16s(TCGContext *s, TCGType type, TCGReg rd, TCGReg rs)
|
||||||
|
{
|
||||||
|
g_assert_not_reached();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void tcg_out_ext8u(TCGContext *s, TCGReg rd, TCGReg rs)
|
||||||
|
{
|
||||||
|
tcg_out_arithi(s, rd, rs, 0xff, ARITH_AND);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void tcg_out_ext16u(TCGContext *s, TCGReg rd, TCGReg rs)
|
||||||
|
{
|
||||||
|
tcg_out_arithi(s, rd, rs, 16, SHIFT_SLL);
|
||||||
|
tcg_out_arithi(s, rd, rd, 16, SHIFT_SRL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void tcg_out_ext32s(TCGContext *s, TCGReg rd, TCGReg rs)
|
||||||
|
{
|
||||||
|
tcg_out_arithi(s, rd, rs, 0, SHIFT_SRA);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void tcg_out_ext32u(TCGContext *s, TCGReg rd, TCGReg rs)
|
||||||
|
{
|
||||||
|
tcg_out_arithi(s, rd, rs, 0, SHIFT_SRL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void tcg_out_exts_i32_i64(TCGContext *s, TCGReg rd, TCGReg rs)
|
||||||
|
{
|
||||||
|
tcg_out_ext32s(s, rd, rs);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void tcg_out_extu_i32_i64(TCGContext *s, TCGReg rd, TCGReg rs)
|
||||||
|
{
|
||||||
|
tcg_out_ext32u(s, rd, rs);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void tcg_out_extrl_i64_i32(TCGContext *s, TCGReg rd, TCGReg rs)
|
||||||
|
{
|
||||||
|
tcg_out_mov(s, TCG_TYPE_I32, rd, rs);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool tcg_out_xchg(TCGContext *s, TCGType type, TCGReg r1, TCGReg r2)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
static void tcg_out_addi_ptr(TCGContext *s, TCGReg rd, TCGReg rs,
|
static void tcg_out_addi_ptr(TCGContext *s, TCGReg rd, TCGReg rs,
|
||||||
tcg_target_long imm)
|
tcg_target_long imm)
|
||||||
{
|
{
|
||||||
@ -871,27 +922,6 @@ static void tcg_out_mb(TCGContext *s, TCGArg a0)
|
|||||||
static const tcg_insn_unit *qemu_ld_trampoline[(MO_SSIZE | MO_BSWAP) + 1];
|
static const tcg_insn_unit *qemu_ld_trampoline[(MO_SSIZE | MO_BSWAP) + 1];
|
||||||
static const tcg_insn_unit *qemu_st_trampoline[(MO_SIZE | MO_BSWAP) + 1];
|
static const tcg_insn_unit *qemu_st_trampoline[(MO_SIZE | MO_BSWAP) + 1];
|
||||||
|
|
||||||
static void emit_extend(TCGContext *s, TCGReg r, int op)
|
|
||||||
{
|
|
||||||
/* Emit zero extend of 8, 16 or 32 bit data as
|
|
||||||
* required by the MO_* value op; do nothing for 64 bit.
|
|
||||||
*/
|
|
||||||
switch (op & MO_SIZE) {
|
|
||||||
case MO_8:
|
|
||||||
tcg_out_arithi(s, r, r, 0xff, ARITH_AND);
|
|
||||||
break;
|
|
||||||
case MO_16:
|
|
||||||
tcg_out_arithi(s, r, r, 16, SHIFT_SLL);
|
|
||||||
tcg_out_arithi(s, r, r, 16, SHIFT_SRL);
|
|
||||||
break;
|
|
||||||
case MO_32:
|
|
||||||
tcg_out_arith(s, r, r, 0, SHIFT_SRL);
|
|
||||||
break;
|
|
||||||
case MO_64:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void build_trampolines(TCGContext *s)
|
static void build_trampolines(TCGContext *s)
|
||||||
{
|
{
|
||||||
static void * const qemu_ld_helpers[] = {
|
static void * const qemu_ld_helpers[] = {
|
||||||
@ -948,8 +978,6 @@ static void build_trampolines(TCGContext *s)
|
|||||||
}
|
}
|
||||||
qemu_st_trampoline[i] = tcg_splitwx_to_rx(s->code_ptr);
|
qemu_st_trampoline[i] = tcg_splitwx_to_rx(s->code_ptr);
|
||||||
|
|
||||||
emit_extend(s, TCG_REG_O2, i);
|
|
||||||
|
|
||||||
/* Set the retaddr operand. */
|
/* Set the retaddr operand. */
|
||||||
tcg_out_mov(s, TCG_TYPE_PTR, TCG_REG_O4, TCG_REG_O7);
|
tcg_out_mov(s, TCG_TYPE_PTR, TCG_REG_O4, TCG_REG_O7);
|
||||||
|
|
||||||
@ -1109,7 +1137,7 @@ static TCGReg tcg_out_tlb_load(TCGContext *s, TCGReg addr, int mem_index,
|
|||||||
|
|
||||||
/* If the guest address must be zero-extended, do so now. */
|
/* If the guest address must be zero-extended, do so now. */
|
||||||
if (TARGET_LONG_BITS == 32) {
|
if (TARGET_LONG_BITS == 32) {
|
||||||
tcg_out_arithi(s, r0, addr, 0, SHIFT_SRL);
|
tcg_out_ext32u(s, r0, addr);
|
||||||
return r0;
|
return r0;
|
||||||
}
|
}
|
||||||
return addr;
|
return addr;
|
||||||
@ -1193,7 +1221,7 @@ static void tcg_out_qemu_ld(TCGContext *s, TCGReg data, TCGReg addr,
|
|||||||
|
|
||||||
/* We let the helper sign-extend SB and SW, but leave SL for here. */
|
/* We let the helper sign-extend SB and SW, but leave SL for here. */
|
||||||
if (is_64 && (memop & MO_SSIZE) == MO_SL) {
|
if (is_64 && (memop & MO_SSIZE) == MO_SL) {
|
||||||
tcg_out_arithi(s, data, TCG_REG_O0, 0, SHIFT_SRA);
|
tcg_out_ext32s(s, data, TCG_REG_O0);
|
||||||
} else {
|
} else {
|
||||||
tcg_out_mov(s, TCG_TYPE_REG, data, TCG_REG_O0);
|
tcg_out_mov(s, TCG_TYPE_REG, data, TCG_REG_O0);
|
||||||
}
|
}
|
||||||
@ -1206,7 +1234,7 @@ static void tcg_out_qemu_ld(TCGContext *s, TCGReg data, TCGReg addr,
|
|||||||
unsigned t_bits;
|
unsigned t_bits;
|
||||||
|
|
||||||
if (TARGET_LONG_BITS == 32) {
|
if (TARGET_LONG_BITS == 32) {
|
||||||
tcg_out_arithi(s, TCG_REG_T1, addr, 0, SHIFT_SRL);
|
tcg_out_ext32u(s, TCG_REG_T1, addr);
|
||||||
addr = TCG_REG_T1;
|
addr = TCG_REG_T1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1296,7 +1324,7 @@ static void tcg_out_qemu_ld(TCGContext *s, TCGReg data, TCGReg addr,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void tcg_out_qemu_st(TCGContext *s, TCGReg data, TCGReg addr,
|
static void tcg_out_qemu_st(TCGContext *s, TCGReg data, TCGReg addr,
|
||||||
MemOpIdx oi)
|
MemOpIdx oi, TCGType data_type)
|
||||||
{
|
{
|
||||||
MemOp memop = get_memop(oi);
|
MemOp memop = get_memop(oi);
|
||||||
tcg_insn_unit *label_ptr;
|
tcg_insn_unit *label_ptr;
|
||||||
@ -1322,7 +1350,8 @@ static void tcg_out_qemu_st(TCGContext *s, TCGReg data, TCGReg addr,
|
|||||||
/* TLB Miss. */
|
/* TLB Miss. */
|
||||||
|
|
||||||
tcg_out_mov(s, TCG_TYPE_REG, TCG_REG_O1, addrz);
|
tcg_out_mov(s, TCG_TYPE_REG, TCG_REG_O1, addrz);
|
||||||
tcg_out_mov(s, TCG_TYPE_REG, TCG_REG_O2, data);
|
tcg_out_movext(s, (memop & MO_SIZE) == MO_64 ? TCG_TYPE_I64 : TCG_TYPE_I32,
|
||||||
|
TCG_REG_O2, data_type, memop & MO_SIZE, data);
|
||||||
|
|
||||||
func = qemu_st_trampoline[memop & (MO_BSWAP | MO_SIZE)];
|
func = qemu_st_trampoline[memop & (MO_BSWAP | MO_SIZE)];
|
||||||
tcg_debug_assert(func != NULL);
|
tcg_debug_assert(func != NULL);
|
||||||
@ -1338,7 +1367,7 @@ static void tcg_out_qemu_st(TCGContext *s, TCGReg data, TCGReg addr,
|
|||||||
unsigned t_bits;
|
unsigned t_bits;
|
||||||
|
|
||||||
if (TARGET_LONG_BITS == 32) {
|
if (TARGET_LONG_BITS == 32) {
|
||||||
tcg_out_arithi(s, TCG_REG_T1, addr, 0, SHIFT_SRL);
|
tcg_out_ext32u(s, TCG_REG_T1, addr);
|
||||||
addr = TCG_REG_T1;
|
addr = TCG_REG_T1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1613,8 +1642,10 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc,
|
|||||||
tcg_out_qemu_ld(s, a0, a1, a2, true);
|
tcg_out_qemu_ld(s, a0, a1, a2, true);
|
||||||
break;
|
break;
|
||||||
case INDEX_op_qemu_st_i32:
|
case INDEX_op_qemu_st_i32:
|
||||||
|
tcg_out_qemu_st(s, a0, a1, a2, TCG_TYPE_I32);
|
||||||
|
break;
|
||||||
case INDEX_op_qemu_st_i64:
|
case INDEX_op_qemu_st_i64:
|
||||||
tcg_out_qemu_st(s, a0, a1, a2);
|
tcg_out_qemu_st(s, a0, a1, a2, TCG_TYPE_I64);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case INDEX_op_ld32s_i64:
|
case INDEX_op_ld32s_i64:
|
||||||
@ -1647,17 +1678,6 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc,
|
|||||||
case INDEX_op_divu_i64:
|
case INDEX_op_divu_i64:
|
||||||
c = ARITH_UDIVX;
|
c = ARITH_UDIVX;
|
||||||
goto gen_arith;
|
goto gen_arith;
|
||||||
case INDEX_op_ext_i32_i64:
|
|
||||||
case INDEX_op_ext32s_i64:
|
|
||||||
tcg_out_arithi(s, a0, a1, 0, SHIFT_SRA);
|
|
||||||
break;
|
|
||||||
case INDEX_op_extu_i32_i64:
|
|
||||||
case INDEX_op_ext32u_i64:
|
|
||||||
tcg_out_arithi(s, a0, a1, 0, SHIFT_SRL);
|
|
||||||
break;
|
|
||||||
case INDEX_op_extrl_i64_i32:
|
|
||||||
tcg_out_mov(s, TCG_TYPE_I32, a0, a1);
|
|
||||||
break;
|
|
||||||
case INDEX_op_extrh_i64_i32:
|
case INDEX_op_extrh_i64_i32:
|
||||||
tcg_out_arithi(s, a0, a1, 32, SHIFT_SRLX);
|
tcg_out_arithi(s, a0, a1, 32, SHIFT_SRLX);
|
||||||
break;
|
break;
|
||||||
@ -1700,8 +1720,21 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc,
|
|||||||
case INDEX_op_call: /* Always emitted via tcg_out_call. */
|
case INDEX_op_call: /* Always emitted via tcg_out_call. */
|
||||||
case INDEX_op_exit_tb: /* Always emitted via tcg_out_exit_tb. */
|
case INDEX_op_exit_tb: /* Always emitted via tcg_out_exit_tb. */
|
||||||
case INDEX_op_goto_tb: /* Always emitted via tcg_out_goto_tb. */
|
case INDEX_op_goto_tb: /* Always emitted via tcg_out_goto_tb. */
|
||||||
|
case INDEX_op_ext8s_i32: /* Always emitted via tcg_reg_alloc_op. */
|
||||||
|
case INDEX_op_ext8s_i64:
|
||||||
|
case INDEX_op_ext8u_i32:
|
||||||
|
case INDEX_op_ext8u_i64:
|
||||||
|
case INDEX_op_ext16s_i32:
|
||||||
|
case INDEX_op_ext16s_i64:
|
||||||
|
case INDEX_op_ext16u_i32:
|
||||||
|
case INDEX_op_ext16u_i64:
|
||||||
|
case INDEX_op_ext32s_i64:
|
||||||
|
case INDEX_op_ext32u_i64:
|
||||||
|
case INDEX_op_ext_i32_i64:
|
||||||
|
case INDEX_op_extu_i32_i64:
|
||||||
|
case INDEX_op_extrl_i64_i32:
|
||||||
default:
|
default:
|
||||||
tcg_abort();
|
g_assert_not_reached();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -72,6 +72,7 @@ static inline TCGLabelQemuLdst *new_ldst_label(TCGContext *s)
|
|||||||
{
|
{
|
||||||
TCGLabelQemuLdst *l = tcg_malloc(sizeof(*l));
|
TCGLabelQemuLdst *l = tcg_malloc(sizeof(*l));
|
||||||
|
|
||||||
|
memset(l, 0, sizeof(*l));
|
||||||
QSIMPLEQ_INSERT_TAIL(&s->ldst_labels, l, next);
|
QSIMPLEQ_INSERT_TAIL(&s->ldst_labels, l, next);
|
||||||
|
|
||||||
return l;
|
return l;
|
||||||
|
125
tcg/tcg.c
125
tcg/tcg.c
@ -105,7 +105,18 @@ static void tcg_out_ld(TCGContext *s, TCGType type, TCGReg ret, TCGReg arg1,
|
|||||||
static bool tcg_out_mov(TCGContext *s, TCGType type, TCGReg ret, TCGReg arg);
|
static bool tcg_out_mov(TCGContext *s, TCGType type, TCGReg ret, TCGReg arg);
|
||||||
static void tcg_out_movi(TCGContext *s, TCGType type,
|
static void tcg_out_movi(TCGContext *s, TCGType type,
|
||||||
TCGReg ret, tcg_target_long arg);
|
TCGReg ret, tcg_target_long arg);
|
||||||
|
static void tcg_out_ext8s(TCGContext *s, TCGType type, TCGReg ret, TCGReg arg);
|
||||||
|
static void tcg_out_ext16s(TCGContext *s, TCGType type, TCGReg ret, TCGReg arg);
|
||||||
|
static void tcg_out_ext8u(TCGContext *s, TCGReg ret, TCGReg arg);
|
||||||
|
static void tcg_out_ext16u(TCGContext *s, TCGReg ret, TCGReg arg);
|
||||||
|
static void tcg_out_ext32s(TCGContext *s, TCGReg ret, TCGReg arg);
|
||||||
|
static void tcg_out_ext32u(TCGContext *s, TCGReg ret, TCGReg arg);
|
||||||
|
static void tcg_out_exts_i32_i64(TCGContext *s, TCGReg ret, TCGReg arg);
|
||||||
|
static void tcg_out_extu_i32_i64(TCGContext *s, TCGReg ret, TCGReg arg);
|
||||||
|
static void tcg_out_extrl_i64_i32(TCGContext *s, TCGReg ret, TCGReg arg);
|
||||||
static void tcg_out_addi_ptr(TCGContext *s, TCGReg, TCGReg, tcg_target_long);
|
static void tcg_out_addi_ptr(TCGContext *s, TCGReg, TCGReg, tcg_target_long);
|
||||||
|
static bool tcg_out_xchg(TCGContext *s, TCGType type, TCGReg r1, TCGReg r2)
|
||||||
|
__attribute__((unused));
|
||||||
static void tcg_out_exit_tb(TCGContext *s, uintptr_t arg);
|
static void tcg_out_exit_tb(TCGContext *s, uintptr_t arg);
|
||||||
static void tcg_out_goto_tb(TCGContext *s, int which);
|
static void tcg_out_goto_tb(TCGContext *s, int which);
|
||||||
static void tcg_out_op(TCGContext *s, TCGOpcode opc,
|
static void tcg_out_op(TCGContext *s, TCGOpcode opc,
|
||||||
@ -343,6 +354,69 @@ void tcg_raise_tb_overflow(TCGContext *s)
|
|||||||
siglongjmp(s->jmp_trans, -2);
|
siglongjmp(s->jmp_trans, -2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* tcg_out_movext -- move and extend
|
||||||
|
* @s: tcg context
|
||||||
|
* @dst_type: integral type for destination
|
||||||
|
* @dst: destination register
|
||||||
|
* @src_type: integral type for source
|
||||||
|
* @src_ext: extension to apply to source
|
||||||
|
* @src: source register
|
||||||
|
*
|
||||||
|
* Move or extend @src into @dst, depending on @src_ext and the types.
|
||||||
|
*/
|
||||||
|
static void __attribute__((unused))
|
||||||
|
tcg_out_movext(TCGContext *s, TCGType dst_type, TCGReg dst,
|
||||||
|
TCGType src_type, MemOp src_ext, TCGReg src)
|
||||||
|
{
|
||||||
|
switch (src_ext) {
|
||||||
|
case MO_UB:
|
||||||
|
tcg_out_ext8u(s, dst, src);
|
||||||
|
break;
|
||||||
|
case MO_SB:
|
||||||
|
tcg_out_ext8s(s, dst_type, dst, src);
|
||||||
|
break;
|
||||||
|
case MO_UW:
|
||||||
|
tcg_out_ext16u(s, dst, src);
|
||||||
|
break;
|
||||||
|
case MO_SW:
|
||||||
|
tcg_out_ext16s(s, dst_type, dst, src);
|
||||||
|
break;
|
||||||
|
case MO_UL:
|
||||||
|
case MO_SL:
|
||||||
|
if (dst_type == TCG_TYPE_I32) {
|
||||||
|
if (src_type == TCG_TYPE_I32) {
|
||||||
|
tcg_out_mov(s, TCG_TYPE_I32, dst, src);
|
||||||
|
} else {
|
||||||
|
tcg_out_extrl_i64_i32(s, dst, src);
|
||||||
|
}
|
||||||
|
} else if (src_type == TCG_TYPE_I32) {
|
||||||
|
if (src_ext & MO_SIGN) {
|
||||||
|
tcg_out_exts_i32_i64(s, dst, src);
|
||||||
|
} else {
|
||||||
|
tcg_out_extu_i32_i64(s, dst, src);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (src_ext & MO_SIGN) {
|
||||||
|
tcg_out_ext32s(s, dst, src);
|
||||||
|
} else {
|
||||||
|
tcg_out_ext32u(s, dst, src);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case MO_UQ:
|
||||||
|
tcg_debug_assert(TCG_TARGET_REG_BITS == 64);
|
||||||
|
if (dst_type == TCG_TYPE_I32) {
|
||||||
|
tcg_out_extrl_i64_i32(s, dst, src);
|
||||||
|
} else {
|
||||||
|
tcg_out_mov(s, TCG_TYPE_I64, dst, src);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
g_assert_not_reached();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#define C_PFX1(P, A) P##A
|
#define C_PFX1(P, A) P##A
|
||||||
#define C_PFX2(P, A, B) P##A##_##B
|
#define C_PFX2(P, A, B) P##A##_##B
|
||||||
#define C_PFX3(P, A, B, C) P##A##_##B##_##C
|
#define C_PFX3(P, A, B, C) P##A##_##B##_##C
|
||||||
@ -1174,9 +1248,7 @@ static TCGTemp *tcg_global_reg_new_internal(TCGContext *s, TCGType type,
|
|||||||
{
|
{
|
||||||
TCGTemp *ts;
|
TCGTemp *ts;
|
||||||
|
|
||||||
if (TCG_TARGET_REG_BITS == 32 && type != TCG_TYPE_I32) {
|
tcg_debug_assert(TCG_TARGET_REG_BITS == 64 || type == TCG_TYPE_I32);
|
||||||
tcg_abort();
|
|
||||||
}
|
|
||||||
|
|
||||||
ts = tcg_global_alloc(s);
|
ts = tcg_global_alloc(s);
|
||||||
ts->base_type = type;
|
ts->base_type = type;
|
||||||
@ -3682,7 +3754,7 @@ static void temp_sync(TCGContext *s, TCGTemp *ts, TCGRegSet allocated_regs,
|
|||||||
|
|
||||||
case TEMP_VAL_DEAD:
|
case TEMP_VAL_DEAD:
|
||||||
default:
|
default:
|
||||||
tcg_abort();
|
g_assert_not_reached();
|
||||||
}
|
}
|
||||||
ts->mem_coherent = 1;
|
ts->mem_coherent = 1;
|
||||||
}
|
}
|
||||||
@ -3769,7 +3841,7 @@ static TCGReg tcg_reg_alloc(TCGContext *s, TCGRegSet required_regs,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
tcg_abort();
|
g_assert_not_reached();
|
||||||
}
|
}
|
||||||
|
|
||||||
static TCGReg tcg_reg_alloc_pair(TCGContext *s, TCGRegSet required_regs,
|
static TCGReg tcg_reg_alloc_pair(TCGContext *s, TCGRegSet required_regs,
|
||||||
@ -3815,7 +3887,7 @@ static TCGReg tcg_reg_alloc_pair(TCGContext *s, TCGRegSet required_regs,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
tcg_abort();
|
g_assert_not_reached();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Make sure the temporary is in a register. If needed, allocate the register
|
/* Make sure the temporary is in a register. If needed, allocate the register
|
||||||
@ -3862,7 +3934,7 @@ static void temp_load(TCGContext *s, TCGTemp *ts, TCGRegSet desired_regs,
|
|||||||
break;
|
break;
|
||||||
case TEMP_VAL_DEAD:
|
case TEMP_VAL_DEAD:
|
||||||
default:
|
default:
|
||||||
tcg_abort();
|
g_assert_not_reached();
|
||||||
}
|
}
|
||||||
set_temp_val_reg(s, ts, reg);
|
set_temp_val_reg(s, ts, reg);
|
||||||
}
|
}
|
||||||
@ -4498,12 +4570,51 @@ static void tcg_reg_alloc_op(TCGContext *s, const TCGOp *op)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* emit instruction */
|
/* emit instruction */
|
||||||
|
switch (op->opc) {
|
||||||
|
case INDEX_op_ext8s_i32:
|
||||||
|
tcg_out_ext8s(s, TCG_TYPE_I32, new_args[0], new_args[1]);
|
||||||
|
break;
|
||||||
|
case INDEX_op_ext8s_i64:
|
||||||
|
tcg_out_ext8s(s, TCG_TYPE_I64, new_args[0], new_args[1]);
|
||||||
|
break;
|
||||||
|
case INDEX_op_ext8u_i32:
|
||||||
|
case INDEX_op_ext8u_i64:
|
||||||
|
tcg_out_ext8u(s, new_args[0], new_args[1]);
|
||||||
|
break;
|
||||||
|
case INDEX_op_ext16s_i32:
|
||||||
|
tcg_out_ext16s(s, TCG_TYPE_I32, new_args[0], new_args[1]);
|
||||||
|
break;
|
||||||
|
case INDEX_op_ext16s_i64:
|
||||||
|
tcg_out_ext16s(s, TCG_TYPE_I64, new_args[0], new_args[1]);
|
||||||
|
break;
|
||||||
|
case INDEX_op_ext16u_i32:
|
||||||
|
case INDEX_op_ext16u_i64:
|
||||||
|
tcg_out_ext16u(s, new_args[0], new_args[1]);
|
||||||
|
break;
|
||||||
|
case INDEX_op_ext32s_i64:
|
||||||
|
tcg_out_ext32s(s, new_args[0], new_args[1]);
|
||||||
|
break;
|
||||||
|
case INDEX_op_ext32u_i64:
|
||||||
|
tcg_out_ext32u(s, new_args[0], new_args[1]);
|
||||||
|
break;
|
||||||
|
case INDEX_op_ext_i32_i64:
|
||||||
|
tcg_out_exts_i32_i64(s, new_args[0], new_args[1]);
|
||||||
|
break;
|
||||||
|
case INDEX_op_extu_i32_i64:
|
||||||
|
tcg_out_extu_i32_i64(s, new_args[0], new_args[1]);
|
||||||
|
break;
|
||||||
|
case INDEX_op_extrl_i64_i32:
|
||||||
|
tcg_out_extrl_i64_i32(s, new_args[0], new_args[1]);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
if (def->flags & TCG_OPF_VECTOR) {
|
if (def->flags & TCG_OPF_VECTOR) {
|
||||||
tcg_out_vec_op(s, op->opc, TCGOP_VECL(op), TCGOP_VECE(op),
|
tcg_out_vec_op(s, op->opc, TCGOP_VECL(op), TCGOP_VECE(op),
|
||||||
new_args, const_args);
|
new_args, const_args);
|
||||||
} else {
|
} else {
|
||||||
tcg_out_op(s, op->opc, new_args, const_args);
|
tcg_out_op(s, op->opc, new_args, const_args);
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
/* move the outputs in the correct register if needed */
|
/* move the outputs in the correct register if needed */
|
||||||
for(i = 0; i < nb_oargs; i++) {
|
for(i = 0; i < nb_oargs; i++) {
|
||||||
|
@ -557,6 +557,99 @@ static void tcg_out_movi(TCGContext *s, TCGType type,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void tcg_out_ext8s(TCGContext *s, TCGType type, TCGReg rd, TCGReg rs)
|
||||||
|
{
|
||||||
|
switch (type) {
|
||||||
|
case TCG_TYPE_I32:
|
||||||
|
tcg_debug_assert(TCG_TARGET_HAS_ext8s_i32);
|
||||||
|
tcg_out_op_rr(s, INDEX_op_ext8s_i32, rd, rs);
|
||||||
|
break;
|
||||||
|
#if TCG_TARGET_REG_BITS == 64
|
||||||
|
case TCG_TYPE_I64:
|
||||||
|
tcg_debug_assert(TCG_TARGET_HAS_ext8s_i64);
|
||||||
|
tcg_out_op_rr(s, INDEX_op_ext8s_i64, rd, rs);
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
default:
|
||||||
|
g_assert_not_reached();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void tcg_out_ext8u(TCGContext *s, TCGReg rd, TCGReg rs)
|
||||||
|
{
|
||||||
|
if (TCG_TARGET_REG_BITS == 64) {
|
||||||
|
tcg_debug_assert(TCG_TARGET_HAS_ext8u_i64);
|
||||||
|
tcg_out_op_rr(s, INDEX_op_ext8u_i64, rd, rs);
|
||||||
|
} else {
|
||||||
|
tcg_debug_assert(TCG_TARGET_HAS_ext8u_i32);
|
||||||
|
tcg_out_op_rr(s, INDEX_op_ext8u_i32, rd, rs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void tcg_out_ext16s(TCGContext *s, TCGType type, TCGReg rd, TCGReg rs)
|
||||||
|
{
|
||||||
|
switch (type) {
|
||||||
|
case TCG_TYPE_I32:
|
||||||
|
tcg_debug_assert(TCG_TARGET_HAS_ext16s_i32);
|
||||||
|
tcg_out_op_rr(s, INDEX_op_ext16s_i32, rd, rs);
|
||||||
|
break;
|
||||||
|
#if TCG_TARGET_REG_BITS == 64
|
||||||
|
case TCG_TYPE_I64:
|
||||||
|
tcg_debug_assert(TCG_TARGET_HAS_ext16s_i64);
|
||||||
|
tcg_out_op_rr(s, INDEX_op_ext16s_i64, rd, rs);
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
default:
|
||||||
|
g_assert_not_reached();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void tcg_out_ext16u(TCGContext *s, TCGReg rd, TCGReg rs)
|
||||||
|
{
|
||||||
|
if (TCG_TARGET_REG_BITS == 64) {
|
||||||
|
tcg_debug_assert(TCG_TARGET_HAS_ext16u_i64);
|
||||||
|
tcg_out_op_rr(s, INDEX_op_ext16u_i64, rd, rs);
|
||||||
|
} else {
|
||||||
|
tcg_debug_assert(TCG_TARGET_HAS_ext16u_i32);
|
||||||
|
tcg_out_op_rr(s, INDEX_op_ext16u_i32, rd, rs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void tcg_out_ext32s(TCGContext *s, TCGReg rd, TCGReg rs)
|
||||||
|
{
|
||||||
|
tcg_debug_assert(TCG_TARGET_REG_BITS == 64);
|
||||||
|
tcg_debug_assert(TCG_TARGET_HAS_ext32s_i64);
|
||||||
|
tcg_out_op_rr(s, INDEX_op_ext32s_i64, rd, rs);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void tcg_out_ext32u(TCGContext *s, TCGReg rd, TCGReg rs)
|
||||||
|
{
|
||||||
|
tcg_debug_assert(TCG_TARGET_REG_BITS == 64);
|
||||||
|
tcg_debug_assert(TCG_TARGET_HAS_ext32u_i64);
|
||||||
|
tcg_out_op_rr(s, INDEX_op_ext32u_i64, rd, rs);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void tcg_out_exts_i32_i64(TCGContext *s, TCGReg rd, TCGReg rs)
|
||||||
|
{
|
||||||
|
tcg_out_ext32s(s, rd, rs);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void tcg_out_extu_i32_i64(TCGContext *s, TCGReg rd, TCGReg rs)
|
||||||
|
{
|
||||||
|
tcg_out_ext32u(s, rd, rs);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void tcg_out_extrl_i64_i32(TCGContext *s, TCGReg rd, TCGReg rs)
|
||||||
|
{
|
||||||
|
tcg_debug_assert(TCG_TARGET_REG_BITS == 64);
|
||||||
|
tcg_out_mov(s, TCG_TYPE_I32, rd, rs);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool tcg_out_xchg(TCGContext *s, TCGType type, TCGReg r1, TCGReg r2)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
static void tcg_out_addi_ptr(TCGContext *s, TCGReg rd, TCGReg rs,
|
static void tcg_out_addi_ptr(TCGContext *s, TCGReg rd, TCGReg rs,
|
||||||
tcg_target_long imm)
|
tcg_target_long imm)
|
||||||
{
|
{
|
||||||
@ -715,14 +808,6 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc,
|
|||||||
|
|
||||||
CASE_32_64(neg) /* Optional (TCG_TARGET_HAS_neg_*). */
|
CASE_32_64(neg) /* Optional (TCG_TARGET_HAS_neg_*). */
|
||||||
CASE_32_64(not) /* Optional (TCG_TARGET_HAS_not_*). */
|
CASE_32_64(not) /* Optional (TCG_TARGET_HAS_not_*). */
|
||||||
CASE_32_64(ext8s) /* Optional (TCG_TARGET_HAS_ext8s_*). */
|
|
||||||
CASE_32_64(ext8u) /* Optional (TCG_TARGET_HAS_ext8u_*). */
|
|
||||||
CASE_32_64(ext16s) /* Optional (TCG_TARGET_HAS_ext16s_*). */
|
|
||||||
CASE_32_64(ext16u) /* Optional (TCG_TARGET_HAS_ext16u_*). */
|
|
||||||
CASE_64(ext32s) /* Optional (TCG_TARGET_HAS_ext32s_i64). */
|
|
||||||
CASE_64(ext32u) /* Optional (TCG_TARGET_HAS_ext32u_i64). */
|
|
||||||
CASE_64(ext_i32)
|
|
||||||
CASE_64(extu_i32)
|
|
||||||
CASE_32_64(ctpop) /* Optional (TCG_TARGET_HAS_ctpop_*). */
|
CASE_32_64(ctpop) /* Optional (TCG_TARGET_HAS_ctpop_*). */
|
||||||
case INDEX_op_bswap32_i32: /* Optional (TCG_TARGET_HAS_bswap32_i32). */
|
case INDEX_op_bswap32_i32: /* Optional (TCG_TARGET_HAS_bswap32_i32). */
|
||||||
case INDEX_op_bswap64_i64: /* Optional (TCG_TARGET_HAS_bswap64_i64). */
|
case INDEX_op_bswap64_i64: /* Optional (TCG_TARGET_HAS_bswap64_i64). */
|
||||||
@ -795,8 +880,21 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc,
|
|||||||
case INDEX_op_call: /* Always emitted via tcg_out_call. */
|
case INDEX_op_call: /* Always emitted via tcg_out_call. */
|
||||||
case INDEX_op_exit_tb: /* Always emitted via tcg_out_exit_tb. */
|
case INDEX_op_exit_tb: /* Always emitted via tcg_out_exit_tb. */
|
||||||
case INDEX_op_goto_tb: /* Always emitted via tcg_out_goto_tb. */
|
case INDEX_op_goto_tb: /* Always emitted via tcg_out_goto_tb. */
|
||||||
|
case INDEX_op_ext8s_i32: /* Always emitted via tcg_reg_alloc_op. */
|
||||||
|
case INDEX_op_ext8s_i64:
|
||||||
|
case INDEX_op_ext8u_i32:
|
||||||
|
case INDEX_op_ext8u_i64:
|
||||||
|
case INDEX_op_ext16s_i32:
|
||||||
|
case INDEX_op_ext16s_i64:
|
||||||
|
case INDEX_op_ext16u_i32:
|
||||||
|
case INDEX_op_ext16u_i64:
|
||||||
|
case INDEX_op_ext32s_i64:
|
||||||
|
case INDEX_op_ext32u_i64:
|
||||||
|
case INDEX_op_ext_i32_i64:
|
||||||
|
case INDEX_op_extu_i32_i64:
|
||||||
|
case INDEX_op_extrl_i64_i32:
|
||||||
default:
|
default:
|
||||||
tcg_abort();
|
g_assert_not_reached();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user