tcg-ia64: Convert to new ldst helpers

Still inline, but updated to the new routines.  Always use the LE
helpers, reusing the bswap between the fast and slot paths.

Signed-off-by: Richard Henderson <rth@twiddle.net>
This commit is contained in:
Richard Henderson 2013-09-06 00:38:52 -04:00
parent af9fe31070
commit 4bdd547aaa

View File

@ -225,6 +225,7 @@ enum {
OPC_BR_CALL_SPTK_MANY_B5 = 0x02100001000ull, OPC_BR_CALL_SPTK_MANY_B5 = 0x02100001000ull,
OPC_BR_RET_SPTK_MANY_B4 = 0x00108001100ull, OPC_BR_RET_SPTK_MANY_B4 = 0x00108001100ull,
OPC_BRL_SPTK_MANY_X3 = 0x18000001000ull, OPC_BRL_SPTK_MANY_X3 = 0x18000001000ull,
OPC_BRL_CALL_SPNT_MANY_X4 = 0x1a200001000ull,
OPC_BRL_CALL_SPTK_MANY_X4 = 0x1a000001000ull, OPC_BRL_CALL_SPTK_MANY_X4 = 0x1a000001000ull,
OPC_CMP_LT_A6 = 0x18000000000ull, OPC_CMP_LT_A6 = 0x18000000000ull,
OPC_CMP_LTU_A6 = 0x1a000000000ull, OPC_CMP_LTU_A6 = 0x1a000000000ull,
@ -815,6 +816,7 @@ static int target_parse_constraint(TCGArgConstraint *ct, const char **pct_str)
#if defined(CONFIG_SOFTMMU) #if defined(CONFIG_SOFTMMU)
tcg_regset_reset_reg(ct->u.regs, TCG_REG_R56); tcg_regset_reset_reg(ct->u.regs, TCG_REG_R56);
tcg_regset_reset_reg(ct->u.regs, TCG_REG_R57); tcg_regset_reset_reg(ct->u.regs, TCG_REG_R57);
tcg_regset_reset_reg(ct->u.regs, TCG_REG_R58);
#endif #endif
break; break;
case 'Z': case 'Z':
@ -1632,12 +1634,12 @@ static inline void tcg_out_qemu_tlb(TCGContext *s, TCGReg addr_reg,
} }
/* helper signature: helper_ld_mmu(CPUState *env, target_ulong addr, /* helper signature: helper_ld_mmu(CPUState *env, target_ulong addr,
int mmu_idx) */ int mmu_idx, uintptr_t retaddr) */
static const void * const qemu_ld_helpers[4] = { static const void * const qemu_ld_helpers[4] = {
helper_ldb_mmu, helper_ret_ldub_mmu,
helper_ldw_mmu, helper_le_lduw_mmu,
helper_ldl_mmu, helper_le_ldul_mmu,
helper_ldq_mmu, helper_le_ldq_mmu,
}; };
static inline void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, static inline void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args,
@ -1648,7 +1650,7 @@ static inline void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args,
}; };
int addr_reg, data_reg, mem_index; int addr_reg, data_reg, mem_index;
TCGMemOp s_bits; TCGMemOp s_bits;
uint64_t bswap1, bswap2; uint64_t fin1, fin2, *desc, func, gp, here;
data_reg = *args++; data_reg = *args++;
addr_reg = *args++; addr_reg = *args++;
@ -1663,52 +1665,60 @@ static inline void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args,
/* P6 is the fast path, and P7 the slow path */ /* P6 is the fast path, and P7 the slow path */
bswap1 = bswap2 = INSN_NOP_I; fin2 = 0;
if (opc & MO_BSWAP) { if (opc & MO_BSWAP) {
bswap1 = tcg_opc_bswap64_i(TCG_REG_P6, TCG_REG_R8, TCG_REG_R8); fin1 = tcg_opc_bswap64_i(TCG_REG_P0, data_reg, TCG_REG_R8);
if (s_bits < MO_64) { if (s_bits < MO_64) {
int shift = 64 - (8 << s_bits); int shift = 64 - (8 << s_bits);
bswap2 = (opc & MO_SIGN ? OPC_EXTR_I11 : OPC_EXTR_U_I11); fin2 = (opc & MO_SIGN ? OPC_EXTR_I11 : OPC_EXTR_U_I11);
bswap2 = tcg_opc_i11(TCG_REG_P6, bswap2, fin2 = tcg_opc_i11(TCG_REG_P0, fin2,
TCG_REG_R8, TCG_REG_R8, shift, 63 - shift); data_reg, data_reg, shift, 63 - shift);
} }
} else {
fin1 = tcg_opc_ext_i(TCG_REG_P0, opc, data_reg, TCG_REG_R8);
} }
tcg_out_bundle(s, mLX, desc = (uintptr_t *)qemu_ld_helpers[s_bits];
func = desc[0];
gp = desc[1];
here = (uintptr_t)s->code_ptr;
tcg_out_bundle(s, mlx,
tcg_opc_mov_a(TCG_REG_P7, TCG_REG_R56, TCG_AREG0), tcg_opc_mov_a(TCG_REG_P7, TCG_REG_R56, TCG_AREG0),
tcg_opc_l2 ((tcg_target_long) qemu_ld_helpers[s_bits]), tcg_opc_l2 (here),
tcg_opc_x2 (TCG_REG_P7, OPC_MOVL_X2, TCG_REG_R2, tcg_opc_x2 (TCG_REG_P7, OPC_MOVL_X2, TCG_REG_R59, here));
(tcg_target_long) qemu_ld_helpers[s_bits])); tcg_out_bundle(s, mLX,
tcg_out_bundle(s, MmI,
tcg_opc_m3 (TCG_REG_P7, OPC_LD8_M3, TCG_REG_R3,
TCG_REG_R2, 8),
tcg_opc_a1 (TCG_REG_P6, OPC_ADD_A1, TCG_REG_R2, tcg_opc_a1 (TCG_REG_P6, OPC_ADD_A1, TCG_REG_R2,
TCG_REG_R2, TCG_REG_R57), TCG_REG_R2, TCG_REG_R57),
tcg_opc_i21(TCG_REG_P7, OPC_MOV_I21, TCG_REG_B6, tcg_opc_l2 (gp),
TCG_REG_R3, 0)); tcg_opc_x2 (TCG_REG_P7, OPC_MOVL_X2, TCG_REG_R1, gp));
tcg_out_bundle(s, MmI, tcg_out_bundle(s, mmi,
tcg_opc_m1 (TCG_REG_P6, opc_ld_m1[s_bits], tcg_opc_m1 (TCG_REG_P6, opc_ld_m1[s_bits],
TCG_REG_R8, TCG_REG_R2), TCG_REG_R8, TCG_REG_R2),
tcg_opc_m1 (TCG_REG_P7, OPC_LD8_M1, TCG_REG_R1, TCG_REG_R2),
bswap1);
tcg_out_bundle(s, miB,
tcg_opc_movi_a(TCG_REG_P7, TCG_REG_R58, mem_index), tcg_opc_movi_a(TCG_REG_P7, TCG_REG_R58, mem_index),
bswap2, INSN_NOP_I);
tcg_opc_b5 (TCG_REG_P7, OPC_BR_CALL_SPTK_MANY_B5, func -= (uintptr_t)s->code_ptr;
TCG_REG_B0, TCG_REG_B6)); tcg_out_bundle(s, mLX,
tcg_out_bundle(s, miI,
INSN_NOP_M, INSN_NOP_M,
INSN_NOP_I, tcg_opc_l4 (func >> 4),
tcg_opc_ext_i(TCG_REG_P0, opc, data_reg, TCG_REG_R8)); tcg_opc_x4 (TCG_REG_P7, OPC_BRL_CALL_SPNT_MANY_X4,
TCG_REG_B0, func >> 4));
/* Note that we always use LE helper functions, so the bswap insns
here for the fast path also apply to the slow path. */
tcg_out_bundle(s, (fin2 ? mII : miI),
INSN_NOP_M,
fin1,
fin2 ? fin2 : INSN_NOP_I);
} }
/* helper signature: helper_st_mmu(CPUState *env, target_ulong addr, /* helper signature: helper_st_mmu(CPUState *env, target_ulong addr,
uintxx_t val, int mmu_idx) */ uintxx_t val, int mmu_idx, uintptr_t retaddr) */
static const void * const qemu_st_helpers[4] = { static const void * const qemu_st_helpers[4] = {
helper_stb_mmu, helper_ret_stb_mmu,
helper_stw_mmu, helper_le_stw_mmu,
helper_stl_mmu, helper_le_stl_mmu,
helper_stq_mmu, helper_le_stq_mmu,
}; };
static inline void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, static inline void tcg_out_qemu_st(TCGContext *s, const TCGArg *args,
@ -1717,56 +1727,64 @@ static inline void tcg_out_qemu_st(TCGContext *s, const TCGArg *args,
static const uint64_t opc_st_m4[4] = { static const uint64_t opc_st_m4[4] = {
OPC_ST1_M4, OPC_ST2_M4, OPC_ST4_M4, OPC_ST8_M4 OPC_ST1_M4, OPC_ST2_M4, OPC_ST4_M4, OPC_ST8_M4
}; };
TCGReg addr_reg, data_reg, store_reg; TCGReg addr_reg, data_reg;
int mem_index; int mem_index;
uint64_t bswap1, bswap2; uint64_t pre1, pre2, *desc, func, gp, here;
TCGMemOp s_bits; TCGMemOp s_bits;
store_reg = data_reg = *args++; data_reg = *args++;
addr_reg = *args++; addr_reg = *args++;
mem_index = *args; mem_index = *args;
s_bits = opc & MO_SIZE; s_bits = opc & MO_SIZE;
bswap1 = bswap2 = INSN_NOP_I; /* Note that we always use LE helper functions, so the bswap insns
that are here for the fast path also apply to the slow path,
and move the data into the argument register. */
pre2 = INSN_NOP_I;
if (opc & MO_BSWAP) { if (opc & MO_BSWAP) {
store_reg = TCG_REG_R56; pre1 = tcg_opc_bswap64_i(TCG_REG_P0, TCG_REG_R58, data_reg);
bswap1 = tcg_opc_bswap64_i(TCG_REG_P0, store_reg, data_reg);
if (s_bits < MO_64) { if (s_bits < MO_64) {
int shift = 64 - (8 << s_bits); int shift = 64 - (8 << s_bits);
bswap2 = tcg_opc_i11(TCG_REG_P0, OPC_EXTR_U_I11, pre2 = tcg_opc_i11(TCG_REG_P0, OPC_EXTR_U_I11,
store_reg, store_reg, shift, 63 - shift); TCG_REG_R58, TCG_REG_R58, shift, 63 - shift);
} }
} else {
/* Just move the data into place for the slow path. */
pre1 = tcg_opc_ext_i(TCG_REG_P0, opc, TCG_REG_R58, data_reg);
} }
tcg_out_qemu_tlb(s, addr_reg, s_bits, tcg_out_qemu_tlb(s, addr_reg, s_bits,
offsetof(CPUArchState, tlb_table[mem_index][0].addr_write), offsetof(CPUArchState, tlb_table[mem_index][0].addr_write),
offsetof(CPUArchState, tlb_table[mem_index][0].addend), offsetof(CPUArchState, tlb_table[mem_index][0].addend),
bswap1, bswap2); pre1, pre2);
/* P6 is the fast path, and P7 the slow path */ /* P6 is the fast path, and P7 the slow path */
tcg_out_bundle(s, mLX,
desc = (uintptr_t *)qemu_st_helpers[s_bits];
func = desc[0];
gp = desc[1];
here = (uintptr_t)s->code_ptr;
tcg_out_bundle(s, mlx,
tcg_opc_mov_a(TCG_REG_P7, TCG_REG_R56, TCG_AREG0), tcg_opc_mov_a(TCG_REG_P7, TCG_REG_R56, TCG_AREG0),
tcg_opc_l2 ((tcg_target_long) qemu_st_helpers[s_bits]), tcg_opc_l2 (here),
tcg_opc_x2 (TCG_REG_P7, OPC_MOVL_X2, TCG_REG_R2, tcg_opc_x2 (TCG_REG_P7, OPC_MOVL_X2, TCG_REG_R60, here));
(tcg_target_long) qemu_st_helpers[s_bits])); tcg_out_bundle(s, mLX,
tcg_out_bundle(s, MmI,
tcg_opc_m3 (TCG_REG_P7, OPC_LD8_M3, TCG_REG_R3,
TCG_REG_R2, 8),
tcg_opc_a1 (TCG_REG_P6, OPC_ADD_A1, TCG_REG_R2, tcg_opc_a1 (TCG_REG_P6, OPC_ADD_A1, TCG_REG_R2,
TCG_REG_R2, TCG_REG_R57), TCG_REG_R2, TCG_REG_R57),
tcg_opc_i21(TCG_REG_P7, OPC_MOV_I21, TCG_REG_B6, tcg_opc_l2 (gp),
TCG_REG_R3, 0)); tcg_opc_x2 (TCG_REG_P7, OPC_MOVL_X2, TCG_REG_R1, gp));
tcg_out_bundle(s, mii, tcg_out_bundle(s, mmi,
tcg_opc_m1 (TCG_REG_P7, OPC_LD8_M1,
TCG_REG_R1, TCG_REG_R2),
tcg_opc_mov_a(TCG_REG_P7, TCG_REG_R58, data_reg),
INSN_NOP_I);
tcg_out_bundle(s, miB,
tcg_opc_m4 (TCG_REG_P6, opc_st_m4[s_bits], tcg_opc_m4 (TCG_REG_P6, opc_st_m4[s_bits],
store_reg, TCG_REG_R2), TCG_REG_R58, TCG_REG_R2),
tcg_opc_movi_a(TCG_REG_P7, TCG_REG_R59, mem_index), tcg_opc_movi_a(TCG_REG_P7, TCG_REG_R59, mem_index),
tcg_opc_b5 (TCG_REG_P7, OPC_BR_CALL_SPTK_MANY_B5, INSN_NOP_I);
TCG_REG_B0, TCG_REG_B6)); func -= (uintptr_t)s->code_ptr;
tcg_out_bundle(s, mLX,
INSN_NOP_M,
tcg_opc_l4 (func >> 4),
tcg_opc_x4 (TCG_REG_P7, OPC_BRL_CALL_SPNT_MANY_X4,
TCG_REG_B0, func >> 4));
} }
#else /* !CONFIG_SOFTMMU */ #else /* !CONFIG_SOFTMMU */