diff options
Diffstat (limited to 'tcg/ppc/tcg-target.c')
-rw-r--r-- | tcg/ppc/tcg-target.c | 230 |
1 files changed, 88 insertions, 142 deletions
diff --git a/tcg/ppc/tcg-target.c b/tcg/ppc/tcg-target.c index 97e33edcfd..dc2c2df890 100644 --- a/tcg/ppc/tcg-target.c +++ b/tcg/ppc/tcg-target.c @@ -22,6 +22,8 @@ * THE SOFTWARE. */ +#include "tcg-be-ldst.h" + static uint8_t *tb_ret_addr; #if defined _CALL_DARWIN || defined __APPLE__ @@ -523,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, @@ -532,15 +534,8 @@ static void add_qemu_ldst_label (TCGContext *s, uint8_t *raddr, uint8_t *label_ptr) { - int idx; - TCGLabelQemuLdst *label; + TCGLabelQemuLdst *label = new_ldst_label(s); - if (s->nb_qemu_ldst_labels >= TCG_MAX_QEMU_LDST) { - tcg_abort(); - } - - idx = s->nb_qemu_ldst_labels++; - label = (TCGLabelQemuLdst *)&s->qemu_ldst_labels[idx]; label->is_ld = is_ld; label->opc = opc; label->datalo_reg = data_reg; @@ -555,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 = @@ -652,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)); @@ -703,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)); @@ -730,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)); @@ -796,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); @@ -811,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); @@ -847,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); @@ -862,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 @@ -886,26 +878,9 @@ 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); } - -void tcg_out_tb_finalize(TCGContext *s) -{ - int i; - TCGLabelQemuLdst *label; - - /* qemu_ld/st slow paths */ - for (i = 0; i < s->nb_qemu_ldst_labels; i++) { - label = (TCGLabelQemuLdst *) &s->qemu_ldst_labels[i]; - if (label->is_ld) { - tcg_out_qemu_ld_slow_path (s, label); - } - else { - tcg_out_qemu_st_slow_path (s, label); - } - } -} #endif #ifdef CONFIG_SOFTMMU @@ -978,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 } @@ -1728,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])); @@ -1941,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" } }, |