mips: MSA support for mips32/mips64.

Full support of MIPS SIMD Architecture Module (MSA) instruction set.

Following IOPs have been implemented using generation of MSA instructions:

  Iop_GetElem8x16, Iop_GetElem16x8, Iop_GetElem32x4, Iop_GetElem64x2,
  Iop_V128to32, Iop_V128HIto64, Iop_V128to64, Iop_F32toF16x4, Iop_Abs64x2,
  Iop_Abs32x4, Iop_Abs16x8, Iop_Abs8x16, Iop_Cnt8x16, Iop_NotV128,
  Iop_Reverse8sIn16_x8, Iop_Reverse8sIn32_x4, Iop_Reverse8sIn64_x2,
  Iop_Cls8x16, Iop_Cls16x8, Iop_Cls32x4, Iop_Clz8x16, Iop_Clz16x8,
  Iop_Clz32x4, Iop_Clz64x2, Iop_Abs32Fx4, Iop_Abs64Fx2, Iop_RecipEst32Fx4,
  Iop_RecipEst64Fx2, Iop_RSqrtEst32Fx4, Iop_RSqrtEst64Fx2, Iop_F16toF32x4,
  Iop_I32UtoFx4, Iop_FtoI32Sx4_RZ, Iop_FtoI32Ux4_RZ, Iop_Add8x16,
  Iop_Add16x8, Iop_Add32x4, Iop_Add64x2, Iop_Sub8x16, Iop_Sub16x8,
  Iop_Sub32x4, Iop_Sub64x2, Iop_QAdd8Sx16, Iop_QAdd16Sx8, Iop_QAdd32Sx4,
  Iop_QAdd64Sx2, Iop_QAdd8Ux16, Iop_QAdd16Ux8, Iop_QAdd32Ux4,
  Iop_QAdd64Ux2, Iop_QSub8Sx16, Iop_QSub16Sx8, Iop_QSub32Sx4,
  Iop_QSub64Sx2, Iop_QSub8Ux16, Iop_QSub16Ux8, Iop_QSub32Ux4,
  Iop_QSub64Ux2, Iop_QDMulHi32Sx4, Iop_QDMulHi16Sx8, Iop_QRDMulHi32Sx4,
  Iop_QRDMulHi16Sx8, Iop_Max8Sx16, Iop_Max16Sx8, Iop_Max32Sx4, Iop_Max64Sx2,
  Iop_Max8Ux16, Iop_Max16Ux8, Iop_Max32Ux4, Iop_Max64Ux2, Iop_Min8Sx16,
  Iop_Min16Sx8, Iop_Min32Sx4, Iop_Min64Sx2, Iop_Min8Ux16, Iop_Min16Ux8,
  Iop_Min32Ux4, Iop_Min64Ux2, Iop_Shl8x16, Iop_Shl16x8, Iop_Shl32x4,
  Iop_Shl64x2, Iop_Shr8x16, Iop_Shr16x8, Iop_Shr32x4, Iop_Shr64x2,
  Iop_Sar8x16, Iop_Sar16x8, Iop_Sar32x4, Iop_Sar64x2, Iop_InterleaveHI8x16,
  Iop_InterleaveHI16x8, Iop_InterleaveHI32x4, Iop_InterleaveHI64x2,
  Iop_InterleaveLO8x16, Iop_InterleaveLO16x8, Iop_InterleaveLO32x4,
  Iop_InterleaveLO64x2, Iop_InterleaveEvenLanes8x16,
  Iop_InterleaveEvenLanes16x8, Iop_InterleaveEvenLanes32x4,
  Iop_InterleaveOddLanes8x16, Iop_InterleaveOddLanes16x8,
  Iop_InterleaveOddLanes32x4, Iop_CmpEQ8x16, Iop_CmpEQ16x8, Iop_CmpEQ32x4,
  Iop_CmpEQ64x2, Iop_CmpGT8Sx16, Iop_CmpGT16Sx8, Iop_CmpGT32Sx4,
  Iop_CmpGT64Sx2, Iop_CmpGT8Ux16, Iop_CmpGT16Ux8, Iop_CmpGT32Ux4,
  Iop_CmpGT64Ux2, Iop_Avg8Sx16, Iop_Avg16Sx8, Iop_Avg32Sx4, Iop_Avg8Ux16,
  Iop_Avg16Ux8, Iop_Avg32Ux4, Iop_Mul8x16, Iop_Mul16x8, Iop_Mul32x4,
  Iop_AndV128, Iop_OrV128, Iop_XorV128, Iop_ShrV128, Iop_ShlV128,
  Iop_ShlN8x16, Iop_ShlN16x8, Iop_ShlN32x4, Iop_ShlN64x2, Iop_SarN8x16,
  Iop_SarN16x8, Iop_SarN32x4, Iop_SarN64x2, Iop_ShrN8x16, Iop_ShrN16x8,
  Iop_ShrN32x4, Iop_ShrN64x2, Iop_QandQSarNnarrow64Sto32Sx2,
  Iop_QandQSarNnarrow32Sto16Sx4, Iop_QandQRSarNnarrow64Sto32Sx2,
  Iop_QandQRSarNnarrow32Sto16Sx4, Iop_CmpEQ32Fx4, Iop_CmpEQ64Fx2,
  Iop_CmpLT32Fx4, Iop_CmpLT64Fx2, Iop_CmpLE32Fx4, Iop_CmpLE64Fx2,
  Iop_CmpUN32Fx4, Iop_CmpUN64Fx2, Iop_64HLtoV128, Iop_Min32Fx4,
  Iop_Min64Fx2, Iop_Max32Fx4, Iop_Max64Fx2, Iop_Sqrt32Fx4,
  Iop_Sqrt64Fx2, Iop_Add32Fx4, Iop_Add64Fx2, Iop_Sub32Fx4,
  Iop_Sub64Fx2, Iop_Mul32Fx4, Iop_Mul64Fx2, Iop_Div32Fx4,
  Iop_Div64Fx2, Iop_F32x4_2toQ16x8, Iop_F64x2_2toQ32x4,
  Iop_ScaleF64, Scale2_64Fx2, Scale2_32Fx4, Iop_Log2_32Fx4, Iop_Log2_64Fx2,
  Iop_PackOddLanes8x16, Iop_PackEvenLanes8x16, Iop_PackOddLanes16x8,
  Iop_PackEvenLanes16x8, Iop_PackOddLanes32x4, Iop_PackEvenLanes32x4.

Folowing IOPs have been implemented without generating MSA instructions:

  Iop_CmpEQ8, Iop_MullU8, Iop_MullS8, Iop_MullU16, Iop_MullS16, Iop_DivS32,
  Iop_DivU32, Iop_DivS64, Iop_DivU64, Iop_F32toI32U, Iop_F64toI64U,
  Iop_I64UtoF64

Imlementation of the following IOPs has been changed in order to use MSA
when it is possible:

  Iop_MAddF64, Iop_MSubF32, Iop_MSubF64.

Contributed by:
  Tamara Vlahovic, Aleksandar Rikalo and Aleksandra Karadzic.

Related BZ issue - #382563.
This commit is contained in:
Petar Jovanovic 2017-10-24 18:00:28 +02:00
parent 91373819a3
commit 4ef3d807e1
10 changed files with 18711 additions and 103 deletions

View File

@ -94,6 +94,20 @@ typedef enum {
SUBS, SUBD, DIVS
} flt_op;
typedef enum {
FADDW=0, FADDD, FSUBW, FSUBD, FMULW, FMULD, FDIVW, FDIVD, FMADDW, FMADDD,
FCAFD, FCAFW, FSAFD, FSAFW, FCEQD, FCEQW, FSEQD, FSEQW, FCLTD, FCLTW, FSLTD,
FSLTW, FCLED, FCLEW, FSLED, FSLEW, FCNED, FCNEW, FSNED, FSNEW, FCUND, FCUNW,
FSUND, FSUNW, FCORD, FCORW, FSORD, FSORW, FCUEQD, FCUEQW, FSUEQD, FSUEQW,
FCUNED, FCUNEW, FSUNED, FSUNEW, FCULED, FCULEW, FSULED, FSULEW, FCULTD,
FCULTW, FSULTD, FSULTW, FEXP2W, FEXP2D, FMINW, FMIND, FMINAW, FMINAD, FMAXW,
FMAXD, FMAXAW, FMAXAD, FFINTSW, FFINTSD, FRCPW, FRCPD, FRSQRTW, FRSQRTD,
FSQRTW, FSQRTD, FRINTW, FRINTD, FTRUNCUW, FTRUNCUD, FTRUNCSW, FTRUNCSD,
FEXDOH, FEXDOW, FEXUPRD, FEXUPRW, FEXUPLD, FEXUPLW, FLOG2W, FLOG2D,
FTQH, FTQW, FFQRW, FFQRD,FFQLW, FFQLD, FTINT_SW, FTINT_SD,
FTINT_UW, FTINT_UD, FFINT_UW, FFINT_UD,
} msa_flt_op;
#if defined (_MIPSEL)
#define MIPS_IEND Iend_LE
#else
@ -109,6 +123,11 @@ extern UInt mips_dirtyhelper_calculate_FCSR_fp32 ( void* guest_state, UInt fs,
extern UInt mips_dirtyhelper_calculate_FCSR_fp64 ( void* guest_state, UInt fs,
UInt ft, flt_op op );
extern UInt mips_dirtyhelper_calculate_MSACSR ( void* gs, UInt ws, UInt wt,
msa_flt_op inst );
extern UInt mips_dirtyhelper_get_MSAIR ( void );
/*---------------------------------------------------------*/
/*--- Condition code stuff ---*/
/*---------------------------------------------------------*/

View File

@ -40,6 +40,12 @@
#include "guest_generic_bb_to_IR.h"
#include "guest_mips_defs.h"
#if defined (__GNUC__)
#define GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__)
#else
#define GCC_VERSION 0
#endif
/* This file contains helper functions for mips guest code. Calls to
these functions are generated by the back end.
*/
@ -176,6 +182,13 @@ void LibVEX_GuestMIPS32_initialise( /*OUT*/ VexGuestMIPS32State * vex_state)
vex_state->guest_ac1 = 0; /* Accumulator 1 */
vex_state->guest_ac2 = 0; /* Accumulator 2 */
vex_state->guest_ac3 = 0; /* Accumulator 3 */
vex_state->guest_w0.w64[0] = 0;
vex_state->guest_w0.w64[1] = 0;
vex_state->guest_w1.w64[0] = 0;
vex_state->guest_w1.w64[1] = 0;
vex_state->guest_w2.w64[0] = 0;
vex_state->guest_w2.w64[1] = 0;
}
void LibVEX_GuestMIPS64_initialise ( /*OUT*/ VexGuestMIPS64State * vex_state )
@ -282,6 +295,8 @@ void LibVEX_GuestMIPS64_initialise ( /*OUT*/ VexGuestMIPS64State * vex_state )
vex_state->guest_LLaddr = 0xFFFFFFFFFFFFFFFFULL;
vex_state->guest_LLdata = 0;
vex_state->guest_MSACSR = 0;
}
/*-----------------------------------------------------------*/
@ -511,6 +526,25 @@ HWord mips_dirtyhelper_rdhwr ( UInt rd )
: "t0", "$f24" \
);
#define ASM_VOLATILE_MSA_UNARY(inst) \
__asm__ volatile(".set push" "\n\t" \
".set mips32r2" "\n\t" \
".set hardfloat" "\n\t" \
".set fp=64" "\n\t" \
".set msa" "\n\t" \
".set noreorder" "\n\t" \
"cfcmsa $t0, $1" "\n\t" \
"ctcmsa $1, %2" "\n\t" \
"ld.b $w24, 0(%1)" "\n\t" \
#inst" $w24, $w24" "\n\t" \
"cfcmsa %0, $1" "\n\t" \
"ctcmsa $1, $t0" "\n\t" \
".set pop" "\n\t" \
: "=r" (ret) \
: "r" (&(addr[ws])), "r" (msacsr) \
: "t0" \
);
#define ASM_VOLATILE_BINARY32(inst) \
__asm__ volatile(".set push" "\n\t" \
".set hardfloat" "\n\t" \
@ -559,6 +593,25 @@ HWord mips_dirtyhelper_rdhwr ( UInt rd )
: "t0", "$f24", "$f26" \
);
#define ASM_VOLATILE_MSA_BINARY(inst) \
__asm__ volatile(".set push" "\n\t" \
".set mips32r2" "\n\t" \
".set hardfloat" "\n\t" \
".set fp=64" "\n\t" \
".set msa" "\n\t" \
"cfcmsa $t0, $1" "\n\t" \
"ctcmsa $1, %3" "\n\t" \
"ld.b $w24, 0(%1)" "\n\t" \
"ld.b $w26, 0(%2)" "\n\t" \
#inst" $w24, $w24, $w26" "\n\t" \
"cfcmsa %0, $1" "\n\t" \
"ctcmsa $1, $t0" "\n\t" \
".set pop" "\n\t" \
: "=r" (ret) \
: "r" (&(addr[ws])), "r" (&(addr[wt])), "r" (msacsr)\
: "t0" \
);
/* TODO: Add cases for all fpu instructions because all fpu instructions are
change the value of FCSR register. */
extern UInt mips_dirtyhelper_calculate_FCSR_fp32 ( void* gs, UInt fs, UInt ft,
@ -767,6 +820,436 @@ extern UInt mips_dirtyhelper_calculate_FCSR_fp64 ( void* gs, UInt fs, UInt ft,
return ret;
}
extern UInt mips_dirtyhelper_calculate_MSACSR ( void* gs, UInt ws, UInt wt,
msa_flt_op inst ) {
UInt ret = 0;
/* GCC 4.8 and later support MIPS MSA. */
#if defined(__mips__) && (defined(__clang__) || (GCC_VERSION >= 408))
#if defined(VGA_mips32)
VexGuestMIPS32State* guest_state = (VexGuestMIPS32State*)gs;
#else
VexGuestMIPS64State* guest_state = (VexGuestMIPS64State*)gs;
#endif
V128 *addr = (V128 *)&guest_state->guest_w0;
UInt msacsr = guest_state->guest_MSACSR;
switch (inst) {
case FADDW:
ASM_VOLATILE_MSA_BINARY(fadd.w)
break;
case FADDD:
ASM_VOLATILE_MSA_BINARY(fadd.d)
break;
case FSUBW:
ASM_VOLATILE_MSA_BINARY(fsub.w);
break;
case FSUBD:
ASM_VOLATILE_MSA_BINARY(fsub.d);
break;
case FMULW:
ASM_VOLATILE_MSA_BINARY(fmul.w);
break;
case FMULD:
ASM_VOLATILE_MSA_BINARY(fmul.d);
break;
case FDIVW:
ASM_VOLATILE_MSA_BINARY(fdiv.w);
break;
case FDIVD:
ASM_VOLATILE_MSA_BINARY(fdiv.d);
break;
case FMADDW:
ASM_VOLATILE_MSA_BINARY(fmadd.w);
break;
case FMADDD:
ASM_VOLATILE_MSA_BINARY(fmadd.d);
break;
case FCAFW:
ASM_VOLATILE_MSA_BINARY(fcaf.w);
break;
case FCAFD:
ASM_VOLATILE_MSA_BINARY(fcaf.d);
break;
case FSAFW:
ASM_VOLATILE_MSA_BINARY(fsaf.w);
break;
case FSAFD:
ASM_VOLATILE_MSA_BINARY(fsaf.d);
break;
case FCEQW:
ASM_VOLATILE_MSA_BINARY(fceq.w);
break;
case FCEQD:
ASM_VOLATILE_MSA_BINARY(fceq.d);
break;
case FSEQW:
ASM_VOLATILE_MSA_BINARY(fseq.w);
break;
case FSEQD:
ASM_VOLATILE_MSA_BINARY(fseq.d);
break;
case FCLTW:
ASM_VOLATILE_MSA_BINARY(fclt.w);
break;
case FCLTD:
ASM_VOLATILE_MSA_BINARY(fclt.d);
break;
case FSLTW:
ASM_VOLATILE_MSA_BINARY(fslt.w);
break;
case FSLTD:
ASM_VOLATILE_MSA_BINARY(fslt.d);
break;
case FCLEW:
ASM_VOLATILE_MSA_BINARY(fcle.w);
break;
case FCLED:
ASM_VOLATILE_MSA_BINARY(fcle.d);
break;
case FSLEW:
ASM_VOLATILE_MSA_BINARY(fsle.w);
break;
case FSLED:
ASM_VOLATILE_MSA_BINARY(fsle.d);
break;
case FCNEW:
ASM_VOLATILE_MSA_BINARY(fcne.w);
break;
case FCNED:
ASM_VOLATILE_MSA_BINARY(fcne.d);
break;
case FSNEW:
ASM_VOLATILE_MSA_BINARY(fsne.w);
break;
case FSNED:
ASM_VOLATILE_MSA_BINARY(fsne.d);
break;
case FEXP2W:
ASM_VOLATILE_MSA_BINARY(fexp2.w);
break;
case FEXP2D:
ASM_VOLATILE_MSA_BINARY(fexp2.d);
break;
case FMINW:
ASM_VOLATILE_MSA_BINARY(fmin.w);
break;
case FMIND:
ASM_VOLATILE_MSA_BINARY(fmin.d);
break;
case FMINAW:
ASM_VOLATILE_MSA_BINARY(fmin_a.w);
break;
case FMINAD:
ASM_VOLATILE_MSA_BINARY(fmin_a.d);
break;
case FCUNW:
ASM_VOLATILE_MSA_BINARY(fcun.w);
break;
case FCUND:
ASM_VOLATILE_MSA_BINARY(fcun.d);
break;
case FSUNW:
ASM_VOLATILE_MSA_BINARY(fsun.w);
break;
case FSUND:
ASM_VOLATILE_MSA_BINARY(fsun.d);
break;
case FCORW:
ASM_VOLATILE_MSA_BINARY(fcor.w);
break;
case FCORD:
ASM_VOLATILE_MSA_BINARY(fcor.d);
break;
case FSORW:
ASM_VOLATILE_MSA_BINARY(fsor.w);
break;
case FSORD:
ASM_VOLATILE_MSA_BINARY(fsor.d);
break;
case FCUEQW:
ASM_VOLATILE_MSA_BINARY(fcueq.w);
break;
case FCUEQD:
ASM_VOLATILE_MSA_BINARY(fcueq.d);
break;
case FSUEQW:
ASM_VOLATILE_MSA_BINARY(fsueq.w);
break;
case FSUEQD:
ASM_VOLATILE_MSA_BINARY(fsueq.d);
break;
case FCUNEW:
ASM_VOLATILE_MSA_BINARY(fcune.w);
break;
case FCUNED:
ASM_VOLATILE_MSA_BINARY(fcune.d);
break;
case FSUNEW:
ASM_VOLATILE_MSA_BINARY(fsune.w);
break;
case FSUNED:
ASM_VOLATILE_MSA_BINARY(fsune.d);
break;
case FCULEW:
ASM_VOLATILE_MSA_BINARY(fcule.w);
break;
case FCULED:
ASM_VOLATILE_MSA_BINARY(fcule.d);
break;
case FSULEW:
ASM_VOLATILE_MSA_BINARY(fsule.w);
break;
case FSULED:
ASM_VOLATILE_MSA_BINARY(fsule.d);
break;
case FCULTW:
ASM_VOLATILE_MSA_BINARY(fcult.w);
break;
case FCULTD:
ASM_VOLATILE_MSA_BINARY(fcult.d);
break;
case FSULTW:
ASM_VOLATILE_MSA_BINARY(fsult.w);
break;
case FSULTD:
ASM_VOLATILE_MSA_BINARY(fsult.d);
case FMAXW:
ASM_VOLATILE_MSA_BINARY(fmax.w);
break;
case FMAXD:
ASM_VOLATILE_MSA_BINARY(fmax.d);
break;
case FMAXAW:
ASM_VOLATILE_MSA_BINARY(fmax_a.w);
break;
case FMAXAD:
ASM_VOLATILE_MSA_BINARY(fmax_a.d);
break;
case FFINTSW:
ASM_VOLATILE_MSA_UNARY(ffint_s.w);
break;
case FFINTSD:
ASM_VOLATILE_MSA_UNARY(ffint_s.d);
break;
case FRCPW:
ASM_VOLATILE_MSA_UNARY(frcp.w);
break;
case FRCPD:
ASM_VOLATILE_MSA_UNARY(frcp.d);
break;
case FRSQRTW:
ASM_VOLATILE_MSA_UNARY(frsqrt.w);
break;
case FRSQRTD:
ASM_VOLATILE_MSA_UNARY(frsqrt.d);
break;
case FSQRTW:
ASM_VOLATILE_MSA_UNARY(fsqrt.w);
break;
case FSQRTD:
ASM_VOLATILE_MSA_UNARY(fsqrt.d);
break;
case FRINTW:
ASM_VOLATILE_MSA_UNARY(frint.w);
break;
case FRINTD:
ASM_VOLATILE_MSA_UNARY(frint.d);
case FTRUNCUW:
ASM_VOLATILE_MSA_UNARY(ftrunc_u.w);
break;
case FTRUNCUD:
ASM_VOLATILE_MSA_UNARY(ftrunc_u.d);
break;
case FTRUNCSW:
ASM_VOLATILE_MSA_UNARY(ftrunc_s.w);
break;
case FTRUNCSD:
ASM_VOLATILE_MSA_UNARY(ftrunc_s.d);
break;
case FEXDOH:
ASM_VOLATILE_MSA_BINARY(fexdo.h);
break;
case FEXDOW:
ASM_VOLATILE_MSA_BINARY(fexdo.w);
break;
case FEXUPRW:
ASM_VOLATILE_MSA_UNARY(fexupr.w);
break;
case FEXUPRD:
ASM_VOLATILE_MSA_UNARY(fexupr.d);
break;
case FEXUPLW:
ASM_VOLATILE_MSA_UNARY(fexupl.w);
break;
case FEXUPLD:
ASM_VOLATILE_MSA_UNARY(fexupl.d);
break;
case FTQH:
ASM_VOLATILE_MSA_BINARY(ftq.h);
break;
case FTQW:
ASM_VOLATILE_MSA_BINARY(ftq.w);
break;
case FFQRD:
ASM_VOLATILE_MSA_UNARY(ffqr.d);
break;
case FFQRW:
ASM_VOLATILE_MSA_UNARY(ffqr.w);
break;
case FFQLD:
ASM_VOLATILE_MSA_UNARY(ffql.d);
break;
case FFQLW:
ASM_VOLATILE_MSA_UNARY(ffql.w);
break;
case FTINT_SD:
ASM_VOLATILE_MSA_UNARY(ftint_s.d);
break;
case FTINT_SW:
ASM_VOLATILE_MSA_UNARY(ftint_s.w);
break;
case FTINT_UD:
ASM_VOLATILE_MSA_UNARY(ftint_u.d);
break;
case FTINT_UW:
ASM_VOLATILE_MSA_UNARY(ftint_u.w);
break;
case FLOG2D:
ASM_VOLATILE_MSA_UNARY(flog2.d);
break;
case FLOG2W:
ASM_VOLATILE_MSA_UNARY(flog2.w);
break;
case FFINT_UD:
ASM_VOLATILE_MSA_UNARY(ffint_u.d);
break;
case FFINT_UW:
ASM_VOLATILE_MSA_UNARY(ffint_u.w);
break;
}
#endif
return ret;
}
extern UInt mips_dirtyhelper_get_MSAIR() {
UInt ret = 0;
/* GCC 4.8 and later support MIPS MSA. */
#if defined(__mips__) && (defined(__clang__) || (GCC_VERSION >= 408))
__asm__ volatile(".set push \n\t"
".set mips32r2 \n\t"
".set hardfloat \n\t"
".set fp=64 \n\t"
".set msa \n\t"
".set noreorder \n\t"
"cfcmsa %0, $0 \n\t"
".set pop \n\t"
: "=r" (ret) : : );
#endif
return ret;
}
/*---------------------------------------------------------------*/
/*--- end guest_mips_helpers.c ---*/
/*---------------------------------------------------------------*/

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -52,6 +52,10 @@
mkHReg(False, HRcFlt64, \
(_enc), (_mode64) ? (_ix64) : (_ix32))
#define VEC(_mode64, _enc, _ix64, _ix32) \
mkHReg(False, HRcVec128, \
(_enc), (_mode64) ? (_ix64) : (_ix32))
ST_IN HReg hregMIPS_GPR16 ( Bool mode64 ) { return GPR(mode64, 16, 0, 0); }
ST_IN HReg hregMIPS_GPR17 ( Bool mode64 ) { return GPR(mode64, 17, 1, 1); }
ST_IN HReg hregMIPS_GPR18 ( Bool mode64 ) { return GPR(mode64, 18, 2, 2); }
@ -75,57 +79,79 @@ ST_IN HReg hregMIPS_F26 ( Bool mode64 ) { return FR (mode64, 26, 17, 17); }
ST_IN HReg hregMIPS_F28 ( Bool mode64 ) { return FR (mode64, 28, 18, 18); }
ST_IN HReg hregMIPS_F30 ( Bool mode64 ) { return FR (mode64, 30, 19, 19); }
ST_IN HReg hregMIPS_W16 ( Bool mode64 ) { return VEC(mode64, 1, 20, 20); }
ST_IN HReg hregMIPS_W17 ( Bool mode64 ) { return VEC(mode64, 3, 21, 21); }
ST_IN HReg hregMIPS_W18 ( Bool mode64 ) { return VEC(mode64, 5, 22, 22); }
ST_IN HReg hregMIPS_W19 ( Bool mode64 ) { return VEC(mode64, 7, 23, 23); }
ST_IN HReg hregMIPS_W20 ( Bool mode64 ) { return VEC(mode64, 9, 24, 24); }
ST_IN HReg hregMIPS_W21 ( Bool mode64 ) { return VEC(mode64, 11, 25, 25); }
ST_IN HReg hregMIPS_W22 ( Bool mode64 ) { return VEC(mode64, 13, 26, 26); }
ST_IN HReg hregMIPS_W23 ( Bool mode64 ) { return VEC(mode64, 15, 27, 27); }
ST_IN HReg hregMIPS_W24 ( Bool mode64 ) { return VEC(mode64, 17, 28, 28); }
ST_IN HReg hregMIPS_W25 ( Bool mode64 ) { return VEC(mode64, 19, 29, 29); }
ST_IN HReg hregMIPS_W26 ( Bool mode64 ) { return VEC(mode64, 21, 30, 30); }
ST_IN HReg hregMIPS_W27 ( Bool mode64 ) { return VEC(mode64, 23, 31, 31); }
ST_IN HReg hregMIPS_W28 ( Bool mode64 ) { return VEC(mode64, 25, 32, 32); }
ST_IN HReg hregMIPS_W29 ( Bool mode64 ) { return VEC(mode64, 27, 33, 33); }
ST_IN HReg hregMIPS_W30 ( Bool mode64 ) { return VEC(mode64, 29, 34, 34); }
ST_IN HReg hregMIPS_W31 ( Bool mode64 ) { return VEC(mode64, 31, 35, 35); }
// DRs are only allocatable in 32-bit mode, so the 64-bit index numbering
// doesn't advance here.
ST_IN HReg hregMIPS_D0 ( Bool mode64 ) { vassert(!mode64);
return DR (mode64, 0, 0, 20); }
return DR (mode64, 0, 0, 36); }
ST_IN HReg hregMIPS_D1 ( Bool mode64 ) { vassert(!mode64);
return DR (mode64, 2, 0, 21); }
return DR (mode64, 2, 0, 37); }
ST_IN HReg hregMIPS_D2 ( Bool mode64 ) { vassert(!mode64);
return DR (mode64, 4, 0, 22); }
return DR (mode64, 4, 0, 38); }
ST_IN HReg hregMIPS_D3 ( Bool mode64 ) { vassert(!mode64);
return DR (mode64, 6, 0, 23); }
return DR (mode64, 6, 0, 39); }
ST_IN HReg hregMIPS_D4 ( Bool mode64 ) { vassert(!mode64);
return DR (mode64, 8, 0, 24); }
return DR (mode64, 8, 0, 40); }
ST_IN HReg hregMIPS_D5 ( Bool mode64 ) { vassert(!mode64);
return DR (mode64, 10, 0, 25); }
return DR (mode64, 10, 0, 41); }
ST_IN HReg hregMIPS_D6 ( Bool mode64 ) { vassert(!mode64);
return DR (mode64, 12, 0, 26); }
return DR (mode64, 12, 0, 42); }
ST_IN HReg hregMIPS_D7 ( Bool mode64 ) { vassert(!mode64);
return DR (mode64, 14, 0, 27); }
return DR (mode64, 14, 0, 43); }
ST_IN HReg hregMIPS_HI ( Bool mode64 ) { return FR (mode64, 33, 20, 28); }
ST_IN HReg hregMIPS_LO ( Bool mode64 ) { return FR (mode64, 34, 21, 29); }
ST_IN HReg hregMIPS_HI ( Bool mode64 ) { return FR (mode64, 33, 36, 44); }
ST_IN HReg hregMIPS_LO ( Bool mode64 ) { return FR (mode64, 34, 37, 45); }
ST_IN HReg hregMIPS_GPR0 ( Bool mode64 ) { return GPR(mode64, 0, 22, 30); }
ST_IN HReg hregMIPS_GPR1 ( Bool mode64 ) { return GPR(mode64, 1, 23, 31); }
ST_IN HReg hregMIPS_GPR2 ( Bool mode64 ) { return GPR(mode64, 2, 24, 32); }
ST_IN HReg hregMIPS_GPR3 ( Bool mode64 ) { return GPR(mode64, 3, 25, 33); }
ST_IN HReg hregMIPS_GPR4 ( Bool mode64 ) { return GPR(mode64, 4, 26, 34); }
ST_IN HReg hregMIPS_GPR5 ( Bool mode64 ) { return GPR(mode64, 5, 27, 35); }
ST_IN HReg hregMIPS_GPR6 ( Bool mode64 ) { return GPR(mode64, 6, 28, 36); }
ST_IN HReg hregMIPS_GPR7 ( Bool mode64 ) { return GPR(mode64, 7, 29, 37); }
ST_IN HReg hregMIPS_GPR8 ( Bool mode64 ) { return GPR(mode64, 8, 30, 38); }
ST_IN HReg hregMIPS_GPR9 ( Bool mode64 ) { return GPR(mode64, 9, 31, 39); }
ST_IN HReg hregMIPS_GPR10 ( Bool mode64 ) { return GPR(mode64, 10, 32, 40); }
ST_IN HReg hregMIPS_GPR11 ( Bool mode64 ) { return GPR(mode64, 11, 33, 41); }
ST_IN HReg hregMIPS_GPR23 ( Bool mode64 ) { return GPR(mode64, 23, 34, 42); }
ST_IN HReg hregMIPS_GPR25 ( Bool mode64 ) { return GPR(mode64, 25, 35, 43); }
ST_IN HReg hregMIPS_GPR29 ( Bool mode64 ) { return GPR(mode64, 29, 36, 44); }
ST_IN HReg hregMIPS_GPR31 ( Bool mode64 ) { return GPR(mode64, 31, 37, 45); }
ST_IN HReg hregMIPS_GPR0 ( Bool mode64 ) { return GPR(mode64, 0, 38, 46); }
ST_IN HReg hregMIPS_GPR1 ( Bool mode64 ) { return GPR(mode64, 1, 39, 47); }
ST_IN HReg hregMIPS_GPR2 ( Bool mode64 ) { return GPR(mode64, 2, 40, 48); }
ST_IN HReg hregMIPS_GPR3 ( Bool mode64 ) { return GPR(mode64, 3, 41, 49); }
ST_IN HReg hregMIPS_GPR4 ( Bool mode64 ) { return GPR(mode64, 4, 42, 50); }
ST_IN HReg hregMIPS_GPR5 ( Bool mode64 ) { return GPR(mode64, 5, 43, 51); }
ST_IN HReg hregMIPS_GPR6 ( Bool mode64 ) { return GPR(mode64, 6, 44, 52); }
ST_IN HReg hregMIPS_GPR7 ( Bool mode64 ) { return GPR(mode64, 7, 45, 53); }
ST_IN HReg hregMIPS_GPR8 ( Bool mode64 ) { return GPR(mode64, 8, 46, 54); }
ST_IN HReg hregMIPS_GPR9 ( Bool mode64 ) { return GPR(mode64, 9, 47, 55); }
ST_IN HReg hregMIPS_GPR10 ( Bool mode64 ) { return GPR(mode64, 10, 48, 56); }
ST_IN HReg hregMIPS_GPR11 ( Bool mode64 ) { return GPR(mode64, 11, 49, 57); }
ST_IN HReg hregMIPS_GPR23 ( Bool mode64 ) { return GPR(mode64, 23, 50, 58); }
ST_IN HReg hregMIPS_GPR25 ( Bool mode64 ) { return GPR(mode64, 25, 51, 59); }
ST_IN HReg hregMIPS_GPR29 ( Bool mode64 ) { return GPR(mode64, 29, 52, 60); }
ST_IN HReg hregMIPS_GPR31 ( Bool mode64 ) { return GPR(mode64, 31, 53, 61); }
#undef ST_IN
#undef GPR
#undef FR
#undef DR
#undef VEC
#define GuestStatePointer(_mode64) hregMIPS_GPR23(_mode64)
#define StackFramePointer(_mode64) hregMIPS_GPR30(_mode64)
#define StackPointer(_mode64) hregMIPS_GPR29(_mode64)
#define Zero(_mode64) hregMIPS_GPR0(_mode64)
/* guest_COND offset */
#define COND_OFFSET(_mode64) ((_mode64) ? 588 : 448)
/* guest_MSACSR offset */
#define MSACSR_OFFSET(_mode64) ((_mode64) ? 1144 : 1016)
/* Num registers used for function calls */
#if defined(VGP_mips32_linux)
/* a0, a1, a2, a3 */
@ -137,6 +163,7 @@ ST_IN HReg hregMIPS_GPR31 ( Bool mode64 ) { return GPR(mode64, 31, 37, 45); }
extern UInt ppHRegMIPS ( HReg, Bool );
#define OPC_MSA 0x78000000
/* --------- Condition codes, Intel encoding. --------- */
typedef enum {
@ -270,6 +297,153 @@ typedef enum {
extern const HChar *showMIPSMaccOp(MIPSMaccOp, Bool);
/* --------- */
typedef enum {
MSA_LD = 8,
MSA_ST = 9
} MSAMI10Op;
extern const HChar *showMsaMI10op(MSAMI10Op);
typedef enum {
MSA_SLDI = 0,
MSA_COPY_S = 2,
MSA_COPY_U = 3,
MSA_INSERT = 4,
MSA_INSVE = 5,
MSA_MOVE = 0xBE,
MSA_CFCMSA = 0x7E,
MSA_CTCMSA = 0x3E
} MSAELMOp;
extern const HChar *showMsaElmOp(MSAELMOp);
typedef enum {
MSA_FILL = 0xC0,
MSA_PCNT = 0xC1,
MSA_NLOC = 0xC2,
MSA_NLZC = 0xC3
} MSA2ROp;
extern const HChar *showMsa2ROp(MSA2ROp);
typedef enum {
MSA_FTRUNC_S = 0x191,
MSA_FTRUNC_U = 0x192,
MSA_FFINT_S = 0x19E,
MSA_FFINT_U = 0x19F,
MSA_FSQRT = 0x193,
MSA_FRSQRT = 0x194,
MSA_FRCP = 0x195,
MSA_FLOG2 = 0x197,
MSA_FEXUPR = 0x199,
MSA_FTINT_U = 0x19D,
MSA_FTINT_S = 0x19C,
} MSA2RFOp;
extern const HChar *showMsa2RFOp(MSA2RFOp);
typedef enum {
MSA_SLL = 0xD,
MSA_ADDV,
MSA_CEQ,
MSA_ADD_A,
MSA_SUBS_S,
MSA_SLD = 0x14,
MSA_SRA = 0x80000D,
MSA_SUBV,
MSA_SUBS_U = 0x800011,
MSA_SRL = 0x100000D,
MSA_MAX_S,
MSA_CLT_S,
MSA_ADDS_S,
MSA_PCKEV = 0x1000014,
MSA_MAX_U = 0x180000E,
MSA_CLT_U,
MSA_ADDS_U,
MSA_PCKOD = 0x1800014,
MSA_MIN_S = 0x200000E,
MSA_ILVL = 0x2000014,
MSA_MIN_U = 0x280000E,
MSA_ILVR = 0x2800014,
MSA_AVER_S = 0x3000010,
MSA_ILVEV = 0x3000014,
MSA_AVER_U = 0x3800010,
MSA_ILVOD = 0x3800014,
MSA_MULV = 0x0000012,
MSA_SPLAT = 0x0800014,
MSA_DIVS = 0x2000012,
MSA_DIVU = 0x2800012,
MSA_VSHF = 0x0000015,
} MSA3ROp;
extern const HChar *showMsa3ROp(MSA3ROp);
typedef enum {
MSA_FADD = 0x000001B,
MSA_FCUN = 0x040001A,
MSA_FSUB = 0x040001B,
MSA_FCEQ = 0x080001A,
MSA_FMUL = 0x080001B,
MSA_FDIV = 0x0C0001B,
MSA_FMADD = 0x100001B,
MSA_FCLT = 0x100001A,
MSA_FMSUB = 0x140001B,
MSA_FEXP2 = 0x1C0001B,
MSA_FMIN = 0x300001B,
MSA_FMIN_A = 0x340001B,
MSA_FMAX = 0x380001B,
MSA_MUL_Q = 0x100001C,
MSA_FCLE = 0x180001A,
MSA_FTQ = 0x280001B,
MSA_FEXDO = 0x200001B,
MSA_MULR_Q = 0x300001C,
} MSA3RFOp;
extern const HChar *showMsa3RFOp(MSA3RFOp);
typedef enum {
MSA_ANDV,
MSA_ORV,
MSA_NORV,
MSA_XORV
} MSAVECOp;
extern const HChar *showMsaVecOp(MSAVECOp);
typedef enum {
MSA_SLLI = 9,
MSA_SAT_S,
MSA_SRAI = 0x800009,
MSA_SRLI = 0x1000009,
MSA_SRARI = 0x100000A
} MSABITOp;
extern const HChar *showMsaBitOp(MSABITOp);
typedef enum {
MSA_B = 0,
MSA_H = 1,
MSA_W = 2,
MSA_D = 3,
} MSADF;
extern HChar showMsaDF(MSADF df);
typedef enum {
MSA_DFN_B = 0x00,
MSA_DFN_H = 0x20,
MSA_DFN_W = 0x30,
MSA_DFN_D = 0x38,
} MSADFNMask;
typedef enum {
MSA_F_WH = 0,
MSA_F_DW = 1,
} MSADFFlx;
extern HChar showMsaDFF(MSADFFlx df, int op);
/* ----- Instruction tags ----- */
typedef enum {
Min_LI, /* load word (32/64-bit) immediate (fake insn) */
@ -321,7 +495,16 @@ typedef enum {
Min_FpCompare, /* FP compare, generating value into int reg */
Min_FpGpMove, /* Move from/to fpr to/from gpr */
Min_MoveCond /* Move Conditional */
Min_MoveCond, /* Move Conditional */
Msa_MI10,
Msa_ELM,
Msa_3R,
Msa_2R,
Msa_VEC,
Msa_BIT,
Msa_3RF,
Msa_2RF,
} MIPSInstrTag;
/* --------- */
@ -498,6 +681,10 @@ typedef struct {
HReg dst;
MIPSAMode *src;
} Load;
struct {
HReg data;
HReg addr;
} MsaLoad;
/* 64/32/16/8 bit stores */
struct {
UChar sz; /* 1|2|4|8 */
@ -621,6 +808,58 @@ typedef struct {
HReg src;
HReg cond;
} MoveCond;
struct {
MSAMI10Op op;
UInt s10;
HReg rs;
HReg wd;
MSADF df;
} MsaMi10;
struct {
MSAELMOp op;
HReg ws;
HReg wd;
UInt dfn;
} MsaElm;
struct {
MSA2ROp op;
MSADF df;
HReg ws;
HReg wd;
} Msa2R;
struct {
MSA3ROp op;
MSADF df;
HReg wt;
HReg ws;
HReg wd;
} Msa3R;
struct {
MSAVECOp op;
HReg wt;
HReg ws;
HReg wd;
} MsaVec;
struct {
MSABITOp op;
MSADF df;
UChar ms;
HReg ws;
HReg wd;
}MsaBit;
struct {
MSA3RFOp op;
MSADFFlx df;
HReg wt;
HReg ws;
HReg wd;
} Msa3RF;
struct {
MSA2RFOp op;
MSADFFlx df;
HReg ws;
HReg wd;
} Msa2RF;
} Min;
} MIPSInstr;
@ -695,6 +934,15 @@ extern MIPSInstr *MIPSInstr_EvCheck(MIPSAMode* amCounter,
MIPSAMode* amFailAddr );
extern MIPSInstr *MIPSInstr_ProfInc( void );
extern MIPSInstr* MIPSInstr_MsaMi10(MSAMI10Op op, UInt s10, HReg rs, HReg wd, MSADF df);
extern MIPSInstr* MIPSInstr_MsaElm(MSAELMOp op, HReg ws, HReg wd, UInt dfn);
extern MIPSInstr* MIPSInstr_Msa3R(MSA3ROp op, MSADF df, HReg wd, HReg ws, HReg wt);
extern MIPSInstr* MIPSInstr_Msa2R(MSA2ROp op, MSADF df, HReg ws, HReg wd);
extern MIPSInstr* MIPSInstr_MsaVec(MSAVECOp op, HReg wt, HReg ws, HReg wd);
extern MIPSInstr* MIPSInstr_MsaBit(MSABITOp op, MSADF df, UChar ms, HReg ws, HReg wd);
extern MIPSInstr* MIPSInstr_Msa3RF(MSA3RFOp op, MSADFFlx df, HReg wd, HReg ws, HReg wt);
extern MIPSInstr* MIPSInstr_Msa2RF(MSA2RFOp op, MSADFFlx df, HReg wd, HReg ws);
extern void ppMIPSInstr(const MIPSInstr *, Bool mode64);
/* Some functions that insulate the register allocator from details
@ -754,6 +1002,7 @@ extern VexInvalRange patchProfInc_MIPS ( VexEndness endness_host,
const ULong* location_of_counter,
Bool mode64 );
#endif /* ndef __VEX_HOST_MIPS_DEFS_H */
/*---------------------------------------------------------------*/

File diff suppressed because it is too large Load Diff

View File

@ -1744,6 +1744,10 @@ static const HChar* show_hwcaps_mips32 ( UInt hwcaps )
{
/* MIPS baseline. */
if (VEX_MIPS_COMP_ID(hwcaps) == VEX_PRID_COMP_MIPS) {
/* MIPS baseline with msa. */
if (VEX_MIPS_PROC_MSA(hwcaps)) {
return "MIPS-baseline-msa";
}
/* MIPS baseline with dspr2. */
if (VEX_MIPS_PROC_DSP2(hwcaps)) {
return "MIPS-baseline-dspr2";
@ -1804,7 +1808,11 @@ static const HChar* show_hwcaps_mips64 ( UInt hwcaps )
/* MIPS64 baseline. */
if (VEX_MIPS_COMP_ID(hwcaps) == VEX_PRID_COMP_MIPS) {
return "mips64-baseline";
/* MIPS baseline with msa. */
if (VEX_MIPS_PROC_MSA(hwcaps)) {
return "MIPS64-baseline-msa";
}
return "MIPS64-baseline";
}
return "Unsupported baseline";

View File

@ -220,6 +220,7 @@ typedef
*/
#define VEX_PRID_IMP_34K 0x9500
#define VEX_PRID_IMP_74K 0x9700
#define VEX_PRID_IMP_P5600 0xa800
/*
* Instead of Company Options values, bits 31:24 will be packed with
@ -257,6 +258,11 @@ typedef
((VEX_MIPS_COMP_ID(x) == VEX_PRID_COMP_MIPS) && \
(VEX_MIPS_PROC_ID(x) == VEX_PRID_IMP_34K)))
/* Check if the processor supports MIPS MSA (SIMD)*/
#define VEX_MIPS_PROC_MSA(x) ((VEX_MIPS_COMP_ID(x) == VEX_PRID_COMP_MIPS) && \
(VEX_MIPS_PROC_ID(x) == VEX_PRID_IMP_P5600) && \
(VEX_MIPS_HOST_FP_MODE(x)))
/* These return statically allocated strings. */
extern const HChar* LibVEX_ppVexArch ( VexArch );

View File

@ -154,7 +154,45 @@ typedef
/* 492 */ UInt guest_LLaddr;
/* 496 */ UInt guest_LLdata;
/* 500 */ UInt _padding2[3];
/* 500 */ UInt _padding2;
/* MIPS32 MSA 128-bit vector registers */
/* 504 */ V128 guest_w0;
/* 520 */ V128 guest_w1;
/* 536 */ V128 guest_w2;
/* 552 */ V128 guest_w3;
/* 568 */ V128 guest_w4;
/* 584 */ V128 guest_w5;
/* 600 */ V128 guest_w6;
/* 616 */ V128 guest_w7;
/* 632 */ V128 guest_w8;
/* 648 */ V128 guest_w9;
/* 664 */ V128 guest_w10;
/* 680 */ V128 guest_w11;
/* 696 */ V128 guest_w12;
/* 712 */ V128 guest_w13;
/* 728 */ V128 guest_w14;
/* 744 */ V128 guest_w15;
/* 760 */ V128 guest_w16;
/* 776 */ V128 guest_w17;
/* 792 */ V128 guest_w18;
/* 808 */ V128 guest_w19;
/* 824 */ V128 guest_w20;
/* 840 */ V128 guest_w21;
/* 856 */ V128 guest_w22;
/* 872 */ V128 guest_w23;
/* 888 */ V128 guest_w24;
/* 904 */ V128 guest_w25;
/* 920 */ V128 guest_w26;
/* 936 */ V128 guest_w27;
/* 952 */ V128 guest_w28;
/* 968 */ V128 guest_w29;
/* 984 */ V128 guest_w30;
/* 1000 */ V128 guest_w31;
/* 1016 */ UInt guest_MSACSR;
/* 1020 */ UInt _padding3;
} VexGuestMIPS32State;
/*---------------------------------------------------------------*/
/*--- Utility functions for MIPS32 guest stuff. ---*/

View File

@ -151,7 +151,43 @@ typedef
/* 616 */ ULong guest_LLaddr;
/* 624 */ ULong guest_LLdata;
/* 632 */ ULong _padding2;
/* MIPS32 MSA 128-bit vector registers */
/* 632 */ V128 guest_w0;
/* 648 */ V128 guest_w1;
/* 664 */ V128 guest_w2;
/* 680 */ V128 guest_w3;
/* 696 */ V128 guest_w4;
/* 712 */ V128 guest_w5;
/* 728 */ V128 guest_w6;
/* 744 */ V128 guest_w7;
/* 760 */ V128 guest_w8;
/* 776 */ V128 guest_w9;
/* 792 */ V128 guest_w10;
/* 808 */ V128 guest_w11;
/* 824 */ V128 guest_w12;
/* 840 */ V128 guest_w13;
/* 856 */ V128 guest_w14;
/* 872 */ V128 guest_w15;
/* 888 */ V128 guest_w16;
/* 904 */ V128 guest_w17;
/* 920 */ V128 guest_w18;
/* 936 */ V128 guest_w19;
/* 952 */ V128 guest_w20;
/* 968 */ V128 guest_w21;
/* 984 */ V128 guest_w22;
/* 1000 */ V128 guest_w23;
/* 1016 */ V128 guest_w24;
/* 1032 */ V128 guest_w25;
/* 1048 */ V128 guest_w26;
/* 1064 */ V128 guest_w27;
/* 1080 */ V128 guest_w28;
/* 1096 */ V128 guest_w29;
/* 1112 */ V128 guest_w30;
/* 1128 */ V128 guest_w31;
/* 1144 */ UInt guest_MSACSR;
/* 1148 */ UInt _padding2;
} VexGuestMIPS64State;
/*---------------------------------------------------------------*/