--- qemu/tcg/ppc64/tcg-target.c 2018/04/24 16:51:10 1.1.1.1 +++ qemu/tcg/ppc64/tcg-target.c 2018/04/24 18:34:55 1.1.1.5 @@ -28,12 +28,6 @@ static uint8_t *tb_ret_addr; #define FAST_PATH -#if TARGET_PHYS_ADDR_BITS == 32 -#define LD_ADDEND LWZ -#else -#define LD_ADDEND LD -#endif - #if TARGET_LONG_BITS == 32 #define LD_ADDR LWZU #define CMP_L 0 @@ -42,11 +36,21 @@ static uint8_t *tb_ret_addr; #define CMP_L (1<<21) #endif +#ifndef GUEST_BASE +#define GUEST_BASE 0 +#endif + +#ifdef CONFIG_USE_GUEST_BASE +#define TCG_GUEST_BASE_REG 30 +#else +#define TCG_GUEST_BASE_REG 0 +#endif + #ifndef NDEBUG static const char * const tcg_target_reg_names[TCG_TARGET_NB_REGS] = { "r0", "r1", - "rp", + "r2", "r3", "r4", "r5", @@ -94,6 +98,9 @@ static const int tcg_target_reg_alloc_or TCG_REG_R29, TCG_REG_R30, TCG_REG_R31, +#ifdef __APPLE__ + TCG_REG_R2, +#endif TCG_REG_R3, TCG_REG_R4, TCG_REG_R5, @@ -102,12 +109,10 @@ static const int tcg_target_reg_alloc_or TCG_REG_R8, TCG_REG_R9, TCG_REG_R10, +#ifndef __APPLE__ TCG_REG_R11, +#endif TCG_REG_R12, - TCG_REG_R13, - TCG_REG_R0, - TCG_REG_R1, - TCG_REG_R2, TCG_REG_R24, TCG_REG_R25, TCG_REG_R26, @@ -130,6 +135,9 @@ static const int tcg_target_call_oarg_re }; static const int tcg_target_callee_save_regs[] = { +#ifdef __APPLE__ + TCG_REG_R11, +#endif TCG_REG_R14, TCG_REG_R15, TCG_REG_R16, @@ -291,6 +299,7 @@ static int tcg_target_const_match (tcg_t #define LWA XO58( 2) #define LWAX XO31(341) +#define ADDIC OPCD( 12) #define ADDI OPCD( 14) #define ADDIS OPCD( 15) #define ORI OPCD( 24) @@ -318,6 +327,7 @@ static int tcg_target_const_match (tcg_t #define CRANDC XO19(129) #define CRNAND XO19(225) #define CROR XO19(449) +#define CRNOR XO19( 33) #define EXTSB XO31(954) #define EXTSH XO31(922) @@ -345,6 +355,9 @@ static int tcg_target_const_match (tcg_t #define MTSPR XO31(467) #define SRAWI XO31(824) #define NEG XO31(104) +#define MFCR XO31( 19) +#define CNTLZW XO31( 26) +#define CNTLZD XO31( 58) #define MULLD XO31(233) #define MULHD XO31( 73) @@ -353,7 +366,7 @@ static int tcg_target_const_match (tcg_t #define DIVDU XO31(457) #define LBZX XO31( 87) -#define LHZX XO31(276) +#define LHZX XO31(279) #define LHAX XO31(343) #define LWZX XO31( 23) #define STBX XO31(215) @@ -373,9 +386,6 @@ static int tcg_target_const_match (tcg_t #define SRAD XO31(794) #define SRADI XO31(413<<1) -#define LMW OPCD( 46) -#define STMW OPCD( 47) - #define TW XO31( 4) #define TRAP (TW | TO (31)) @@ -425,7 +435,7 @@ static const uint32_t tcg_to_bc[10] = { [TCG_COND_GTU] = BC | BI (7, CR_GT) | BO_COND_TRUE, }; -static void tcg_out_mov (TCGContext *s, int ret, int arg) +static void tcg_out_mov (TCGContext *s, TCGType type, int ret, int arg) { tcg_out32 (s, OR | SAB (arg, ret, arg)); } @@ -452,8 +462,9 @@ static void tcg_out_movi (TCGContext *s, int ret, tcg_target_long arg) { int32_t arg32 = arg; + arg = type == TCG_TYPE_I32 ? arg & 0xffffffff : arg; - if (type == TCG_TYPE_I32 || arg == arg32) { + if (arg == arg32) { tcg_out_movi32 (s, ret, arg32); } else { @@ -474,8 +485,31 @@ static void tcg_out_movi (TCGContext *s, } } +static void tcg_out_b (TCGContext *s, int mask, tcg_target_long target) +{ + tcg_target_long disp; + + disp = target - (tcg_target_long) s->code_ptr; + if ((disp << 38) >> 38 == disp) + tcg_out32 (s, B | (disp & 0x3fffffc) | mask); + else { + tcg_out_movi (s, TCG_TYPE_I64, 0, (tcg_target_long) target); + tcg_out32 (s, MTSPR | RS (0) | CTR); + tcg_out32 (s, BCCTR | BO_ALWAYS | mask); + } +} + static void tcg_out_call (TCGContext *s, tcg_target_long arg, int const_arg) { +#ifdef __APPLE__ + if (const_arg) { + tcg_out_b (s, LK, arg); + } + else { + tcg_out32 (s, MTSPR | RS (arg) | LR); + tcg_out32 (s, BCLR | BO_ALWAYS | LK); + } +#else int reg; if (const_arg) { @@ -489,6 +523,7 @@ static void tcg_out_call (TCGContext *s, tcg_out32 (s, LD | RT (11) | RA (reg) | 16); tcg_out32 (s, LD | RT (2) | RA (reg) | 8); tcg_out32 (s, BCCTR | BO_ALWAYS | LK); +#endif } static void tcg_out_ldst (TCGContext *s, int ret, int addr, @@ -513,20 +548,6 @@ static void tcg_out_ldsta (TCGContext *s } } -static void tcg_out_b (TCGContext *s, int mask, tcg_target_long target) -{ - tcg_target_long disp; - - disp = target - (tcg_target_long) s->code_ptr; - if ((disp << 38) >> 38 == disp) - tcg_out32 (s, B | (disp & 0x3fffffc) | mask); - else { - tcg_out_movi (s, TCG_TYPE_I64, 0, (tcg_target_long) target); - tcg_out32 (s, MTSPR | RS (0) | CTR); - tcg_out32 (s, BCCTR | BO_ALWAYS | mask); - } -} - #if defined (CONFIG_SOFTMMU) #include "../../softmmu_defs.h" @@ -595,7 +616,7 @@ static void tcg_out_tlb_read (TCGContext static void tcg_out_qemu_ld (TCGContext *s, const TCGArg *args, int opc) { - int addr_reg, data_reg, r0, r1, mem_index, s_bits, bswap; + int addr_reg, data_reg, r0, r1, rbase, mem_index, s_bits, bswap; #ifdef CONFIG_SOFTMMU int r2; void *label1_ptr, *label2_ptr; @@ -610,6 +631,7 @@ static void tcg_out_qemu_ld (TCGContext r0 = 3; r1 = 4; r2 = 0; + rbase = 0; tcg_out_tlb_read (s, r0, r1, r2, addr_reg, s_bits, offsetof (CPUState, tlb_table[mem_index][0].addr_read)); @@ -622,7 +644,7 @@ static void tcg_out_qemu_ld (TCGContext #endif /* slow path */ - tcg_out_mov (s, 3, addr_reg); + tcg_out_mov (s, TCG_TYPE_I64, 3, addr_reg); tcg_out_movi (s, TCG_TYPE_I64, 4, mem_index); tcg_out_call (s, (tcg_target_long) qemu_ld_helpers[s_bits], 1); @@ -642,7 +664,7 @@ static void tcg_out_qemu_ld (TCGContext case 2: case 3: if (data_reg != 3) - tcg_out_mov (s, data_reg, 3); + tcg_out_mov (s, TCG_TYPE_I64, data_reg, 3); break; } label2_ptr = s->code_ptr; @@ -654,7 +676,7 @@ static void tcg_out_qemu_ld (TCGContext #endif /* r0 now contains &env->tlb_table[mem_index][index].addr_read */ - tcg_out32 (s, (LD_ADDEND + tcg_out32 (s, (LD | RT (r0) | RA (r0) | (offsetof (CPUTLBEntry, addend) @@ -670,6 +692,7 @@ static void tcg_out_qemu_ld (TCGContext #endif r0 = addr_reg; r1 = 3; + rbase = GUEST_BASE ? TCG_GUEST_BASE_REG : 0; #endif #ifdef TARGET_WORDS_BIGENDIAN @@ -680,35 +703,48 @@ static void tcg_out_qemu_ld (TCGContext switch (opc) { default: case 0: - tcg_out32 (s, LBZ | RT (data_reg) | RA (r0)); + tcg_out32 (s, LBZX | TAB (data_reg, rbase, r0)); break; case 0|4: - tcg_out32 (s, LBZ | RT (data_reg) | RA (r0)); + tcg_out32 (s, LBZX | TAB (data_reg, rbase, r0)); tcg_out32 (s, EXTSB | RA (data_reg) | RS (data_reg)); break; case 1: - if (bswap) tcg_out32 (s, LHBRX | RT (data_reg) | RB (r0)); - else tcg_out32 (s, LHZ | RT (data_reg) | RA (r0)); + if (bswap) + tcg_out32 (s, LHBRX | TAB (data_reg, rbase, r0)); + else + tcg_out32 (s, LHZX | TAB (data_reg, rbase, r0)); break; case 1|4: if (bswap) { - tcg_out32 (s, LHBRX | RT (data_reg) | RB (r0)); + tcg_out32 (s, LHBRX | TAB (data_reg, rbase, r0)); tcg_out32 (s, EXTSH | RA (data_reg) | RS (data_reg)); } - else tcg_out32 (s, LHA | RT (data_reg) | RA (r0)); + else tcg_out32 (s, LHAX | TAB (data_reg, rbase, r0)); break; case 2: - if (bswap) tcg_out32 (s, LWBRX | RT (data_reg) | RB (r0)); - else tcg_out32 (s, LWZ | RT (data_reg)| RA (r0)); + if (bswap) + tcg_out32 (s, LWBRX | TAB (data_reg, rbase, r0)); + else + tcg_out32 (s, LWZX | TAB (data_reg, rbase, r0)); break; case 2|4: if (bswap) { - tcg_out32 (s, LWBRX | RT (data_reg) | RB (r0)); + tcg_out32 (s, LWBRX | TAB (data_reg, rbase, r0)); tcg_out32 (s, EXTSW | RA (data_reg) | RS (data_reg)); } - else tcg_out32 (s, LWA | RT (data_reg)| RA (r0)); + else tcg_out32 (s, LWAX | TAB (data_reg, rbase, r0)); break; case 3: +#ifdef CONFIG_USE_GUEST_BASE + if (bswap) { + tcg_out32 (s, ADDI | RT (r1) | RA (r0) | 4); + tcg_out32 (s, LWBRX | TAB (data_reg, rbase, r0)); + tcg_out32 (s, LWBRX | TAB ( r1, rbase, r1)); + tcg_out_rld (s, RLDIMI, data_reg, r1, 32, 0); + } + else tcg_out32 (s, LDX | TAB (data_reg, rbase, r0)); +#else if (bswap) { tcg_out_movi32 (s, 0, 4); tcg_out32 (s, LWBRX | RT (data_reg) | RB (r0)); @@ -716,6 +752,7 @@ static void tcg_out_qemu_ld (TCGContext tcg_out_rld (s, RLDIMI, data_reg, r1, 32, 0); } else tcg_out32 (s, LD | RT (data_reg) | RA (r0)); +#endif break; } @@ -726,7 +763,7 @@ static void tcg_out_qemu_ld (TCGContext static void tcg_out_qemu_st (TCGContext *s, const TCGArg *args, int opc) { - int addr_reg, r0, r1, data_reg, mem_index, bswap; + int addr_reg, r0, r1, rbase, data_reg, mem_index, bswap; #ifdef CONFIG_SOFTMMU int r2; void *label1_ptr, *label2_ptr; @@ -740,6 +777,7 @@ static void tcg_out_qemu_st (TCGContext r0 = 3; r1 = 4; r2 = 0; + rbase = 0; tcg_out_tlb_read (s, r0, r1, r2, addr_reg, opc, offsetof (CPUState, tlb_table[mem_index][0].addr_write)); @@ -752,7 +790,7 @@ static void tcg_out_qemu_st (TCGContext #endif /* slow path */ - tcg_out_mov (s, 3, addr_reg); + tcg_out_mov (s, TCG_TYPE_I64, 3, addr_reg); tcg_out_rld (s, RLDICL, 4, data_reg, 0, 64 - (1 << (3 + opc))); tcg_out_movi (s, TCG_TYPE_I64, 5, mem_index); @@ -766,7 +804,7 @@ static void tcg_out_qemu_st (TCGContext reloc_pc14 (label1_ptr, (tcg_target_long) s->code_ptr); #endif - tcg_out32 (s, (LD_ADDEND + tcg_out32 (s, (LD | RT (r0) | RA (r0) | (offsetof (CPUTLBEntry, addend) @@ -782,6 +820,7 @@ static void tcg_out_qemu_st (TCGContext #endif r1 = 3; r0 = addr_reg; + rbase = GUEST_BASE ? TCG_GUEST_BASE_REG : 0; #endif #ifdef TARGET_WORDS_BIGENDIAN @@ -791,24 +830,28 @@ static void tcg_out_qemu_st (TCGContext #endif switch (opc) { case 0: - tcg_out32 (s, STB | RS (data_reg) | RA (r0)); + tcg_out32 (s, STBX | SAB (data_reg, rbase, r0)); break; case 1: - if (bswap) tcg_out32 (s, STHBRX | RS (data_reg) | RA (0) | RB (r0)); - else tcg_out32 (s, STH | RS (data_reg) | RA (r0)); + if (bswap) + tcg_out32 (s, STHBRX | SAB (data_reg, rbase, r0)); + else + tcg_out32 (s, STHX | SAB (data_reg, rbase, r0)); break; case 2: - if (bswap) tcg_out32 (s, STWBRX | RS (data_reg) | RA (0) | RB (r0)); - else tcg_out32 (s, STW | RS (data_reg) | RA (r0)); + if (bswap) + tcg_out32 (s, STWBRX | SAB (data_reg, rbase, r0)); + else + tcg_out32 (s, STWX | SAB (data_reg, rbase, r0)); break; case 3: if (bswap) { - tcg_out32 (s, STWBRX | RS (data_reg) | RA (0) | RB (r0)); + tcg_out32 (s, STWBRX | SAB (data_reg, rbase, r0)); tcg_out32 (s, ADDI | RT (r1) | RA (r0) | 4); tcg_out_rld (s, RLDICL, 0, data_reg, 32, 0); - tcg_out32 (s, STWBRX | RS (0) | RA (0) | RB (r1)); + tcg_out32 (s, STWBRX | SAB (0, rbase, r1)); } - else tcg_out32 (s, STD | RS (data_reg) | RA (r0)); + else tcg_out32 (s, STDX | SAB (data_reg, rbase, r0)); break; } @@ -817,10 +860,12 @@ static void tcg_out_qemu_st (TCGContext #endif } -void tcg_target_qemu_prologue (TCGContext *s) +static void tcg_target_qemu_prologue (TCGContext *s) { int i, frame_size; +#ifndef __APPLE__ uint64_t addr; +#endif frame_size = 0 + 8 /* back chain */ @@ -834,10 +879,12 @@ void tcg_target_qemu_prologue (TCGContex ; frame_size = (frame_size + 15) & ~15; +#ifndef __APPLE__ /* First emit adhoc function descriptor */ addr = (uint64_t) s->code_ptr + 24; tcg_out32 (s, addr >> 32); tcg_out32 (s, addr); /* entry point */ s->code_ptr += 16; /* skip TOC and environment pointer */ +#endif /* Prologue */ tcg_out32 (s, MFSPR | RT (0) | LR); @@ -851,6 +898,13 @@ void tcg_target_qemu_prologue (TCGContex ); tcg_out32 (s, STD | RS (0) | RA (1) | (frame_size + 16)); +#ifdef CONFIG_USE_GUEST_BASE + if (GUEST_BASE) { + tcg_out_movi (s, TCG_TYPE_I64, TCG_GUEST_BASE_REG, GUEST_BASE); + tcg_regset_set_reg(s->reserved_regs, TCG_GUEST_BASE_REG); + } +#endif + tcg_out32 (s, MTSPR | RS (3) | CTR); tcg_out32 (s, BCCTR | BO_ALWAYS); @@ -992,6 +1046,123 @@ static void tcg_out_cmp (TCGContext *s, } +static void tcg_out_setcond (TCGContext *s, TCGType type, TCGCond cond, + TCGArg arg0, TCGArg arg1, TCGArg arg2, + int const_arg2) +{ + int crop, sh, arg; + + switch (cond) { + case TCG_COND_EQ: + if (const_arg2) { + if (!arg2) { + arg = arg1; + } + else { + arg = 0; + if ((uint16_t) arg2 == arg2) { + tcg_out32 (s, XORI | RS (arg1) | RA (0) | arg2); + } + else { + tcg_out_movi (s, type, 0, arg2); + tcg_out32 (s, XOR | SAB (arg1, 0, 0)); + } + } + } + else { + arg = 0; + tcg_out32 (s, XOR | SAB (arg1, 0, arg2)); + } + + if (type == TCG_TYPE_I64) { + tcg_out32 (s, CNTLZD | RS (arg) | RA (0)); + tcg_out_rld (s, RLDICL, arg0, 0, 58, 6); + } + else { + tcg_out32 (s, CNTLZW | RS (arg) | RA (0)); + tcg_out32 (s, (RLWINM + | RA (arg0) + | RS (0) + | SH (27) + | MB (5) + | ME (31) + ) + ); + } + break; + + case TCG_COND_NE: + if (const_arg2) { + if (!arg2) { + arg = arg1; + } + else { + arg = 0; + if ((uint16_t) arg2 == arg2) { + tcg_out32 (s, XORI | RS (arg1) | RA (0) | arg2); + } + else { + tcg_out_movi (s, type, 0, arg2); + tcg_out32 (s, XOR | SAB (arg1, 0, 0)); + } + } + } + else { + arg = 0; + tcg_out32 (s, XOR | SAB (arg1, 0, arg2)); + } + + if (arg == arg1 && arg1 == arg0) { + tcg_out32 (s, ADDIC | RT (0) | RA (arg) | 0xffff); + tcg_out32 (s, SUBFE | TAB (arg0, 0, arg)); + } + else { + tcg_out32 (s, ADDIC | RT (arg0) | RA (arg) | 0xffff); + tcg_out32 (s, SUBFE | TAB (arg0, arg0, arg)); + } + break; + + case TCG_COND_GT: + case TCG_COND_GTU: + sh = 30; + crop = 0; + goto crtest; + + case TCG_COND_LT: + case TCG_COND_LTU: + sh = 29; + crop = 0; + goto crtest; + + case TCG_COND_GE: + case TCG_COND_GEU: + sh = 31; + crop = CRNOR | BT (7, CR_EQ) | BA (7, CR_LT) | BB (7, CR_LT); + goto crtest; + + case TCG_COND_LE: + case TCG_COND_LEU: + sh = 31; + crop = CRNOR | BT (7, CR_EQ) | BA (7, CR_GT) | BB (7, CR_GT); + crtest: + tcg_out_cmp (s, cond, arg1, arg2, const_arg2, 7, type == TCG_TYPE_I64); + if (crop) tcg_out32 (s, crop); + tcg_out32 (s, MFCR | RT (0)); + tcg_out32 (s, (RLWINM + | RA (arg0) + | RS (0) + | SH (sh) + | MB (31) + | ME (31) + ) + ); + break; + + default: + tcg_abort (); + } +} + static void tcg_out_bc (TCGContext *s, int bc, int label_index) { TCGLabel *l = &s->labels[label_index]; @@ -1007,7 +1178,7 @@ static void tcg_out_bc (TCGContext *s, i } } -static void tcg_out_brcond (TCGContext *s, int cond, +static void tcg_out_brcond (TCGContext *s, TCGCond cond, TCGArg arg1, TCGArg arg2, int const_arg2, int label_index, int arch64) { @@ -1026,7 +1197,7 @@ void ppc_tb_set_jmp_target (unsigned lon flush_icache_range (jmp_addr, jmp_addr + patch_size); } -static void tcg_out_op (TCGContext *s, int opc, const TCGArg *args, +static void tcg_out_op (TCGContext *s, TCGOpcode opc, const TCGArg *args, const int *const_args) { int c; @@ -1344,6 +1515,7 @@ static void tcg_out_op (TCGContext *s, i 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; @@ -1381,6 +1553,15 @@ static void tcg_out_op (TCGContext *s, i tcg_out32 (s, c | RS (args[1]) | RA (args[0])); break; + case INDEX_op_setcond_i32: + tcg_out_setcond (s, TCG_TYPE_I32, args[3], args[0], args[1], args[2], + const_args[2]); + break; + case INDEX_op_setcond_i64: + tcg_out_setcond (s, TCG_TYPE_I64, args[3], args[0], args[1], args[2], + const_args[2]); + break; + default: tcg_dump_ops (s, stderr); tcg_abort (); @@ -1463,6 +1644,7 @@ static const TCGTargetOpDef ppc_op_defs[ { 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" } }, @@ -1470,7 +1652,7 @@ static const TCGTargetOpDef ppc_op_defs[ { INDEX_op_qemu_st8, { "S", "S" } }, { INDEX_op_qemu_st16, { "S", "S" } }, { INDEX_op_qemu_st32, { "S", "S" } }, - { INDEX_op_qemu_st64, { "S", "S", "S" } }, + { INDEX_op_qemu_st64, { "S", "S" } }, { INDEX_op_ext8s_i32, { "r", "r" } }, { INDEX_op_ext16s_i32, { "r", "r" } }, @@ -1478,15 +1660,21 @@ static const TCGTargetOpDef ppc_op_defs[ { INDEX_op_ext16s_i64, { "r", "r" } }, { INDEX_op_ext32s_i64, { "r", "r" } }, + { INDEX_op_setcond_i32, { "r", "r", "ri" } }, + { INDEX_op_setcond_i64, { "r", "r", "ri" } }, + { -1 }, }; -void tcg_target_init (TCGContext *s) +static void tcg_target_init (TCGContext *s) { tcg_regset_set32 (tcg_target_available_regs[TCG_TYPE_I32], 0, 0xffffffff); tcg_regset_set32 (tcg_target_available_regs[TCG_TYPE_I64], 0, 0xffffffff); tcg_regset_set32 (tcg_target_call_clobber_regs, 0, (1 << TCG_REG_R0) | +#ifdef __APPLE__ + (1 << TCG_REG_R2) | +#endif (1 << TCG_REG_R3) | (1 << TCG_REG_R4) | (1 << TCG_REG_R5) | @@ -1502,7 +1690,9 @@ void tcg_target_init (TCGContext *s) tcg_regset_clear (s->reserved_regs); tcg_regset_set_reg (s->reserved_regs, TCG_REG_R0); tcg_regset_set_reg (s->reserved_regs, TCG_REG_R1); +#ifndef __APPLE__ tcg_regset_set_reg (s->reserved_regs, TCG_REG_R2); +#endif tcg_regset_set_reg (s->reserved_regs, TCG_REG_R13); tcg_add_target_add_op_defs (ppc_op_defs);