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:
parent
af9fe31070
commit
4bdd547aaa
@ -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 */
|
||||||
|
Loading…
Reference in New Issue
Block a user