diff options
author | Aurelien Jarno | 2010-04-05 13:19:56 +0200 |
---|---|---|
committer | Aurelien Jarno | 2010-04-05 15:16:44 +0200 |
commit | 116348def2bb446d972bdc2f44bd77ff631f85de (patch) | |
tree | 546cbdb5e78378fffbd6961c244daa17f2ec33e3 /tcg/mips/tcg-target.c | |
parent | tcg/mips: fix 64-bit linux-user on big endian MIPS (diff) | |
download | qemu-116348def2bb446d972bdc2f44bd77ff631f85de.tar.gz qemu-116348def2bb446d972bdc2f44bd77ff631f85de.tar.xz qemu-116348def2bb446d972bdc2f44bd77ff631f85de.zip |
tcg/mips: use seb/seh instructions on MIPS32R2
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
Diffstat (limited to 'tcg/mips/tcg-target.c')
-rw-r--r-- | tcg/mips/tcg-target.c | 45 |
1 files changed, 39 insertions, 6 deletions
diff --git a/tcg/mips/tcg-target.c b/tcg/mips/tcg-target.c index a33e785f94..f4fb615bf0 100644 --- a/tcg/mips/tcg-target.c +++ b/tcg/mips/tcg-target.c @@ -270,7 +270,6 @@ static inline int tcg_target_const_match(tcg_target_long val, /* instruction opcodes */ enum { - OPC_SPECIAL = 0x00 << 26, OPC_BEQ = 0x04 << 26, OPC_BNE = 0x05 << 26, OPC_ADDIU = 0x09 << 26, @@ -289,6 +288,8 @@ enum { OPC_SB = 0x28 << 26, OPC_SH = 0x29 << 26, OPC_SW = 0x2B << 26, + + OPC_SPECIAL = 0x00 << 26, OPC_SLL = OPC_SPECIAL | 0x00, OPC_SRL = OPC_SPECIAL | 0x02, OPC_SRA = OPC_SPECIAL | 0x03, @@ -311,6 +312,10 @@ enum { OPC_NOR = OPC_SPECIAL | 0x27, OPC_SLT = OPC_SPECIAL | 0x2A, OPC_SLTU = OPC_SPECIAL | 0x2B, + + OPC_SPECIAL3 = 0x1f << 26, + OPC_SEB = OPC_SPECIAL3 | 0x420, + OPC_SEH = OPC_SPECIAL3 | 0x620, }; /* @@ -441,6 +446,26 @@ static inline void tcg_out_bswap32(TCGContext *s, int ret, int arg) tcg_out_opc_reg(s, OPC_OR, ret, ret, TCG_REG_AT); } +static inline void tcg_out_ext8s(TCGContext *s, int ret, int arg) +{ +#ifdef _MIPS_ARCH_MIPS32R2 + tcg_out_opc_reg(s, OPC_SEB, ret, 0, arg); +#else + tcg_out_opc_sa(s, OPC_SLL, ret, arg, 24); + tcg_out_opc_sa(s, OPC_SRA, ret, ret, 24); +#endif +} + +static inline void tcg_out_ext16s(TCGContext *s, int ret, int arg) +{ +#ifdef _MIPS_ARCH_MIPS32R2 + tcg_out_opc_reg(s, OPC_SEH, ret, 0, arg); +#else + tcg_out_opc_sa(s, OPC_SLL, ret, arg, 16); + tcg_out_opc_sa(s, OPC_SRA, ret, ret, 16); +#endif +} + static inline void tcg_out_ldst(TCGContext *s, int opc, int arg, int arg1, tcg_target_long arg2) { @@ -838,15 +863,13 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, tcg_out_opc_imm(s, OPC_ANDI, data_reg1, TCG_REG_V0, 0xff); break; case 0 | 4: - tcg_out_opc_sa(s, OPC_SLL, TCG_REG_V0, TCG_REG_V0, 24); - tcg_out_opc_sa(s, OPC_SRA, data_reg1, TCG_REG_V0, 24); + tcg_out_ext8s(s, data_reg1, TCG_REG_V0); break; case 1: tcg_out_opc_imm(s, OPC_ANDI, data_reg1, TCG_REG_V0, 0xffff); break; case 1 | 4: - tcg_out_opc_sa(s, OPC_SLL, TCG_REG_V0, TCG_REG_V0, 16); - tcg_out_opc_sa(s, OPC_SRA, data_reg1, TCG_REG_V0, 16); + tcg_out_ext16s(s, data_reg1, TCG_REG_V0); break; case 2: tcg_out_mov(s, data_reg1, TCG_REG_V0); @@ -1149,7 +1172,7 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc, break; case INDEX_op_ld8u_i32: - tcg_out_ldst(s, OPC_LBU, args[0], args[1], args[2]); + tcg_out_ldst(s, OPC_LBU, args[0], args[1], args[2]); break; case INDEX_op_ld8s_i32: tcg_out_ldst(s, OPC_LB, args[0], args[1], args[2]); @@ -1293,6 +1316,13 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc, } break; + case INDEX_op_ext8s_i32: + tcg_out_ext8s(s, args[0], args[1]); + break; + case INDEX_op_ext16s_i32: + tcg_out_ext16s(s, args[0], args[1]); + break; + case INDEX_op_brcond_i32: tcg_out_brcond(s, args[2], args[0], args[1], args[3]); break; @@ -1380,6 +1410,9 @@ static const TCGTargetOpDef mips_op_defs[] = { { INDEX_op_shr_i32, { "r", "rZ", "riZ" } }, { INDEX_op_sar_i32, { "r", "rZ", "riZ" } }, + { INDEX_op_ext8s_i32, { "r", "rZ" } }, + { INDEX_op_ext16s_i32, { "r", "rZ" } }, + { INDEX_op_brcond_i32, { "rZ", "rZ" } }, { INDEX_op_setcond_i32, { "r", "rZ", "rZ" } }, { INDEX_op_setcond2_i32, { "r", "rZ", "rZ", "rZ", "rZ" } }, |