diff options
Diffstat (limited to 'tcg/ppc/tcg-target.inc.c')
| -rw-r--r-- | tcg/ppc/tcg-target.inc.c | 117 |
1 files changed, 105 insertions, 12 deletions
diff --git a/tcg/ppc/tcg-target.inc.c b/tcg/ppc/tcg-target.inc.c index a3262cfb0c..64f67d2c77 100644 --- a/tcg/ppc/tcg-target.inc.c +++ b/tcg/ppc/tcg-target.inc.c @@ -77,11 +77,15 @@ #define TCG_CT_CONST_U32 0x800 #define TCG_CT_CONST_ZERO 0x1000 #define TCG_CT_CONST_MONE 0x2000 +#define TCG_CT_CONST_WSZ 0x4000 static tcg_insn_unit *tb_ret_addr; #include "elf.h" -static bool have_isa_2_06; + +bool have_isa_2_06; +bool have_isa_3_00; + #define HAVE_ISA_2_06 have_isa_2_06 #define HAVE_ISEL have_isa_2_06 @@ -259,12 +263,10 @@ static void patch_reloc(tcg_insn_unit *code_ptr, int type, } /* parse target specific constraints */ -static int target_parse_constraint(TCGArgConstraint *ct, const char **pct_str) +static const char *target_parse_constraint(TCGArgConstraint *ct, + const char *ct_str, TCGType type) { - const char *ct_str; - - ct_str = *pct_str; - switch (ct_str[0]) { + switch (*ct_str++) { case 'A': case 'B': case 'C': case 'D': ct->ct |= TCG_CT_REG; tcg_regset_set_reg(ct->u.regs, 3 + ct_str[0] - 'A'); @@ -307,15 +309,16 @@ static int target_parse_constraint(TCGArgConstraint *ct, const char **pct_str) case 'U': ct->ct |= TCG_CT_CONST_U32; break; + case 'W': + ct->ct |= TCG_CT_CONST_WSZ; + break; case 'Z': ct->ct |= TCG_CT_CONST_ZERO; break; default: - return -1; + return NULL; } - ct_str++; - *pct_str = ct_str; - return 0; + return ct_str; } /* test if a constant matches the constraint */ @@ -345,6 +348,9 @@ static int tcg_target_const_match(tcg_target_long val, TCGType type, return 1; } else if ((ct & TCG_CT_CONST_MONE) && val == -1) { return 1; + } else if ((ct & TCG_CT_CONST_WSZ) + && val == (type == TCG_TYPE_I32 ? 32 : 64)) { + return 1; } return 0; } @@ -449,6 +455,10 @@ static int tcg_target_const_match(tcg_target_long val, TCGType type, #define NOR XO31(124) #define CNTLZW XO31( 26) #define CNTLZD XO31( 58) +#define CNTTZW XO31(538) +#define CNTTZD XO31(570) +#define CNTPOPW XO31(378) +#define CNTPOPD XO31(506) #define ANDC XO31( 60) #define ORC XO31(412) #define EQV XO31(284) @@ -1170,6 +1180,32 @@ static void tcg_out_movcond(TCGContext *s, TCGType type, TCGCond cond, } } +static void tcg_out_cntxz(TCGContext *s, TCGType type, uint32_t opc, + TCGArg a0, TCGArg a1, TCGArg a2, bool const_a2) +{ + if (const_a2 && a2 == (type == TCG_TYPE_I32 ? 32 : 64)) { + tcg_out32(s, opc | RA(a0) | RS(a1)); + } else { + tcg_out_cmp(s, TCG_COND_EQ, a1, 0, 1, 7, type); + /* Note that the only other valid constant for a2 is 0. */ + if (HAVE_ISEL) { + tcg_out32(s, opc | RA(TCG_REG_R0) | RS(a1)); + tcg_out32(s, tcg_to_isel[TCG_COND_EQ] | TAB(a0, a2, TCG_REG_R0)); + } else if (!const_a2 && a0 == a2) { + tcg_out32(s, tcg_to_bc[TCG_COND_EQ] | 8); + tcg_out32(s, opc | RA(a0) | RS(a1)); + } else { + tcg_out32(s, opc | RA(a0) | RS(a1)); + tcg_out32(s, tcg_to_bc[TCG_COND_NE] | 8); + if (const_a2) { + tcg_out_movi(s, type, a0, 0); + } else { + tcg_out_mov(s, type, a0, a2); + } + } + } +} + static void tcg_out_cmp2(TCGContext *s, const TCGArg *args, const int *const_args) { @@ -2107,6 +2143,30 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, const TCGArg *args, tcg_out32(s, NOR | SAB(args[1], args[0], args[2])); break; + case INDEX_op_clz_i32: + tcg_out_cntxz(s, TCG_TYPE_I32, CNTLZW, args[0], args[1], + args[2], const_args[2]); + break; + case INDEX_op_ctz_i32: + tcg_out_cntxz(s, TCG_TYPE_I32, CNTTZW, args[0], args[1], + args[2], const_args[2]); + break; + case INDEX_op_ctpop_i32: + tcg_out32(s, CNTPOPW | SAB(args[1], args[0], 0)); + break; + + case INDEX_op_clz_i64: + tcg_out_cntxz(s, TCG_TYPE_I64, CNTLZD, args[0], args[1], + args[2], const_args[2]); + break; + case INDEX_op_ctz_i64: + tcg_out_cntxz(s, TCG_TYPE_I64, CNTTZD, args[0], args[1], + args[2], const_args[2]); + break; + case INDEX_op_ctpop_i64: + tcg_out32(s, CNTPOPD | SAB(args[1], args[0], 0)); + break; + case INDEX_op_mul_i32: a0 = args[0], a1 = args[1], a2 = args[2]; if (const_args[2]) { @@ -2396,6 +2456,14 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, const TCGArg *args, } break; + case INDEX_op_extract_i32: + tcg_out_rlw(s, RLWINM, args[0], args[1], + 32 - args[2], 32 - args[3], 31); + break; + case INDEX_op_extract_i64: + tcg_out_rld(s, RLDICL, args[0], args[1], 64 - args[2], 64 - args[3]); + break; + case INDEX_op_movcond_i32: tcg_out_movcond(s, TCG_TYPE_I32, args[5], args[0], args[1], args[2], args[3], args[4], const_args[2]); @@ -2511,6 +2579,9 @@ static const TCGTargetOpDef ppc_op_defs[] = { { INDEX_op_eqv_i32, { "r", "r", "ri" } }, { INDEX_op_nand_i32, { "r", "r", "r" } }, { INDEX_op_nor_i32, { "r", "r", "r" } }, + { INDEX_op_clz_i32, { "r", "r", "rZW" } }, + { INDEX_op_ctz_i32, { "r", "r", "rZW" } }, + { INDEX_op_ctpop_i32, { "r", "r" } }, { INDEX_op_shl_i32, { "r", "r", "ri" } }, { INDEX_op_shr_i32, { "r", "r", "ri" } }, @@ -2530,6 +2601,7 @@ static const TCGTargetOpDef ppc_op_defs[] = { { INDEX_op_movcond_i32, { "r", "r", "ri", "rZ", "rZ" } }, { INDEX_op_deposit_i32, { "r", "0", "rZ" } }, + { INDEX_op_extract_i32, { "r", "r" } }, { INDEX_op_muluh_i32, { "r", "r", "r" } }, { INDEX_op_mulsh_i32, { "r", "r", "r" } }, @@ -2558,6 +2630,9 @@ static const TCGTargetOpDef ppc_op_defs[] = { { INDEX_op_eqv_i64, { "r", "r", "r" } }, { INDEX_op_nand_i64, { "r", "r", "r" } }, { INDEX_op_nor_i64, { "r", "r", "r" } }, + { INDEX_op_clz_i64, { "r", "r", "rZW" } }, + { INDEX_op_ctz_i64, { "r", "r", "rZW" } }, + { INDEX_op_ctpop_i64, { "r", "r" } }, { INDEX_op_shl_i64, { "r", "r", "ri" } }, { INDEX_op_shr_i64, { "r", "r", "ri" } }, @@ -2585,6 +2660,7 @@ static const TCGTargetOpDef ppc_op_defs[] = { { INDEX_op_movcond_i64, { "r", "r", "ri", "rZ", "rZ" } }, { INDEX_op_deposit_i64, { "r", "0", "rZ" } }, + { INDEX_op_extract_i64, { "r", "r" } }, { INDEX_op_mulsh_i64, { "r", "r", "r" } }, { INDEX_op_muluh_i64, { "r", "r", "r" } }, @@ -2624,12 +2700,31 @@ static const TCGTargetOpDef ppc_op_defs[] = { { -1 }, }; +static const TCGTargetOpDef *tcg_target_op_def(TCGOpcode op) +{ + int i, n = ARRAY_SIZE(ppc_op_defs); + + for (i = 0; i < n; ++i) { + if (ppc_op_defs[i].op == op) { + return &ppc_op_defs[i]; + } + } + return NULL; +} + static void tcg_target_init(TCGContext *s) { unsigned long hwcap = qemu_getauxval(AT_HWCAP); + unsigned long hwcap2 = qemu_getauxval(AT_HWCAP2); + if (hwcap & PPC_FEATURE_ARCH_2_06) { have_isa_2_06 = true; } +#ifdef PPC_FEATURE2_ARCH_3_00 + if (hwcap2 & PPC_FEATURE2_ARCH_3_00) { + have_isa_3_00 = true; + } +#endif tcg_regset_set32(tcg_target_available_regs[TCG_TYPE_I32], 0, 0xffffffff); tcg_regset_set32(tcg_target_available_regs[TCG_TYPE_I64], 0, 0xffffffff); @@ -2660,8 +2755,6 @@ static void tcg_target_init(TCGContext *s) if (USE_REG_RA) { tcg_regset_set_reg(s->reserved_regs, TCG_REG_RA); /* return addr */ } - - tcg_add_target_add_op_defs(ppc_op_defs); } #ifdef __ELF__ |