提交 1680d485 编写于 作者: A Anthony Liguori

Merge remote-tracking branch 'rth/tcg-ldst-6' into staging

# By Richard Henderson
# Via Richard Henderson
* rth/tcg-ldst-6:
  target-alpha: Convert to new ldst opcodes
  tcg-ppc64: Support new ldst opcodes
  tcg-ppc: Support new ldst opcodes
  tcg-ppc64: Convert to le/be ldst helpers
  tcg-ppc: Convert to le/be ldst helpers
  tcg-ppc64: Use TCGMemOp within qemu_ldst routines
  tcg-ppc: Use TCGMemOp within qemu_ldst routines
  tcg-arm: Improve GUEST_BASE qemu_ld/st
  tcg-arm: Convert to new ldst opcodes
  tcg-arm: Tidy variable naming convention in qemu_ld/st
  tcg-arm: Convert to le/be ldst helpers
  tcg-arm: Use TCGMemOp within qemu_ldst routines
  tcg-i386: Support new ldst opcodes
  tcg-i386: Remove "cb" output restriction from qemu_st8 for i386
  tcg-i386: Tidy softmmu routines
  tcg-i386: Use TCGMemOp within qemu_ldst routines
  tcg: Use TCGMemOp for TCGLabelQemuLdst.opc

Message-id: 1381620683-4568-1-git-send-email-rth@twiddle.net
Signed-off-by: NAnthony Liguori <aliguori@amazon.com>
......@@ -168,44 +168,38 @@ static inline ExitStatus gen_invalid(DisasContext *ctx)
static inline void gen_qemu_ldf(TCGv t0, TCGv t1, int flags)
{
TCGv tmp = tcg_temp_new();
TCGv_i32 tmp32 = tcg_temp_new_i32();
tcg_gen_qemu_ld32u(tmp, t1, flags);
tcg_gen_trunc_i64_i32(tmp32, tmp);
tcg_gen_qemu_ld_i32(tmp32, t1, flags, MO_LEUL);
gen_helper_memory_to_f(t0, tmp32);
tcg_temp_free_i32(tmp32);
tcg_temp_free(tmp);
}
static inline void gen_qemu_ldg(TCGv t0, TCGv t1, int flags)
{
TCGv tmp = tcg_temp_new();
tcg_gen_qemu_ld64(tmp, t1, flags);
tcg_gen_qemu_ld_i64(tmp, t1, flags, MO_LEQ);
gen_helper_memory_to_g(t0, tmp);
tcg_temp_free(tmp);
}
static inline void gen_qemu_lds(TCGv t0, TCGv t1, int flags)
{
TCGv tmp = tcg_temp_new();
TCGv_i32 tmp32 = tcg_temp_new_i32();
tcg_gen_qemu_ld32u(tmp, t1, flags);
tcg_gen_trunc_i64_i32(tmp32, tmp);
tcg_gen_qemu_ld_i32(tmp32, t1, flags, MO_LEUL);
gen_helper_memory_to_s(t0, tmp32);
tcg_temp_free_i32(tmp32);
tcg_temp_free(tmp);
}
static inline void gen_qemu_ldl_l(TCGv t0, TCGv t1, int flags)
{
tcg_gen_qemu_ld32s(t0, t1, flags);
tcg_gen_qemu_ld_i64(t0, t1, flags, MO_LESL);
tcg_gen_mov_i64(cpu_lock_addr, t1);
tcg_gen_mov_i64(cpu_lock_value, t0);
}
static inline void gen_qemu_ldq_l(TCGv t0, TCGv t1, int flags)
{
tcg_gen_qemu_ld64(t0, t1, flags);
tcg_gen_qemu_ld_i64(t0, t1, flags, MO_LEQ);
tcg_gen_mov_i64(cpu_lock_addr, t1);
tcg_gen_mov_i64(cpu_lock_value, t0);
}
......@@ -247,11 +241,8 @@ static inline void gen_load_mem(DisasContext *ctx,
static inline void gen_qemu_stf(TCGv t0, TCGv t1, int flags)
{
TCGv_i32 tmp32 = tcg_temp_new_i32();
TCGv tmp = tcg_temp_new();
gen_helper_f_to_memory(tmp32, t0);
tcg_gen_extu_i32_i64(tmp, tmp32);
tcg_gen_qemu_st32(tmp, t1, flags);
tcg_temp_free(tmp);
tcg_gen_qemu_st_i32(tmp32, t1, flags, MO_LEUL);
tcg_temp_free_i32(tmp32);
}
......@@ -259,18 +250,15 @@ static inline void gen_qemu_stg(TCGv t0, TCGv t1, int flags)
{
TCGv tmp = tcg_temp_new();
gen_helper_g_to_memory(tmp, t0);
tcg_gen_qemu_st64(tmp, t1, flags);
tcg_gen_qemu_st_i64(tmp, t1, flags, MO_LEQ);
tcg_temp_free(tmp);
}
static inline void gen_qemu_sts(TCGv t0, TCGv t1, int flags)
{
TCGv_i32 tmp32 = tcg_temp_new_i32();
TCGv tmp = tcg_temp_new();
gen_helper_s_to_memory(tmp32, t0);
tcg_gen_extu_i32_i64(tmp, tmp32);
tcg_gen_qemu_st32(tmp, t1, flags);
tcg_temp_free(tmp);
tcg_gen_qemu_st_i32(tmp32, t1, flags, MO_LEUL);
tcg_temp_free_i32(tmp32);
}
......@@ -348,18 +336,11 @@ static ExitStatus gen_store_conditional(DisasContext *ctx, int ra, int rb,
tcg_gen_brcond_i64(TCG_COND_NE, addr, cpu_lock_addr, lab_fail);
val = tcg_temp_new();
if (quad) {
tcg_gen_qemu_ld64(val, addr, ctx->mem_idx);
} else {
tcg_gen_qemu_ld32s(val, addr, ctx->mem_idx);
}
tcg_gen_qemu_ld_i64(val, addr, ctx->mem_idx, quad ? MO_LEQ : MO_LESL);
tcg_gen_brcond_i64(TCG_COND_NE, val, cpu_lock_value, lab_fail);
if (quad) {
tcg_gen_qemu_st64(cpu_ir[ra], addr, ctx->mem_idx);
} else {
tcg_gen_qemu_st32(cpu_ir[ra], addr, ctx->mem_idx);
}
tcg_gen_qemu_st_i64(cpu_ir[ra], addr, ctx->mem_idx,
quad ? MO_LEQ : MO_LEUL);
tcg_gen_movi_i64(cpu_ir[ra], 1);
tcg_gen_br(lab_done);
......@@ -2966,11 +2947,11 @@ static ExitStatus translate_one(DisasContext *ctx, uint32_t insn)
goto invalid_opc;
case 0xA:
/* Longword virtual access with protection check (hw_ldl/w) */
tcg_gen_qemu_ld32s(cpu_ir[ra], addr, MMU_KERNEL_IDX);
tcg_gen_qemu_ld_i64(cpu_ir[ra], addr, MMU_KERNEL_IDX, MO_LESL);
break;
case 0xB:
/* Quadword virtual access with protection check (hw_ldq/w) */
tcg_gen_qemu_ld64(cpu_ir[ra], addr, MMU_KERNEL_IDX);
tcg_gen_qemu_ld_i64(cpu_ir[ra], addr, MMU_KERNEL_IDX, MO_LEQ);
break;
case 0xC:
/* Longword virtual access with alt access mode (hw_ldl/a)*/
......@@ -2981,12 +2962,12 @@ static ExitStatus translate_one(DisasContext *ctx, uint32_t insn)
case 0xE:
/* Longword virtual access with alternate access mode and
protection checks (hw_ldl/wa) */
tcg_gen_qemu_ld32s(cpu_ir[ra], addr, MMU_USER_IDX);
tcg_gen_qemu_ld_i64(cpu_ir[ra], addr, MMU_USER_IDX, MO_LESL);
break;
case 0xF:
/* Quadword virtual access with alternate access mode and
protection checks (hw_ldq/wa) */
tcg_gen_qemu_ld64(cpu_ir[ra], addr, MMU_USER_IDX);
tcg_gen_qemu_ld_i64(cpu_ir[ra], addr, MMU_USER_IDX, MO_LEQ);
break;
}
tcg_temp_free(addr);
......
此差异已折叠。
......@@ -85,7 +85,7 @@ extern bool use_idiv_instructions;
#define TCG_TARGET_HAS_div_i32 use_idiv_instructions
#define TCG_TARGET_HAS_rem_i32 0
#define TCG_TARGET_HAS_new_ldst 0
#define TCG_TARGET_HAS_new_ldst 1
extern bool tcg_target_deposit_valid(int ofs, int len);
#define TCG_TARGET_deposit_i32_valid tcg_target_deposit_valid
......
此差异已折叠。
......@@ -130,7 +130,7 @@ typedef enum {
#define TCG_TARGET_HAS_mulsh_i64 0
#endif
#define TCG_TARGET_HAS_new_ldst 0
#define TCG_TARGET_HAS_new_ldst 1
#define TCG_TARGET_deposit_i32_valid(ofs, len) \
(((ofs) == 0 && (len) == 8) || ((ofs) == 8 && (len) == 8) || \
......
......@@ -525,7 +525,7 @@ static void tcg_out_call (TCGContext *s, tcg_target_long arg, int const_arg,
static void add_qemu_ldst_label (TCGContext *s,
int is_ld,
int opc,
TCGMemOp opc,
int data_reg,
int data_reg2,
int addrlo_reg,
......@@ -550,32 +550,38 @@ static void add_qemu_ldst_label (TCGContext *s,
/* helper signature: helper_ret_ld_mmu(CPUState *env, target_ulong addr,
* int mmu_idx, uintptr_t ra)
*/
static const void * const qemu_ld_helpers[4] = {
helper_ret_ldub_mmu,
helper_ret_lduw_mmu,
helper_ret_ldul_mmu,
helper_ret_ldq_mmu,
static const void * const qemu_ld_helpers[16] = {
[MO_UB] = helper_ret_ldub_mmu,
[MO_LEUW] = helper_le_lduw_mmu,
[MO_LEUL] = helper_le_ldul_mmu,
[MO_LEQ] = helper_le_ldq_mmu,
[MO_BEUW] = helper_be_lduw_mmu,
[MO_BEUL] = helper_be_ldul_mmu,
[MO_BEQ] = helper_be_ldq_mmu,
};
/* helper signature: helper_ret_st_mmu(CPUState *env, target_ulong addr,
* uintxx_t val, int mmu_idx, uintptr_t ra)
*/
static const void * const qemu_st_helpers[4] = {
helper_ret_stb_mmu,
helper_ret_stw_mmu,
helper_ret_stl_mmu,
helper_ret_stq_mmu,
static const void * const qemu_st_helpers[16] = {
[MO_UB] = helper_ret_stb_mmu,
[MO_LEUW] = helper_le_stw_mmu,
[MO_LEUL] = helper_le_stl_mmu,
[MO_LEQ] = helper_le_stq_mmu,
[MO_BEUW] = helper_be_stw_mmu,
[MO_BEUL] = helper_be_stl_mmu,
[MO_BEQ] = helper_be_stq_mmu,
};
static void *ld_trampolines[4];
static void *st_trampolines[4];
static void *ld_trampolines[16];
static void *st_trampolines[16];
/* Perform the TLB load and compare. Branches to the slow path, placing the
address of the branch in *LABEL_PTR. Loads the addend of the TLB into R0.
Clobbers R1 and R2. */
static void tcg_out_tlb_check(TCGContext *s, TCGReg r0, TCGReg r1, TCGReg r2,
TCGReg addrlo, TCGReg addrhi, int s_bits,
TCGReg addrlo, TCGReg addrhi, TCGMemOp s_bits,
int mem_index, int is_load, uint8_t **label_ptr)
{
int cmp_off =
......@@ -647,50 +653,44 @@ static void tcg_out_tlb_check(TCGContext *s, TCGReg r0, TCGReg r1, TCGReg r2,
}
#endif
static void tcg_out_qemu_ld (TCGContext *s, const TCGArg *args, int opc)
static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, bool is64)
{
TCGReg addrlo, datalo, datahi, rbase;
int bswap;
TCGReg addrlo, datalo, datahi, rbase, addrhi __attribute__((unused));
TCGMemOp opc, bswap;
#ifdef CONFIG_SOFTMMU
int mem_index;
TCGReg addrhi;
uint8_t *label_ptr;
#endif
datalo = *args++;
datahi = (opc == 3 ? *args++ : 0);
datahi = (is64 ? *args++ : 0);
addrlo = *args++;
addrhi = (TARGET_LONG_BITS == 64 ? *args++ : 0);
opc = *args++;
bswap = opc & MO_BSWAP;
#ifdef CONFIG_SOFTMMU
addrhi = (TARGET_LONG_BITS == 64 ? *args++ : 0);
mem_index = *args;
tcg_out_tlb_check(s, TCG_REG_R3, TCG_REG_R4, TCG_REG_R0, addrlo,
addrhi, opc & 3, mem_index, 0, &label_ptr);
addrhi, opc & MO_SIZE, mem_index, 0, &label_ptr);
rbase = TCG_REG_R3;
#else /* !CONFIG_SOFTMMU */
rbase = GUEST_BASE ? TCG_GUEST_BASE_REG : 0;
#endif
#ifdef TARGET_WORDS_BIGENDIAN
bswap = 0;
#else
bswap = 1;
#endif
switch (opc) {
switch (opc & MO_SSIZE) {
default:
case 0:
case MO_UB:
tcg_out32(s, LBZX | TAB(datalo, rbase, addrlo));
break;
case 0|4:
case MO_SB:
tcg_out32(s, LBZX | TAB(datalo, rbase, addrlo));
tcg_out32(s, EXTSB | RA(datalo) | RS(datalo));
break;
case 1:
case MO_UW:
tcg_out32(s, (bswap ? LHBRX : LHZX) | TAB(datalo, rbase, addrlo));
break;
case 1|4:
case MO_SW:
if (bswap) {
tcg_out32(s, LHBRX | TAB(datalo, rbase, addrlo));
tcg_out32(s, EXTSH | RA(datalo) | RS(datalo));
......@@ -698,10 +698,10 @@ static void tcg_out_qemu_ld (TCGContext *s, const TCGArg *args, int opc)
tcg_out32(s, LHAX | TAB(datalo, rbase, addrlo));
}
break;
case 2:
case MO_UL:
tcg_out32(s, (bswap ? LWBRX : LWZX) | TAB(datalo, rbase, addrlo));
break;
case 3:
case MO_Q:
if (bswap) {
tcg_out32(s, ADDI | RT(TCG_REG_R0) | RA(addrlo) | 4);
tcg_out32(s, LWBRX | TAB(datalo, rbase, addrlo));
......@@ -725,47 +725,44 @@ static void tcg_out_qemu_ld (TCGContext *s, const TCGArg *args, int opc)
#endif
}
static void tcg_out_qemu_st (TCGContext *s, const TCGArg *args, int opc)
static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, bool is64)
{
TCGReg addrlo, datalo, datahi, rbase;
int bswap;
TCGReg addrlo, datalo, datahi, rbase, addrhi __attribute__((unused));
TCGMemOp opc, bswap, s_bits;
#ifdef CONFIG_SOFTMMU
int mem_index;
TCGReg addrhi;
uint8_t *label_ptr;
#endif
datalo = *args++;
datahi = (opc == 3 ? *args++ : 0);
datahi = (is64 ? *args++ : 0);
addrlo = *args++;
addrhi = (TARGET_LONG_BITS == 64 ? *args++ : 0);
opc = *args++;
bswap = opc & MO_BSWAP;
s_bits = opc & MO_SIZE;
#ifdef CONFIG_SOFTMMU
addrhi = (TARGET_LONG_BITS == 64 ? *args++ : 0);
mem_index = *args;
tcg_out_tlb_check(s, TCG_REG_R3, TCG_REG_R4, TCG_REG_R0, addrlo,
addrhi, opc & 3, mem_index, 0, &label_ptr);
addrhi, s_bits, mem_index, 0, &label_ptr);
rbase = TCG_REG_R3;
#else /* !CONFIG_SOFTMMU */
rbase = GUEST_BASE ? TCG_GUEST_BASE_REG : 0;
#endif
#ifdef TARGET_WORDS_BIGENDIAN
bswap = 0;
#else
bswap = 1;
#endif
switch (opc) {
case 0:
switch (s_bits) {
case MO_8:
tcg_out32(s, STBX | SAB(datalo, rbase, addrlo));
break;
case 1:
case MO_16:
tcg_out32(s, (bswap ? STHBRX : STHX) | SAB(datalo, rbase, addrlo));
break;
case 2:
case MO_32:
default:
tcg_out32(s, (bswap ? STWBRX : STWX) | SAB(datalo, rbase, addrlo));
break;
case 3:
case MO_64:
if (bswap) {
tcg_out32(s, ADDI | RT(TCG_REG_R0) | RA(addrlo) | 4);
tcg_out32(s, STWBRX | SAB(datalo, rbase, addrlo));
......@@ -791,6 +788,7 @@ static void tcg_out_qemu_st (TCGContext *s, const TCGArg *args, int opc)
static void tcg_out_qemu_ld_slow_path(TCGContext *s, TCGLabelQemuLdst *l)
{
TCGReg ir, datalo, datahi;
TCGMemOp opc = l->opc;
reloc_pc14 (l->label_ptr[0], (uintptr_t)s->code_ptr);
......@@ -806,22 +804,20 @@ static void tcg_out_qemu_ld_slow_path(TCGContext *s, TCGLabelQemuLdst *l)
}
tcg_out_movi(s, TCG_TYPE_I32, ir++, l->mem_index);
tcg_out32(s, MFSPR | RT(ir++) | LR);
tcg_out_b(s, LK, (uintptr_t)ld_trampolines[l->opc & 3]);
tcg_out_b(s, LK, (uintptr_t)ld_trampolines[opc & ~MO_SIGN]);
datalo = l->datalo_reg;
switch (l->opc) {
case 0|4:
switch (opc & MO_SSIZE) {
case MO_SB:
tcg_out32(s, EXTSB | RA(datalo) | RS(TCG_REG_R3));
break;
case 1|4:
case MO_SW:
tcg_out32(s, EXTSH | RA(datalo) | RS(TCG_REG_R3));
break;
case 0:
case 1:
case 2:
default:
tcg_out_mov(s, TCG_TYPE_I32, datalo, TCG_REG_R3);
break;
case 3:
case MO_Q:
datahi = l->datahi_reg;
if (datalo != TCG_REG_R3) {
tcg_out_mov(s, TCG_TYPE_I32, datalo, TCG_REG_R4);
......@@ -842,6 +838,7 @@ static void tcg_out_qemu_ld_slow_path(TCGContext *s, TCGLabelQemuLdst *l)
static void tcg_out_qemu_st_slow_path(TCGContext *s, TCGLabelQemuLdst *l)
{
TCGReg ir, datalo;
TCGMemOp opc = l->opc;
reloc_pc14 (l->label_ptr[0], (tcg_target_long) s->code_ptr);
......@@ -857,19 +854,19 @@ static void tcg_out_qemu_st_slow_path(TCGContext *s, TCGLabelQemuLdst *l)
}
datalo = l->datalo_reg;
switch (l->opc) {
case 0:
switch (opc & MO_SIZE) {
case MO_8:
tcg_out32(s, (RLWINM | RA (ir) | RS (datalo)
| SH (0) | MB (24) | ME (31)));
break;
case 1:
case MO_16:
tcg_out32(s, (RLWINM | RA (ir) | RS (datalo)
| SH (0) | MB (16) | ME (31)));
break;
case 2:
default:
tcg_out_mov(s, TCG_TYPE_I32, ir, datalo);
break;
case 3:
case MO_64:
#ifdef TCG_TARGET_CALL_ALIGN_ARGS
ir |= 1;
#endif
......@@ -881,7 +878,7 @@ static void tcg_out_qemu_st_slow_path(TCGContext *s, TCGLabelQemuLdst *l)
tcg_out_movi(s, TCG_TYPE_I32, ir++, l->mem_index);
tcg_out32(s, MFSPR | RT(ir++) | LR);
tcg_out_b(s, LK, (uintptr_t)st_trampolines[l->opc]);
tcg_out_b(s, LK, (uintptr_t)st_trampolines[opc]);
tcg_out_b(s, 0, (uintptr_t)l->raddr);
}
#endif
......@@ -956,12 +953,15 @@ static void tcg_target_qemu_prologue (TCGContext *s)
tcg_out32 (s, BCLR | BO_ALWAYS);
#ifdef CONFIG_SOFTMMU
for (i = 0; i < 4; ++i) {
ld_trampolines[i] = s->code_ptr;
emit_ldst_trampoline (s, qemu_ld_helpers[i]);
st_trampolines[i] = s->code_ptr;
emit_ldst_trampoline (s, qemu_st_helpers[i]);
for (i = 0; i < 16; ++i) {
if (qemu_ld_helpers[i]) {
ld_trampolines[i] = s->code_ptr;
emit_ldst_trampoline(s, qemu_ld_helpers[i]);
}
if (qemu_st_helpers[i]) {
st_trampolines[i] = s->code_ptr;
emit_ldst_trampoline(s, qemu_st_helpers[i]);
}
}
#endif
}
......@@ -1706,36 +1706,18 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, const TCGArg *args,
tcg_out32 (s, NOR | SAB (args[1], args[0], args[1]));
break;
case INDEX_op_qemu_ld8u:
case INDEX_op_qemu_ld_i32:
tcg_out_qemu_ld(s, args, 0);
break;
case INDEX_op_qemu_ld8s:
tcg_out_qemu_ld(s, args, 0 | 4);
break;
case INDEX_op_qemu_ld16u:
case INDEX_op_qemu_ld_i64:
tcg_out_qemu_ld(s, args, 1);
break;
case INDEX_op_qemu_ld16s:
tcg_out_qemu_ld(s, args, 1 | 4);
break;
case INDEX_op_qemu_ld32:
tcg_out_qemu_ld(s, args, 2);
break;
case INDEX_op_qemu_ld64:
tcg_out_qemu_ld(s, args, 3);
break;
case INDEX_op_qemu_st8:
case INDEX_op_qemu_st_i32:
tcg_out_qemu_st(s, args, 0);
break;
case INDEX_op_qemu_st16:
case INDEX_op_qemu_st_i64:
tcg_out_qemu_st(s, args, 1);
break;
case INDEX_op_qemu_st32:
tcg_out_qemu_st(s, args, 2);
break;
case INDEX_op_qemu_st64:
tcg_out_qemu_st(s, args, 3);
break;
case INDEX_op_ext8s_i32:
tcg_out32 (s, EXTSB | RS (args[1]) | RA (args[0]));
......@@ -1919,29 +1901,15 @@ static const TCGTargetOpDef ppc_op_defs[] = {
{ INDEX_op_bswap32_i32, { "r", "r" } },
#if TARGET_LONG_BITS == 32
{ INDEX_op_qemu_ld8u, { "r", "L" } },
{ INDEX_op_qemu_ld8s, { "r", "L" } },
{ INDEX_op_qemu_ld16u, { "r", "L" } },
{ INDEX_op_qemu_ld16s, { "r", "L" } },
{ INDEX_op_qemu_ld32, { "r", "L" } },
{ INDEX_op_qemu_ld64, { "L", "L", "L" } },
{ INDEX_op_qemu_st8, { "K", "K" } },
{ INDEX_op_qemu_st16, { "K", "K" } },
{ INDEX_op_qemu_st32, { "K", "K" } },
{ INDEX_op_qemu_st64, { "M", "M", "M" } },
{ INDEX_op_qemu_ld_i32, { "r", "L" } },
{ INDEX_op_qemu_ld_i64, { "L", "L", "L" } },
{ INDEX_op_qemu_st_i32, { "K", "K" } },
{ INDEX_op_qemu_st_i64, { "M", "M", "M" } },
#else
{ INDEX_op_qemu_ld8u, { "r", "L", "L" } },
{ INDEX_op_qemu_ld8s, { "r", "L", "L" } },
{ INDEX_op_qemu_ld16u, { "r", "L", "L" } },
{ INDEX_op_qemu_ld16s, { "r", "L", "L" } },
{ INDEX_op_qemu_ld32, { "r", "L", "L" } },
{ INDEX_op_qemu_ld64, { "L", "L", "L", "L" } },
{ INDEX_op_qemu_st8, { "K", "K", "K" } },
{ INDEX_op_qemu_st16, { "K", "K", "K" } },
{ INDEX_op_qemu_st32, { "K", "K", "K" } },
{ INDEX_op_qemu_st64, { "M", "M", "M", "M" } },
{ INDEX_op_qemu_ld_i32, { "r", "L", "L" } },
{ INDEX_op_qemu_ld_i64, { "L", "L", "L", "L" } },
{ INDEX_op_qemu_st_i32, { "K", "K", "K" } },
{ INDEX_op_qemu_st_i64, { "M", "M", "M", "M" } },
#endif
{ INDEX_op_ext8s_i32, { "r", "r" } },
......
......@@ -99,7 +99,7 @@ typedef enum {
#define TCG_TARGET_HAS_muluh_i32 0
#define TCG_TARGET_HAS_mulsh_i32 0
#define TCG_TARGET_HAS_new_ldst 0
#define TCG_TARGET_HAS_new_ldst 1
#define TCG_AREG0 TCG_REG_R27
......
......@@ -809,22 +809,28 @@ static void tcg_out_mem_long(TCGContext *s, int opi, int opx, TCGReg rt,
}
}
static const uint32_t qemu_ldx_opc[8] = {
#ifdef TARGET_WORDS_BIGENDIAN
LBZX, LHZX, LWZX, LDX,
0, LHAX, LWAX, LDX
#else
LBZX, LHBRX, LWBRX, LDBRX,
0, 0, 0, LDBRX,
#endif
static const uint32_t qemu_ldx_opc[16] = {
[MO_UB] = LBZX,
[MO_UW] = LHZX,
[MO_UL] = LWZX,
[MO_Q] = LDX,
[MO_SW] = LHAX,
[MO_SL] = LWAX,
[MO_BSWAP | MO_UB] = LBZX,
[MO_BSWAP | MO_UW] = LHBRX,
[MO_BSWAP | MO_UL] = LWBRX,
[MO_BSWAP | MO_Q] = LDBRX,
};
static const uint32_t qemu_stx_opc[4] = {
#ifdef TARGET_WORDS_BIGENDIAN
STBX, STHX, STWX, STDX
#else
STBX, STHBRX, STWBRX, STDBRX,
#endif
static const uint32_t qemu_stx_opc[16] = {
[MO_UB] = STBX,
[MO_UW] = STHX,
[MO_UL] = STWX,
[MO_Q] = STDX,
[MO_BSWAP | MO_UB] = STBX,
[MO_BSWAP | MO_UW] = STHBRX,
[MO_BSWAP | MO_UL] = STWBRX,
[MO_BSWAP | MO_Q] = STDBRX,
};
static const uint32_t qemu_exts_opc[4] = {
......@@ -835,28 +841,34 @@ static const uint32_t qemu_exts_opc[4] = {
/* helper signature: helper_ld_mmu(CPUState *env, target_ulong addr,
* int mmu_idx, uintptr_t ra)
*/
static const void * const qemu_ld_helpers[4] = {
helper_ret_ldub_mmu,
helper_ret_lduw_mmu,
helper_ret_ldul_mmu,
helper_ret_ldq_mmu,
static const void * const qemu_ld_helpers[16] = {
[MO_UB] = helper_ret_ldub_mmu,
[MO_LEUW] = helper_le_lduw_mmu,
[MO_LEUL] = helper_le_ldul_mmu,
[MO_LEQ] = helper_le_ldq_mmu,
[MO_BEUW] = helper_be_lduw_mmu,
[MO_BEUL] = helper_be_ldul_mmu,
[MO_BEQ] = helper_be_ldq_mmu,
};
/* helper signature: helper_st_mmu(CPUState *env, target_ulong addr,
* uintxx_t val, int mmu_idx, uintptr_t ra)
*/
static const void * const qemu_st_helpers[4] = {
helper_ret_stb_mmu,
helper_ret_stw_mmu,
helper_ret_stl_mmu,
helper_ret_stq_mmu,
static const void * const qemu_st_helpers[16] = {
[MO_UB] = helper_ret_stb_mmu,
[MO_LEUW] = helper_le_stw_mmu,
[MO_LEUL] = helper_le_stl_mmu,
[MO_LEQ] = helper_le_stq_mmu,
[MO_BEUW] = helper_be_stw_mmu,
[MO_BEUL] = helper_be_stl_mmu,
[MO_BEQ] = helper_be_stq_mmu,
};
/* Perform the TLB load and compare. Places the result of the comparison
in CR7, loads the addend of the TLB into R3, and returns the register
containing the guest address (zero-extended into R4). Clobbers R0 and R2. */
static TCGReg tcg_out_tlb_read(TCGContext *s, int s_bits, TCGReg addr_reg,
static TCGReg tcg_out_tlb_read(TCGContext *s, TCGMemOp s_bits, TCGReg addr_reg,
int mem_index, bool is_read)
{
int cmp_off
......@@ -929,7 +941,7 @@ static TCGReg tcg_out_tlb_read(TCGContext *s, int s_bits, TCGReg addr_reg,
/* Record the context of a call to the out of line helper code for the slow
path for a load or store, so that we can later generate the correct
helper code. */
static void add_qemu_ldst_label(TCGContext *s, bool is_ld, int opc,
static void add_qemu_ldst_label(TCGContext *s, bool is_ld, TCGMemOp opc,
int data_reg, int addr_reg, int mem_index,
uint8_t *raddr, uint8_t *label_ptr)
{
......@@ -946,8 +958,7 @@ static void add_qemu_ldst_label(TCGContext *s, bool is_ld, int opc,
static void tcg_out_qemu_ld_slow_path(TCGContext *s, TCGLabelQemuLdst *lb)
{
int opc = lb->opc;
int s_bits = opc & 3;
TCGMemOp opc = lb->opc;
reloc_pc14(lb->label_ptr[0], (uintptr_t)s->code_ptr);
......@@ -960,10 +971,10 @@ static void tcg_out_qemu_ld_slow_path(TCGContext *s, TCGLabelQemuLdst *lb)
tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_R5, lb->mem_index);
tcg_out32(s, MFSPR | RT(TCG_REG_R6) | LR);
tcg_out_call(s, (tcg_target_long)qemu_ld_helpers[s_bits], 1);
tcg_out_call(s, (tcg_target_long)qemu_ld_helpers[opc & ~MO_SIGN], 1);
if (opc & 4) {
uint32_t insn = qemu_exts_opc[s_bits];
if (opc & MO_SIGN) {
uint32_t insn = qemu_exts_opc[opc & MO_SIZE];
tcg_out32(s, insn | RA(lb->datalo_reg) | RS(TCG_REG_R3));
} else {
tcg_out_mov(s, TCG_TYPE_I64, lb->datalo_reg, TCG_REG_R3);
......@@ -974,7 +985,8 @@ static void tcg_out_qemu_ld_slow_path(TCGContext *s, TCGLabelQemuLdst *lb)
static void tcg_out_qemu_st_slow_path(TCGContext *s, TCGLabelQemuLdst *lb)
{
int opc = lb->opc;
TCGMemOp opc = lb->opc;
TCGMemOp s_bits = opc & MO_SIZE;
reloc_pc14(lb->label_ptr[0], (uintptr_t)s->code_ptr);
......@@ -985,7 +997,7 @@ static void tcg_out_qemu_st_slow_path(TCGContext *s, TCGLabelQemuLdst *lb)
tcg_out_mov(s, TCG_TYPE_I64, TCG_REG_R4, lb->addrlo_reg);
tcg_out_rld(s, RLDICL, TCG_REG_R5, lb->datalo_reg,
0, 64 - (1 << (3 + opc)));
0, 64 - (1 << (3 + s_bits)));
tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_R6, lb->mem_index);
tcg_out32(s, MFSPR | RT(TCG_REG_R7) | LR);
......@@ -995,22 +1007,17 @@ static void tcg_out_qemu_st_slow_path(TCGContext *s, TCGLabelQemuLdst *lb)
}
#endif /* SOFTMMU */
static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, int opc)
static void tcg_out_qemu_ld(TCGContext *s, TCGReg data_reg, TCGReg addr_reg,
TCGMemOp opc, int mem_index)
{
TCGReg addr_reg, data_reg, rbase;
uint32_t insn, s_bits;
TCGReg rbase;
uint32_t insn;
TCGMemOp s_bits = opc & MO_SIZE;
#ifdef CONFIG_SOFTMMU
int mem_index;
void *label_ptr;
#endif
data_reg = *args++;
addr_reg = *args++;
s_bits = opc & 3;
#ifdef CONFIG_SOFTMMU
mem_index = *args;
addr_reg = tcg_out_tlb_read(s, s_bits, addr_reg, mem_index, true);
/* Load a pointer into the current opcode w/conditional branch-link. */
......@@ -1035,7 +1042,7 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, int opc)
} else if (insn) {
tcg_out32(s, insn | TAB(data_reg, rbase, addr_reg));
} else {
insn = qemu_ldx_opc[s_bits];
insn = qemu_ldx_opc[opc & (MO_SIZE | MO_BSWAP)];
tcg_out32(s, insn | TAB(data_reg, rbase, addr_reg));
insn = qemu_exts_opc[s_bits];
tcg_out32(s, insn | RA(data_reg) | RS(data_reg));
......@@ -1047,22 +1054,17 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, int opc)
#endif
}
static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, int opc)
static void tcg_out_qemu_st(TCGContext *s, TCGReg data_reg, TCGReg addr_reg,
TCGMemOp opc, int mem_index)
{
TCGReg addr_reg, rbase, data_reg;
TCGReg rbase;
uint32_t insn;
#ifdef CONFIG_SOFTMMU
int mem_index;
void *label_ptr;
#endif
data_reg = *args++;
addr_reg = *args++;
#ifdef CONFIG_SOFTMMU
mem_index = *args;
addr_reg = tcg_out_tlb_read(s, opc, addr_reg, mem_index, false);
addr_reg = tcg_out_tlb_read(s, opc & MO_SIZE, addr_reg, mem_index, false);
/* Load a pointer into the current opcode w/conditional branch-link. */
label_ptr = s->code_ptr;
......@@ -1826,39 +1828,13 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, const TCGArg *args,
tcg_out32(s, DIVDU | TAB(args[0], args[1], args[2]));
break;
case INDEX_op_qemu_ld8u:
tcg_out_qemu_ld(s, args, 0);
break;
case INDEX_op_qemu_ld8s:
tcg_out_qemu_ld(s, args, 0 | 4);
break;
case INDEX_op_qemu_ld16u:
tcg_out_qemu_ld(s, args, 1);
break;
case INDEX_op_qemu_ld16s:
tcg_out_qemu_ld(s, args, 1 | 4);
break;
case INDEX_op_qemu_ld32:
case INDEX_op_qemu_ld32u:
tcg_out_qemu_ld(s, args, 2);
break;
case INDEX_op_qemu_ld32s:
tcg_out_qemu_ld(s, args, 2 | 4);
break;
case INDEX_op_qemu_ld64:
tcg_out_qemu_ld(s, args, 3);
break;
case INDEX_op_qemu_st8:
tcg_out_qemu_st(s, args, 0);
break;
case INDEX_op_qemu_st16:
tcg_out_qemu_st(s, args, 1);
break;
case INDEX_op_qemu_st32:
tcg_out_qemu_st(s, args, 2);
case INDEX_op_qemu_ld_i32:
case INDEX_op_qemu_ld_i64:
tcg_out_qemu_ld(s, args[0], args[1], args[2], args[3]);
break;
case INDEX_op_qemu_st64:
tcg_out_qemu_st(s, args, 3);
case INDEX_op_qemu_st_i32:
case INDEX_op_qemu_st_i64:
tcg_out_qemu_st(s, args[0], args[1], args[2], args[3]);
break;
case INDEX_op_ext8s_i32:
......@@ -2121,19 +2097,10 @@ static const TCGTargetOpDef ppc_op_defs[] = {
{ INDEX_op_neg_i64, { "r", "r" } },
{ INDEX_op_not_i64, { "r", "r" } },
{ INDEX_op_qemu_ld8u, { "r", "L" } },
{ INDEX_op_qemu_ld8s, { "r", "L" } },
{ INDEX_op_qemu_ld16u, { "r", "L" } },
{ INDEX_op_qemu_ld16s, { "r", "L" } },
{ INDEX_op_qemu_ld32, { "r", "L" } },
{ INDEX_op_qemu_ld32u, { "r", "L" } },
{ INDEX_op_qemu_ld32s, { "r", "L" } },
{ INDEX_op_qemu_ld64, { "r", "L" } },
{ INDEX_op_qemu_st8, { "S", "S" } },
{ INDEX_op_qemu_st16, { "S", "S" } },
{ INDEX_op_qemu_st32, { "S", "S" } },
{ INDEX_op_qemu_st64, { "S", "S" } },
{ INDEX_op_qemu_ld_i32, { "r", "L" } },
{ INDEX_op_qemu_ld_i64, { "r", "L" } },
{ INDEX_op_qemu_st_i32, { "S", "S" } },
{ INDEX_op_qemu_st_i64, { "S", "S" } },
{ INDEX_op_ext8s_i32, { "r", "r" } },
{ INDEX_op_ext16s_i32, { "r", "r" } },
......
......@@ -123,7 +123,7 @@ typedef enum {
#define TCG_TARGET_HAS_muluh_i64 1
#define TCG_TARGET_HAS_mulsh_i64 1
#define TCG_TARGET_HAS_new_ldst 0
#define TCG_TARGET_HAS_new_ldst 1
#define TCG_AREG0 TCG_REG_R27
......
......@@ -25,7 +25,7 @@
typedef struct TCGLabelQemuLdst {
int is_ld:1; /* qemu_ld: 1, qemu_st: 0 */
int opc:4;
TCGMemOp opc:4;
TCGReg addrlo_reg; /* reg index for low word of guest virtual addr */
TCGReg addrhi_reg; /* reg index for high word of guest virtual addr */
TCGReg datalo_reg; /* reg index for low word to be loaded or stored */
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册