Commit cd5c0095 authored by dusan.simicic's avatar dusan.simicic Committed by Commit bot

MIPS[64]: Support for MSA instructions

This patch adds support for MIPS SIMD (MSA) instructions in Assembler
and Decoder (disassembler) classes. MSA instructions are implemented for
both mips32 and mips64 architectures.

BUG=

Review-Url: https://codereview.chromium.org/2740123004
Cr-Commit-Position: refs/heads/master@{#44148}
parent fc44d57b
......@@ -596,7 +596,10 @@ CPU::CPU()
CPUInfo cpu_info;
char* cpu_model = cpu_info.ExtractField("cpu model");
has_fpu_ = HasListItem(cpu_model, "FPU");
char* ASEs = cpu_info.ExtractField("ASEs implemented");
has_msa_ = HasListItem(ASEs, "msa");
delete[] cpu_model;
delete[] ASEs;
#ifdef V8_HOST_ARCH_MIPS
is_fp64_mode_ = __detect_fp64_mode();
architecture_ = __detect_mips_arch_revision();
......
......@@ -113,6 +113,7 @@ class V8_BASE_EXPORT CPU final {
// mips features
bool is_fp64_mode() const { return is_fp64_mode_; }
bool has_msa() const { return has_msa_; }
private:
char vendor_[13];
......@@ -154,6 +155,7 @@ class V8_BASE_EXPORT CPU final {
bool has_vfp3_d32_;
bool is_fp64_mode_;
bool has_non_stop_time_stamp_counter_;
bool has_msa_;
};
} // namespace base
......
......@@ -778,6 +778,7 @@ enum CpuFeature {
MIPSr1,
MIPSr2,
MIPSr6,
MIPS_SIMD, // MSA instructions
// ARM64
ALWAYS_ALIGN_CSP,
// PPC
......
......@@ -90,6 +90,7 @@ void CpuFeatures::ProbeImpl(bool cross_compile) {
if (cpu.is_fp64_mode()) supported_ |= 1u << FP64FPU;
#elif defined(FPU_MODE_FP64)
supported_ |= 1u << FP64FPU;
if (cpu.has_msa()) supported_ |= 1u << MIPS_SIMD;
#endif
#if defined(_MIPS_ARCH_MIPS32RX)
if (cpu.architecture() == 6) {
......@@ -1167,6 +1168,127 @@ void Assembler::GenInstrJump(Opcode opcode,
BlockTrampolinePoolFor(1); // For associated delay slot.
}
// MSA instructions
void Assembler::GenInstrMsaI8(SecondaryField operation, uint32_t imm8,
MSARegister ws, MSARegister wd) {
DCHECK(IsMipsArchVariant(kMips32r6) && IsEnabled(MIPS_SIMD));
DCHECK(ws.is_valid() && wd.is_valid() && is_uint8(imm8));
Instr instr = MSA | operation | ((imm8 & kImm8Mask) << kWtShift) |
(ws.code() << kWsShift) | (wd.code() << kWdShift);
emit(instr);
}
void Assembler::GenInstrMsaI5(SecondaryField operation, SecondaryField df,
int32_t imm5, MSARegister ws, MSARegister wd) {
DCHECK(IsMipsArchVariant(kMips32r6) && IsEnabled(MIPS_SIMD));
DCHECK(ws.is_valid() && wd.is_valid());
DCHECK((operation == MAXI_S) || (operation == MINI_S) ||
(operation == CEQI) || (operation == CLTI_S) ||
(operation == CLEI_S)
? is_int5(imm5)
: is_uint5(imm5));
Instr instr = MSA | operation | df | ((imm5 & kImm5Mask) << kWtShift) |
(ws.code() << kWsShift) | (wd.code() << kWdShift);
emit(instr);
}
void Assembler::GenInstrMsaBit(SecondaryField operation, SecondaryField df,
uint32_t m, MSARegister ws, MSARegister wd) {
DCHECK(IsMipsArchVariant(kMips32r6) && IsEnabled(MIPS_SIMD));
DCHECK(ws.is_valid() && wd.is_valid() && is_valid_msa_df_m(df, m));
Instr instr = MSA | operation | df | (m << kWtShift) |
(ws.code() << kWsShift) | (wd.code() << kWdShift);
emit(instr);
}
void Assembler::GenInstrMsaI10(SecondaryField operation, SecondaryField df,
int32_t imm10, MSARegister wd) {
DCHECK(IsMipsArchVariant(kMips32r6) && IsEnabled(MIPS_SIMD));
DCHECK(wd.is_valid() && is_int10(imm10));
Instr instr = MSA | operation | df | ((imm10 & kImm10Mask) << kWsShift) |
(wd.code() << kWdShift);
emit(instr);
}
template <typename RegType>
void Assembler::GenInstrMsa3R(SecondaryField operation, SecondaryField df,
RegType t, MSARegister ws, MSARegister wd) {
DCHECK(IsMipsArchVariant(kMips32r6) && IsEnabled(MIPS_SIMD));
DCHECK(t.is_valid() && ws.is_valid() && wd.is_valid());
Instr instr = MSA | operation | df | (t.code() << kWtShift) |
(ws.code() << kWsShift) | (wd.code() << kWdShift);
emit(instr);
}
template <typename DstType, typename SrcType>
void Assembler::GenInstrMsaElm(SecondaryField operation, SecondaryField df,
uint32_t n, SrcType src, DstType dst) {
DCHECK(IsMipsArchVariant(kMips32r6) && IsEnabled(MIPS_SIMD));
DCHECK(src.is_valid() && dst.is_valid() && is_valid_msa_df_n(df, n));
Instr instr = MSA | operation | df | (n << kWtShift) |
(src.code() << kWsShift) | (dst.code() << kWdShift) |
MSA_ELM_MINOR;
emit(instr);
}
void Assembler::GenInstrMsa3RF(SecondaryField operation, uint32_t df,
MSARegister wt, MSARegister ws, MSARegister wd) {
DCHECK(IsMipsArchVariant(kMips32r6) && IsEnabled(MIPS_SIMD));
DCHECK(wt.is_valid() && ws.is_valid() && wd.is_valid());
DCHECK(df < 2);
Instr instr = MSA | operation | (df << 21) | (wt.code() << kWtShift) |
(ws.code() << kWsShift) | (wd.code() << kWdShift);
emit(instr);
}
void Assembler::GenInstrMsaVec(SecondaryField operation, MSARegister wt,
MSARegister ws, MSARegister wd) {
DCHECK(IsMipsArchVariant(kMips32r6) && IsEnabled(MIPS_SIMD));
DCHECK(wt.is_valid() && ws.is_valid() && wd.is_valid());
Instr instr = MSA | operation | (wt.code() << kWtShift) |
(ws.code() << kWsShift) | (wd.code() << kWdShift) |
MSA_VEC_2R_2RF_MINOR;
emit(instr);
}
void Assembler::GenInstrMsaMI10(SecondaryField operation, int32_t s10,
Register rs, MSARegister wd) {
DCHECK(IsMipsArchVariant(kMips32r6) && IsEnabled(MIPS_SIMD));
DCHECK(rs.is_valid() && wd.is_valid() && is_int10(s10));
Instr instr = MSA | operation | ((s10 & kImm10Mask) << kWtShift) |
(rs.code() << kWsShift) | (wd.code() << kWdShift);
emit(instr);
}
void Assembler::GenInstrMsa2R(SecondaryField operation, SecondaryField df,
MSARegister ws, MSARegister wd) {
DCHECK(IsMipsArchVariant(kMips32r6) && IsEnabled(MIPS_SIMD));
DCHECK(ws.is_valid() && wd.is_valid());
Instr instr = MSA | MSA_2R_FORMAT | operation | df | (ws.code() << kWsShift) |
(wd.code() << kWdShift) | MSA_VEC_2R_2RF_MINOR;
emit(instr);
}
void Assembler::GenInstrMsa2RF(SecondaryField operation, SecondaryField df,
MSARegister ws, MSARegister wd) {
DCHECK(IsMipsArchVariant(kMips32r6) && IsEnabled(MIPS_SIMD));
DCHECK(ws.is_valid() && wd.is_valid());
Instr instr = MSA | MSA_2RF_FORMAT | operation | df |
(ws.code() << kWsShift) | (wd.code() << kWdShift) |
MSA_VEC_2R_2RF_MINOR;
emit(instr);
}
void Assembler::GenInstrMsaBranch(SecondaryField operation, MSARegister wt,
int32_t offset16) {
DCHECK(IsMipsArchVariant(kMips32r6) && IsEnabled(MIPS_SIMD));
DCHECK(wt.is_valid() && is_int16(offset16));
BlockTrampolinePoolScope block_trampoline_pool(this);
Instr instr =
COP1 | operation | (wt.code() << kWtShift) | (offset16 & kImm16Mask);
emit(instr);
BlockTrampolinePoolFor(1); // For associated delay slot.
}
// Returns the next free trampoline entry.
int32_t Assembler::get_trampoline_entry(int32_t pos) {
......@@ -2869,6 +2991,505 @@ void Assembler::bc1t(int16_t offset, uint16_t cc) {
emit(instr);
}
// ---------- MSA instructions ------------
#define MSA_BRANCH_LIST(V) \
V(bz_v, BZ_V) \
V(bz_b, BZ_B) \
V(bz_h, BZ_H) \
V(bz_w, BZ_W) \
V(bz_d, BZ_D) \
V(bnz_v, BNZ_V) \
V(bnz_b, BNZ_B) \
V(bnz_h, BNZ_H) \
V(bnz_w, BNZ_W) \
V(bnz_d, BNZ_D)
#define MSA_BRANCH(name, opcode) \
void Assembler::name(MSARegister wt, int16_t offset) { \
GenInstrMsaBranch(opcode, wt, offset); \
}
MSA_BRANCH_LIST(MSA_BRANCH)
#undef MSA_BRANCH
#undef MSA_BRANCH_LIST
#define MSA_LD_ST_LIST(V) \
V(ld_b, LD_B) \
V(ld_h, LD_H) \
V(ld_w, LD_W) \
V(ld_d, LD_D) \
V(st_b, ST_B) \
V(st_h, ST_H) \
V(st_w, ST_W) \
V(st_d, ST_D)
#define MSA_LD_ST(name, opcode) \
void Assembler::name(MSARegister wd, const MemOperand& rs) { \
if (is_int10(rs.offset())) { \
GenInstrMsaMI10(opcode, rs.offset(), rs.rm(), wd); \
} else { \
LoadRegPlusOffsetToAt(rs); \
GenInstrMsaMI10(opcode, 0, at, wd); \
} \
}
MSA_LD_ST_LIST(MSA_LD_ST)
#undef MSA_LD_ST
#undef MSA_BRANCH_LIST
#define MSA_I10_LIST(V) \
V(ldi_b, I5_DF_b) \
V(ldi_h, I5_DF_h) \
V(ldi_w, I5_DF_w) \
V(ldi_d, I5_DF_d)
#define MSA_I10(name, format) \
void Assembler::name(MSARegister wd, int32_t imm10) { \
GenInstrMsaI10(LDI, format, imm10, wd); \
}
MSA_I10_LIST(MSA_I10)
#undef MSA_I10
#undef MSA_I10_LIST
#define MSA_I5_LIST(V) \
V(addvi, ADDVI) \
V(subvi, SUBVI) \
V(maxi_s, MAXI_S) \
V(maxi_u, MAXI_U) \
V(mini_s, MINI_S) \
V(mini_u, MINI_U) \
V(ceqi, CEQI) \
V(clti_s, CLTI_S) \
V(clti_u, CLTI_U) \
V(clei_s, CLEI_S) \
V(clei_u, CLEI_U)
#define MSA_I5_FORMAT(name, opcode, format) \
void Assembler::name##_##format(MSARegister wd, MSARegister ws, \
uint32_t imm5) { \
GenInstrMsaI5(opcode, I5_DF_##format, imm5, ws, wd); \
}
#define MSA_I5(name, opcode) \
MSA_I5_FORMAT(name, opcode, b) \
MSA_I5_FORMAT(name, opcode, h) \
MSA_I5_FORMAT(name, opcode, w) \
MSA_I5_FORMAT(name, opcode, d)
MSA_I5_LIST(MSA_I5)
#undef MSA_I5
#undef MSA_I5_FORMAT
#undef MSA_I5_LIST
#define MSA_I8_LIST(V) \
V(andi_b, ANDI_B) \
V(ori_b, ORI_B) \
V(nori_b, NORI_B) \
V(xori_b, XORI_B) \
V(bmnzi_b, BMNZI_B) \
V(bmzi_b, BMZI_B) \
V(bseli_b, BSELI_B) \
V(shf_b, SHF_B) \
V(shf_h, SHF_H) \
V(shf_w, SHF_W)
#define MSA_I8(name, opcode) \
void Assembler::name(MSARegister wd, MSARegister ws, uint32_t imm8) { \
GenInstrMsaI8(opcode, imm8, ws, wd); \
}
MSA_I8_LIST(MSA_I8)
#undef MSA_I8
#undef MSA_I8_LIST
#define MSA_VEC_LIST(V) \
V(and_v, AND_V) \
V(or_v, OR_V) \
V(nor_v, NOR_V) \
V(xor_v, XOR_V) \
V(bmnz_v, BMNZ_V) \
V(bmz_v, BMZ_V) \
V(bsel_v, BSEL_V)
#define MSA_VEC(name, opcode) \
void Assembler::name(MSARegister wd, MSARegister ws, MSARegister wt) { \
GenInstrMsaVec(opcode, wt, ws, wd); \
}
MSA_VEC_LIST(MSA_VEC)
#undef MSA_VEC
#undef MSA_VEC_LIST
#define MSA_2R_LIST(V) \
V(pcnt, PCNT) \
V(nloc, NLOC) \
V(nlzc, NLZC)
#define MSA_2R_FORMAT(name, opcode, format) \
void Assembler::name##_##format(MSARegister wd, MSARegister ws) { \
GenInstrMsa2R(opcode, MSA_2R_DF_##format, ws, wd); \
}
#define MSA_2R(name, opcode) \
MSA_2R_FORMAT(name, opcode, b) \
MSA_2R_FORMAT(name, opcode, h) \
MSA_2R_FORMAT(name, opcode, w) \
MSA_2R_FORMAT(name, opcode, d)
MSA_2R_LIST(MSA_2R)
#undef MSA_2R
#undef MSA_2R_FORMAT
#undef MSA_2R_LIST
#define MSA_FILL(format) \
void Assembler::fill_##format(MSARegister wd, Register rs) { \
DCHECK(IsMipsArchVariant(kMips32r6) && IsEnabled(MIPS_SIMD)); \
DCHECK(rs.is_valid() && wd.is_valid()); \
Instr instr = MSA | MSA_2R_FORMAT | FILL | MSA_2R_DF_##format | \
(rs.code() << kWsShift) | (wd.code() << kWdShift) | \
MSA_VEC_2R_2RF_MINOR; \
emit(instr); \
}
MSA_FILL(b)
MSA_FILL(h)
MSA_FILL(w)
#undef MSA_FILL
#define MSA_2RF_LIST(V) \
V(fclass, FCLASS) \
V(ftrunc_s, FTRUNC_S) \
V(ftrunc_u, FTRUNC_U) \
V(fsqrt, FSQRT) \
V(frsqrt, FRSQRT) \
V(frcp, FRCP) \
V(frint, FRINT) \
V(flog2, FLOG2) \
V(fexupl, FEXUPL) \
V(fexupr, FEXUPR) \
V(ffql, FFQL) \
V(ffqr, FFQR) \
V(ftint_s, FTINT_S) \
V(ftint_u, FTINT_U) \
V(ffint_s, FFINT_S) \
V(ffint_u, FFINT_U)
#define MSA_2RF_FORMAT(name, opcode, format) \
void Assembler::name##_##format(MSARegister wd, MSARegister ws) { \
GenInstrMsa2RF(opcode, MSA_2RF_DF_##format, ws, wd); \
}
#define MSA_2RF(name, opcode) \
MSA_2RF_FORMAT(name, opcode, w) \
MSA_2RF_FORMAT(name, opcode, d)
MSA_2RF_LIST(MSA_2RF)
#undef MSA_2RF
#undef MSA_2RF_FORMAT
#undef MSA_2RF_LIST
#define MSA_3R_LIST(V) \
V(sll, SLL_MSA) \
V(sra, SRA_MSA) \
V(srl, SRL_MSA) \
V(bclr, BCLR) \
V(bset, BSET) \
V(bneg, BNEG) \
V(binsl, BINSL) \
V(binsr, BINSR) \
V(addv, ADDV) \
V(subv, SUBV) \
V(max_s, MAX_S) \
V(max_u, MAX_U) \
V(min_s, MIN_S) \
V(min_u, MIN_U) \
V(max_a, MAX_A) \
V(min_a, MIN_A) \
V(ceq, CEQ) \
V(clt_s, CLT_S) \
V(clt_u, CLT_U) \
V(cle_s, CLE_S) \
V(cle_u, CLE_U) \
V(add_a, ADD_A) \
V(adds_a, ADDS_A) \
V(adds_s, ADDS_S) \
V(adds_u, ADDS_U) \
V(ave_s, AVE_S) \
V(ave_u, AVE_U) \
V(aver_s, AVER_S) \
V(aver_u, AVER_U) \
V(subs_s, SUBS_S) \
V(subs_u, SUBS_U) \
V(subsus_u, SUBSUS_U) \
V(subsuu_s, SUBSUU_S) \
V(asub_s, ASUB_S) \
V(asub_u, ASUB_U) \
V(mulv, MULV) \
V(maddv, MADDV) \
V(msubv, MSUBV) \
V(div_s, DIV_S_MSA) \
V(div_u, DIV_U) \
V(mod_s, MOD_S) \
V(mod_u, MOD_U) \
V(dotp_s, DOTP_S) \
V(dotp_u, DOTP_U) \
V(dpadd_s, DPADD_S) \
V(dpadd_u, DPADD_U) \
V(dpsub_s, DPSUB_S) \
V(dpsub_u, DPSUB_U) \
V(pckev, PCKEV) \
V(pckod, PCKOD) \
V(ilvl, ILVL) \
V(ilvr, ILVR) \
V(ilvev, ILVEV) \
V(ilvod, ILVOD) \
V(vshf, VSHF) \
V(srar, SRAR) \
V(srlr, SRLR) \
V(hadd_s, HADD_S) \
V(hadd_u, HADD_U) \
V(hsub_s, HSUB_S) \
V(hsub_u, HSUB_U)
#define MSA_3R_FORMAT(name, opcode, format) \
void Assembler::name##_##format(MSARegister wd, MSARegister ws, \
MSARegister wt) { \
GenInstrMsa3R<MSARegister>(opcode, MSA_3R_DF_##format, wt, ws, wd); \
}
#define MSA_3R_FORMAT_SLD_SPLAT(name, opcode, format) \
void Assembler::name##_##format(MSARegister wd, MSARegister ws, \
Register rt) { \
GenInstrMsa3R<Register>(opcode, MSA_3R_DF_##format, rt, ws, wd); \
}
#define MSA_3R(name, opcode) \
MSA_3R_FORMAT(name, opcode, b) \
MSA_3R_FORMAT(name, opcode, h) \
MSA_3R_FORMAT(name, opcode, w) \
MSA_3R_FORMAT(name, opcode, d)
#define MSA_3R_SLD_SPLAT(name, opcode) \
MSA_3R_FORMAT_SLD_SPLAT(name, opcode, b) \
MSA_3R_FORMAT_SLD_SPLAT(name, opcode, h) \
MSA_3R_FORMAT_SLD_SPLAT(name, opcode, w) \
MSA_3R_FORMAT_SLD_SPLAT(name, opcode, d)
MSA_3R_LIST(MSA_3R)
MSA_3R_SLD_SPLAT(sld, SLD)
MSA_3R_SLD_SPLAT(splat, SPLAT)
#undef MSA_3R
#undef MSA_3R_FORMAT
#undef MSA_3R_FORMAT_SLD_SPLAT
#undef MSA_3R_SLD_SPLAT
#undef MSA_3R_LIST
#define MSA_3RF_LIST1(V) \
V(fcaf, FCAF) \
V(fcun, FCUN) \
V(fceq, FCEQ) \
V(fcueq, FCUEQ) \
V(fclt, FCLT) \
V(fcult, FCULT) \
V(fcle, FCLE) \
V(fcule, FCULE) \
V(fsaf, FSAF) \
V(fsun, FSUN) \
V(fseq, FSEQ) \
V(fsueq, FSUEQ) \
V(fslt, FSLT) \
V(fsult, FSULT) \
V(fsle, FSLE) \
V(fsule, FSULE) \
V(fadd, FADD) \
V(fsub, FSUB) \
V(fmul, FMUL) \
V(fdiv, FDIV) \
V(fmadd, FMADD) \
V(fmsub, FMSUB) \
V(fexp2, FEXP2) \
V(fmin, FMIN) \
V(fmin_a, FMIN_A) \
V(fmax, FMAX) \
V(fmax_a, FMAX_A) \
V(fcor, FCOR) \
V(fcune, FCUNE) \
V(fcne, FCNE) \
V(fsor, FSOR) \
V(fsune, FSUNE) \
V(fsne, FSNE)
#define MSA_3RF_LIST2(V) \
V(fexdo, FEXDO) \
V(ftq, FTQ) \
V(mul_q, MUL_Q) \
V(madd_q, MADD_Q) \
V(msub_q, MSUB_Q) \
V(mulr_q, MULR_Q) \
V(maddr_q, MADDR_Q) \
V(msubr_q, MSUBR_Q)
#define MSA_3RF_FORMAT(name, opcode, df, df_c) \
void Assembler::name##_##df(MSARegister wd, MSARegister ws, \
MSARegister wt) { \
GenInstrMsa3RF(opcode, df_c, wt, ws, wd); \
}
#define MSA_3RF_1(name, opcode) \
MSA_3RF_FORMAT(name, opcode, w, 0) \
MSA_3RF_FORMAT(name, opcode, d, 1)
#define MSA_3RF_2(name, opcode) \
MSA_3RF_FORMAT(name, opcode, h, 0) \
MSA_3RF_FORMAT(name, opcode, w, 1)
MSA_3RF_LIST1(MSA_3RF_1)
MSA_3RF_LIST2(MSA_3RF_2)
#undef MSA_3RF_1
#undef MSA_3RF_2
#undef MSA_3RF_FORMAT
#undef MSA_3RF_LIST1
#undef MSA_3RF_LIST2
void Assembler::sldi_b(MSARegister wd, MSARegister ws, uint32_t n) {
GenInstrMsaElm<MSARegister, MSARegister>(SLDI, ELM_DF_B, n, ws, wd);
}
void Assembler::sldi_h(MSARegister wd, MSARegister ws, uint32_t n) {
GenInstrMsaElm<MSARegister, MSARegister>(SLDI, ELM_DF_H, n, ws, wd);
}
void Assembler::sldi_w(MSARegister wd, MSARegister ws, uint32_t n) {
GenInstrMsaElm<MSARegister, MSARegister>(SLDI, ELM_DF_W, n, ws, wd);
}
void Assembler::sldi_d(MSARegister wd, MSARegister ws, uint32_t n) {
GenInstrMsaElm<MSARegister, MSARegister>(SLDI, ELM_DF_D, n, ws, wd);
}
void Assembler::splati_b(MSARegister wd, MSARegister ws, uint32_t n) {
GenInstrMsaElm<MSARegister, MSARegister>(SPLATI, ELM_DF_B, n, ws, wd);
}
void Assembler::splati_h(MSARegister wd, MSARegister ws, uint32_t n) {
GenInstrMsaElm<MSARegister, MSARegister>(SPLATI, ELM_DF_H, n, ws, wd);
}
void Assembler::splati_w(MSARegister wd, MSARegister ws, uint32_t n) {
GenInstrMsaElm<MSARegister, MSARegister>(SPLATI, ELM_DF_W, n, ws, wd);
}
void Assembler::splati_d(MSARegister wd, MSARegister ws, uint32_t n) {
GenInstrMsaElm<MSARegister, MSARegister>(SPLATI, ELM_DF_D, n, ws, wd);
}
void Assembler::copy_s_b(Register rd, MSARegister ws, uint32_t n) {
GenInstrMsaElm<Register, MSARegister>(COPY_S, ELM_DF_B, n, ws, rd);
}
void Assembler::copy_s_h(Register rd, MSARegister ws, uint32_t n) {
GenInstrMsaElm<Register, MSARegister>(COPY_S, ELM_DF_H, n, ws, rd);
}
void Assembler::copy_s_w(Register rd, MSARegister ws, uint32_t n) {
GenInstrMsaElm<Register, MSARegister>(COPY_S, ELM_DF_W, n, ws, rd);
}
void Assembler::copy_u_b(Register rd, MSARegister ws, uint32_t n) {
GenInstrMsaElm<Register, MSARegister>(COPY_U, ELM_DF_B, n, ws, rd);
}
void Assembler::copy_u_h(Register rd, MSARegister ws, uint32_t n) {
GenInstrMsaElm<Register, MSARegister>(COPY_U, ELM_DF_H, n, ws, rd);
}
void Assembler::copy_u_w(Register rd, MSARegister ws, uint32_t n) {
GenInstrMsaElm<Register, MSARegister>(COPY_U, ELM_DF_W, n, ws, rd);
}
void Assembler::insert_b(MSARegister wd, uint32_t n, Register rs) {
GenInstrMsaElm<MSARegister, Register>(INSERT, ELM_DF_B, n, rs, wd);
}
void Assembler::insert_h(MSARegister wd, uint32_t n, Register rs) {
GenInstrMsaElm<MSARegister, Register>(INSERT, ELM_DF_H, n, rs, wd);
}
void Assembler::insert_w(MSARegister wd, uint32_t n, Register rs) {
GenInstrMsaElm<MSARegister, Register>(INSERT, ELM_DF_W, n, rs, wd);
}
void Assembler::insve_b(MSARegister wd, uint32_t n, MSARegister ws) {
GenInstrMsaElm<MSARegister, MSARegister>(INSVE, ELM_DF_B, n, ws, wd);
}
void Assembler::insve_h(MSARegister wd, uint32_t n, MSARegister ws) {
GenInstrMsaElm<MSARegister, MSARegister>(INSVE, ELM_DF_H, n, ws, wd);
}
void Assembler::insve_w(MSARegister wd, uint32_t n, MSARegister ws) {
GenInstrMsaElm<MSARegister, MSARegister>(INSVE, ELM_DF_W, n, ws, wd);
}
void Assembler::insve_d(MSARegister wd, uint32_t n, MSARegister ws) {
GenInstrMsaElm<MSARegister, MSARegister>(INSVE, ELM_DF_D, n, ws, wd);
}
void Assembler::move_v(MSARegister wd, MSARegister ws) {
DCHECK(IsMipsArchVariant(kMips32r6) && IsEnabled(MIPS_SIMD));
DCHECK(ws.is_valid() && wd.is_valid());
Instr instr = MSA | MOVE_V | (ws.code() << kWsShift) |
(wd.code() << kWdShift) | MSA_ELM_MINOR;
emit(instr);
}
void Assembler::ctcmsa(MSAControlRegister cd, Register rs) {
DCHECK(IsMipsArchVariant(kMips32r6) && IsEnabled(MIPS_SIMD));
DCHECK(cd.is_valid() && rs.is_valid());
Instr instr = MSA | CTCMSA | (rs.code() << kWsShift) |
(cd.code() << kWdShift) | MSA_ELM_MINOR;
emit(instr);
}
void Assembler::cfcmsa(Register rd, MSAControlRegister cs) {
DCHECK(IsMipsArchVariant(kMips32r6) && IsEnabled(MIPS_SIMD));
DCHECK(rd.is_valid() && cs.is_valid());
Instr instr = MSA | CFCMSA | (cs.code() << kWsShift) |
(rd.code() << kWdShift) | MSA_ELM_MINOR;
emit(instr);
}
#define MSA_BIT_LIST(V) \
V(slli, SLLI) \
V(srai, SRAI) \
V(srli, SRLI) \
V(bclri, BCLRI) \
V(bseti, BSETI) \
V(bnegi, BNEGI) \
V(binsli, BINSLI) \
V(binsri, BINSRI) \
V(sat_s, SAT_S) \
V(sat_u, SAT_U) \
V(srari, SRARI) \
V(srlri, SRLRI)
#define MSA_BIT_FORMAT(name, opcode, format) \
void Assembler::name##_##format(MSARegister wd, MSARegister ws, \
uint32_t m) { \
GenInstrMsaBit(opcode, BIT_DF_##format, m, ws, wd); \
}
#define MSA_BIT(name, opcode) \
MSA_BIT_FORMAT(name, opcode, b) \
MSA_BIT_FORMAT(name, opcode, h) \
MSA_BIT_FORMAT(name, opcode, w) \
MSA_BIT_FORMAT(name, opcode, d)
MSA_BIT_LIST(MSA_BIT)
#undef MSA_BIT
#undef MSA_BIT_FORMAT
#undef MSA_BIT_LIST
int Assembler::RelocateInternalReference(RelocInfo::Mode rmode, byte* pc,
intptr_t pc_delta) {
......
......@@ -64,7 +64,11 @@ namespace internal {
V(f24) V(f25) V(f26) V(f27) V(f28) V(f29) V(f30) V(f31)
#define FLOAT_REGISTERS DOUBLE_REGISTERS
#define SIMD128_REGISTERS DOUBLE_REGISTERS
#define SIMD128_REGISTERS(V) \
V(w0) V(w1) V(w2) V(w3) V(w4) V(w5) V(w6) V(w7) \
V(w8) V(w9) V(w10) V(w11) V(w12) V(w13) V(w14) V(w15) \
V(w16) V(w17) V(w18) V(w19) V(w20) V(w21) V(w22) V(w23) \
V(w24) V(w25) V(w26) V(w27) V(w28) V(w29) V(w30) V(w31)
#define ALLOCATABLE_DOUBLE_REGISTERS(V) \
V(f0) V(f2) V(f4) V(f6) V(f8) V(f10) V(f12) V(f14) \
......@@ -162,7 +166,7 @@ struct FPURegister {
DOUBLE_REGISTERS(REGISTER_CODE)
#undef REGISTER_CODE
kAfterLast,
kCode_no_reg = -1
kCode_no_reg = kInvalidFPURegister
};
static constexpr int kMaxNumRegisters = Code::kAfterLast;
......@@ -213,6 +217,44 @@ struct FPURegister {
int reg_code;
};
// MIPS SIMD (MSA) register
struct MSARegister {
enum Code {
#define REGISTER_CODE(R) kCode_##R,
SIMD128_REGISTERS(REGISTER_CODE)
#undef REGISTER_CODE
kAfterLast,
kCode_no_reg = kInvalidMSARegister
};
static const int kMaxNumRegisters = Code::kAfterLast;
inline static int NumRegisters();
bool is_valid() const { return 0 <= reg_code && reg_code < kMaxNumRegisters; }
bool is(MSARegister reg) const { return reg_code == reg.reg_code; }
int code() const {
DCHECK(is_valid());
return reg_code;
}
int bit() const {
DCHECK(is_valid());
return 1 << reg_code;
}
static MSARegister from_code(int code) {
MSARegister r = {code};
return r;
}
void setcode(int f) {
reg_code = f;
DCHECK(is_valid());
}
// Unfortunately we can't make this private in a struct.
int reg_code;
};
// A few double registers are reserved: one as a scratch register and one to
// hold 0.0.
// f28: 0.0
......@@ -231,10 +273,7 @@ typedef FPURegister FloatRegister;
typedef FPURegister DoubleRegister;
// TODO(mips) Define SIMD registers.
typedef FPURegister Simd128Register;
constexpr DoubleRegister no_freg = {-1};
constexpr DoubleRegister no_freg = {kInvalidFPURegister};
constexpr DoubleRegister f0 = {0}; // Return value in hard float mode.
constexpr DoubleRegister f1 = {1};
......@@ -269,6 +308,44 @@ constexpr DoubleRegister f29 = {29};
constexpr DoubleRegister f30 = {30};
constexpr DoubleRegister f31 = {31};
// SIMD registers.
typedef MSARegister Simd128Register;
const Simd128Register no_msareg = {kInvalidMSARegister};
constexpr Simd128Register w0 = {0};
constexpr Simd128Register w1 = {1};
constexpr Simd128Register w2 = {2};
constexpr Simd128Register w3 = {3};
constexpr Simd128Register w4 = {4};
constexpr Simd128Register w5 = {5};
constexpr Simd128Register w6 = {6};
constexpr Simd128Register w7 = {7};
constexpr Simd128Register w8 = {8};
constexpr Simd128Register w9 = {9};
constexpr Simd128Register w10 = {10};
constexpr Simd128Register w11 = {11};
constexpr Simd128Register w12 = {12};
constexpr Simd128Register w13 = {13};
constexpr Simd128Register w14 = {14};
constexpr Simd128Register w15 = {15};
constexpr Simd128Register w16 = {16};
constexpr Simd128Register w17 = {17};
constexpr Simd128Register w18 = {18};
constexpr Simd128Register w19 = {19};
constexpr Simd128Register w20 = {20};
constexpr Simd128Register w21 = {21};
constexpr Simd128Register w22 = {22};
constexpr Simd128Register w23 = {23};
constexpr Simd128Register w24 = {24};
constexpr Simd128Register w25 = {25};
constexpr Simd128Register w26 = {26};
constexpr Simd128Register w27 = {27};
constexpr Simd128Register w28 = {28};
constexpr Simd128Register w29 = {29};
constexpr Simd128Register w30 = {30};
constexpr Simd128Register w31 = {31};
// Register aliases.
// cp is assumed to be a callee saved register.
constexpr Register kRootRegister = s6;
......@@ -304,6 +381,32 @@ struct FPUControlRegister {
constexpr FPUControlRegister no_fpucreg = {kInvalidFPUControlRegister};
constexpr FPUControlRegister FCSR = {kFCSRRegister};
// MSA control registers
struct MSAControlRegister {
bool is_valid() const {
return (reg_code == kMSAIRRegister) || (reg_code == kMSACSRRegister);
}
bool is(MSAControlRegister creg) const { return reg_code == creg.reg_code; }
int code() const {
DCHECK(is_valid());
return reg_code;
}
int bit() const {
DCHECK(is_valid());
return 1 << reg_code;
}
void setcode(int f) {
reg_code = f;
DCHECK(is_valid());
}
// Unfortunately we can't make this private in a struct.
int reg_code;
};
constexpr MSAControlRegister no_msacreg = {kInvalidMSAControlRegister};
constexpr MSAControlRegister MSAIR = {kMSAIRRegister};
constexpr MSAControlRegister MSACSR = {kMSACSRRegister};
// -----------------------------------------------------------------------------
// Machine instruction Operands.
......@@ -981,6 +1084,563 @@ class Assembler : public AssemblerBase {
}
void fcmp(FPURegister src1, const double src2, FPUCondition cond);
// MSA instructions
void bz_v(MSARegister wt, int16_t offset);
void bz_b(MSARegister wt, int16_t offset);
void bz_h(MSARegister wt, int16_t offset);
void bz_w(MSARegister wt, int16_t offset);
void bz_d(MSARegister wt, int16_t offset);
void bnz_v(MSARegister wt, int16_t offset);
void bnz_b(MSARegister wt, int16_t offset);
void bnz_h(MSARegister wt, int16_t offset);
void bnz_w(MSARegister wt, int16_t offset);
void bnz_d(MSARegister wt, int16_t offset);
void ld_b(MSARegister wd, const MemOperand& rs);
void ld_h(MSARegister wd, const MemOperand& rs);
void ld_w(MSARegister wd, const MemOperand& rs);
void ld_d(MSARegister wd, const MemOperand& rs);
void st_b(MSARegister wd, const MemOperand& rs);
void st_h(MSARegister wd, const MemOperand& rs);
void st_w(MSARegister wd, const MemOperand& rs);
void st_d(MSARegister wd, const MemOperand& rs);
void ldi_b(MSARegister wd, int32_t imm10);
void ldi_h(MSARegister wd, int32_t imm10);
void ldi_w(MSARegister wd, int32_t imm10);
void ldi_d(MSARegister wd, int32_t imm10);
void addvi_b(MSARegister wd, MSARegister ws, uint32_t imm5);
void addvi_h(MSARegister wd, MSARegister ws, uint32_t imm5);
void addvi_w(MSARegister wd, MSARegister ws, uint32_t imm5);
void addvi_d(MSARegister wd, MSARegister ws, uint32_t imm5);
void subvi_b(MSARegister wd, MSARegister ws, uint32_t imm5);
void subvi_h(MSARegister wd, MSARegister ws, uint32_t imm5);
void subvi_w(MSARegister wd, MSARegister ws, uint32_t imm5);
void subvi_d(MSARegister wd, MSARegister ws, uint32_t imm5);
void maxi_s_b(MSARegister wd, MSARegister ws, uint32_t imm5);
void maxi_s_h(MSARegister wd, MSARegister ws, uint32_t imm5);
void maxi_s_w(MSARegister wd, MSARegister ws, uint32_t imm5);
void maxi_s_d(MSARegister wd, MSARegister ws, uint32_t imm5);
void maxi_u_b(MSARegister wd, MSARegister ws, uint32_t imm5);
void maxi_u_h(MSARegister wd, MSARegister ws, uint32_t imm5);
void maxi_u_w(MSARegister wd, MSARegister ws, uint32_t imm5);
void maxi_u_d(MSARegister wd, MSARegister ws, uint32_t imm5);
void mini_s_b(MSARegister wd, MSARegister ws, uint32_t imm5);
void mini_s_h(MSARegister wd, MSARegister ws, uint32_t imm5);
void mini_s_w(MSARegister wd, MSARegister ws, uint32_t imm5);
void mini_s_d(MSARegister wd, MSARegister ws, uint32_t imm5);
void mini_u_b(MSARegister wd, MSARegister ws, uint32_t imm5);
void mini_u_h(MSARegister wd, MSARegister ws, uint32_t imm5);
void mini_u_w(MSARegister wd, MSARegister ws, uint32_t imm5);
void mini_u_d(MSARegister wd, MSARegister ws, uint32_t imm5);
void ceqi_b(MSARegister wd, MSARegister ws, uint32_t imm5);
void ceqi_h(MSARegister wd, MSARegister ws, uint32_t imm5);
void ceqi_w(MSARegister wd, MSARegister ws, uint32_t imm5);
void ceqi_d(MSARegister wd, MSARegister ws, uint32_t imm5);
void clti_s_b(MSARegister wd, MSARegister ws, uint32_t imm5);
void clti_s_h(MSARegister wd, MSARegister ws, uint32_t imm5);
void clti_s_w(MSARegister wd, MSARegister ws, uint32_t imm5);
void clti_s_d(MSARegister wd, MSARegister ws, uint32_t imm5);
void clti_u_b(MSARegister wd, MSARegister ws, uint32_t imm5);
void clti_u_h(MSARegister wd, MSARegister ws, uint32_t imm5);
void clti_u_w(MSARegister wd, MSARegister ws, uint32_t imm5);
void clti_u_d(MSARegister wd, MSARegister ws, uint32_t imm5);
void clei_s_b(MSARegister wd, MSARegister ws, uint32_t imm5);
void clei_s_h(MSARegister wd, MSARegister ws, uint32_t imm5);
void clei_s_w(MSARegister wd, MSARegister ws, uint32_t imm5);
void clei_s_d(MSARegister wd, MSARegister ws, uint32_t imm5);
void clei_u_b(MSARegister wd, MSARegister ws, uint32_t imm5);
void clei_u_h(MSARegister wd, MSARegister ws, uint32_t imm5);
void clei_u_w(MSARegister wd, MSARegister ws, uint32_t imm5);
void clei_u_d(MSARegister wd, MSARegister ws, uint32_t imm5);
void andi_b(MSARegister wd, MSARegister ws, uint32_t imm8);
void ori_b(MSARegister wd, MSARegister ws, uint32_t imm8);
void nori_b(MSARegister wd, MSARegister ws, uint32_t imm8);
void xori_b(MSARegister wd, MSARegister ws, uint32_t imm8);
void bmnzi_b(MSARegister wd, MSARegister ws, uint32_t imm8);
void bmzi_b(MSARegister wd, MSARegister ws, uint32_t imm8);
void bseli_b(MSARegister wd, MSARegister ws, uint32_t imm8);
void shf_b(MSARegister wd, MSARegister ws, uint32_t imm8);
void shf_h(MSARegister wd, MSARegister ws, uint32_t imm8);
void shf_w(MSARegister wd, MSARegister ws, uint32_t imm8);
void and_v(MSARegister wd, MSARegister ws, MSARegister wt);
void or_v(MSARegister wd, MSARegister ws, MSARegister wt);
void nor_v(MSARegister wd, MSARegister ws, MSARegister wt);
void xor_v(MSARegister wd, MSARegister ws, MSARegister wt);
void bmnz_v(MSARegister wd, MSARegister ws, MSARegister wt);
void bmz_v(MSARegister wd, MSARegister ws, MSARegister wt);
void bsel_v(MSARegister wd, MSARegister ws, MSARegister wt);
void fill_b(MSARegister wd, Register rs);
void fill_h(MSARegister wd, Register rs);
void fill_w(MSARegister wd, Register rs);
void pcnt_b(MSARegister wd, MSARegister ws);
void pcnt_h(MSARegister wd, MSARegister ws);
void pcnt_w(MSARegister wd, MSARegister ws);
void pcnt_d(MSARegister wd, MSARegister ws);
void nloc_b(MSARegister wd, MSARegister ws);
void nloc_h(MSARegister wd, MSARegister ws);
void nloc_w(MSARegister wd, MSARegister ws);
void nloc_d(MSARegister wd, MSARegister ws);
void nlzc_b(MSARegister wd, MSARegister ws);
void nlzc_h(MSARegister wd, MSARegister ws);
void nlzc_w(MSARegister wd, MSARegister ws);
void nlzc_d(MSARegister wd, MSARegister ws);
void fclass_w(MSARegister wd, MSARegister ws);
void fclass_d(MSARegister wd, MSARegister ws);
void ftrunc_s_w(MSARegister wd, MSARegister ws);
void ftrunc_s_d(MSARegister wd, MSARegister ws);
void ftrunc_u_w(MSARegister wd, MSARegister ws);
void ftrunc_u_d(MSARegister wd, MSARegister ws);
void fsqrt_w(MSARegister wd, MSARegister ws);
void fsqrt_d(MSARegister wd, MSARegister ws);
void frsqrt_w(MSARegister wd, MSARegister ws);
void frsqrt_d(MSARegister wd, MSARegister ws);
void frcp_w(MSARegister wd, MSARegister ws);
void frcp_d(MSARegister wd, MSARegister ws);
void frint_w(MSARegister wd, MSARegister ws);
void frint_d(MSARegister wd, MSARegister ws);
void flog2_w(MSARegister wd, MSARegister ws);
void flog2_d(MSARegister wd, MSARegister ws);
void fexupl_w(MSARegister wd, MSARegister ws);
void fexupl_d(MSARegister wd, MSARegister ws);
void fexupr_w(MSARegister wd, MSARegister ws);
void fexupr_d(MSARegister wd, MSARegister ws);
void ffql_w(MSARegister wd, MSARegister ws);
void ffql_d(MSARegister wd, MSARegister ws);
void ffqr_w(MSARegister wd, MSARegister ws);
void ffqr_d(MSARegister wd, MSARegister ws);
void ftint_s_w(MSARegister wd, MSARegister ws);
void ftint_s_d(MSARegister wd, MSARegister ws);
void ftint_u_w(MSARegister wd, MSARegister ws);
void ftint_u_d(MSARegister wd, MSARegister ws);
void ffint_s_w(MSARegister wd, MSARegister ws);
void ffint_s_d(MSARegister wd, MSARegister ws);
void ffint_u_w(MSARegister wd, MSARegister ws);
void ffint_u_d(MSARegister wd, MSARegister ws);
void sll_b(MSARegister wd, MSARegister ws, MSARegister wt);
void sll_h(MSARegister wd, MSARegister ws, MSARegister wt);
void sll_w(MSARegister wd, MSARegister ws, MSARegister wt);
void sll_d(MSARegister wd, MSARegister ws, MSARegister wt);
void sra_b(MSARegister wd, MSARegister ws, MSARegister wt);
void sra_h(MSARegister wd, MSARegister ws, MSARegister wt);
void sra_w(MSARegister wd, MSARegister ws, MSARegister wt);
void sra_d(MSARegister wd, MSARegister ws, MSARegister wt);
void srl_b(MSARegister wd, MSARegister ws, MSARegister wt);
void srl_h(MSARegister wd, MSARegister ws, MSARegister wt);
void srl_w(MSARegister wd, MSARegister ws, MSARegister wt);
void srl_d(MSARegister wd, MSARegister ws, MSARegister wt);
void bclr_b(MSARegister wd, MSARegister ws, MSARegister wt);
void bclr_h(MSARegister wd, MSARegister ws, MSARegister wt);
void bclr_w(MSARegister wd, MSARegister ws, MSARegister wt);
void bclr_d(MSARegister wd, MSARegister ws, MSARegister wt);
void bset_b(MSARegister wd, MSARegister ws, MSARegister wt);
void bset_h(MSARegister wd, MSARegister ws, MSARegister wt);
void bset_w(MSARegister wd, MSARegister ws, MSARegister wt);
void bset_d(MSARegister wd, MSARegister ws, MSARegister wt);
void bneg_b(MSARegister wd, MSARegister ws, MSARegister wt);
void bneg_h(MSARegister wd, MSARegister ws, MSARegister wt);
void bneg_w(MSARegister wd, MSARegister ws, MSARegister wt);
void bneg_d(MSARegister wd, MSARegister ws, MSARegister wt);
void binsl_b(MSARegister wd, MSARegister ws, MSARegister wt);
void binsl_h(MSARegister wd, MSARegister ws, MSARegister wt);
void binsl_w(MSARegister wd, MSARegister ws, MSARegister wt);
void binsl_d(MSARegister wd, MSARegister ws, MSARegister wt);
void binsr_b(MSARegister wd, MSARegister ws, MSARegister wt);
void binsr_h(MSARegister wd, MSARegister ws, MSARegister wt);
void binsr_w(MSARegister wd, MSARegister ws, MSARegister wt);
void binsr_d(MSARegister wd, MSARegister ws, MSARegister wt);
void addv_b(MSARegister wd, MSARegister ws, MSARegister wt);
void addv_h(MSARegister wd, MSARegister ws, MSARegister wt);
void addv_w(MSARegister wd, MSARegister ws, MSARegister wt);
void addv_d(MSARegister wd, MSARegister ws, MSARegister wt);
void subv_b(MSARegister wd, MSARegister ws, MSARegister wt);
void subv_h(MSARegister wd, MSARegister ws, MSARegister wt);
void subv_w(MSARegister wd, MSARegister ws, MSARegister wt);
void subv_d(MSARegister wd, MSARegister ws, MSARegister wt);
void max_s_b(MSARegister wd, MSARegister ws, MSARegister wt);
void max_s_h(MSARegister wd, MSARegister ws, MSARegister wt);
void max_s_w(MSARegister wd, MSARegister ws, MSARegister wt);
void max_s_d(MSARegister wd, MSARegister ws, MSARegister wt);
void max_u_b(MSARegister wd, MSARegister ws, MSARegister wt);
void max_u_h(MSARegister wd, MSARegister ws, MSARegister wt);
void max_u_w(MSARegister wd, MSARegister ws, MSARegister wt);
void max_u_d(MSARegister wd, MSARegister ws, MSARegister wt);
void min_s_b(MSARegister wd, MSARegister ws, MSARegister wt);
void min_s_h(MSARegister wd, MSARegister ws, MSARegister wt);
void min_s_w(MSARegister wd, MSARegister ws, MSARegister wt);
void min_s_d(MSARegister wd, MSARegister ws, MSARegister wt);
void min_u_b(MSARegister wd, MSARegister ws, MSARegister wt);
void min_u_h(MSARegister wd, MSARegister ws, MSARegister wt);
void min_u_w(MSARegister wd, MSARegister ws, MSARegister wt);
void min_u_d(MSARegister wd, MSARegister ws, MSARegister wt);
void max_a_b(MSARegister wd, MSARegister ws, MSARegister wt);
void max_a_h(MSARegister wd, MSARegister ws, MSARegister wt);
void max_a_w(MSARegister wd, MSARegister ws, MSARegister wt);
void max_a_d(MSARegister wd, MSARegister ws, MSARegister wt);
void min_a_b(MSARegister wd, MSARegister ws, MSARegister wt);
void min_a_h(MSARegister wd, MSARegister ws, MSARegister wt);
void min_a_w(MSARegister wd, MSARegister ws, MSARegister wt);
void min_a_d(MSARegister wd, MSARegister ws, MSARegister wt);
void ceq_b(MSARegister wd, MSARegister ws, MSARegister wt);
void ceq_h(MSARegister wd, MSARegister ws, MSARegister wt);
void ceq_w(MSARegister wd, MSARegister ws, MSARegister wt);
void ceq_d(MSARegister wd, MSARegister ws, MSARegister wt);
void clt_s_b(MSARegister wd, MSARegister ws, MSARegister wt);
void clt_s_h(MSARegister wd, MSARegister ws, MSARegister wt);
void clt_s_w(MSARegister wd, MSARegister ws, MSARegister wt);
void clt_s_d(MSARegister wd, MSARegister ws, MSARegister wt);
void clt_u_b(MSARegister wd, MSARegister ws, MSARegister wt);
void clt_u_h(MSARegister wd, MSARegister ws, MSARegister wt);
void clt_u_w(MSARegister wd, MSARegister ws, MSARegister wt);
void clt_u_d(MSARegister wd, MSARegister ws, MSARegister wt);
void cle_s_b(MSARegister wd, MSARegister ws, MSARegister wt);
void cle_s_h(MSARegister wd, MSARegister ws, MSARegister wt);
void cle_s_w(MSARegister wd, MSARegister ws, MSARegister wt);
void cle_s_d(MSARegister wd, MSARegister ws, MSARegister wt);
void cle_u_b(MSARegister wd, MSARegister ws, MSARegister wt);
void cle_u_h(MSARegister wd, MSARegister ws, MSARegister wt);
void cle_u_w(MSARegister wd, MSARegister ws, MSARegister wt);
void cle_u_d(MSARegister wd, MSARegister ws, MSARegister wt);
void add_a_b(MSARegister wd, MSARegister ws, MSARegister wt);
void add_a_h(MSARegister wd, MSARegister ws, MSARegister wt);
void add_a_w(MSARegister wd, MSARegister ws, MSARegister wt);
void add_a_d(MSARegister wd, MSARegister ws, MSARegister wt);
void adds_a_b(MSARegister wd, MSARegister ws, MSARegister wt);
void adds_a_h(MSARegister wd, MSARegister ws, MSARegister wt);
void adds_a_w(MSARegister wd, MSARegister ws, MSARegister wt);
void adds_a_d(MSARegister wd, MSARegister ws, MSARegister wt);
void adds_s_b(MSARegister wd, MSARegister ws, MSARegister wt);
void adds_s_h(MSARegister wd, MSARegister ws, MSARegister wt);
void adds_s_w(MSARegister wd, MSARegister ws, MSARegister wt);
void adds_s_d(MSARegister wd, MSARegister ws, MSARegister wt);
void adds_u_b(MSARegister wd, MSARegister ws, MSARegister wt);
void adds_u_h(MSARegister wd, MSARegister ws, MSARegister wt);
void adds_u_w(MSARegister wd, MSARegister ws, MSARegister wt);
void adds_u_d(MSARegister wd, MSARegister ws, MSARegister wt);
void ave_s_b(MSARegister wd, MSARegister ws, MSARegister wt);
void ave_s_h(MSARegister wd, MSARegister ws, MSARegister wt);
void ave_s_w(MSARegister wd, MSARegister ws, MSARegister wt);
void ave_s_d(MSARegister wd, MSARegister ws, MSARegister wt);
void ave_u_b(MSARegister wd, MSARegister ws, MSARegister wt);
void ave_u_h(MSARegister wd, MSARegister ws, MSARegister wt);
void ave_u_w(MSARegister wd, MSARegister ws, MSARegister wt);
void ave_u_d(MSARegister wd, MSARegister ws, MSARegister wt);
void aver_s_b(MSARegister wd, MSARegister ws, MSARegister wt);
void aver_s_h(MSARegister wd, MSARegister ws, MSARegister wt);
void aver_s_w(MSARegister wd, MSARegister ws, MSARegister wt);
void aver_s_d(MSARegister wd, MSARegister ws, MSARegister wt);
void aver_u_b(MSARegister wd, MSARegister ws, MSARegister wt);
void aver_u_h(MSARegister wd, MSARegister ws, MSARegister wt);
void aver_u_w(MSARegister wd, MSARegister ws, MSARegister wt);
void aver_u_d(MSARegister wd, MSARegister ws, MSARegister wt);
void subs_s_b(MSARegister wd, MSARegister ws, MSARegister wt);
void subs_s_h(MSARegister wd, MSARegister ws, MSARegister wt);
void subs_s_w(MSARegister wd, MSARegister ws, MSARegister wt);
void subs_s_d(MSARegister wd, MSARegister ws, MSARegister wt);
void subs_u_b(MSARegister wd, MSARegister ws, MSARegister wt);
void subs_u_h(MSARegister wd, MSARegister ws, MSARegister wt);
void subs_u_w(MSARegister wd, MSARegister ws, MSARegister wt);
void subs_u_d(MSARegister wd, MSARegister ws, MSARegister wt);
void subsus_u_b(MSARegister wd, MSARegister ws, MSARegister wt);
void subsus_u_h(MSARegister wd, MSARegister ws, MSARegister wt);
void subsus_u_w(MSARegister wd, MSARegister ws, MSARegister wt);
void subsus_u_d(MSARegister wd, MSARegister ws, MSARegister wt);
void subsus_s_b(MSARegister wd, MSARegister ws, MSARegister wt);
void subsus_s_h(MSARegister wd, MSARegister ws, MSARegister wt);
void subsus_s_w(MSARegister wd, MSARegister ws, MSARegister wt);
void subsus_s_d(MSARegister wd, MSARegister ws, MSARegister wt);
void subsuu_u_b(MSARegister wd, MSARegister ws, MSARegister wt);
void subsuu_u_h(MSARegister wd, MSARegister ws, MSARegister wt);
void subsuu_u_w(MSARegister wd, MSARegister ws, MSARegister wt);
void subsuu_u_d(MSARegister wd, MSARegister ws, MSARegister wt);
void subsuu_s_b(MSARegister wd, MSARegister ws, MSARegister wt);
void subsuu_s_h(MSARegister wd, MSARegister ws, MSARegister wt);
void subsuu_s_w(MSARegister wd, MSARegister ws, MSARegister wt);
void subsuu_s_d(MSARegister wd, MSARegister ws, MSARegister wt);
void asub_s_b(MSARegister wd, MSARegister ws, MSARegister wt);
void asub_s_h(MSARegister wd, MSARegister ws, MSARegister wt);
void asub_s_w(MSARegister wd, MSARegister ws, MSARegister wt);
void asub_s_d(MSARegister wd, MSARegister ws, MSARegister wt);
void asub_u_b(MSARegister wd, MSARegister ws, MSARegister wt);
void asub_u_h(MSARegister wd, MSARegister ws, MSARegister wt);
void asub_u_w(MSARegister wd, MSARegister ws, MSARegister wt);
void asub_u_d(MSARegister wd, MSARegister ws, MSARegister wt);
void mulv_b(MSARegister wd, MSARegister ws, MSARegister wt);
void mulv_h(MSARegister wd, MSARegister ws, MSARegister wt);
void mulv_w(MSARegister wd, MSARegister ws, MSARegister wt);
void mulv_d(MSARegister wd, MSARegister ws, MSARegister wt);
void maddv_b(MSARegister wd, MSARegister ws, MSARegister wt);
void maddv_h(MSARegister wd, MSARegister ws, MSARegister wt);
void maddv_w(MSARegister wd, MSARegister ws, MSARegister wt);
void maddv_d(MSARegister wd, MSARegister ws, MSARegister wt);
void msubv_b(MSARegister wd, MSARegister ws, MSARegister wt);
void msubv_h(MSARegister wd, MSARegister ws, MSARegister wt);
void msubv_w(MSARegister wd, MSARegister ws, MSARegister wt);
void msubv_d(MSARegister wd, MSARegister ws, MSARegister wt);
void div_s_b(MSARegister wd, MSARegister ws, MSARegister wt);
void div_s_h(MSARegister wd, MSARegister ws, MSARegister wt);
void div_s_w(MSARegister wd, MSARegister ws, MSARegister wt);
void div_s_d(MSARegister wd, MSARegister ws, MSARegister wt);
void div_u_b(MSARegister wd, MSARegister ws, MSARegister wt);
void div_u_h(MSARegister wd, MSARegister ws, MSARegister wt);
void div_u_w(MSARegister wd, MSARegister ws, MSARegister wt);
void div_u_d(MSARegister wd, MSARegister ws, MSARegister wt);
void mod_s_b(MSARegister wd, MSARegister ws, MSARegister wt);
void mod_s_h(MSARegister wd, MSARegister ws, MSARegister wt);
void mod_s_w(MSARegister wd, MSARegister ws, MSARegister wt);
void mod_s_d(MSARegister wd, MSARegister ws, MSARegister wt);
void mod_u_b(MSARegister wd, MSARegister ws, MSARegister wt);
void mod_u_h(MSARegister wd, MSARegister ws, MSARegister wt);
void mod_u_w(MSARegister wd, MSARegister ws, MSARegister wt);
void mod_u_d(MSARegister wd, MSARegister ws, MSARegister wt);
void dotp_s_b(MSARegister wd, MSARegister ws, MSARegister wt);
void dotp_s_h(MSARegister wd, MSARegister ws, MSARegister wt);
void dotp_s_w(MSARegister wd, MSARegister ws, MSARegister wt);
void dotp_s_d(MSARegister wd, MSARegister ws, MSARegister wt);
void dotp_u_b(MSARegister wd, MSARegister ws, MSARegister wt);
void dotp_u_h(MSARegister wd, MSARegister ws, MSARegister wt);
void dotp_u_w(MSARegister wd, MSARegister ws, MSARegister wt);
void dotp_u_d(MSARegister wd, MSARegister ws, MSARegister wt);
void dpadd_s_b(MSARegister wd, MSARegister ws, MSARegister wt);
void dpadd_s_h(MSARegister wd, MSARegister ws, MSARegister wt);
void dpadd_s_w(MSARegister wd, MSARegister ws, MSARegister wt);
void dpadd_s_d(MSARegister wd, MSARegister ws, MSARegister wt);
void dpadd_u_b(MSARegister wd, MSARegister ws, MSARegister wt);
void dpadd_u_h(MSARegister wd, MSARegister ws, MSARegister wt);
void dpadd_u_w(MSARegister wd, MSARegister ws, MSARegister wt);
void dpadd_u_d(MSARegister wd, MSARegister ws, MSARegister wt);
void dpsub_s_b(MSARegister wd, MSARegister ws, MSARegister wt);
void dpsub_s_h(MSARegister wd, MSARegister ws, MSARegister wt);
void dpsub_s_w(MSARegister wd, MSARegister ws, MSARegister wt);
void dpsub_s_d(MSARegister wd, MSARegister ws, MSARegister wt);
void dpsub_u_b(MSARegister wd, MSARegister ws, MSARegister wt);
void dpsub_u_h(MSARegister wd, MSARegister ws, MSARegister wt);
void dpsub_u_w(MSARegister wd, MSARegister ws, MSARegister wt);
void dpsub_u_d(MSARegister wd, MSARegister ws, MSARegister wt);
void sld_b(MSARegister wd, MSARegister ws, Register rt);
void sld_h(MSARegister wd, MSARegister ws, Register rt);
void sld_w(MSARegister wd, MSARegister ws, Register rt);
void sld_d(MSARegister wd, MSARegister ws, Register rt);
void splat_b(MSARegister wd, MSARegister ws, Register rt);
void splat_h(MSARegister wd, MSARegister ws, Register rt);
void splat_w(MSARegister wd, MSARegister ws, Register rt);
void splat_d(MSARegister wd, MSARegister ws, Register rt);
void pckev_b(MSARegister wd, MSARegister ws, MSARegister wt);
void pckev_h(MSARegister wd, MSARegister ws, MSARegister wt);
void pckev_w(MSARegister wd, MSARegister ws, MSARegister wt);
void pckev_d(MSARegister wd, MSARegister ws, MSARegister wt);
void pckod_b(MSARegister wd, MSARegister ws, MSARegister wt);
void pckod_h(MSARegister wd, MSARegister ws, MSARegister wt);
void pckod_w(MSARegister wd, MSARegister ws, MSARegister wt);
void pckod_d(MSARegister wd, MSARegister ws, MSARegister wt);
void ilvl_b(MSARegister wd, MSARegister ws, MSARegister wt);
void ilvl_h(MSARegister wd, MSARegister ws, MSARegister wt);
void ilvl_w(MSARegister wd, MSARegister ws, MSARegister wt);
void ilvl_d(MSARegister wd, MSARegister ws, MSARegister wt);
void ilvr_b(MSARegister wd, MSARegister ws, MSARegister wt);
void ilvr_h(MSARegister wd, MSARegister ws, MSARegister wt);
void ilvr_w(MSARegister wd, MSARegister ws, MSARegister wt);
void ilvr_d(MSARegister wd, MSARegister ws, MSARegister wt);
void ilvev_b(MSARegister wd, MSARegister ws, MSARegister wt);
void ilvev_h(MSARegister wd, MSARegister ws, MSARegister wt);
void ilvev_w(MSARegister wd, MSARegister ws, MSARegister wt);
void ilvev_d(MSARegister wd, MSARegister ws, MSARegister wt);
void ilvod_b(MSARegister wd, MSARegister ws, MSARegister wt);
void ilvod_h(MSARegister wd, MSARegister ws, MSARegister wt);
void ilvod_w(MSARegister wd, MSARegister ws, MSARegister wt);
void ilvod_d(MSARegister wd, MSARegister ws, MSARegister wt);
void vshf_b(MSARegister wd, MSARegister ws, MSARegister wt);
void vshf_h(MSARegister wd, MSARegister ws, MSARegister wt);
void vshf_w(MSARegister wd, MSARegister ws, MSARegister wt);
void vshf_d(MSARegister wd, MSARegister ws, MSARegister wt);
void srar_b(MSARegister wd, MSARegister ws, MSARegister wt);
void srar_h(MSARegister wd, MSARegister ws, MSARegister wt);
void srar_w(MSARegister wd, MSARegister ws, MSARegister wt);
void srar_d(MSARegister wd, MSARegister ws, MSARegister wt);
void srlr_b(MSARegister wd, MSARegister ws, MSARegister wt);
void srlr_h(MSARegister wd, MSARegister ws, MSARegister wt);
void srlr_w(MSARegister wd, MSARegister ws, MSARegister wt);
void srlr_d(MSARegister wd, MSARegister ws, MSARegister wt);
void hadd_s_b(MSARegister wd, MSARegister ws, MSARegister wt);
void hadd_s_h(MSARegister wd, MSARegister ws, MSARegister wt);
void hadd_s_w(MSARegister wd, MSARegister ws, MSARegister wt);
void hadd_s_d(MSARegister wd, MSARegister ws, MSARegister wt);
void hadd_u_b(MSARegister wd, MSARegister ws, MSARegister wt);
void hadd_u_h(MSARegister wd, MSARegister ws, MSARegister wt);
void hadd_u_w(MSARegister wd, MSARegister ws, MSARegister wt);
void hadd_u_d(MSARegister wd, MSARegister ws, MSARegister wt);
void hsub_s_b(MSARegister wd, MSARegister ws, MSARegister wt);
void hsub_s_h(MSARegister wd, MSARegister ws, MSARegister wt);
void hsub_s_w(MSARegister wd, MSARegister ws, MSARegister wt);
void hsub_s_d(MSARegister wd, MSARegister ws, MSARegister wt);
void hsub_u_b(MSARegister wd, MSARegister ws, MSARegister wt);
void hsub_u_h(MSARegister wd, MSARegister ws, MSARegister wt);
void hsub_u_w(MSARegister wd, MSARegister ws, MSARegister wt);
void hsub_u_d(MSARegister wd, MSARegister ws, MSARegister wt);
void fcaf_w(MSARegister wd, MSARegister ws, MSARegister wt);
void fcaf_d(MSARegister wd, MSARegister ws, MSARegister wt);
void fcun_w(MSARegister wd, MSARegister ws, MSARegister wt);
void fcun_d(MSARegister wd, MSARegister ws, MSARegister wt);
void fceq_w(MSARegister wd, MSARegister ws, MSARegister wt);
void fceq_d(MSARegister wd, MSARegister ws, MSARegister wt);
void fcueq_w(MSARegister wd, MSARegister ws, MSARegister wt);
void fcueq_d(MSARegister wd, MSARegister ws, MSARegister wt);
void fclt_w(MSARegister wd, MSARegister ws, MSARegister wt);
void fclt_d(MSARegister wd, MSARegister ws, MSARegister wt);
void fcult_w(MSARegister wd, MSARegister ws, MSARegister wt);
void fcult_d(MSARegister wd, MSARegister ws, MSARegister wt);
void fcle_w(MSARegister wd, MSARegister ws, MSARegister wt);
void fcle_d(MSARegister wd, MSARegister ws, MSARegister wt);
void fcule_w(MSARegister wd, MSARegister ws, MSARegister wt);
void fcule_d(MSARegister wd, MSARegister ws, MSARegister wt);
void fsaf_w(MSARegister wd, MSARegister ws, MSARegister wt);
void fsaf_d(MSARegister wd, MSARegister ws, MSARegister wt);
void fsun_w(MSARegister wd, MSARegister ws, MSARegister wt);
void fsun_d(MSARegister wd, MSARegister ws, MSARegister wt);
void fseq_w(MSARegister wd, MSARegister ws, MSARegister wt);
void fseq_d(MSARegister wd, MSARegister ws, MSARegister wt);
void fsueq_w(MSARegister wd, MSARegister ws, MSARegister wt);
void fsueq_d(MSARegister wd, MSARegister ws, MSARegister wt);
void fslt_w(MSARegister wd, MSARegister ws, MSARegister wt);
void fslt_d(MSARegister wd, MSARegister ws, MSARegister wt);
void fsult_w(MSARegister wd, MSARegister ws, MSARegister wt);
void fsult_d(MSARegister wd, MSARegister ws, MSARegister wt);
void fsle_w(MSARegister wd, MSARegister ws, MSARegister wt);
void fsle_d(MSARegister wd, MSARegister ws, MSARegister wt);
void fsule_w(MSARegister wd, MSARegister ws, MSARegister wt);
void fsule_d(MSARegister wd, MSARegister ws, MSARegister wt);
void fadd_w(MSARegister wd, MSARegister ws, MSARegister wt);
void fadd_d(MSARegister wd, MSARegister ws, MSARegister wt);
void fsub_w(MSARegister wd, MSARegister ws, MSARegister wt);
void fsub_d(MSARegister wd, MSARegister ws, MSARegister wt);
void fmul_w(MSARegister wd, MSARegister ws, MSARegister wt);
void fmul_d(MSARegister wd, MSARegister ws, MSARegister wt);
void fdiv_w(MSARegister wd, MSARegister ws, MSARegister wt);
void fdiv_d(MSARegister wd, MSARegister ws, MSARegister wt);
void fmadd_w(MSARegister wd, MSARegister ws, MSARegister wt);
void fmadd_d(MSARegister wd, MSARegister ws, MSARegister wt);
void fmsub_w(MSARegister wd, MSARegister ws, MSARegister wt);
void fmsub_d(MSARegister wd, MSARegister ws, MSARegister wt);
void fexp2_w(MSARegister wd, MSARegister ws, MSARegister wt);
void fexp2_d(MSARegister wd, MSARegister ws, MSARegister wt);
void fexdo_h(MSARegister wd, MSARegister ws, MSARegister wt);
void fexdo_w(MSARegister wd, MSARegister ws, MSARegister wt);
void ftq_h(MSARegister wd, MSARegister ws, MSARegister wt);
void ftq_w(MSARegister wd, MSARegister ws, MSARegister wt);
void fmin_w(MSARegister wd, MSARegister ws, MSARegister wt);
void fmin_d(MSARegister wd, MSARegister ws, MSARegister wt);
void fmin_a_w(MSARegister wd, MSARegister ws, MSARegister wt);
void fmin_a_d(MSARegister wd, MSARegister ws, MSARegister wt);
void fmax_w(MSARegister wd, MSARegister ws, MSARegister wt);
void fmax_d(MSARegister wd, MSARegister ws, MSARegister wt);
void fmax_a_w(MSARegister wd, MSARegister ws, MSARegister wt);
void fmax_a_d(MSARegister wd, MSARegister ws, MSARegister wt);
void fcor_w(MSARegister wd, MSARegister ws, MSARegister wt);
void fcor_d(MSARegister wd, MSARegister ws, MSARegister wt);
void fcune_w(MSARegister wd, MSARegister ws, MSARegister wt);
void fcune_d(MSARegister wd, MSARegister ws, MSARegister wt);
void fcne_w(MSARegister wd, MSARegister ws, MSARegister wt);
void fcne_d(MSARegister wd, MSARegister ws, MSARegister wt);
void mul_q_h(MSARegister wd, MSARegister ws, MSARegister wt);
void mul_q_w(MSARegister wd, MSARegister ws, MSARegister wt);
void madd_q_h(MSARegister wd, MSARegister ws, MSARegister wt);
void madd_q_w(MSARegister wd, MSARegister ws, MSARegister wt);
void msub_q_h(MSARegister wd, MSARegister ws, MSARegister wt);
void msub_q_w(MSARegister wd, MSARegister ws, MSARegister wt);
void fsor_w(MSARegister wd, MSARegister ws, MSARegister wt);
void fsor_d(MSARegister wd, MSARegister ws, MSARegister wt);
void fsune_w(MSARegister wd, MSARegister ws, MSARegister wt);
void fsune_d(MSARegister wd, MSARegister ws, MSARegister wt);
void fsne_w(MSARegister wd, MSARegister ws, MSARegister wt);
void fsne_d(MSARegister wd, MSARegister ws, MSARegister wt);
void mulr_q_h(MSARegister wd, MSARegister ws, MSARegister wt);
void mulr_q_w(MSARegister wd, MSARegister ws, MSARegister wt);
void maddr_q_h(MSARegister wd, MSARegister ws, MSARegister wt);
void maddr_q_w(MSARegister wd, MSARegister ws, MSARegister wt);
void msubr_q_h(MSARegister wd, MSARegister ws, MSARegister wt);
void msubr_q_w(MSARegister wd, MSARegister ws, MSARegister wt);
void sldi_b(MSARegister wd, MSARegister ws, uint32_t n);
void sldi_h(MSARegister wd, MSARegister ws, uint32_t n);
void sldi_w(MSARegister wd, MSARegister ws, uint32_t n);
void sldi_d(MSARegister wd, MSARegister ws, uint32_t n);
void splati_b(MSARegister wd, MSARegister ws, uint32_t n);
void splati_h(MSARegister wd, MSARegister ws, uint32_t n);
void splati_w(MSARegister wd, MSARegister ws, uint32_t n);
void splati_d(MSARegister wd, MSARegister ws, uint32_t n);
void copy_s_b(Register rd, MSARegister ws, uint32_t n);
void copy_s_h(Register rd, MSARegister ws, uint32_t n);
void copy_s_w(Register rd, MSARegister ws, uint32_t n);
void copy_u_b(Register rd, MSARegister ws, uint32_t n);
void copy_u_h(Register rd, MSARegister ws, uint32_t n);
void copy_u_w(Register rd, MSARegister ws, uint32_t n);
void insert_b(MSARegister wd, uint32_t n, Register rs);
void insert_h(MSARegister wd, uint32_t n, Register rs);
void insert_w(MSARegister wd, uint32_t n, Register rs);
void insve_b(MSARegister wd, uint32_t n, MSARegister ws);
void insve_h(MSARegister wd, uint32_t n, MSARegister ws);
void insve_w(MSARegister wd, uint32_t n, MSARegister ws);
void insve_d(MSARegister wd, uint32_t n, MSARegister ws);
void move_v(MSARegister wd, MSARegister ws);
void ctcmsa(MSAControlRegister cd, Register rs);
void cfcmsa(Register rd, MSAControlRegister cs);
void slli_b(MSARegister wd, MSARegister ws, uint32_t m);
void slli_h(MSARegister wd, MSARegister ws, uint32_t m);
void slli_w(MSARegister wd, MSARegister ws, uint32_t m);
void slli_d(MSARegister wd, MSARegister ws, uint32_t m);
void srai_b(MSARegister wd, MSARegister ws, uint32_t m);
void srai_h(MSARegister wd, MSARegister ws, uint32_t m);
void srai_w(MSARegister wd, MSARegister ws, uint32_t m);
void srai_d(MSARegister wd, MSARegister ws, uint32_t m);
void srli_b(MSARegister wd, MSARegister ws, uint32_t m);
void srli_h(MSARegister wd, MSARegister ws, uint32_t m);
void srli_w(MSARegister wd, MSARegister ws, uint32_t m);
void srli_d(MSARegister wd, MSARegister ws, uint32_t m);
void bclri_b(MSARegister wd, MSARegister ws, uint32_t m);
void bclri_h(MSARegister wd, MSARegister ws, uint32_t m);
void bclri_w(MSARegister wd, MSARegister ws, uint32_t m);
void bclri_d(MSARegister wd, MSARegister ws, uint32_t m);
void bseti_b(MSARegister wd, MSARegister ws, uint32_t m);
void bseti_h(MSARegister wd, MSARegister ws, uint32_t m);
void bseti_w(MSARegister wd, MSARegister ws, uint32_t m);
void bseti_d(MSARegister wd, MSARegister ws, uint32_t m);
void bnegi_b(MSARegister wd, MSARegister ws, uint32_t m);
void bnegi_h(MSARegister wd, MSARegister ws, uint32_t m);
void bnegi_w(MSARegister wd, MSARegister ws, uint32_t m);
void bnegi_d(MSARegister wd, MSARegister ws, uint32_t m);
void binsli_b(MSARegister wd, MSARegister ws, uint32_t m);
void binsli_h(MSARegister wd, MSARegister ws, uint32_t m);
void binsli_w(MSARegister wd, MSARegister ws, uint32_t m);
void binsli_d(MSARegister wd, MSARegister ws, uint32_t m);
void binsri_b(MSARegister wd, MSARegister ws, uint32_t m);
void binsri_h(MSARegister wd, MSARegister ws, uint32_t m);
void binsri_w(MSARegister wd, MSARegister ws, uint32_t m);
void binsri_d(MSARegister wd, MSARegister ws, uint32_t m);
void sat_s_b(MSARegister wd, MSARegister ws, uint32_t m);
void sat_s_h(MSARegister wd, MSARegister ws, uint32_t m);
void sat_s_w(MSARegister wd, MSARegister ws, uint32_t m);
void sat_s_d(MSARegister wd, MSARegister ws, uint32_t m);
void sat_u_b(MSARegister wd, MSARegister ws, uint32_t m);
void sat_u_h(MSARegister wd, MSARegister ws, uint32_t m);
void sat_u_w(MSARegister wd, MSARegister ws, uint32_t m);
void sat_u_d(MSARegister wd, MSARegister ws, uint32_t m);
void srari_b(MSARegister wd, MSARegister ws, uint32_t m);
void srari_h(MSARegister wd, MSARegister ws, uint32_t m);
void srari_w(MSARegister wd, MSARegister ws, uint32_t m);
void srari_d(MSARegister wd, MSARegister ws, uint32_t m);
void srlri_b(MSARegister wd, MSARegister ws, uint32_t m);
void srlri_h(MSARegister wd, MSARegister ws, uint32_t m);
void srlri_w(MSARegister wd, MSARegister ws, uint32_t m);
void srlri_d(MSARegister wd, MSARegister ws, uint32_t m);
// Check the code size generated from label to here.
int SizeOfCodeGeneratedSince(Label* label) {
return pc_offset() - label->pos();
......@@ -1377,6 +2037,74 @@ class Assembler : public AssemblerBase {
void GenInstrJump(Opcode opcode,
uint32_t address);
// MSA
void GenInstrMsaI8(SecondaryField operation, uint32_t imm8, MSARegister ws,
MSARegister wd);
void GenInstrMsaI5(SecondaryField operation, SecondaryField df, int32_t imm5,
MSARegister ws, MSARegister wd);
void GenInstrMsaBit(SecondaryField operation, SecondaryField df, uint32_t m,
MSARegister ws, MSARegister wd);
void GenInstrMsaI10(SecondaryField operation, SecondaryField df,
int32_t imm10, MSARegister wd);
template <typename RegType>
void GenInstrMsa3R(SecondaryField operation, SecondaryField df, RegType t,
MSARegister ws, MSARegister wd);
template <typename DstType, typename SrcType>
void GenInstrMsaElm(SecondaryField operation, SecondaryField df, uint32_t n,
SrcType src, DstType dst);
void GenInstrMsa3RF(SecondaryField operation, uint32_t df, MSARegister wt,
MSARegister ws, MSARegister wd);
void GenInstrMsaVec(SecondaryField operation, MSARegister wt, MSARegister ws,
MSARegister wd);
void GenInstrMsaMI10(SecondaryField operation, int32_t s10, Register rs,
MSARegister wd);
void GenInstrMsa2R(SecondaryField operation, SecondaryField df,
MSARegister ws, MSARegister wd);
void GenInstrMsa2RF(SecondaryField operation, SecondaryField df,
MSARegister ws, MSARegister wd);
void GenInstrMsaBranch(SecondaryField operation, MSARegister wt,
int32_t offset16);
inline bool is_valid_msa_df_m(SecondaryField bit_df, uint32_t m) {
switch (bit_df) {
case BIT_DF_b:
return is_uint3(m);
case BIT_DF_h:
return is_uint4(m);
case BIT_DF_w:
return is_uint5(m);
case BIT_DF_d:
return is_uint6(m);
default:
return false;
}
}
inline bool is_valid_msa_df_n(SecondaryField elm_df, uint32_t n) {
switch (elm_df) {
case ELM_DF_B:
return is_uint4(n);
case ELM_DF_H:
return is_uint3(n);
case ELM_DF_W:
return is_uint2(n);
case ELM_DF_D:
return is_uint1(n);
default:
return false;
}
}
// Labels.
void print(Label* L);
......
......@@ -122,6 +122,44 @@ int FPURegisters::Number(const char* name) {
return kInvalidFPURegister;
}
const char* MSARegisters::names_[kNumMSARegisters] = {
"w0", "w1", "w2", "w3", "w4", "w5", "w6", "w7", "w8", "w9", "w10",
"w11", "w12", "w13", "w14", "w15", "w16", "w17", "w18", "w19", "w20", "w21",
"w22", "w23", "w24", "w25", "w26", "w27", "w28", "w29", "w30", "w31"};
const MSARegisters::RegisterAlias MSARegisters::aliases_[] = {
{kInvalidRegister, NULL}};
const char* MSARegisters::Name(int creg) {
const char* result;
if ((0 <= creg) && (creg < kNumMSARegisters)) {
result = names_[creg];
} else {
result = "nocreg";
}
return result;
}
int MSARegisters::Number(const char* name) {
// Look through the canonical names.
for (int i = 0; i < kNumMSARegisters; i++) {
if (strcmp(names_[i], name) == 0) {
return i;
}
}
// Look through the alias names.
int i = 0;
while (aliases_[i].creg != kInvalidRegister) {
if (strcmp(aliases_[i].name, name) == 0) {
return aliases_[i].creg;
}
i++;
}
// No Cregister with the reguested name found.
return kInvalidMSARegister;
}
} // namespace internal
} // namespace v8
......
......@@ -154,6 +154,14 @@ const int kPCRegister = 34;
const int kNumFPURegisters = 32;
const int kInvalidFPURegister = -1;
// Number of MSA registers
const int kNumMSARegisters = 32;
const int kInvalidMSARegister = -1;
const int kInvalidMSAControlRegister = -1;
const int kMSAIRRegister = 0;
const int kMSACSRRegister = 1;
// FPU (coprocessor 1) control registers. Currently only FCSR is implemented.
const int kFCSRRegister = 31;
const int kInvalidFPUControlRegister = -1;
......@@ -239,6 +247,24 @@ class FPURegisters {
static const RegisterAlias aliases_[];
};
// Helper functions for converting between register numbers and names.
class MSARegisters {
public:
// Return the name of the register.
static const char* Name(int reg);
// Lookup the register number for the name provided.
static int Number(const char* name);
struct RegisterAlias {
int creg;
const char* name;
};
private:
static const char* names_[kNumMSARegisters];
static const RegisterAlias aliases_[];
};
// -----------------------------------------------------------------------------
// Instructions encoding constants.
......@@ -297,6 +323,14 @@ const int kImm28Shift = 0;
const int kImm28Bits = 28;
const int kImm32Shift = 0;
const int kImm32Bits = 32;
const int kMsaImm8Shift = 16;
const int kMsaImm8Bits = 8;
const int kMsaImm5Shift = 16;
const int kMsaImm5Bits = 5;
const int kMsaImm10Shift = 11;
const int kMsaImm10Bits = 10;
const int kMsaImmMI10Shift = 16;
const int kMsaImmMI10Bits = 10;
// In branches and jumps immediate fields point to words, not bytes,
// and are therefore shifted by 2.
......@@ -316,6 +350,12 @@ const int kFBccShift = 18;
const int kFBccBits = 3;
const int kFBtrueShift = 16;
const int kFBtrueBits = 1;
const int kWtBits = 5;
const int kWtShift = 16;
const int kWsBits = 5;
const int kWsShift = 11;
const int kWdBits = 5;
const int kWdShift = 6;
// ----- Miscellaneous useful masks.
// Instruction bit masks.
......@@ -326,6 +366,10 @@ const int kImm19Mask = ((1 << kImm19Bits) - 1) << kImm19Shift;
const int kImm21Mask = ((1 << kImm21Bits) - 1) << kImm21Shift;
const int kImm26Mask = ((1 << kImm26Bits) - 1) << kImm26Shift;
const int kImm28Mask = ((1 << kImm28Bits) - 1) << kImm28Shift;
const int kImm5Mask = ((1 << 5) - 1);
const int kImm8Mask = ((1 << 8) - 1);
const int kImm10Mask = ((1 << 10) - 1);
const int kMsaI5I10Mask = ((7U << 23) | ((1 << 6) - 1));
const int kRsFieldMask = ((1 << kRsBits) - 1) << kRsShift;
const int kRtFieldMask = ((1 << kRtBits) - 1) << kRtShift;
const int kRdFieldMask = ((1 << kRdBits) - 1) << kRdShift;
......@@ -369,6 +413,7 @@ enum Opcode : uint32_t {
DADDI = ((3U << 3) + 0) << kOpcodeShift, // This is also BNEC.
SPECIAL2 = ((3U << 3) + 4) << kOpcodeShift,
MSA = ((3U << 3) + 6) << kOpcodeShift,
SPECIAL3 = ((3U << 3) + 7) << kOpcodeShift,
LB = ((4U << 3) + 0) << kOpcodeShift,
......@@ -621,7 +666,7 @@ enum SecondaryField : uint32_t {
SELEQZ_C = ((2U << 3) + 4), // COP1 on FPR registers.
MOVF = ((2U << 3) + 1), // Function field for MOVT.fmt and MOVF.fmt
SELNEZ_C = ((2U << 3) + 7), // COP1 on FPR registers.
// COP1 Encoding of Function Field When rs=PS.
// COP1 Encoding of Function Field When rs=PS.
// COP1X Encoding of Function Field.
MADD_S = ((4U << 3) + 0),
......@@ -641,9 +686,267 @@ enum SecondaryField : uint32_t {
// POP76 Encoding of rs Field.
JIALC = ((0U << 5) + 0),
// COP1 Encoding of rs Field for MSA Branch Instructions
BZ_V = (((1U << 3) + 3) << kRsShift),
BNZ_V = (((1U << 3) + 7) << kRsShift),
BZ_B = (((3U << 3) + 0) << kRsShift),
BZ_H = (((3U << 3) + 1) << kRsShift),
BZ_W = (((3U << 3) + 2) << kRsShift),
BZ_D = (((3U << 3) + 3) << kRsShift),
BNZ_B = (((3U << 3) + 4) << kRsShift),
BNZ_H = (((3U << 3) + 5) << kRsShift),
BNZ_W = (((3U << 3) + 6) << kRsShift),
BNZ_D = (((3U << 3) + 7) << kRsShift),
// MSA: Operation Field for MI10 Instruction Formats
MSA_LD = (8U << 2),
MSA_ST = (9U << 2),
LD_B = ((8U << 2) + 0),
LD_H = ((8U << 2) + 1),
LD_W = ((8U << 2) + 2),
LD_D = ((8U << 2) + 3),
ST_B = ((9U << 2) + 0),
ST_H = ((9U << 2) + 1),
ST_W = ((9U << 2) + 2),
ST_D = ((9U << 2) + 3),
// MSA: Operation Field for I5 Instruction Format
ADDVI = ((0U << 23) + 6),
SUBVI = ((1U << 23) + 6),
MAXI_S = ((2U << 23) + 6),
MAXI_U = ((3U << 23) + 6),
MINI_S = ((4U << 23) + 6),
MINI_U = ((5U << 23) + 6),
CEQI = ((0U << 23) + 7),
CLTI_S = ((2U << 23) + 7),
CLTI_U = ((3U << 23) + 7),
CLEI_S = ((4U << 23) + 7),
CLEI_U = ((5U << 23) + 7),
LDI = ((6U << 23) + 7), // I10 instruction format
I5_DF_b = (0U << 21),
I5_DF_h = (1U << 21),
I5_DF_w = (2U << 21),
I5_DF_d = (3U << 21),
// MSA: Operation Field for I8 Instruction Format
ANDI_B = ((0U << 24) + 0),
ORI_B = ((1U << 24) + 0),
NORI_B = ((2U << 24) + 0),
XORI_B = ((3U << 24) + 0),
BMNZI_B = ((0U << 24) + 1),
BMZI_B = ((1U << 24) + 1),
BSELI_B = ((2U << 24) + 1),
SHF_B = ((0U << 24) + 2),
SHF_H = ((1U << 24) + 2),
SHF_W = ((2U << 24) + 2),
MSA_VEC_2R_2RF_MINOR = ((3U << 3) + 6),
// MSA: Operation Field for VEC Instruction Formats
AND_V = (((0U << 2) + 0) << 21),
OR_V = (((0U << 2) + 1) << 21),
NOR_V = (((0U << 2) + 2) << 21),
XOR_V = (((0U << 2) + 3) << 21),
BMNZ_V = (((1U << 2) + 0) << 21),
BMZ_V = (((1U << 2) + 1) << 21),
BSEL_V = (((1U << 2) + 2) << 21),
// MSA: Operation Field for 2R Instruction Formats
MSA_2R_FORMAT = (((6U << 2) + 0) << 21),
FILL = (0U << 18),
PCNT = (1U << 18),
NLOC = (2U << 18),
NLZC = (3U << 18),
MSA_2R_DF_b = (0U << 16),
MSA_2R_DF_h = (1U << 16),
MSA_2R_DF_w = (2U << 16),
MSA_2R_DF_d = (3U << 16),
// MSA: Operation Field for 2RF Instruction Formats
MSA_2RF_FORMAT = (((6U << 2) + 1) << 21),
FCLASS = (0U << 17),
FTRUNC_S = (1U << 17),
FTRUNC_U = (2U << 17),
FSQRT = (3U << 17),
FRSQRT = (4U << 17),
FRCP = (5U << 17),
FRINT = (6U << 17),
FLOG2 = (7U << 17),
FEXUPL = (8U << 17),
FEXUPR = (9U << 17),
FFQL = (10U << 17),
FFQR = (11U << 17),
FTINT_S = (12U << 17),
FTINT_U = (13U << 17),
FFINT_S = (14U << 17),
FFINT_U = (15U << 17),
MSA_2RF_DF_w = (0U << 16),
MSA_2RF_DF_d = (1U << 16),
// MSA: Operation Field for 3R Instruction Format
SLL_MSA = ((0U << 23) + 13),
SRA_MSA = ((1U << 23) + 13),
SRL_MSA = ((2U << 23) + 13),
BCLR = ((3U << 23) + 13),
BSET = ((4U << 23) + 13),
BNEG = ((5U << 23) + 13),
BINSL = ((6U << 23) + 13),
BINSR = ((7U << 23) + 13),
ADDV = ((0U << 23) + 14),
SUBV = ((1U << 23) + 14),
MAX_S = ((2U << 23) + 14),
MAX_U = ((3U << 23) + 14),
MIN_S = ((4U << 23) + 14),
MIN_U = ((5U << 23) + 14),
MAX_A = ((6U << 23) + 14),
MIN_A = ((7U << 23) + 14),
CEQ = ((0U << 23) + 15),
CLT_S = ((2U << 23) + 15),
CLT_U = ((3U << 23) + 15),
CLE_S = ((4U << 23) + 15),
CLE_U = ((5U << 23) + 15),
ADD_A = ((0U << 23) + 16),
ADDS_A = ((1U << 23) + 16),
ADDS_S = ((2U << 23) + 16),
ADDS_U = ((3U << 23) + 16),
AVE_S = ((4U << 23) + 16),
AVE_U = ((5U << 23) + 16),
AVER_S = ((6U << 23) + 16),
AVER_U = ((7U << 23) + 16),
SUBS_S = ((0U << 23) + 17),
SUBS_U = ((1U << 23) + 17),
SUBSUS_U = ((2U << 23) + 17),
SUBSUU_S = ((3U << 23) + 17),
ASUB_S = ((4U << 23) + 17),
ASUB_U = ((5U << 23) + 17),
MULV = ((0U << 23) + 18),
MADDV = ((1U << 23) + 18),
MSUBV = ((2U << 23) + 18),
DIV_S_MSA = ((4U << 23) + 18),
DIV_U = ((5U << 23) + 18),
MOD_S = ((6U << 23) + 18),
MOD_U = ((7U << 23) + 18),
DOTP_S = ((0U << 23) + 19),
DOTP_U = ((1U << 23) + 19),
DPADD_S = ((2U << 23) + 19),
DPADD_U = ((3U << 23) + 19),
DPSUB_S = ((4U << 23) + 19),
DPSUB_U = ((5U << 23) + 19),
SLD = ((0U << 23) + 20),
SPLAT = ((1U << 23) + 20),
PCKEV = ((2U << 23) + 20),
PCKOD = ((3U << 23) + 20),
ILVL = ((4U << 23) + 20),
ILVR = ((5U << 23) + 20),
ILVEV = ((6U << 23) + 20),
ILVOD = ((7U << 23) + 20),
VSHF = ((0U << 23) + 21),
SRAR = ((1U << 23) + 21),
SRLR = ((2U << 23) + 21),
HADD_S = ((4U << 23) + 21),
HADD_U = ((5U << 23) + 21),
HSUB_S = ((6U << 23) + 21),
HSUB_U = ((7U << 23) + 21),
MSA_3R_DF_b = (0U << 21),
MSA_3R_DF_h = (1U << 21),
MSA_3R_DF_w = (2U << 21),
MSA_3R_DF_d = (3U << 21),
// MSA: Operation Field for 3RF Instruction Format
FCAF = ((0U << 22) + 26),
FCUN = ((1U << 22) + 26),
FCEQ = ((2U << 22) + 26),
FCUEQ = ((3U << 22) + 26),
FCLT = ((4U << 22) + 26),
FCULT = ((5U << 22) + 26),
FCLE = ((6U << 22) + 26),
FCULE = ((7U << 22) + 26),
FSAF = ((8U << 22) + 26),
FSUN = ((9U << 22) + 26),
FSEQ = ((10U << 22) + 26),
FSUEQ = ((11U << 22) + 26),
FSLT = ((12U << 22) + 26),
FSULT = ((13U << 22) + 26),
FSLE = ((14U << 22) + 26),
FSULE = ((15U << 22) + 26),
FADD = ((0U << 22) + 27),
FSUB = ((1U << 22) + 27),
FMUL = ((2U << 22) + 27),
FDIV = ((3U << 22) + 27),
FMADD = ((4U << 22) + 27),
FMSUB = ((5U << 22) + 27),
FEXP2 = ((7U << 22) + 27),
FEXDO = ((8U << 22) + 27),
FTQ = ((10U << 22) + 27),
FMIN = ((12U << 22) + 27),
FMIN_A = ((13U << 22) + 27),
FMAX = ((14U << 22) + 27),
FMAX_A = ((15U << 22) + 27),
FCOR = ((1U << 22) + 28),
FCUNE = ((2U << 22) + 28),
FCNE = ((3U << 22) + 28),
MUL_Q = ((4U << 22) + 28),
MADD_Q = ((5U << 22) + 28),
MSUB_Q = ((6U << 22) + 28),
FSOR = ((9U << 22) + 28),
FSUNE = ((10U << 22) + 28),
FSNE = ((11U << 22) + 28),
MULR_Q = ((12U << 22) + 28),
MADDR_Q = ((13U << 22) + 28),
MSUBR_Q = ((14U << 22) + 28),
// MSA: Operation Field for ELM Instruction Format
MSA_ELM_MINOR = ((3U << 3) + 1),
SLDI = (0U << 22),
CTCMSA = ((0U << 22) | (62U << 16)),
SPLATI = (1U << 22),
CFCMSA = ((1U << 22) | (62U << 16)),
COPY_S = (2U << 22),
MOVE_V = ((2U << 22) | (62U << 16)),
COPY_U = (3U << 22),
INSERT = (4U << 22),
INSVE = (5U << 22),
ELM_DF_B = ((0U << 4) << 16),
ELM_DF_H = ((4U << 3) << 16),
ELM_DF_W = ((12U << 2) << 16),
ELM_DF_D = ((28U << 1) << 16),
// MSA: Operation Field for BIT Instruction Format
SLLI = ((0U << 23) + 9),
SRAI = ((1U << 23) + 9),
SRLI = ((2U << 23) + 9),
BCLRI = ((3U << 23) + 9),
BSETI = ((4U << 23) + 9),
BNEGI = ((5U << 23) + 9),
BINSLI = ((6U << 23) + 9),
BINSRI = ((7U << 23) + 9),
SAT_S = ((0U << 23) + 10),
SAT_U = ((1U << 23) + 10),
SRARI = ((2U << 23) + 10),
SRLRI = ((3U << 23) + 10),
BIT_DF_b = ((14U << 3) << 16),
BIT_DF_h = ((6U << 4) << 16),
BIT_DF_w = ((2U << 5) << 16),
BIT_DF_d = ((0U << 6) << 16),
NULLSF = 0U
};
enum MSAMinorOpcode : uint32_t {
kMsaMinorUndefined = 0,
kMsaMinorI8,
kMsaMinorI5,
kMsaMinorI10,
kMsaMinorBIT,
kMsaMinor3R,
kMsaMinor3RF,
kMsaMinorELM,
kMsaMinorVEC,
kMsaMinor2R,
kMsaMinor2RF,
kMsaMinorMI10
};
// ----- Emulated conditions.
// On MIPS we use this enum to abstract from conditional branch instructions.
// The 'U' prefix is used to specify unsigned comparisons.
......@@ -970,6 +1273,62 @@ class InstructionBase {
// Get the encoding type of the instruction.
inline Type InstructionType() const;
inline MSAMinorOpcode MSAMinorOpcodeField() const {
int op = this->FunctionFieldRaw();
switch (op) {
case 0:
case 1:
case 2:
return kMsaMinorI8;
case 6:
return kMsaMinorI5;
case 7:
return (((this->InstructionBits() & kMsaI5I10Mask) == LDI)
? kMsaMinorI10
: kMsaMinorI5);
case 9:
case 10:
return kMsaMinorBIT;
case 13:
case 14:
case 15:
case 16:
case 17:
case 18:
case 19:
case 20:
case 21:
return kMsaMinor3R;
case 25:
return kMsaMinorELM;
case 26:
case 27:
case 28:
return kMsaMinor3RF;
case 30:
switch (this->RsFieldRawNoAssert()) {
case MSA_2R_FORMAT:
return kMsaMinor2R;
case MSA_2RF_FORMAT:
return kMsaMinor2RF;
default:
return kMsaMinorVEC;
}
break;
case 32:
case 33:
case 34:
case 35:
case 36:
case 37:
case 38:
case 39:
return kMsaMinorMI10;
default:
return kMsaMinorUndefined;
}
}
protected:
InstructionBase() {}
};
......@@ -1026,6 +1385,18 @@ class InstructionGetters : public T {
return this->Bits(kFrShift + kFrBits - 1, kFrShift);
}
inline int WdValue() const {
return this->Bits(kWdShift + kWdBits - 1, kWdShift);
}
inline int WsValue() const {
return this->Bits(kWsShift + kWsBits - 1, kWsShift);
}
inline int WtValue() const {
return this->Bits(kWtShift + kWtBits - 1, kWtShift);
}
inline int Bp2Value() const {
DCHECK(this->InstructionType() == InstructionBase::kRegisterType);
return this->Bits(kBp2Shift + kBp2Bits - 1, kBp2Shift);
......@@ -1123,6 +1494,68 @@ class InstructionGetters : public T {
return this->Bits(kImm26Shift + kImm26Bits - 1, kImm26Shift);
}
inline int32_t MsaImm8Value() const {
DCHECK(this->InstructionType() == InstructionBase::kImmediateType);
return this->Bits(kMsaImm8Shift + kMsaImm8Bits - 1, kMsaImm8Shift);
}
inline int32_t MsaImm5Value() const {
DCHECK(this->InstructionType() == InstructionBase::kImmediateType);
return this->Bits(kMsaImm5Shift + kMsaImm5Bits - 1, kMsaImm5Shift);
}
inline int32_t MsaImm10Value() const {
DCHECK(this->InstructionType() == InstructionBase::kImmediateType);
return this->Bits(kMsaImm10Shift + kMsaImm10Bits - 1, kMsaImm10Shift);
}
inline int32_t MsaImmMI10Value() const {
DCHECK(this->InstructionType() == InstructionBase::kImmediateType);
return this->Bits(kMsaImmMI10Shift + kMsaImmMI10Bits - 1, kMsaImmMI10Shift);
}
inline int32_t MsaBitDf() const {
DCHECK(this->InstructionType() == InstructionBase::kImmediateType);
int32_t df_m = this->Bits(22, 16);
if (((df_m >> 6) & 1U) == 0) {
return 3;
} else if (((df_m >> 5) & 3U) == 2) {
return 2;
} else if (((df_m >> 4) & 7U) == 6) {
return 1;
} else if (((df_m >> 3) & 15U) == 14) {
return 0;
} else {
return -1;
}
}
inline int32_t MsaBitMValue() const {
DCHECK(this->InstructionType() == InstructionBase::kImmediateType);
return this->Bits(16 + this->MsaBitDf() + 3, 16);
}
inline int32_t MsaElmDf() const {
DCHECK(this->InstructionType() == InstructionBase::kImmediateType);
int32_t df_n = this->Bits(21, 16);
if (((df_n >> 4) & 3U) == 0) {
return 0;
} else if (((df_n >> 3) & 7U) == 4) {
return 1;
} else if (((df_n >> 2) & 15U) == 12) {
return 2;
} else if (((df_n >> 1) & 31U) == 28) {
return 3;
} else {
return -1;
}
}
inline int32_t MsaElmNValue() const {
DCHECK(this->InstructionType() == InstructionBase::kImmediateType);
return this->Bits(16 + 4 - this->MsaElmDf(), 16);
}
static bool IsForbiddenAfterBranchInstr(Instr instr);
// Say if the instruction should not be used in a branch delay slot or
......@@ -1139,6 +1572,33 @@ class InstructionGetters : public T {
bool IsLinkingInstruction() const;
// Say if the instruction is a break or a trap.
bool IsTrap() const;
inline bool IsMSABranchInstr() const {
if (this->OpcodeFieldRaw() == COP1) {
switch (this->RsFieldRaw()) {
case BZ_V:
case BZ_B:
case BZ_H:
case BZ_W:
case BZ_D:
case BNZ_V:
case BNZ_B:
case BNZ_H:
case BNZ_W:
case BNZ_D:
return true;
default:
return false;
}
}
return false;
}
inline bool IsMSAInstr() const {
if (this->IsMSABranchInstr() || (this->OpcodeFieldRaw() == MSA))
return true;
return false;
}
};
class Instruction : public InstructionGetters<InstructionBase> {
......@@ -1220,6 +1680,18 @@ InstructionBase::Type InstructionBase::InstructionType() const {
case BC1EQZ:
case BC1NEZ:
return kImmediateType;
// MSA Branch instructions
case BZ_V:
case BNZ_V:
case BZ_B:
case BZ_H:
case BZ_W:
case BZ_D:
case BNZ_B:
case BNZ_H:
case BNZ_W:
case BNZ_D:
return kImmediateType;
default:
return kRegisterType;
}
......@@ -1232,6 +1704,18 @@ InstructionBase::Type InstructionBase::InstructionType() const {
case JAL:
return kJumpType;
case MSA:
switch (MSAMinorOpcodeField()) {
case kMsaMinor3R:
case kMsaMinor3RF:
case kMsaMinorVEC:
case kMsaMinor2R:
case kMsaMinor2RF:
return kRegisterType;
default:
return kImmediateType;
}
default:
return kImmediateType;
}
......
......@@ -59,6 +59,17 @@ class Decoder {
int InstructionDecode(byte* instruction);
private:
const uint32_t kMsaI8Mask = ((3U << 24) | ((1 << 6) - 1));
const uint32_t kMsaI5Mask = ((7U << 23) | ((1 << 6) - 1));
const uint32_t kMsaMI10Mask = (15U << 2);
const uint32_t kMsaBITMask = ((7U << 23) | ((1 << 6) - 1));
const uint32_t kMsaELMMask = (15U << 22);
const uint32_t kMsa3RMask = ((7U << 23) | ((1 << 6) - 1));
const uint32_t kMsa3RFMask = ((15U << 22) | ((1 << 6) - 1));
const uint32_t kMsaVECMask = (23U << 21);
const uint32_t kMsa2RMask = (7U << 18);
const uint32_t kMsa2RFMask = (15U << 17);
// Bottleneck functions to print into the out_buffer.
void PrintChar(const char ch);
void Print(const char* str);
......@@ -66,7 +77,9 @@ class Decoder {
// Printing of common values.
void PrintRegister(int reg);
void PrintFPURegister(int freg);
void PrintMSARegister(int wreg);
void PrintFPUStatusRegister(int freg);
void PrintMSAControlRegister(int creg);
void PrintRs(Instruction* instr);
void PrintRt(Instruction* instr);
void PrintRd(Instruction* instr);
......@@ -100,12 +113,22 @@ class Decoder {
void PrintPCImm26(Instruction* instr);
void PrintCode(Instruction* instr); // For break and trap instructions.
void PrintFormat(Instruction* instr); // For floating format postfix.
void PrintMsaDataFormat(Instruction* instr);
void PrintMsaXImm8(Instruction* instr);
void PrintMsaImm8(Instruction* instr);
void PrintMsaImm5(Instruction* instr);
void PrintMsaSImm5(Instruction* instr);
void PrintMsaSImm10(Instruction* instr, bool is_mi10 = false);
void PrintMsaImmBit(Instruction* instr);
void PrintMsaImmElm(Instruction* instr);
void PrintMsaCopy(Instruction* instr);
// Printing of instruction name.
void PrintInstructionName(Instruction* instr);
// Handle formatting of instructions and their options.
int FormatRegister(Instruction* instr, const char* option);
int FormatFPURegister(Instruction* instr, const char* option);
int FormatMSARegister(Instruction* instr, const char* option);
int FormatOption(Instruction* instr, const char* option);
void Format(Instruction* instr, const char* format);
void Unknown(Instruction* instr);
......@@ -123,6 +146,17 @@ class Decoder {
void DecodeTypeRegister(Instruction* instr);
void DecodeTypeImmediate(Instruction* instr);
void DecodeTypeJump(Instruction* instr);
void DecodeTypeMsaI8(Instruction* instr);
void DecodeTypeMsaI5(Instruction* instr);
void DecodeTypeMsaI10(Instruction* instr);
void DecodeTypeMsaELM(Instruction* instr);
void DecodeTypeMsaBIT(Instruction* instr);
void DecodeTypeMsaMI10(Instruction* instr);
void DecodeTypeMsa3R(Instruction* instr);
void DecodeTypeMsa3RF(Instruction* instr);
void DecodeTypeMsaVec(Instruction* instr);
void DecodeTypeMsa2R(Instruction* instr);
void DecodeTypeMsa2RF(Instruction* instr);
const disasm::NameConverter& converter_;
v8::internal::Vector<char> out_buffer_;
......@@ -183,6 +217,7 @@ void Decoder::PrintFPURegister(int freg) {
Print(converter_.NameOfXMMRegister(freg));
}
void Decoder::PrintMSARegister(int wreg) { Print(MSARegisters::Name(wreg)); }
void Decoder::PrintFPUStatusRegister(int freg) {
switch (freg) {
......@@ -194,6 +229,18 @@ void Decoder::PrintFPUStatusRegister(int freg) {
}
}
void Decoder::PrintMSAControlRegister(int creg) {
switch (creg) {
case kMSAIRRegister:
Print("MSAIR");
break;
case kMSACSRRegister:
Print("MSACSR");
break;
default:
Print("no_msacreg");
}
}
void Decoder::PrintFs(Instruction* instr) {
int freg = instr->RsValue();
......@@ -441,6 +488,53 @@ void Decoder::PrintCode(Instruction* instr) {
}
}
void Decoder::PrintMsaXImm8(Instruction* instr) {
int32_t imm = instr->MsaImm8Value();
out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "0x%x", imm);
}
void Decoder::PrintMsaImm8(Instruction* instr) {
int32_t imm = instr->MsaImm8Value();
out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "%u", imm);
}
void Decoder::PrintMsaImm5(Instruction* instr) {
int32_t imm = instr->MsaImm5Value();
out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "%u", imm);
}
void Decoder::PrintMsaSImm5(Instruction* instr) {
int32_t imm = instr->MsaImm5Value();
imm <<= (32 - kMsaImm5Bits);
imm >>= (32 - kMsaImm5Bits);
out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "%d", imm);
}
void Decoder::PrintMsaSImm10(Instruction* instr, bool is_mi10) {
int32_t imm = is_mi10 ? instr->MsaImmMI10Value() : instr->MsaImm10Value();
imm <<= (32 - kMsaImm10Bits);
imm >>= (32 - kMsaImm10Bits);
out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "%d", imm);
}
void Decoder::PrintMsaImmBit(Instruction* instr) {
int32_t m = instr->MsaBitMValue();
out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "%u", m);
}
void Decoder::PrintMsaImmElm(Instruction* instr) {
int32_t n = instr->MsaElmNValue();
out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "%u", n);
}
void Decoder::PrintMsaCopy(Instruction* instr) {
int32_t rd = instr->WdValue();
int32_t ws = instr->WsValue();
int32_t n = instr->MsaElmNValue();
out_buffer_pos_ +=
SNPrintF(out_buffer_ + out_buffer_pos_, "%s, %s[%u]",
converter_.NameOfCPURegister(rd), MSARegisters::Name(ws), n);
}
void Decoder::PrintFormat(Instruction* instr) {
char formatLetter = ' ';
......@@ -464,6 +558,84 @@ void Decoder::PrintFormat(Instruction* instr) {
PrintChar(formatLetter);
}
void Decoder::PrintMsaDataFormat(Instruction* instr) {
DCHECK(instr->IsMSAInstr());
char df = ' ';
if (instr->IsMSABranchInstr()) {
switch (instr->RsFieldRaw()) {
case BZ_V:
case BNZ_V:
df = 'v';
break;
case BZ_B:
case BNZ_B:
df = 'b';
break;
case BZ_H:
case BNZ_H:
df = 'h';
break;
case BZ_W:
case BNZ_W:
df = 'w';
break;
case BZ_D:
case BNZ_D:
df = 'd';
break;
default:
UNREACHABLE();
break;
}
} else {
char DF[] = {'b', 'h', 'w', 'd'};
switch (instr->MSAMinorOpcodeField()) {
case kMsaMinorI5:
case kMsaMinorI10:
case kMsaMinor3R:
df = DF[instr->Bits(22, 21)];
break;
case kMsaMinorMI10:
df = DF[instr->Bits(1, 0)];
break;
case kMsaMinorBIT:
df = DF[instr->MsaBitDf()];
break;
case kMsaMinorELM:
df = DF[instr->MsaElmDf()];
break;
case kMsaMinor3RF: {
uint32_t opcode = instr->InstructionBits() & kMsa3RFMask;
switch (opcode) {
case FEXDO:
case FTQ:
case MUL_Q:
case MADD_Q:
case MSUB_Q:
case MULR_Q:
case MADDR_Q:
case MSUBR_Q:
df = DF[1 + instr->Bit(21)];
break;
default:
df = DF[2 + instr->Bit(21)];
break;
}
} break;
case kMsaMinor2R:
df = DF[instr->Bits(17, 16)];
break;
case kMsaMinor2RF:
df = DF[2 + instr->Bit(16)];
break;
default:
UNREACHABLE();
break;
}
}
PrintChar(df);
}
// Printing of instruction name.
void Decoder::PrintInstructionName(Instruction* instr) {
......@@ -537,6 +709,27 @@ int Decoder::FormatFPURegister(Instruction* instr, const char* format) {
return -1;
}
// Handle all MSARegister based formatting in this function to reduce the
// complexity of FormatOption.
int Decoder::FormatMSARegister(Instruction* instr, const char* format) {
DCHECK(format[0] == 'w');
if (format[1] == 's') {
int reg = instr->WsValue();
PrintMSARegister(reg);
return 2;
} else if (format[1] == 't') {
int reg = instr->WtValue();
PrintMSARegister(reg);
return 2;
} else if (format[1] == 'd') {
int reg = instr->WdValue();
PrintMSARegister(reg);
return 2;
}
UNREACHABLE();
return -1;
}
// FormatOption takes a formatting string and interprets it based on
// the current instructions. The format string points to the first
......@@ -613,6 +806,16 @@ int Decoder::FormatOption(Instruction* instr, const char* format) {
break;
}
return 6;
} else if (format[4] == '0' && format[5] == 's') {
DCHECK(STRING_STARTS_WITH(format, "imm10s"));
if (format[6] == '1') {
DCHECK(STRING_STARTS_WITH(format, "imm10s1"));
PrintMsaSImm10(instr, false);
} else if (format[6] == '2') {
DCHECK(STRING_STARTS_WITH(format, "imm10s2"));
PrintMsaSImm10(instr, true);
}
return 7;
}
} else if (format[3] == '2' && format[4] == '1') {
DCHECK(STRING_STARTS_WITH(format, "imm21"));
......@@ -681,6 +884,28 @@ int Decoder::FormatOption(Instruction* instr, const char* format) {
}
}
return 6;
} else if (format[3] == '5') {
DCHECK(STRING_STARTS_WITH(format, "imm5"));
if (format[4] == 'u') {
DCHECK(STRING_STARTS_WITH(format, "imm5u"));
PrintMsaImm5(instr);
} else if (format[4] == 's') {
DCHECK(STRING_STARTS_WITH(format, "imm5s"));
PrintMsaSImm5(instr);
}
return 5;
} else if (format[3] == '8') {
DCHECK(STRING_STARTS_WITH(format, "imm8"));
PrintMsaImm8(instr);
return 4;
} else if (format[3] == 'b') {
DCHECK(STRING_STARTS_WITH(format, "immb"));
PrintMsaImmBit(instr);
return 4;
} else if (format[3] == 'e') {
DCHECK(STRING_STARTS_WITH(format, "imme"));
PrintMsaImmElm(instr);
return 4;
}
}
case 'r': { // 'r: registers.
......@@ -689,6 +914,9 @@ int Decoder::FormatOption(Instruction* instr, const char* format) {
case 'f': { // 'f: FPUregisters.
return FormatFPURegister(instr, format);
}
case 'w': { // 'w: MSA Register
return FormatMSARegister(instr, format);
}
case 's': { // 'sa.
switch (format[1]) {
case 'a':
......@@ -744,7 +972,11 @@ int Decoder::FormatOption(Instruction* instr, const char* format) {
return 2;
}
case 't':
PrintFormat(instr);
if (instr->IsMSAInstr()) {
PrintMsaDataFormat(instr);
} else {
PrintFormat(instr);
}
return 1;
}
UNREACHABLE();
......@@ -1401,6 +1633,27 @@ void Decoder::DecodeTypeRegister(Instruction* instr) {
case SPECIAL3:
DecodeTypeRegisterSPECIAL3(instr);
break;
case MSA:
switch (instr->MSAMinorOpcodeField()) {
case kMsaMinor3R:
DecodeTypeMsa3R(instr);
break;
case kMsaMinor3RF:
DecodeTypeMsa3RF(instr);
break;
case kMsaMinorVEC:
DecodeTypeMsaVec(instr);
break;
case kMsaMinor2R:
DecodeTypeMsa2R(instr);
break;
case kMsaMinor2RF:
DecodeTypeMsa2RF(instr);
break;
default:
UNREACHABLE();
}
break;
default:
UNREACHABLE();
}
......@@ -1424,6 +1677,20 @@ void Decoder::DecodeTypeImmediate(Instruction* instr) {
case BC1NEZ:
Format(instr, "bc1nez 'ft, 'imm16u -> 'imm16p4s2");
break;
case BZ_V:
case BZ_B:
case BZ_H:
case BZ_W:
case BZ_D:
Format(instr, "bz.'t 'wt, 'imm16s -> 'imm16p4s2");
break;
case BNZ_V:
case BNZ_B:
case BNZ_H:
case BNZ_W:
case BNZ_D:
Format(instr, "bnz.'t 'wt, 'imm16s -> 'imm16p4s2");
break;
default:
UNREACHABLE();
}
......@@ -1683,6 +1950,31 @@ void Decoder::DecodeTypeImmediate(Instruction* instr) {
}
break;
}
case MSA:
switch (instr->MSAMinorOpcodeField()) {
case kMsaMinorI8:
DecodeTypeMsaI8(instr);
break;
case kMsaMinorI5:
DecodeTypeMsaI5(instr);
break;
case kMsaMinorI10:
DecodeTypeMsaI10(instr);
break;
case kMsaMinorELM:
DecodeTypeMsaELM(instr);
break;
case kMsaMinorBIT:
DecodeTypeMsaBIT(instr);
break;
case kMsaMinorMI10:
DecodeTypeMsaMI10(instr);
break;
default:
UNREACHABLE();
break;
}
break;
default:
printf("a 0x%x \n", instr->OpcodeFieldRaw());
UNREACHABLE();
......@@ -1704,6 +1996,636 @@ void Decoder::DecodeTypeJump(Instruction* instr) {
}
}
void Decoder::DecodeTypeMsaI8(Instruction* instr) {
uint32_t opcode = instr->InstructionBits() & kMsaI8Mask;
switch (opcode) {
case ANDI_B:
Format(instr, "andi.b 'wd, 'ws, 'imm8");
break;
case ORI_B:
Format(instr, "ori.b 'wd, 'ws, 'imm8");
break;
case NORI_B:
Format(instr, "nori.b 'wd, 'ws, 'imm8");
break;
case XORI_B:
Format(instr, "xori.b 'wd, 'ws, 'imm8");
break;
case BMNZI_B:
Format(instr, "bmnzi.b 'wd, 'ws, 'imm8");
break;
case BMZI_B:
Format(instr, "bmzi.b 'wd, 'ws, 'imm8");
break;
case BSELI_B:
Format(instr, "bseli.b 'wd, 'ws, 'imm8");
break;
case SHF_B:
Format(instr, "shf.b 'wd, 'ws, 'imm8");
break;
case SHF_H:
Format(instr, "shf.h 'wd, 'ws, 'imm8");
break;
case SHF_W:
Format(instr, "shf.w 'wd, 'ws, 'imm8");
break;
default:
UNREACHABLE();
}
}
void Decoder::DecodeTypeMsaI5(Instruction* instr) {
uint32_t opcode = instr->InstructionBits() & kMsaI5Mask;
switch (opcode) {
case ADDVI:
Format(instr, "addvi.'t 'wd, 'ws, 'imm5u");
break;
case SUBVI:
Format(instr, "subvi.'t 'wd, 'ws, 'imm5u");
break;
case MAXI_S:
Format(instr, "maxi_s.'t 'wd, 'ws, 'imm5s");
break;
case MAXI_U:
Format(instr, "maxi_u.'t 'wd, 'ws, 'imm5u");
break;
case MINI_S:
Format(instr, "mini_s.'t 'wd, 'ws, 'imm5s");
break;
case MINI_U:
Format(instr, "mini_u.'t 'wd, 'ws, 'imm5u");
break;
case CEQI:
Format(instr, "ceqi.'t 'wd, 'ws, 'imm5s");
break;
case CLTI_S:
Format(instr, "clti_s.'t 'wd, 'ws, 'imm5s");
break;
case CLTI_U:
Format(instr, "clti_u.'t 'wd, 'ws, 'imm5u");
break;
case CLEI_S:
Format(instr, "clei_s.'t 'wd, 'ws, 'imm5s");
break;
case CLEI_U:
Format(instr, "clei_u.'t 'wd, 'ws, 'imm5u");
break;
default:
UNREACHABLE();
}
}
void Decoder::DecodeTypeMsaI10(Instruction* instr) {
uint32_t opcode = instr->InstructionBits() & kMsaI5Mask;
if (opcode == LDI) {
Format(instr, "ldi.'t 'wd, 'imm10s1");
} else {
UNREACHABLE();
}
}
void Decoder::DecodeTypeMsaELM(Instruction* instr) {
uint32_t opcode = instr->InstructionBits() & kMsaELMMask;
switch (opcode) {
case SLDI:
if (instr->Bits(21, 16) == 0x3E) {
Format(instr, "ctcmsa ");
PrintMSAControlRegister(instr->WdValue());
Print(", ");
PrintRegister(instr->WsValue());
} else {
Format(instr, "sldi.'t 'wd, 'ws['imme]");
}
break;
case SPLATI:
if (instr->Bits(21, 16) == 0x3E) {
Format(instr, "cfcmsa ");
PrintRegister(instr->WdValue());
Print(", ");
PrintMSAControlRegister(instr->WsValue());
} else {
Format(instr, "splati.'t 'wd, 'ws['imme]");
}
break;
case COPY_S:
if (instr->Bits(21, 16) == 0x3E) {
Format(instr, "move.v 'wd, 'ws");
} else {
Format(instr, "copy_s.'t ");
PrintMsaCopy(instr);
}
break;
case COPY_U:
Format(instr, "copy_u.'t ");
PrintMsaCopy(instr);
break;
case INSERT:
Format(instr, "insert.'t 'wd['imme], ");
PrintRegister(instr->WsValue());
break;
case INSVE:
Format(instr, "insve.'t 'wd['imme], 'ws[0]");
break;
default:
UNREACHABLE();
}
}
void Decoder::DecodeTypeMsaBIT(Instruction* instr) {
uint32_t opcode = instr->InstructionBits() & kMsaBITMask;
switch (opcode) {
case SLLI:
Format(instr, "slli.'t 'wd, 'ws, 'immb");
break;
case SRAI:
Format(instr, "srai.'t 'wd, 'ws, 'immb");
break;
case SRLI:
Format(instr, "srli.'t 'wd, 'ws, 'immb");
break;
case BCLRI:
Format(instr, "bclri.'t 'wd, 'ws, 'immb");
break;
case BSETI:
Format(instr, "bseti.'t 'wd, 'ws, 'immb");
break;
case BNEGI:
Format(instr, "bnegi.'t 'wd, 'ws, 'immb");
break;
case BINSLI:
Format(instr, "binsli.'t 'wd, 'ws, 'immb");
break;
case BINSRI:
Format(instr, "binsri.'t 'wd, 'ws, 'immb");
break;
case SAT_S:
Format(instr, "sat_s.'t 'wd, 'ws, 'immb");
break;
case SAT_U:
Format(instr, "sat_u.'t 'wd, 'ws, 'immb");
break;
case SRARI:
Format(instr, "srari.'t 'wd, 'ws, 'immb");
break;
case SRLRI:
Format(instr, "srlri.'t 'wd, 'ws, 'immb");
break;
default:
UNREACHABLE();
}
}
void Decoder::DecodeTypeMsaMI10(Instruction* instr) {
uint32_t opcode = instr->InstructionBits() & kMsaMI10Mask;
if (opcode == MSA_LD) {
Format(instr, "ld.'t 'wd, 'imm10s2(");
PrintRegister(instr->WsValue());
Print(")");
} else if (opcode == MSA_ST) {
Format(instr, "st.'t 'wd, 'imm10s2(");
PrintRegister(instr->WsValue());
Print(")");
} else {
UNREACHABLE();
}
}
void Decoder::DecodeTypeMsa3R(Instruction* instr) {
uint32_t opcode = instr->InstructionBits() & kMsa3RMask;
switch (opcode) {
case SLL_MSA:
Format(instr, "sll.'t 'wd, 'ws, 'wt");
break;
case SRA_MSA:
Format(instr, "sra.'t 'wd, 'ws, 'wt");
break;
case SRL_MSA:
Format(instr, "srl.'t 'wd, 'ws, 'wt");
break;
case BCLR:
Format(instr, "bclr.'t 'wd, 'ws, 'wt");
break;
case BSET:
Format(instr, "bset.'t 'wd, 'ws, 'wt");
break;
case BNEG:
Format(instr, "bneg.'t 'wd, 'ws, 'wt");
break;
case BINSL:
Format(instr, "binsl.'t 'wd, 'ws, 'wt");
break;
case BINSR:
Format(instr, "binsr.'t 'wd, 'ws, 'wt");
break;
case ADDV:
Format(instr, "addv.'t 'wd, 'ws, 'wt");
break;
case SUBV:
Format(instr, "subv.'t 'wd, 'ws, 'wt");
break;
case MAX_S:
Format(instr, "max_s.'t 'wd, 'ws, 'wt");
break;
case MAX_U:
Format(instr, "max_u.'t 'wd, 'ws, 'wt");
break;
case MIN_S:
Format(instr, "min_s.'t 'wd, 'ws, 'wt");
break;
case MIN_U:
Format(instr, "min_u.'t 'wd, 'ws, 'wt");
break;
case MAX_A:
Format(instr, "max_a.'t 'wd, 'ws, 'wt");
break;
case MIN_A:
Format(instr, "min_a.'t 'wd, 'ws, 'wt");
break;
case CEQ:
Format(instr, "ceq.'t 'wd, 'ws, 'wt");
break;
case CLT_S:
Format(instr, "clt_s.'t 'wd, 'ws, 'wt");
break;
case CLT_U:
Format(instr, "clt_u.'t 'wd, 'ws, 'wt");
break;
case CLE_S:
Format(instr, "cle_s.'t 'wd, 'ws, 'wt");
break;
case CLE_U:
Format(instr, "cle_u.'t 'wd, 'ws, 'wt");
break;
case ADD_A:
Format(instr, "add_a.'t 'wd, 'ws, 'wt");
break;
case ADDS_A:
Format(instr, "adds_a.'t 'wd, 'ws, 'wt");
break;
case ADDS_S:
Format(instr, "adds_s.'t 'wd, 'ws, 'wt");
break;
case ADDS_U:
Format(instr, "adds_u.'t 'wd, 'ws, 'wt");
break;
case AVE_S:
Format(instr, "ave_s.'t 'wd, 'ws, 'wt");
break;
case AVE_U:
Format(instr, "ave_u.'t 'wd, 'ws, 'wt");
break;
case AVER_S:
Format(instr, "aver_s.'t 'wd, 'ws, 'wt");
break;
case AVER_U:
Format(instr, "aver_u.'t 'wd, 'ws, 'wt");
break;
case SUBS_S:
Format(instr, "subs_s.'t 'wd, 'ws, 'wt");
break;
case SUBS_U:
Format(instr, "subs_u.'t 'wd, 'ws, 'wt");
break;
case SUBSUS_U:
Format(instr, "subsus_u.'t 'wd, 'ws, 'wt");
break;
case SUBSUU_S:
Format(instr, "subsuu_s.'t 'wd, 'ws, 'wt");
break;
case ASUB_S:
Format(instr, "asub_s.'t 'wd, 'ws, 'wt");
break;
case ASUB_U:
Format(instr, "asub_u.'t 'wd, 'ws, 'wt");
break;
case MULV:
Format(instr, "mulv.'t 'wd, 'ws, 'wt");
break;
case MADDV:
Format(instr, "maddv.'t 'wd, 'ws, 'wt");
break;
case MSUBV:
Format(instr, "msubv.'t 'wd, 'ws, 'wt");
break;
case DIV_S_MSA:
Format(instr, "div_s.'t 'wd, 'ws, 'wt");
break;
case DIV_U:
Format(instr, "div_u.'t 'wd, 'ws, 'wt");
break;
case MOD_S:
Format(instr, "mod_s.'t 'wd, 'ws, 'wt");
break;
case MOD_U:
Format(instr, "mod_u.'t 'wd, 'ws, 'wt");
break;
case DOTP_S:
Format(instr, "dotp_s.'t 'wd, 'ws, 'wt");
break;
case DOTP_U:
Format(instr, "dotp_u.'t 'wd, 'ws, 'wt");
break;
case DPADD_S:
Format(instr, "dpadd_s.'t 'wd, 'ws, 'wt");
break;
case DPADD_U:
Format(instr, "dpadd_u.'t 'wd, 'ws, 'wt");
break;
case DPSUB_S:
Format(instr, "dpsub_s.'t 'wd, 'ws, 'wt");
break;
case DPSUB_U:
Format(instr, "dpsub_u.'t 'wd, 'ws, 'wt");
break;
case SLD:
Format(instr, "sld.'t 'wd, 'ws['rt]");
break;
case SPLAT:
Format(instr, "splat.'t 'wd, 'ws['rt]");
break;
case PCKEV:
Format(instr, "pckev.'t 'wd, 'ws, 'wt");
break;
case PCKOD:
Format(instr, "pckod.'t 'wd, 'ws, 'wt");
break;
case ILVL:
Format(instr, "ilvl.'t 'wd, 'ws, 'wt");
break;
case ILVR:
Format(instr, "ilvr.'t 'wd, 'ws, 'wt");
break;
case ILVEV:
Format(instr, "ilvev.'t 'wd, 'ws, 'wt");
break;
case ILVOD:
Format(instr, "ilvod.'t 'wd, 'ws, 'wt");
break;
case VSHF:
Format(instr, "vshf.'t 'wd, 'ws, 'wt");
break;
case SRAR:
Format(instr, "srar.'t 'wd, 'ws, 'wt");
break;
case SRLR:
Format(instr, "srlr.'t 'wd, 'ws, 'wt");
break;
case HADD_S:
Format(instr, "hadd_s.'t 'wd, 'ws, 'wt");
break;
case HADD_U:
Format(instr, "hadd_u.'t 'wd, 'ws, 'wt");
break;
case HSUB_S:
Format(instr, "hsub_s.'t 'wd, 'ws, 'wt");
break;
case HSUB_U:
Format(instr, "hsub_u.'t 'wd, 'ws, 'wt");
break;
default:
UNREACHABLE();
}
}
void Decoder::DecodeTypeMsa3RF(Instruction* instr) {
uint32_t opcode = instr->InstructionBits() & kMsa3RFMask;
switch (opcode) {
case FCAF:
Format(instr, "fcaf.'t 'wd, 'ws, 'wt");
break;
case FCUN:
Format(instr, "fcun.'t 'wd, 'ws, 'wt");
break;
case FCEQ:
Format(instr, "fceq.'t 'wd, 'ws, 'wt");
break;
case FCUEQ:
Format(instr, "fcueq.'t 'wd, 'ws, 'wt");
break;
case FCLT:
Format(instr, "fclt.'t 'wd, 'ws, 'wt");
break;
case FCULT:
Format(instr, "fcult.'t 'wd, 'ws, 'wt");
break;
case FCLE:
Format(instr, "fcle.'t 'wd, 'ws, 'wt");
break;
case FCULE:
Format(instr, "fcule.'t 'wd, 'ws, 'wt");
break;
case FSAF:
Format(instr, "fsaf.'t 'wd, 'ws, 'wt");
break;
case FSUN:
Format(instr, "fsun.'t 'wd, 'ws, 'wt");
break;
case FSEQ:
Format(instr, "fseq.'t 'wd, 'ws, 'wt");
break;
case FSUEQ:
Format(instr, "fsueq.'t 'wd, 'ws, 'wt");
break;
case FSLT:
Format(instr, "fslt.'t 'wd, 'ws, 'wt");
break;
case FSULT:
Format(instr, "fsult.'t 'wd, 'ws, 'wt");
break;
case FSLE:
Format(instr, "fsle.'t 'wd, 'ws, 'wt");
break;
case FSULE:
Format(instr, "fsule.'t 'wd, 'ws, 'wt");
break;
case FADD:
Format(instr, "fadd.'t 'wd, 'ws, 'wt");
break;
case FSUB:
Format(instr, "fsub.'t 'wd, 'ws, 'wt");
break;
case FMUL:
Format(instr, "fmul.'t 'wd, 'ws, 'wt");
break;
case FDIV:
Format(instr, "fdiv.'t 'wd, 'ws, 'wt");
break;
case FMADD:
Format(instr, "fmadd.'t 'wd, 'ws, 'wt");
break;
case FMSUB:
Format(instr, "fmsub.'t 'wd, 'ws, 'wt");
break;
case FEXP2:
Format(instr, "fexp2.'t 'wd, 'ws, 'wt");
break;
case FEXDO:
Format(instr, "fexdo.'t 'wd, 'ws, 'wt");
break;
case FTQ:
Format(instr, "ftq.'t 'wd, 'ws, 'wt");
break;
case FMIN:
Format(instr, "fmin.'t 'wd, 'ws, 'wt");
break;
case FMIN_A:
Format(instr, "fmin_a.'t 'wd, 'ws, 'wt");
break;
case FMAX:
Format(instr, "fmax.'t 'wd, 'ws, 'wt");
break;
case FMAX_A:
Format(instr, "fmax_a.'t 'wd, 'ws, 'wt");
break;
case FCOR:
Format(instr, "fcor.'t 'wd, 'ws, 'wt");
break;
case FCUNE:
Format(instr, "fcune.'t 'wd, 'ws, 'wt");
break;
case FCNE:
Format(instr, "fcne.'t 'wd, 'ws, 'wt");
break;
case MUL_Q:
Format(instr, "mul_q.'t 'wd, 'ws, 'wt");
break;
case MADD_Q:
Format(instr, "madd_q.'t 'wd, 'ws, 'wt");
break;
case MSUB_Q:
Format(instr, "msub_q.'t 'wd, 'ws, 'wt");
break;
case FSOR:
Format(instr, "fsor.'t 'wd, 'ws, 'wt");
break;
case FSUNE:
Format(instr, "fsune.'t 'wd, 'ws, 'wt");
break;
case FSNE:
Format(instr, "fsne.'t 'wd, 'ws, 'wt");
break;
case MULR_Q:
Format(instr, "mulr_q.'t 'wd, 'ws, 'wt");
break;
case MADDR_Q:
Format(instr, "maddr_q.'t 'wd, 'ws, 'wt");
break;
case MSUBR_Q:
Format(instr, "msubr_q.'t 'wd, 'ws, 'wt");
break;
default:
UNREACHABLE();
}
}
void Decoder::DecodeTypeMsaVec(Instruction* instr) {
uint32_t opcode = instr->InstructionBits() & kMsaVECMask;
switch (opcode) {
case AND_V:
Format(instr, "and.v 'wd, 'ws, 'wt");
break;
case OR_V:
Format(instr, "or.v 'wd, 'ws, 'wt");
break;
case NOR_V:
Format(instr, "nor.v 'wd, 'ws, 'wt");
break;
case XOR_V:
Format(instr, "xor.v 'wd, 'ws, 'wt");
break;
case BMNZ_V:
Format(instr, "bmnz.v 'wd, 'ws, 'wt");
break;
case BMZ_V:
Format(instr, "bmz.v 'wd, 'ws, 'wt");
break;
case BSEL_V:
Format(instr, "bsel.v 'wd, 'ws, 'wt");
break;
default:
UNREACHABLE();
}
}
void Decoder::DecodeTypeMsa2R(Instruction* instr) {
uint32_t opcode = instr->InstructionBits() & kMsa2RMask;
switch (opcode) {
case FILL: {
Format(instr, "fill.'t 'wd, ");
PrintRegister(instr->WsValue()); // rs value is in ws field
} break;
case PCNT:
Format(instr, "pcnt.'t 'wd, 'ws");
break;
case NLOC:
Format(instr, "nloc.'t 'wd, 'ws");
break;
case NLZC:
Format(instr, "nlzc.'t 'wd, 'ws");
break;
default:
UNREACHABLE();
}
}
void Decoder::DecodeTypeMsa2RF(Instruction* instr) {
uint32_t opcode = instr->InstructionBits() & kMsa2RFMask;
switch (opcode) {
case FCLASS:
Format(instr, "fclass.'t 'wd, 'ws");
break;
case FTRUNC_S:
Format(instr, "ftrunc_s.'t 'wd, 'ws");
break;
case FTRUNC_U:
Format(instr, "ftrunc_u.'t 'wd, 'ws");
break;
case FSQRT:
Format(instr, "fsqrt.'t 'wd, 'ws");
break;
case FRSQRT:
Format(instr, "frsqrt.'t 'wd, 'ws");
break;
case FRCP:
Format(instr, "frcp.'t 'wd, 'ws");
break;
case FRINT:
Format(instr, "frint.'t 'wd, 'ws");
break;
case FLOG2:
Format(instr, "flog2.'t 'wd, 'ws");
break;
case FEXUPL:
Format(instr, "fexupl.'t 'wd, 'ws");
break;
case FEXUPR:
Format(instr, "fexupr.'t 'wd, 'ws");
break;
case FFQL:
Format(instr, "ffql.'t 'wd, 'ws");
break;
case FFQR:
Format(instr, "ffqr.'t 'wd, 'ws");
break;
case FTINT_S:
Format(instr, "ftint_s.'t 'wd, 'ws");
break;
case FTINT_U:
Format(instr, "ftint_u.'t 'wd, 'ws");
break;
case FFINT_S:
Format(instr, "ffint_s.'t 'wd, 'ws");
break;
case FFINT_U:
Format(instr, "ffint_u.'t 'wd, 'ws");
break;
default:
UNREACHABLE();
}
}
// Disassemble the instruction at *instr_ptr into the output buffer.
int Decoder::InstructionDecode(byte* instr_ptr) {
......
......@@ -79,6 +79,7 @@ void CpuFeatures::ProbeImpl(bool cross_compile) {
// Probe for additional features at runtime.
base::CPU cpu;
if (cpu.has_fpu()) supported_ |= 1u << FPU;
if (cpu.has_msa()) supported_ |= 1u << MIPS_SIMD;
#endif
}
......@@ -1135,6 +1136,127 @@ void Assembler::GenInstrJump(Opcode opcode,
BlockTrampolinePoolFor(1); // For associated delay slot.
}
// MSA instructions
void Assembler::GenInstrMsaI8(SecondaryField operation, uint32_t imm8,
MSARegister ws, MSARegister wd) {
DCHECK((kArchVariant == kMips64r6) && IsEnabled(MIPS_SIMD));
DCHECK(ws.is_valid() && wd.is_valid() && is_uint8(imm8));
Instr instr = MSA | operation | ((imm8 & kImm8Mask) << kWtShift) |
(ws.code() << kWsShift) | (wd.code() << kWdShift);
emit(instr);
}
void Assembler::GenInstrMsaI5(SecondaryField operation, SecondaryField df,
int32_t imm5, MSARegister ws, MSARegister wd) {
DCHECK((kArchVariant == kMips64r6) && IsEnabled(MIPS_SIMD));
DCHECK(ws.is_valid() && wd.is_valid());
DCHECK((operation == MAXI_S) || (operation == MINI_S) ||
(operation == CEQI) || (operation == CLTI_S) ||
(operation == CLEI_S)
? is_int5(imm5)
: is_uint5(imm5));
Instr instr = MSA | operation | df | ((imm5 & kImm5Mask) << kWtShift) |
(ws.code() << kWsShift) | (wd.code() << kWdShift);
emit(instr);
}
void Assembler::GenInstrMsaBit(SecondaryField operation, SecondaryField df,
uint32_t m, MSARegister ws, MSARegister wd) {
DCHECK((kArchVariant == kMips64r6) && IsEnabled(MIPS_SIMD));
DCHECK(ws.is_valid() && wd.is_valid() && is_valid_msa_df_m(df, m));
Instr instr = MSA | operation | df | (m << kWtShift) |
(ws.code() << kWsShift) | (wd.code() << kWdShift);
emit(instr);
}
void Assembler::GenInstrMsaI10(SecondaryField operation, SecondaryField df,
int32_t imm10, MSARegister wd) {
DCHECK((kArchVariant == kMips64r6) && IsEnabled(MIPS_SIMD));
DCHECK(wd.is_valid() && is_int10(imm10));
Instr instr = MSA | operation | df | ((imm10 & kImm10Mask) << kWsShift) |
(wd.code() << kWdShift);
emit(instr);
}
template <typename RegType>
void Assembler::GenInstrMsa3R(SecondaryField operation, SecondaryField df,
RegType t, MSARegister ws, MSARegister wd) {
DCHECK((kArchVariant == kMips64r6) && IsEnabled(MIPS_SIMD));
DCHECK(t.is_valid() && ws.is_valid() && wd.is_valid());
Instr instr = MSA | operation | df | (t.code() << kWtShift) |
(ws.code() << kWsShift) | (wd.code() << kWdShift);
emit(instr);
}
template <typename DstType, typename SrcType>
void Assembler::GenInstrMsaElm(SecondaryField operation, SecondaryField df,
uint32_t n, SrcType src, DstType dst) {
DCHECK((kArchVariant == kMips64r6) && IsEnabled(MIPS_SIMD));
DCHECK(src.is_valid() && dst.is_valid() && is_valid_msa_df_n(df, n));
Instr instr = MSA | operation | df | (n << kWtShift) |
(src.code() << kWsShift) | (dst.code() << kWdShift) |
MSA_ELM_MINOR;
emit(instr);
}
void Assembler::GenInstrMsa3RF(SecondaryField operation, uint32_t df,
MSARegister wt, MSARegister ws, MSARegister wd) {
DCHECK((kArchVariant == kMips64r6) && IsEnabled(MIPS_SIMD));
DCHECK(wt.is_valid() && ws.is_valid() && wd.is_valid());
DCHECK(df < 2);
Instr instr = MSA | operation | (df << 21) | (wt.code() << kWtShift) |
(ws.code() << kWsShift) | (wd.code() << kWdShift);
emit(instr);
}
void Assembler::GenInstrMsaVec(SecondaryField operation, MSARegister wt,
MSARegister ws, MSARegister wd) {
DCHECK((kArchVariant == kMips64r6) && IsEnabled(MIPS_SIMD));
DCHECK(wt.is_valid() && ws.is_valid() && wd.is_valid());
Instr instr = MSA | operation | (wt.code() << kWtShift) |
(ws.code() << kWsShift) | (wd.code() << kWdShift) |
MSA_VEC_2R_2RF_MINOR;
emit(instr);
}
void Assembler::GenInstrMsaMI10(SecondaryField operation, int32_t s10,
Register rs, MSARegister wd) {
DCHECK((kArchVariant == kMips64r6) && IsEnabled(MIPS_SIMD));
DCHECK(rs.is_valid() && wd.is_valid() && is_int10(s10));
Instr instr = MSA | operation | ((s10 & kImm10Mask) << kWtShift) |
(rs.code() << kWsShift) | (wd.code() << kWdShift);
emit(instr);
}
void Assembler::GenInstrMsa2R(SecondaryField operation, SecondaryField df,
MSARegister ws, MSARegister wd) {
DCHECK((kArchVariant == kMips64r6) && IsEnabled(MIPS_SIMD));
DCHECK(ws.is_valid() && wd.is_valid());
Instr instr = MSA | MSA_2R_FORMAT | operation | df | (ws.code() << kWsShift) |
(wd.code() << kWdShift) | MSA_VEC_2R_2RF_MINOR;
emit(instr);
}
void Assembler::GenInstrMsa2RF(SecondaryField operation, SecondaryField df,
MSARegister ws, MSARegister wd) {
DCHECK((kArchVariant == kMips64r6) && IsEnabled(MIPS_SIMD));
DCHECK(ws.is_valid() && wd.is_valid());
Instr instr = MSA | MSA_2RF_FORMAT | operation | df |
(ws.code() << kWsShift) | (wd.code() << kWdShift) |
MSA_VEC_2R_2RF_MINOR;
emit(instr);
}
void Assembler::GenInstrMsaBranch(SecondaryField operation, MSARegister wt,
int32_t offset16) {
DCHECK((kArchVariant == kMips64r6) && IsEnabled(MIPS_SIMD));
DCHECK(wt.is_valid() && is_int16(offset16));
BlockTrampolinePoolScope block_trampoline_pool(this);
Instr instr =
COP1 | operation | (wt.code() << kWtShift) | (offset16 & kImm16Mask);
emit(instr);
BlockTrampolinePoolFor(1); // For associated delay slot.
}
// Returns the next free trampoline entry.
int32_t Assembler::get_trampoline_entry(int32_t pos) {
......@@ -3196,6 +3318,514 @@ void Assembler::bc1t(int16_t offset, uint16_t cc) {
emit(instr);
}
// ---------- MSA instructions ------------
#define MSA_BRANCH_LIST(V) \
V(bz_v, BZ_V) \
V(bz_b, BZ_B) \
V(bz_h, BZ_H) \
V(bz_w, BZ_W) \
V(bz_d, BZ_D) \
V(bnz_v, BNZ_V) \
V(bnz_b, BNZ_B) \
V(bnz_h, BNZ_H) \
V(bnz_w, BNZ_W) \
V(bnz_d, BNZ_D)
#define MSA_BRANCH(name, opcode) \
void Assembler::name(MSARegister wt, int16_t offset) { \
GenInstrMsaBranch(opcode, wt, offset); \
}
MSA_BRANCH_LIST(MSA_BRANCH)
#undef MSA_BRANCH
#undef MSA_BRANCH_LIST
#define MSA_LD_ST_LIST(V) \
V(ld_b, LD_B) \
V(ld_h, LD_H) \
V(ld_w, LD_W) \
V(ld_d, LD_D) \
V(st_b, ST_B) \
V(st_h, ST_H) \
V(st_w, ST_W) \
V(st_d, ST_D)
#define MSA_LD_ST(name, opcode) \
void Assembler::name(MSARegister wd, const MemOperand& rs) { \
if (is_int10(rs.offset())) { \
GenInstrMsaMI10(opcode, rs.offset(), rs.rm(), wd); \
} else { \
LoadRegPlusOffsetToAt(rs); \
GenInstrMsaMI10(opcode, 0, at, wd); \
} \
}
MSA_LD_ST_LIST(MSA_LD_ST)
#undef MSA_LD_ST
#undef MSA_BRANCH_LIST
#define MSA_I10_LIST(V) \
V(ldi_b, I5_DF_b) \
V(ldi_h, I5_DF_h) \
V(ldi_w, I5_DF_w) \
V(ldi_d, I5_DF_d)
#define MSA_I10(name, format) \
void Assembler::name(MSARegister wd, int32_t imm10) { \
GenInstrMsaI10(LDI, format, imm10, wd); \
}
MSA_I10_LIST(MSA_I10)
#undef MSA_I10
#undef MSA_I10_LIST
#define MSA_I5_LIST(V) \
V(addvi, ADDVI) \
V(subvi, SUBVI) \
V(maxi_s, MAXI_S) \
V(maxi_u, MAXI_U) \
V(mini_s, MINI_S) \
V(mini_u, MINI_U) \
V(ceqi, CEQI) \
V(clti_s, CLTI_S) \
V(clti_u, CLTI_U) \
V(clei_s, CLEI_S) \
V(clei_u, CLEI_U)
#define MSA_I5_FORMAT(name, opcode, format) \
void Assembler::name##_##format(MSARegister wd, MSARegister ws, \
uint32_t imm5) { \
GenInstrMsaI5(opcode, I5_DF_##format, imm5, ws, wd); \
}
#define MSA_I5(name, opcode) \
MSA_I5_FORMAT(name, opcode, b) \
MSA_I5_FORMAT(name, opcode, h) \
MSA_I5_FORMAT(name, opcode, w) \
MSA_I5_FORMAT(name, opcode, d)
MSA_I5_LIST(MSA_I5)
#undef MSA_I5
#undef MSA_I5_FORMAT
#undef MSA_I5_LIST
#define MSA_I8_LIST(V) \
V(andi_b, ANDI_B) \
V(ori_b, ORI_B) \
V(nori_b, NORI_B) \
V(xori_b, XORI_B) \
V(bmnzi_b, BMNZI_B) \
V(bmzi_b, BMZI_B) \
V(bseli_b, BSELI_B) \
V(shf_b, SHF_B) \
V(shf_h, SHF_H) \
V(shf_w, SHF_W)
#define MSA_I8(name, opcode) \
void Assembler::name(MSARegister wd, MSARegister ws, uint32_t imm8) { \
GenInstrMsaI8(opcode, imm8, ws, wd); \
}
MSA_I8_LIST(MSA_I8)
#undef MSA_I8
#undef MSA_I8_LIST
#define MSA_VEC_LIST(V) \
V(and_v, AND_V) \
V(or_v, OR_V) \
V(nor_v, NOR_V) \
V(xor_v, XOR_V) \
V(bmnz_v, BMNZ_V) \
V(bmz_v, BMZ_V) \
V(bsel_v, BSEL_V)
#define MSA_VEC(name, opcode) \
void Assembler::name(MSARegister wd, MSARegister ws, MSARegister wt) { \
GenInstrMsaVec(opcode, wt, ws, wd); \
}
MSA_VEC_LIST(MSA_VEC)
#undef MSA_VEC
#undef MSA_VEC_LIST
#define MSA_2R_LIST(V) \
V(pcnt, PCNT) \
V(nloc, NLOC) \
V(nlzc, NLZC)
#define MSA_2R_FORMAT(name, opcode, format) \
void Assembler::name##_##format(MSARegister wd, MSARegister ws) { \
GenInstrMsa2R(opcode, MSA_2R_DF_##format, ws, wd); \
}
#define MSA_2R(name, opcode) \
MSA_2R_FORMAT(name, opcode, b) \
MSA_2R_FORMAT(name, opcode, h) \
MSA_2R_FORMAT(name, opcode, w) \
MSA_2R_FORMAT(name, opcode, d)
MSA_2R_LIST(MSA_2R)
#undef MSA_2R
#undef MSA_2R_FORMAT
#undef MSA_2R_LIST
#define MSA_FILL(format) \
void Assembler::fill_##format(MSARegister wd, Register rs) { \
DCHECK((kArchVariant == kMips64r6) && IsEnabled(MIPS_SIMD)); \
DCHECK(rs.is_valid() && wd.is_valid()); \
Instr instr = MSA | MSA_2R_FORMAT | FILL | MSA_2R_DF_##format | \
(rs.code() << kWsShift) | (wd.code() << kWdShift) | \
MSA_VEC_2R_2RF_MINOR; \
emit(instr); \
}
MSA_FILL(b)
MSA_FILL(h)
MSA_FILL(w)
MSA_FILL(d)
#undef MSA_FILL
#define MSA_2RF_LIST(V) \
V(fclass, FCLASS) \
V(ftrunc_s, FTRUNC_S) \
V(ftrunc_u, FTRUNC_U) \
V(fsqrt, FSQRT) \
V(frsqrt, FRSQRT) \
V(frcp, FRCP) \
V(frint, FRINT) \
V(flog2, FLOG2) \
V(fexupl, FEXUPL) \
V(fexupr, FEXUPR) \
V(ffql, FFQL) \
V(ffqr, FFQR) \
V(ftint_s, FTINT_S) \
V(ftint_u, FTINT_U) \
V(ffint_s, FFINT_S) \
V(ffint_u, FFINT_U)
#define MSA_2RF_FORMAT(name, opcode, format) \
void Assembler::name##_##format(MSARegister wd, MSARegister ws) { \
GenInstrMsa2RF(opcode, MSA_2RF_DF_##format, ws, wd); \
}
#define MSA_2RF(name, opcode) \
MSA_2RF_FORMAT(name, opcode, w) \
MSA_2RF_FORMAT(name, opcode, d)
MSA_2RF_LIST(MSA_2RF)
#undef MSA_2RF
#undef MSA_2RF_FORMAT
#undef MSA_2RF_LIST
#define MSA_3R_LIST(V) \
V(sll, SLL_MSA) \
V(sra, SRA_MSA) \
V(srl, SRL_MSA) \
V(bclr, BCLR) \
V(bset, BSET) \
V(bneg, BNEG) \
V(binsl, BINSL) \
V(binsr, BINSR) \
V(addv, ADDV) \
V(subv, SUBV) \
V(max_s, MAX_S) \
V(max_u, MAX_U) \
V(min_s, MIN_S) \
V(min_u, MIN_U) \
V(max_a, MAX_A) \
V(min_a, MIN_A) \
V(ceq, CEQ) \
V(clt_s, CLT_S) \
V(clt_u, CLT_U) \
V(cle_s, CLE_S) \
V(cle_u, CLE_U) \
V(add_a, ADD_A) \
V(adds_a, ADDS_A) \
V(adds_s, ADDS_S) \
V(adds_u, ADDS_U) \
V(ave_s, AVE_S) \
V(ave_u, AVE_U) \
V(aver_s, AVER_S) \
V(aver_u, AVER_U) \
V(subs_s, SUBS_S) \
V(subs_u, SUBS_U) \
V(subsus_u, SUBSUS_U) \
V(subsuu_s, SUBSUU_S) \
V(asub_s, ASUB_S) \
V(asub_u, ASUB_U) \
V(mulv, MULV) \
V(maddv, MADDV) \
V(msubv, MSUBV) \
V(div_s, DIV_S_MSA) \
V(div_u, DIV_U) \
V(mod_s, MOD_S) \
V(mod_u, MOD_U) \
V(dotp_s, DOTP_S) \
V(dotp_u, DOTP_U) \
V(dpadd_s, DPADD_S) \
V(dpadd_u, DPADD_U) \
V(dpsub_s, DPSUB_S) \
V(dpsub_u, DPSUB_U) \
V(pckev, PCKEV) \
V(pckod, PCKOD) \
V(ilvl, ILVL) \
V(ilvr, ILVR) \
V(ilvev, ILVEV) \
V(ilvod, ILVOD) \
V(vshf, VSHF) \
V(srar, SRAR) \
V(srlr, SRLR) \
V(hadd_s, HADD_S) \
V(hadd_u, HADD_U) \
V(hsub_s, HSUB_S) \
V(hsub_u, HSUB_U)
#define MSA_3R_FORMAT(name, opcode, format) \
void Assembler::name##_##format(MSARegister wd, MSARegister ws, \
MSARegister wt) { \
GenInstrMsa3R<MSARegister>(opcode, MSA_3R_DF_##format, wt, ws, wd); \
}
#define MSA_3R_FORMAT_SLD_SPLAT(name, opcode, format) \
void Assembler::name##_##format(MSARegister wd, MSARegister ws, \
Register rt) { \
GenInstrMsa3R<Register>(opcode, MSA_3R_DF_##format, rt, ws, wd); \
}
#define MSA_3R(name, opcode) \
MSA_3R_FORMAT(name, opcode, b) \
MSA_3R_FORMAT(name, opcode, h) \
MSA_3R_FORMAT(name, opcode, w) \
MSA_3R_FORMAT(name, opcode, d)
#define MSA_3R_SLD_SPLAT(name, opcode) \
MSA_3R_FORMAT_SLD_SPLAT(name, opcode, b) \
MSA_3R_FORMAT_SLD_SPLAT(name, opcode, h) \
MSA_3R_FORMAT_SLD_SPLAT(name, opcode, w) \
MSA_3R_FORMAT_SLD_SPLAT(name, opcode, d)
MSA_3R_LIST(MSA_3R)
MSA_3R_SLD_SPLAT(sld, SLD)
MSA_3R_SLD_SPLAT(splat, SPLAT)
#undef MSA_3R
#undef MSA_3R_FORMAT
#undef MSA_3R_FORMAT_SLD_SPLAT
#undef MSA_3R_SLD_SPLAT
#undef MSA_3R_LIST
#define MSA_3RF_LIST1(V) \
V(fcaf, FCAF) \
V(fcun, FCUN) \
V(fceq, FCEQ) \
V(fcueq, FCUEQ) \
V(fclt, FCLT) \
V(fcult, FCULT) \
V(fcle, FCLE) \
V(fcule, FCULE) \
V(fsaf, FSAF) \
V(fsun, FSUN) \
V(fseq, FSEQ) \
V(fsueq, FSUEQ) \
V(fslt, FSLT) \
V(fsult, FSULT) \
V(fsle, FSLE) \
V(fsule, FSULE) \
V(fadd, FADD) \
V(fsub, FSUB) \
V(fmul, FMUL) \
V(fdiv, FDIV) \
V(fmadd, FMADD) \
V(fmsub, FMSUB) \
V(fexp2, FEXP2) \
V(fmin, FMIN) \
V(fmin_a, FMIN_A) \
V(fmax, FMAX) \
V(fmax_a, FMAX_A) \
V(fcor, FCOR) \
V(fcune, FCUNE) \
V(fcne, FCNE) \
V(fsor, FSOR) \
V(fsune, FSUNE) \
V(fsne, FSNE)
#define MSA_3RF_LIST2(V) \
V(fexdo, FEXDO) \
V(ftq, FTQ) \
V(mul_q, MUL_Q) \
V(madd_q, MADD_Q) \
V(msub_q, MSUB_Q) \
V(mulr_q, MULR_Q) \
V(maddr_q, MADDR_Q) \
V(msubr_q, MSUBR_Q)
#define MSA_3RF_FORMAT(name, opcode, df, df_c) \
void Assembler::name##_##df(MSARegister wd, MSARegister ws, \
MSARegister wt) { \
GenInstrMsa3RF(opcode, df_c, wt, ws, wd); \
}
#define MSA_3RF_1(name, opcode) \
MSA_3RF_FORMAT(name, opcode, w, 0) \
MSA_3RF_FORMAT(name, opcode, d, 1)
#define MSA_3RF_2(name, opcode) \
MSA_3RF_FORMAT(name, opcode, h, 0) \
MSA_3RF_FORMAT(name, opcode, w, 1)
MSA_3RF_LIST1(MSA_3RF_1)
MSA_3RF_LIST2(MSA_3RF_2)
#undef MSA_3RF_1
#undef MSA_3RF_2
#undef MSA_3RF_FORMAT
#undef MSA_3RF_LIST1
#undef MSA_3RF_LIST2
void Assembler::sldi_b(MSARegister wd, MSARegister ws, uint32_t n) {
GenInstrMsaElm<MSARegister, MSARegister>(SLDI, ELM_DF_B, n, ws, wd);
}
void Assembler::sldi_h(MSARegister wd, MSARegister ws, uint32_t n) {
GenInstrMsaElm<MSARegister, MSARegister>(SLDI, ELM_DF_H, n, ws, wd);
}
void Assembler::sldi_w(MSARegister wd, MSARegister ws, uint32_t n) {
GenInstrMsaElm<MSARegister, MSARegister>(SLDI, ELM_DF_W, n, ws, wd);
}
void Assembler::sldi_d(MSARegister wd, MSARegister ws, uint32_t n) {
GenInstrMsaElm<MSARegister, MSARegister>(SLDI, ELM_DF_D, n, ws, wd);
}
void Assembler::splati_b(MSARegister wd, MSARegister ws, uint32_t n) {
GenInstrMsaElm<MSARegister, MSARegister>(SPLATI, ELM_DF_B, n, ws, wd);
}
void Assembler::splati_h(MSARegister wd, MSARegister ws, uint32_t n) {
GenInstrMsaElm<MSARegister, MSARegister>(SPLATI, ELM_DF_H, n, ws, wd);
}
void Assembler::splati_w(MSARegister wd, MSARegister ws, uint32_t n) {
GenInstrMsaElm<MSARegister, MSARegister>(SPLATI, ELM_DF_W, n, ws, wd);
}
void Assembler::splati_d(MSARegister wd, MSARegister ws, uint32_t n) {
GenInstrMsaElm<MSARegister, MSARegister>(SPLATI, ELM_DF_D, n, ws, wd);
}
void Assembler::copy_s_b(Register rd, MSARegister ws, uint32_t n) {
GenInstrMsaElm<Register, MSARegister>(COPY_S, ELM_DF_B, n, ws, rd);
}
void Assembler::copy_s_h(Register rd, MSARegister ws, uint32_t n) {
GenInstrMsaElm<Register, MSARegister>(COPY_S, ELM_DF_H, n, ws, rd);
}
void Assembler::copy_s_w(Register rd, MSARegister ws, uint32_t n) {
GenInstrMsaElm<Register, MSARegister>(COPY_S, ELM_DF_W, n, ws, rd);
}
void Assembler::copy_s_d(Register rd, MSARegister ws, uint32_t n) {
GenInstrMsaElm<Register, MSARegister>(COPY_S, ELM_DF_D, n, ws, rd);
}
void Assembler::copy_u_b(Register rd, MSARegister ws, uint32_t n) {
GenInstrMsaElm<Register, MSARegister>(COPY_U, ELM_DF_B, n, ws, rd);
}
void Assembler::copy_u_h(Register rd, MSARegister ws, uint32_t n) {
GenInstrMsaElm<Register, MSARegister>(COPY_U, ELM_DF_H, n, ws, rd);
}
void Assembler::copy_u_w(Register rd, MSARegister ws, uint32_t n) {
GenInstrMsaElm<Register, MSARegister>(COPY_U, ELM_DF_W, n, ws, rd);
}
void Assembler::insert_b(MSARegister wd, uint32_t n, Register rs) {
GenInstrMsaElm<MSARegister, Register>(INSERT, ELM_DF_B, n, rs, wd);
}
void Assembler::insert_h(MSARegister wd, uint32_t n, Register rs) {
GenInstrMsaElm<MSARegister, Register>(INSERT, ELM_DF_H, n, rs, wd);
}
void Assembler::insert_w(MSARegister wd, uint32_t n, Register rs) {
GenInstrMsaElm<MSARegister, Register>(INSERT, ELM_DF_W, n, rs, wd);
}
void Assembler::insert_d(MSARegister wd, uint32_t n, Register rs) {
GenInstrMsaElm<MSARegister, Register>(INSERT, ELM_DF_D, n, rs, wd);
}
void Assembler::insve_b(MSARegister wd, uint32_t n, MSARegister ws) {
GenInstrMsaElm<MSARegister, MSARegister>(INSVE, ELM_DF_B, n, ws, wd);
}
void Assembler::insve_h(MSARegister wd, uint32_t n, MSARegister ws) {
GenInstrMsaElm<MSARegister, MSARegister>(INSVE, ELM_DF_H, n, ws, wd);
}
void Assembler::insve_w(MSARegister wd, uint32_t n, MSARegister ws) {
GenInstrMsaElm<MSARegister, MSARegister>(INSVE, ELM_DF_W, n, ws, wd);
}
void Assembler::insve_d(MSARegister wd, uint32_t n, MSARegister ws) {
GenInstrMsaElm<MSARegister, MSARegister>(INSVE, ELM_DF_D, n, ws, wd);
}
void Assembler::move_v(MSARegister wd, MSARegister ws) {
DCHECK((kArchVariant == kMips64r6) && IsEnabled(MIPS_SIMD));
DCHECK(ws.is_valid() && wd.is_valid());
Instr instr = MSA | MOVE_V | (ws.code() << kWsShift) |
(wd.code() << kWdShift) | MSA_ELM_MINOR;
emit(instr);
}
void Assembler::ctcmsa(MSAControlRegister cd, Register rs) {
DCHECK((kArchVariant == kMips64r6) && IsEnabled(MIPS_SIMD));
DCHECK(cd.is_valid() && rs.is_valid());
Instr instr = MSA | CTCMSA | (rs.code() << kWsShift) |
(cd.code() << kWdShift) | MSA_ELM_MINOR;
emit(instr);
}
void Assembler::cfcmsa(Register rd, MSAControlRegister cs) {
DCHECK((kArchVariant == kMips64r6) && IsEnabled(MIPS_SIMD));
DCHECK(rd.is_valid() && cs.is_valid());
Instr instr = MSA | CFCMSA | (cs.code() << kWsShift) |
(rd.code() << kWdShift) | MSA_ELM_MINOR;
emit(instr);
}
#define MSA_BIT_LIST(V) \
V(slli, SLLI) \
V(srai, SRAI) \
V(srli, SRLI) \
V(bclri, BCLRI) \
V(bseti, BSETI) \
V(bnegi, BNEGI) \
V(binsli, BINSLI) \
V(binsri, BINSRI) \
V(sat_s, SAT_S) \
V(sat_u, SAT_U) \
V(srari, SRARI) \
V(srlri, SRLRI)
#define MSA_BIT_FORMAT(name, opcode, format) \
void Assembler::name##_##format(MSARegister wd, MSARegister ws, \
uint32_t m) { \
GenInstrMsaBit(opcode, BIT_DF_##format, m, ws, wd); \
}
#define MSA_BIT(name, opcode) \
MSA_BIT_FORMAT(name, opcode, b) \
MSA_BIT_FORMAT(name, opcode, h) \
MSA_BIT_FORMAT(name, opcode, w) \
MSA_BIT_FORMAT(name, opcode, d)
MSA_BIT_LIST(MSA_BIT)
#undef MSA_BIT
#undef MSA_BIT_FORMAT
#undef MSA_BIT_LIST
int Assembler::RelocateInternalReference(RelocInfo::Mode rmode, byte* pc,
intptr_t pc_delta) {
......
......@@ -64,7 +64,11 @@ namespace internal {
V(f24) V(f25) V(f26) V(f27) V(f28) V(f29) V(f30) V(f31)
#define FLOAT_REGISTERS DOUBLE_REGISTERS
#define SIMD128_REGISTERS DOUBLE_REGISTERS
#define SIMD128_REGISTERS(V) \
V(w0) V(w1) V(w2) V(w3) V(w4) V(w5) V(w6) V(w7) \
V(w8) V(w9) V(w10) V(w11) V(w12) V(w13) V(w14) V(w15) \
V(w16) V(w17) V(w18) V(w19) V(w20) V(w21) V(w22) V(w23) \
V(w24) V(w25) V(w26) V(w27) V(w28) V(w29) V(w30) V(w31)
#define ALLOCATABLE_DOUBLE_REGISTERS(V) \
V(f0) V(f2) V(f4) V(f6) V(f8) V(f10) V(f12) V(f14) \
......@@ -163,7 +167,7 @@ struct FPURegister {
DOUBLE_REGISTERS(REGISTER_CODE)
#undef REGISTER_CODE
kAfterLast,
kCode_no_reg = -1
kCode_no_reg = kInvalidFPURegister
};
static constexpr int kMaxNumRegisters = Code::kAfterLast;
......@@ -217,6 +221,44 @@ struct FPURegister {
int reg_code;
};
// MIPS SIMD (MSA) register
struct MSARegister {
enum Code {
#define REGISTER_CODE(R) kCode_##R,
SIMD128_REGISTERS(REGISTER_CODE)
#undef REGISTER_CODE
kAfterLast,
kCode_no_reg = kInvalidMSARegister
};
static const int kMaxNumRegisters = Code::kAfterLast;
inline static int NumRegisters();
bool is_valid() const { return 0 <= reg_code && reg_code < kMaxNumRegisters; }
bool is(MSARegister reg) const { return reg_code == reg.reg_code; }
int code() const {
DCHECK(is_valid());
return reg_code;
}
int bit() const {
DCHECK(is_valid());
return 1 << reg_code;
}
static MSARegister from_code(int code) {
MSARegister r = {code};
return r;
}
void setcode(int f) {
reg_code = f;
DCHECK(is_valid());
}
// Unfortunately we can't make this private in a struct.
int reg_code;
};
// A few double registers are reserved: one as a scratch register and one to
// hold 0.0.
// f28: 0.0
......@@ -235,10 +277,7 @@ typedef FPURegister FloatRegister;
typedef FPURegister DoubleRegister;
// TODO(mips64) Define SIMD registers.
typedef FPURegister Simd128Register;
constexpr DoubleRegister no_freg = {-1};
constexpr DoubleRegister no_freg = {kInvalidFPURegister};
constexpr DoubleRegister f0 = {0}; // Return value in hard float mode.
constexpr DoubleRegister f1 = {1};
......@@ -273,6 +312,44 @@ constexpr DoubleRegister f29 = {29};
constexpr DoubleRegister f30 = {30};
constexpr DoubleRegister f31 = {31};
// SIMD registers.
typedef MSARegister Simd128Register;
const Simd128Register no_msareg = {kInvalidMSARegister};
constexpr Simd128Register w0 = {0};
constexpr Simd128Register w1 = {1};
constexpr Simd128Register w2 = {2};
constexpr Simd128Register w3 = {3};
constexpr Simd128Register w4 = {4};
constexpr Simd128Register w5 = {5};
constexpr Simd128Register w6 = {6};
constexpr Simd128Register w7 = {7};
constexpr Simd128Register w8 = {8};
constexpr Simd128Register w9 = {9};
constexpr Simd128Register w10 = {10};
constexpr Simd128Register w11 = {11};
constexpr Simd128Register w12 = {12};
constexpr Simd128Register w13 = {13};
constexpr Simd128Register w14 = {14};
constexpr Simd128Register w15 = {15};
constexpr Simd128Register w16 = {16};
constexpr Simd128Register w17 = {17};
constexpr Simd128Register w18 = {18};
constexpr Simd128Register w19 = {19};
constexpr Simd128Register w20 = {20};
constexpr Simd128Register w21 = {21};
constexpr Simd128Register w22 = {22};
constexpr Simd128Register w23 = {23};
constexpr Simd128Register w24 = {24};
constexpr Simd128Register w25 = {25};
constexpr Simd128Register w26 = {26};
constexpr Simd128Register w27 = {27};
constexpr Simd128Register w28 = {28};
constexpr Simd128Register w29 = {29};
constexpr Simd128Register w30 = {30};
constexpr Simd128Register w31 = {31};
// Register aliases.
// cp is assumed to be a callee saved register.
constexpr Register kRootRegister = s6;
......@@ -309,6 +386,32 @@ struct FPUControlRegister {
constexpr FPUControlRegister no_fpucreg = {kInvalidFPUControlRegister};
constexpr FPUControlRegister FCSR = {kFCSRRegister};
// MSA control registers
struct MSAControlRegister {
bool is_valid() const {
return (reg_code == kMSAIRRegister) || (reg_code == kMSACSRRegister);
}
bool is(MSAControlRegister creg) const { return reg_code == creg.reg_code; }
int code() const {
DCHECK(is_valid());
return reg_code;
}
int bit() const {
DCHECK(is_valid());
return 1 << reg_code;
}
void setcode(int f) {
reg_code = f;
DCHECK(is_valid());
}
// Unfortunately we can't make this private in a struct.
int reg_code;
};
constexpr MSAControlRegister no_msacreg = {kInvalidMSAControlRegister};
constexpr MSAControlRegister MSAIR = {kMSAIRRegister};
constexpr MSAControlRegister MSACSR = {kMSACSRRegister};
// -----------------------------------------------------------------------------
// Machine instruction Operands.
constexpr int kSmiShift = kSmiTagSize + kSmiShiftSize;
......@@ -1045,6 +1148,566 @@ class Assembler : public AssemblerBase {
}
void fcmp(FPURegister src1, const double src2, FPUCondition cond);
// MSA instructions
void bz_v(MSARegister wt, int16_t offset);
void bz_b(MSARegister wt, int16_t offset);
void bz_h(MSARegister wt, int16_t offset);
void bz_w(MSARegister wt, int16_t offset);
void bz_d(MSARegister wt, int16_t offset);
void bnz_v(MSARegister wt, int16_t offset);
void bnz_b(MSARegister wt, int16_t offset);
void bnz_h(MSARegister wt, int16_t offset);
void bnz_w(MSARegister wt, int16_t offset);
void bnz_d(MSARegister wt, int16_t offset);
void ld_b(MSARegister wd, const MemOperand& rs);
void ld_h(MSARegister wd, const MemOperand& rs);
void ld_w(MSARegister wd, const MemOperand& rs);
void ld_d(MSARegister wd, const MemOperand& rs);
void st_b(MSARegister wd, const MemOperand& rs);
void st_h(MSARegister wd, const MemOperand& rs);
void st_w(MSARegister wd, const MemOperand& rs);
void st_d(MSARegister wd, const MemOperand& rs);
void ldi_b(MSARegister wd, int32_t imm10);
void ldi_h(MSARegister wd, int32_t imm10);
void ldi_w(MSARegister wd, int32_t imm10);
void ldi_d(MSARegister wd, int32_t imm10);
void addvi_b(MSARegister wd, MSARegister ws, uint32_t imm5);
void addvi_h(MSARegister wd, MSARegister ws, uint32_t imm5);
void addvi_w(MSARegister wd, MSARegister ws, uint32_t imm5);
void addvi_d(MSARegister wd, MSARegister ws, uint32_t imm5);
void subvi_b(MSARegister wd, MSARegister ws, uint32_t imm5);
void subvi_h(MSARegister wd, MSARegister ws, uint32_t imm5);
void subvi_w(MSARegister wd, MSARegister ws, uint32_t imm5);
void subvi_d(MSARegister wd, MSARegister ws, uint32_t imm5);
void maxi_s_b(MSARegister wd, MSARegister ws, uint32_t imm5);
void maxi_s_h(MSARegister wd, MSARegister ws, uint32_t imm5);
void maxi_s_w(MSARegister wd, MSARegister ws, uint32_t imm5);
void maxi_s_d(MSARegister wd, MSARegister ws, uint32_t imm5);
void maxi_u_b(MSARegister wd, MSARegister ws, uint32_t imm5);
void maxi_u_h(MSARegister wd, MSARegister ws, uint32_t imm5);
void maxi_u_w(MSARegister wd, MSARegister ws, uint32_t imm5);
void maxi_u_d(MSARegister wd, MSARegister ws, uint32_t imm5);
void mini_s_b(MSARegister wd, MSARegister ws, uint32_t imm5);
void mini_s_h(MSARegister wd, MSARegister ws, uint32_t imm5);
void mini_s_w(MSARegister wd, MSARegister ws, uint32_t imm5);
void mini_s_d(MSARegister wd, MSARegister ws, uint32_t imm5);
void mini_u_b(MSARegister wd, MSARegister ws, uint32_t imm5);
void mini_u_h(MSARegister wd, MSARegister ws, uint32_t imm5);
void mini_u_w(MSARegister wd, MSARegister ws, uint32_t imm5);
void mini_u_d(MSARegister wd, MSARegister ws, uint32_t imm5);
void ceqi_b(MSARegister wd, MSARegister ws, uint32_t imm5);
void ceqi_h(MSARegister wd, MSARegister ws, uint32_t imm5);
void ceqi_w(MSARegister wd, MSARegister ws, uint32_t imm5);
void ceqi_d(MSARegister wd, MSARegister ws, uint32_t imm5);
void clti_s_b(MSARegister wd, MSARegister ws, uint32_t imm5);
void clti_s_h(MSARegister wd, MSARegister ws, uint32_t imm5);
void clti_s_w(MSARegister wd, MSARegister ws, uint32_t imm5);
void clti_s_d(MSARegister wd, MSARegister ws, uint32_t imm5);
void clti_u_b(MSARegister wd, MSARegister ws, uint32_t imm5);
void clti_u_h(MSARegister wd, MSARegister ws, uint32_t imm5);
void clti_u_w(MSARegister wd, MSARegister ws, uint32_t imm5);
void clti_u_d(MSARegister wd, MSARegister ws, uint32_t imm5);
void clei_s_b(MSARegister wd, MSARegister ws, uint32_t imm5);
void clei_s_h(MSARegister wd, MSARegister ws, uint32_t imm5);
void clei_s_w(MSARegister wd, MSARegister ws, uint32_t imm5);
void clei_s_d(MSARegister wd, MSARegister ws, uint32_t imm5);
void clei_u_b(MSARegister wd, MSARegister ws, uint32_t imm5);
void clei_u_h(MSARegister wd, MSARegister ws, uint32_t imm5);
void clei_u_w(MSARegister wd, MSARegister ws, uint32_t imm5);
void clei_u_d(MSARegister wd, MSARegister ws, uint32_t imm5);
void andi_b(MSARegister wd, MSARegister ws, uint32_t imm8);
void ori_b(MSARegister wd, MSARegister ws, uint32_t imm8);
void nori_b(MSARegister wd, MSARegister ws, uint32_t imm8);
void xori_b(MSARegister wd, MSARegister ws, uint32_t imm8);
void bmnzi_b(MSARegister wd, MSARegister ws, uint32_t imm8);
void bmzi_b(MSARegister wd, MSARegister ws, uint32_t imm8);
void bseli_b(MSARegister wd, MSARegister ws, uint32_t imm8);
void shf_b(MSARegister wd, MSARegister ws, uint32_t imm8);
void shf_h(MSARegister wd, MSARegister ws, uint32_t imm8);
void shf_w(MSARegister wd, MSARegister ws, uint32_t imm8);
void and_v(MSARegister wd, MSARegister ws, MSARegister wt);
void or_v(MSARegister wd, MSARegister ws, MSARegister wt);
void nor_v(MSARegister wd, MSARegister ws, MSARegister wt);
void xor_v(MSARegister wd, MSARegister ws, MSARegister wt);
void bmnz_v(MSARegister wd, MSARegister ws, MSARegister wt);
void bmz_v(MSARegister wd, MSARegister ws, MSARegister wt);
void bsel_v(MSARegister wd, MSARegister ws, MSARegister wt);
void fill_b(MSARegister wd, Register rs);
void fill_h(MSARegister wd, Register rs);
void fill_w(MSARegister wd, Register rs);
void fill_d(MSARegister wd, Register rs);
void pcnt_b(MSARegister wd, MSARegister ws);
void pcnt_h(MSARegister wd, MSARegister ws);
void pcnt_w(MSARegister wd, MSARegister ws);
void pcnt_d(MSARegister wd, MSARegister ws);
void nloc_b(MSARegister wd, MSARegister ws);
void nloc_h(MSARegister wd, MSARegister ws);
void nloc_w(MSARegister wd, MSARegister ws);
void nloc_d(MSARegister wd, MSARegister ws);
void nlzc_b(MSARegister wd, MSARegister ws);
void nlzc_h(MSARegister wd, MSARegister ws);
void nlzc_w(MSARegister wd, MSARegister ws);
void nlzc_d(MSARegister wd, MSARegister ws);
void fclass_w(MSARegister wd, MSARegister ws);
void fclass_d(MSARegister wd, MSARegister ws);
void ftrunc_s_w(MSARegister wd, MSARegister ws);
void ftrunc_s_d(MSARegister wd, MSARegister ws);
void ftrunc_u_w(MSARegister wd, MSARegister ws);
void ftrunc_u_d(MSARegister wd, MSARegister ws);
void fsqrt_w(MSARegister wd, MSARegister ws);
void fsqrt_d(MSARegister wd, MSARegister ws);
void frsqrt_w(MSARegister wd, MSARegister ws);
void frsqrt_d(MSARegister wd, MSARegister ws);
void frcp_w(MSARegister wd, MSARegister ws);
void frcp_d(MSARegister wd, MSARegister ws);
void frint_w(MSARegister wd, MSARegister ws);
void frint_d(MSARegister wd, MSARegister ws);
void flog2_w(MSARegister wd, MSARegister ws);
void flog2_d(MSARegister wd, MSARegister ws);
void fexupl_w(MSARegister wd, MSARegister ws);
void fexupl_d(MSARegister wd, MSARegister ws);
void fexupr_w(MSARegister wd, MSARegister ws);
void fexupr_d(MSARegister wd, MSARegister ws);
void ffql_w(MSARegister wd, MSARegister ws);
void ffql_d(MSARegister wd, MSARegister ws);
void ffqr_w(MSARegister wd, MSARegister ws);
void ffqr_d(MSARegister wd, MSARegister ws);
void ftint_s_w(MSARegister wd, MSARegister ws);
void ftint_s_d(MSARegister wd, MSARegister ws);
void ftint_u_w(MSARegister wd, MSARegister ws);
void ftint_u_d(MSARegister wd, MSARegister ws);
void ffint_s_w(MSARegister wd, MSARegister ws);
void ffint_s_d(MSARegister wd, MSARegister ws);
void ffint_u_w(MSARegister wd, MSARegister ws);
void ffint_u_d(MSARegister wd, MSARegister ws);
void sll_b(MSARegister wd, MSARegister ws, MSARegister wt);
void sll_h(MSARegister wd, MSARegister ws, MSARegister wt);
void sll_w(MSARegister wd, MSARegister ws, MSARegister wt);
void sll_d(MSARegister wd, MSARegister ws, MSARegister wt);
void sra_b(MSARegister wd, MSARegister ws, MSARegister wt);
void sra_h(MSARegister wd, MSARegister ws, MSARegister wt);
void sra_w(MSARegister wd, MSARegister ws, MSARegister wt);
void sra_d(MSARegister wd, MSARegister ws, MSARegister wt);
void srl_b(MSARegister wd, MSARegister ws, MSARegister wt);
void srl_h(MSARegister wd, MSARegister ws, MSARegister wt);
void srl_w(MSARegister wd, MSARegister ws, MSARegister wt);
void srl_d(MSARegister wd, MSARegister ws, MSARegister wt);
void bclr_b(MSARegister wd, MSARegister ws, MSARegister wt);
void bclr_h(MSARegister wd, MSARegister ws, MSARegister wt);
void bclr_w(MSARegister wd, MSARegister ws, MSARegister wt);
void bclr_d(MSARegister wd, MSARegister ws, MSARegister wt);
void bset_b(MSARegister wd, MSARegister ws, MSARegister wt);
void bset_h(MSARegister wd, MSARegister ws, MSARegister wt);
void bset_w(MSARegister wd, MSARegister ws, MSARegister wt);
void bset_d(MSARegister wd, MSARegister ws, MSARegister wt);
void bneg_b(MSARegister wd, MSARegister ws, MSARegister wt);
void bneg_h(MSARegister wd, MSARegister ws, MSARegister wt);
void bneg_w(MSARegister wd, MSARegister ws, MSARegister wt);
void bneg_d(MSARegister wd, MSARegister ws, MSARegister wt);
void binsl_b(MSARegister wd, MSARegister ws, MSARegister wt);
void binsl_h(MSARegister wd, MSARegister ws, MSARegister wt);
void binsl_w(MSARegister wd, MSARegister ws, MSARegister wt);
void binsl_d(MSARegister wd, MSARegister ws, MSARegister wt);
void binsr_b(MSARegister wd, MSARegister ws, MSARegister wt);
void binsr_h(MSARegister wd, MSARegister ws, MSARegister wt);
void binsr_w(MSARegister wd, MSARegister ws, MSARegister wt);
void binsr_d(MSARegister wd, MSARegister ws, MSARegister wt);
void addv_b(MSARegister wd, MSARegister ws, MSARegister wt);
void addv_h(MSARegister wd, MSARegister ws, MSARegister wt);
void addv_w(MSARegister wd, MSARegister ws, MSARegister wt);
void addv_d(MSARegister wd, MSARegister ws, MSARegister wt);
void subv_b(MSARegister wd, MSARegister ws, MSARegister wt);
void subv_h(MSARegister wd, MSARegister ws, MSARegister wt);
void subv_w(MSARegister wd, MSARegister ws, MSARegister wt);
void subv_d(MSARegister wd, MSARegister ws, MSARegister wt);
void max_s_b(MSARegister wd, MSARegister ws, MSARegister wt);
void max_s_h(MSARegister wd, MSARegister ws, MSARegister wt);
void max_s_w(MSARegister wd, MSARegister ws, MSARegister wt);
void max_s_d(MSARegister wd, MSARegister ws, MSARegister wt);
void max_u_b(MSARegister wd, MSARegister ws, MSARegister wt);
void max_u_h(MSARegister wd, MSARegister ws, MSARegister wt);
void max_u_w(MSARegister wd, MSARegister ws, MSARegister wt);
void max_u_d(MSARegister wd, MSARegister ws, MSARegister wt);
void min_s_b(MSARegister wd, MSARegister ws, MSARegister wt);
void min_s_h(MSARegister wd, MSARegister ws, MSARegister wt);
void min_s_w(MSARegister wd, MSARegister ws, MSARegister wt);
void min_s_d(MSARegister wd, MSARegister ws, MSARegister wt);
void min_u_b(MSARegister wd, MSARegister ws, MSARegister wt);
void min_u_h(MSARegister wd, MSARegister ws, MSARegister wt);
void min_u_w(MSARegister wd, MSARegister ws, MSARegister wt);
void min_u_d(MSARegister wd, MSARegister ws, MSARegister wt);
void max_a_b(MSARegister wd, MSARegister ws, MSARegister wt);
void max_a_h(MSARegister wd, MSARegister ws, MSARegister wt);
void max_a_w(MSARegister wd, MSARegister ws, MSARegister wt);
void max_a_d(MSARegister wd, MSARegister ws, MSARegister wt);
void min_a_b(MSARegister wd, MSARegister ws, MSARegister wt);
void min_a_h(MSARegister wd, MSARegister ws, MSARegister wt);
void min_a_w(MSARegister wd, MSARegister ws, MSARegister wt);
void min_a_d(MSARegister wd, MSARegister ws, MSARegister wt);
void ceq_b(MSARegister wd, MSARegister ws, MSARegister wt);
void ceq_h(MSARegister wd, MSARegister ws, MSARegister wt);
void ceq_w(MSARegister wd, MSARegister ws, MSARegister wt);
void ceq_d(MSARegister wd, MSARegister ws, MSARegister wt);
void clt_s_b(MSARegister wd, MSARegister ws, MSARegister wt);
void clt_s_h(MSARegister wd, MSARegister ws, MSARegister wt);
void clt_s_w(MSARegister wd, MSARegister ws, MSARegister wt);
void clt_s_d(MSARegister wd, MSARegister ws, MSARegister wt);
void clt_u_b(MSARegister wd, MSARegister ws, MSARegister wt);
void clt_u_h(MSARegister wd, MSARegister ws, MSARegister wt);
void clt_u_w(MSARegister wd, MSARegister ws, MSARegister wt);
void clt_u_d(MSARegister wd, MSARegister ws, MSARegister wt);
void cle_s_b(MSARegister wd, MSARegister ws, MSARegister wt);
void cle_s_h(MSARegister wd, MSARegister ws, MSARegister wt);
void cle_s_w(MSARegister wd, MSARegister ws, MSARegister wt);
void cle_s_d(MSARegister wd, MSARegister ws, MSARegister wt);
void cle_u_b(MSARegister wd, MSARegister ws, MSARegister wt);
void cle_u_h(MSARegister wd, MSARegister ws, MSARegister wt);
void cle_u_w(MSARegister wd, MSARegister ws, MSARegister wt);
void cle_u_d(MSARegister wd, MSARegister ws, MSARegister wt);
void add_a_b(MSARegister wd, MSARegister ws, MSARegister wt);
void add_a_h(MSARegister wd, MSARegister ws, MSARegister wt);
void add_a_w(MSARegister wd, MSARegister ws, MSARegister wt);
void add_a_d(MSARegister wd, MSARegister ws, MSARegister wt);
void adds_a_b(MSARegister wd, MSARegister ws, MSARegister wt);
void adds_a_h(MSARegister wd, MSARegister ws, MSARegister wt);
void adds_a_w(MSARegister wd, MSARegister ws, MSARegister wt);
void adds_a_d(MSARegister wd, MSARegister ws, MSARegister wt);
void adds_s_b(MSARegister wd, MSARegister ws, MSARegister wt);
void adds_s_h(MSARegister wd, MSARegister ws, MSARegister wt);
void adds_s_w(MSARegister wd, MSARegister ws, MSARegister wt);
void adds_s_d(MSARegister wd, MSARegister ws, MSARegister wt);
void adds_u_b(MSARegister wd, MSARegister ws, MSARegister wt);
void adds_u_h(MSARegister wd, MSARegister ws, MSARegister wt);
void adds_u_w(MSARegister wd, MSARegister ws, MSARegister wt);
void adds_u_d(MSARegister wd, MSARegister ws, MSARegister wt);
void ave_s_b(MSARegister wd, MSARegister ws, MSARegister wt);
void ave_s_h(MSARegister wd, MSARegister ws, MSARegister wt);
void ave_s_w(MSARegister wd, MSARegister ws, MSARegister wt);
void ave_s_d(MSARegister wd, MSARegister ws, MSARegister wt);
void ave_u_b(MSARegister wd, MSARegister ws, MSARegister wt);
void ave_u_h(MSARegister wd, MSARegister ws, MSARegister wt);
void ave_u_w(MSARegister wd, MSARegister ws, MSARegister wt);
void ave_u_d(MSARegister wd, MSARegister ws, MSARegister wt);
void aver_s_b(MSARegister wd, MSARegister ws, MSARegister wt);
void aver_s_h(MSARegister wd, MSARegister ws, MSARegister wt);
void aver_s_w(MSARegister wd, MSARegister ws, MSARegister wt);
void aver_s_d(MSARegister wd, MSARegister ws, MSARegister wt);
void aver_u_b(MSARegister wd, MSARegister ws, MSARegister wt);
void aver_u_h(MSARegister wd, MSARegister ws, MSARegister wt);
void aver_u_w(MSARegister wd, MSARegister ws, MSARegister wt);
void aver_u_d(MSARegister wd, MSARegister ws, MSARegister wt);
void subs_s_b(MSARegister wd, MSARegister ws, MSARegister wt);
void subs_s_h(MSARegister wd, MSARegister ws, MSARegister wt);
void subs_s_w(MSARegister wd, MSARegister ws, MSARegister wt);
void subs_s_d(MSARegister wd, MSARegister ws, MSARegister wt);
void subs_u_b(MSARegister wd, MSARegister ws, MSARegister wt);
void subs_u_h(MSARegister wd, MSARegister ws, MSARegister wt);
void subs_u_w(MSARegister wd, MSARegister ws, MSARegister wt);
void subs_u_d(MSARegister wd, MSARegister ws, MSARegister wt);
void subsus_u_b(MSARegister wd, MSARegister ws, MSARegister wt);
void subsus_u_h(MSARegister wd, MSARegister ws, MSARegister wt);
void subsus_u_w(MSARegister wd, MSARegister ws, MSARegister wt);
void subsus_u_d(MSARegister wd, MSARegister ws, MSARegister wt);
void subsus_s_b(MSARegister wd, MSARegister ws, MSARegister wt);
void subsus_s_h(MSARegister wd, MSARegister ws, MSARegister wt);
void subsus_s_w(MSARegister wd, MSARegister ws, MSARegister wt);
void subsus_s_d(MSARegister wd, MSARegister ws, MSARegister wt);
void subsuu_u_b(MSARegister wd, MSARegister ws, MSARegister wt);
void subsuu_u_h(MSARegister wd, MSARegister ws, MSARegister wt);
void subsuu_u_w(MSARegister wd, MSARegister ws, MSARegister wt);
void subsuu_u_d(MSARegister wd, MSARegister ws, MSARegister wt);
void subsuu_s_b(MSARegister wd, MSARegister ws, MSARegister wt);
void subsuu_s_h(MSARegister wd, MSARegister ws, MSARegister wt);
void subsuu_s_w(MSARegister wd, MSARegister ws, MSARegister wt);
void subsuu_s_d(MSARegister wd, MSARegister ws, MSARegister wt);
void asub_s_b(MSARegister wd, MSARegister ws, MSARegister wt);
void asub_s_h(MSARegister wd, MSARegister ws, MSARegister wt);
void asub_s_w(MSARegister wd, MSARegister ws, MSARegister wt);
void asub_s_d(MSARegister wd, MSARegister ws, MSARegister wt);
void asub_u_b(MSARegister wd, MSARegister ws, MSARegister wt);
void asub_u_h(MSARegister wd, MSARegister ws, MSARegister wt);
void asub_u_w(MSARegister wd, MSARegister ws, MSARegister wt);
void asub_u_d(MSARegister wd, MSARegister ws, MSARegister wt);
void mulv_b(MSARegister wd, MSARegister ws, MSARegister wt);
void mulv_h(MSARegister wd, MSARegister ws, MSARegister wt);
void mulv_w(MSARegister wd, MSARegister ws, MSARegister wt);
void mulv_d(MSARegister wd, MSARegister ws, MSARegister wt);
void maddv_b(MSARegister wd, MSARegister ws, MSARegister wt);
void maddv_h(MSARegister wd, MSARegister ws, MSARegister wt);
void maddv_w(MSARegister wd, MSARegister ws, MSARegister wt);
void maddv_d(MSARegister wd, MSARegister ws, MSARegister wt);
void msubv_b(MSARegister wd, MSARegister ws, MSARegister wt);
void msubv_h(MSARegister wd, MSARegister ws, MSARegister wt);
void msubv_w(MSARegister wd, MSARegister ws, MSARegister wt);
void msubv_d(MSARegister wd, MSARegister ws, MSARegister wt);
void div_s_b(MSARegister wd, MSARegister ws, MSARegister wt);
void div_s_h(MSARegister wd, MSARegister ws, MSARegister wt);
void div_s_w(MSARegister wd, MSARegister ws, MSARegister wt);
void div_s_d(MSARegister wd, MSARegister ws, MSARegister wt);
void div_u_b(MSARegister wd, MSARegister ws, MSARegister wt);
void div_u_h(MSARegister wd, MSARegister ws, MSARegister wt);
void div_u_w(MSARegister wd, MSARegister ws, MSARegister wt);
void div_u_d(MSARegister wd, MSARegister ws, MSARegister wt);
void mod_s_b(MSARegister wd, MSARegister ws, MSARegister wt);
void mod_s_h(MSARegister wd, MSARegister ws, MSARegister wt);
void mod_s_w(MSARegister wd, MSARegister ws, MSARegister wt);
void mod_s_d(MSARegister wd, MSARegister ws, MSARegister wt);
void mod_u_b(MSARegister wd, MSARegister ws, MSARegister wt);
void mod_u_h(MSARegister wd, MSARegister ws, MSARegister wt);
void mod_u_w(MSARegister wd, MSARegister ws, MSARegister wt);
void mod_u_d(MSARegister wd, MSARegister ws, MSARegister wt);
void dotp_s_b(MSARegister wd, MSARegister ws, MSARegister wt);
void dotp_s_h(MSARegister wd, MSARegister ws, MSARegister wt);
void dotp_s_w(MSARegister wd, MSARegister ws, MSARegister wt);
void dotp_s_d(MSARegister wd, MSARegister ws, MSARegister wt);
void dotp_u_b(MSARegister wd, MSARegister ws, MSARegister wt);
void dotp_u_h(MSARegister wd, MSARegister ws, MSARegister wt);
void dotp_u_w(MSARegister wd, MSARegister ws, MSARegister wt);
void dotp_u_d(MSARegister wd, MSARegister ws, MSARegister wt);
void dpadd_s_b(MSARegister wd, MSARegister ws, MSARegister wt);
void dpadd_s_h(MSARegister wd, MSARegister ws, MSARegister wt);
void dpadd_s_w(MSARegister wd, MSARegister ws, MSARegister wt);
void dpadd_s_d(MSARegister wd, MSARegister ws, MSARegister wt);
void dpadd_u_b(MSARegister wd, MSARegister ws, MSARegister wt);
void dpadd_u_h(MSARegister wd, MSARegister ws, MSARegister wt);
void dpadd_u_w(MSARegister wd, MSARegister ws, MSARegister wt);
void dpadd_u_d(MSARegister wd, MSARegister ws, MSARegister wt);
void dpsub_s_b(MSARegister wd, MSARegister ws, MSARegister wt);
void dpsub_s_h(MSARegister wd, MSARegister ws, MSARegister wt);
void dpsub_s_w(MSARegister wd, MSARegister ws, MSARegister wt);
void dpsub_s_d(MSARegister wd, MSARegister ws, MSARegister wt);
void dpsub_u_b(MSARegister wd, MSARegister ws, MSARegister wt);
void dpsub_u_h(MSARegister wd, MSARegister ws, MSARegister wt);
void dpsub_u_w(MSARegister wd, MSARegister ws, MSARegister wt);
void dpsub_u_d(MSARegister wd, MSARegister ws, MSARegister wt);
void sld_b(MSARegister wd, MSARegister ws, Register rt);
void sld_h(MSARegister wd, MSARegister ws, Register rt);
void sld_w(MSARegister wd, MSARegister ws, Register rt);
void sld_d(MSARegister wd, MSARegister ws, Register rt);
void splat_b(MSARegister wd, MSARegister ws, Register rt);
void splat_h(MSARegister wd, MSARegister ws, Register rt);
void splat_w(MSARegister wd, MSARegister ws, Register rt);
void splat_d(MSARegister wd, MSARegister ws, Register rt);
void pckev_b(MSARegister wd, MSARegister ws, MSARegister wt);
void pckev_h(MSARegister wd, MSARegister ws, MSARegister wt);
void pckev_w(MSARegister wd, MSARegister ws, MSARegister wt);
void pckev_d(MSARegister wd, MSARegister ws, MSARegister wt);
void pckod_b(MSARegister wd, MSARegister ws, MSARegister wt);
void pckod_h(MSARegister wd, MSARegister ws, MSARegister wt);
void pckod_w(MSARegister wd, MSARegister ws, MSARegister wt);
void pckod_d(MSARegister wd, MSARegister ws, MSARegister wt);
void ilvl_b(MSARegister wd, MSARegister ws, MSARegister wt);
void ilvl_h(MSARegister wd, MSARegister ws, MSARegister wt);
void ilvl_w(MSARegister wd, MSARegister ws, MSARegister wt);
void ilvl_d(MSARegister wd, MSARegister ws, MSARegister wt);
void ilvr_b(MSARegister wd, MSARegister ws, MSARegister wt);
void ilvr_h(MSARegister wd, MSARegister ws, MSARegister wt);
void ilvr_w(MSARegister wd, MSARegister ws, MSARegister wt);
void ilvr_d(MSARegister wd, MSARegister ws, MSARegister wt);
void ilvev_b(MSARegister wd, MSARegister ws, MSARegister wt);
void ilvev_h(MSARegister wd, MSARegister ws, MSARegister wt);
void ilvev_w(MSARegister wd, MSARegister ws, MSARegister wt);
void ilvev_d(MSARegister wd, MSARegister ws, MSARegister wt);
void ilvod_b(MSARegister wd, MSARegister ws, MSARegister wt);
void ilvod_h(MSARegister wd, MSARegister ws, MSARegister wt);
void ilvod_w(MSARegister wd, MSARegister ws, MSARegister wt);
void ilvod_d(MSARegister wd, MSARegister ws, MSARegister wt);
void vshf_b(MSARegister wd, MSARegister ws, MSARegister wt);
void vshf_h(MSARegister wd, MSARegister ws, MSARegister wt);
void vshf_w(MSARegister wd, MSARegister ws, MSARegister wt);
void vshf_d(MSARegister wd, MSARegister ws, MSARegister wt);
void srar_b(MSARegister wd, MSARegister ws, MSARegister wt);
void srar_h(MSARegister wd, MSARegister ws, MSARegister wt);
void srar_w(MSARegister wd, MSARegister ws, MSARegister wt);
void srar_d(MSARegister wd, MSARegister ws, MSARegister wt);
void srlr_b(MSARegister wd, MSARegister ws, MSARegister wt);
void srlr_h(MSARegister wd, MSARegister ws, MSARegister wt);
void srlr_w(MSARegister wd, MSARegister ws, MSARegister wt);
void srlr_d(MSARegister wd, MSARegister ws, MSARegister wt);
void hadd_s_b(MSARegister wd, MSARegister ws, MSARegister wt);
void hadd_s_h(MSARegister wd, MSARegister ws, MSARegister wt);
void hadd_s_w(MSARegister wd, MSARegister ws, MSARegister wt);
void hadd_s_d(MSARegister wd, MSARegister ws, MSARegister wt);
void hadd_u_b(MSARegister wd, MSARegister ws, MSARegister wt);
void hadd_u_h(MSARegister wd, MSARegister ws, MSARegister wt);
void hadd_u_w(MSARegister wd, MSARegister ws, MSARegister wt);
void hadd_u_d(MSARegister wd, MSARegister ws, MSARegister wt);
void hsub_s_b(MSARegister wd, MSARegister ws, MSARegister wt);
void hsub_s_h(MSARegister wd, MSARegister ws, MSARegister wt);
void hsub_s_w(MSARegister wd, MSARegister ws, MSARegister wt);
void hsub_s_d(MSARegister wd, MSARegister ws, MSARegister wt);
void hsub_u_b(MSARegister wd, MSARegister ws, MSARegister wt);
void hsub_u_h(MSARegister wd, MSARegister ws, MSARegister wt);
void hsub_u_w(MSARegister wd, MSARegister ws, MSARegister wt);
void hsub_u_d(MSARegister wd, MSARegister ws, MSARegister wt);
void fcaf_w(MSARegister wd, MSARegister ws, MSARegister wt);
void fcaf_d(MSARegister wd, MSARegister ws, MSARegister wt);
void fcun_w(MSARegister wd, MSARegister ws, MSARegister wt);
void fcun_d(MSARegister wd, MSARegister ws, MSARegister wt);
void fceq_w(MSARegister wd, MSARegister ws, MSARegister wt);
void fceq_d(MSARegister wd, MSARegister ws, MSARegister wt);
void fcueq_w(MSARegister wd, MSARegister ws, MSARegister wt);
void fcueq_d(MSARegister wd, MSARegister ws, MSARegister wt);
void fclt_w(MSARegister wd, MSARegister ws, MSARegister wt);
void fclt_d(MSARegister wd, MSARegister ws, MSARegister wt);
void fcult_w(MSARegister wd, MSARegister ws, MSARegister wt);
void fcult_d(MSARegister wd, MSARegister ws, MSARegister wt);
void fcle_w(MSARegister wd, MSARegister ws, MSARegister wt);
void fcle_d(MSARegister wd, MSARegister ws, MSARegister wt);
void fcule_w(MSARegister wd, MSARegister ws, MSARegister wt);
void fcule_d(MSARegister wd, MSARegister ws, MSARegister wt);
void fsaf_w(MSARegister wd, MSARegister ws, MSARegister wt);
void fsaf_d(MSARegister wd, MSARegister ws, MSARegister wt);
void fsun_w(MSARegister wd, MSARegister ws, MSARegister wt);
void fsun_d(MSARegister wd, MSARegister ws, MSARegister wt);
void fseq_w(MSARegister wd, MSARegister ws, MSARegister wt);
void fseq_d(MSARegister wd, MSARegister ws, MSARegister wt);
void fsueq_w(MSARegister wd, MSARegister ws, MSARegister wt);
void fsueq_d(MSARegister wd, MSARegister ws, MSARegister wt);
void fslt_w(MSARegister wd, MSARegister ws, MSARegister wt);
void fslt_d(MSARegister wd, MSARegister ws, MSARegister wt);
void fsult_w(MSARegister wd, MSARegister ws, MSARegister wt);
void fsult_d(MSARegister wd, MSARegister ws, MSARegister wt);
void fsle_w(MSARegister wd, MSARegister ws, MSARegister wt);
void fsle_d(MSARegister wd, MSARegister ws, MSARegister wt);
void fsule_w(MSARegister wd, MSARegister ws, MSARegister wt);
void fsule_d(MSARegister wd, MSARegister ws, MSARegister wt);
void fadd_w(MSARegister wd, MSARegister ws, MSARegister wt);
void fadd_d(MSARegister wd, MSARegister ws, MSARegister wt);
void fsub_w(MSARegister wd, MSARegister ws, MSARegister wt);
void fsub_d(MSARegister wd, MSARegister ws, MSARegister wt);
void fmul_w(MSARegister wd, MSARegister ws, MSARegister wt);
void fmul_d(MSARegister wd, MSARegister ws, MSARegister wt);
void fdiv_w(MSARegister wd, MSARegister ws, MSARegister wt);
void fdiv_d(MSARegister wd, MSARegister ws, MSARegister wt);
void fmadd_w(MSARegister wd, MSARegister ws, MSARegister wt);
void fmadd_d(MSARegister wd, MSARegister ws, MSARegister wt);
void fmsub_w(MSARegister wd, MSARegister ws, MSARegister wt);
void fmsub_d(MSARegister wd, MSARegister ws, MSARegister wt);
void fexp2_w(MSARegister wd, MSARegister ws, MSARegister wt);
void fexp2_d(MSARegister wd, MSARegister ws, MSARegister wt);
void fexdo_h(MSARegister wd, MSARegister ws, MSARegister wt);
void fexdo_w(MSARegister wd, MSARegister ws, MSARegister wt);
void ftq_h(MSARegister wd, MSARegister ws, MSARegister wt);
void ftq_w(MSARegister wd, MSARegister ws, MSARegister wt);
void fmin_w(MSARegister wd, MSARegister ws, MSARegister wt);
void fmin_d(MSARegister wd, MSARegister ws, MSARegister wt);
void fmin_a_w(MSARegister wd, MSARegister ws, MSARegister wt);
void fmin_a_d(MSARegister wd, MSARegister ws, MSARegister wt);
void fmax_w(MSARegister wd, MSARegister ws, MSARegister wt);
void fmax_d(MSARegister wd, MSARegister ws, MSARegister wt);
void fmax_a_w(MSARegister wd, MSARegister ws, MSARegister wt);
void fmax_a_d(MSARegister wd, MSARegister ws, MSARegister wt);
void fcor_w(MSARegister wd, MSARegister ws, MSARegister wt);
void fcor_d(MSARegister wd, MSARegister ws, MSARegister wt);
void fcune_w(MSARegister wd, MSARegister ws, MSARegister wt);
void fcune_d(MSARegister wd, MSARegister ws, MSARegister wt);
void fcne_w(MSARegister wd, MSARegister ws, MSARegister wt);
void fcne_d(MSARegister wd, MSARegister ws, MSARegister wt);
void mul_q_h(MSARegister wd, MSARegister ws, MSARegister wt);
void mul_q_w(MSARegister wd, MSARegister ws, MSARegister wt);
void madd_q_h(MSARegister wd, MSARegister ws, MSARegister wt);
void madd_q_w(MSARegister wd, MSARegister ws, MSARegister wt);
void msub_q_h(MSARegister wd, MSARegister ws, MSARegister wt);
void msub_q_w(MSARegister wd, MSARegister ws, MSARegister wt);
void fsor_w(MSARegister wd, MSARegister ws, MSARegister wt);
void fsor_d(MSARegister wd, MSARegister ws, MSARegister wt);
void fsune_w(MSARegister wd, MSARegister ws, MSARegister wt);
void fsune_d(MSARegister wd, MSARegister ws, MSARegister wt);
void fsne_w(MSARegister wd, MSARegister ws, MSARegister wt);
void fsne_d(MSARegister wd, MSARegister ws, MSARegister wt);
void mulr_q_h(MSARegister wd, MSARegister ws, MSARegister wt);
void mulr_q_w(MSARegister wd, MSARegister ws, MSARegister wt);
void maddr_q_h(MSARegister wd, MSARegister ws, MSARegister wt);
void maddr_q_w(MSARegister wd, MSARegister ws, MSARegister wt);
void msubr_q_h(MSARegister wd, MSARegister ws, MSARegister wt);
void msubr_q_w(MSARegister wd, MSARegister ws, MSARegister wt);
void sldi_b(MSARegister wd, MSARegister ws, uint32_t n);
void sldi_h(MSARegister wd, MSARegister ws, uint32_t n);
void sldi_w(MSARegister wd, MSARegister ws, uint32_t n);
void sldi_d(MSARegister wd, MSARegister ws, uint32_t n);
void splati_b(MSARegister wd, MSARegister ws, uint32_t n);
void splati_h(MSARegister wd, MSARegister ws, uint32_t n);
void splati_w(MSARegister wd, MSARegister ws, uint32_t n);
void splati_d(MSARegister wd, MSARegister ws, uint32_t n);
void copy_s_b(Register rd, MSARegister ws, uint32_t n);
void copy_s_h(Register rd, MSARegister ws, uint32_t n);
void copy_s_w(Register rd, MSARegister ws, uint32_t n);
void copy_s_d(Register rd, MSARegister ws, uint32_t n);
void copy_u_b(Register rd, MSARegister ws, uint32_t n);
void copy_u_h(Register rd, MSARegister ws, uint32_t n);
void copy_u_w(Register rd, MSARegister ws, uint32_t n);
void insert_b(MSARegister wd, uint32_t n, Register rs);
void insert_h(MSARegister wd, uint32_t n, Register rs);
void insert_w(MSARegister wd, uint32_t n, Register rs);
void insert_d(MSARegister wd, uint32_t n, Register rs);
void insve_b(MSARegister wd, uint32_t n, MSARegister ws);
void insve_h(MSARegister wd, uint32_t n, MSARegister ws);
void insve_w(MSARegister wd, uint32_t n, MSARegister ws);
void insve_d(MSARegister wd, uint32_t n, MSARegister ws);
void move_v(MSARegister wd, MSARegister ws);
void ctcmsa(MSAControlRegister cd, Register rs);
void cfcmsa(Register rd, MSAControlRegister cs);
void slli_b(MSARegister wd, MSARegister ws, uint32_t m);
void slli_h(MSARegister wd, MSARegister ws, uint32_t m);
void slli_w(MSARegister wd, MSARegister ws, uint32_t m);
void slli_d(MSARegister wd, MSARegister ws, uint32_t m);
void srai_b(MSARegister wd, MSARegister ws, uint32_t m);
void srai_h(MSARegister wd, MSARegister ws, uint32_t m);
void srai_w(MSARegister wd, MSARegister ws, uint32_t m);
void srai_d(MSARegister wd, MSARegister ws, uint32_t m);
void srli_b(MSARegister wd, MSARegister ws, uint32_t m);
void srli_h(MSARegister wd, MSARegister ws, uint32_t m);
void srli_w(MSARegister wd, MSARegister ws, uint32_t m);
void srli_d(MSARegister wd, MSARegister ws, uint32_t m);
void bclri_b(MSARegister wd, MSARegister ws, uint32_t m);
void bclri_h(MSARegister wd, MSARegister ws, uint32_t m);
void bclri_w(MSARegister wd, MSARegister ws, uint32_t m);
void bclri_d(MSARegister wd, MSARegister ws, uint32_t m);
void bseti_b(MSARegister wd, MSARegister ws, uint32_t m);
void bseti_h(MSARegister wd, MSARegister ws, uint32_t m);
void bseti_w(MSARegister wd, MSARegister ws, uint32_t m);
void bseti_d(MSARegister wd, MSARegister ws, uint32_t m);
void bnegi_b(MSARegister wd, MSARegister ws, uint32_t m);
void bnegi_h(MSARegister wd, MSARegister ws, uint32_t m);
void bnegi_w(MSARegister wd, MSARegister ws, uint32_t m);
void bnegi_d(MSARegister wd, MSARegister ws, uint32_t m);
void binsli_b(MSARegister wd, MSARegister ws, uint32_t m);
void binsli_h(MSARegister wd, MSARegister ws, uint32_t m);
void binsli_w(MSARegister wd, MSARegister ws, uint32_t m);
void binsli_d(MSARegister wd, MSARegister ws, uint32_t m);
void binsri_b(MSARegister wd, MSARegister ws, uint32_t m);
void binsri_h(MSARegister wd, MSARegister ws, uint32_t m);
void binsri_w(MSARegister wd, MSARegister ws, uint32_t m);
void binsri_d(MSARegister wd, MSARegister ws, uint32_t m);
void sat_s_b(MSARegister wd, MSARegister ws, uint32_t m);
void sat_s_h(MSARegister wd, MSARegister ws, uint32_t m);
void sat_s_w(MSARegister wd, MSARegister ws, uint32_t m);
void sat_s_d(MSARegister wd, MSARegister ws, uint32_t m);
void sat_u_b(MSARegister wd, MSARegister ws, uint32_t m);
void sat_u_h(MSARegister wd, MSARegister ws, uint32_t m);
void sat_u_w(MSARegister wd, MSARegister ws, uint32_t m);
void sat_u_d(MSARegister wd, MSARegister ws, uint32_t m);
void srari_b(MSARegister wd, MSARegister ws, uint32_t m);
void srari_h(MSARegister wd, MSARegister ws, uint32_t m);
void srari_w(MSARegister wd, MSARegister ws, uint32_t m);
void srari_d(MSARegister wd, MSARegister ws, uint32_t m);
void srlri_b(MSARegister wd, MSARegister ws, uint32_t m);
void srlri_h(MSARegister wd, MSARegister ws, uint32_t m);
void srlri_w(MSARegister wd, MSARegister ws, uint32_t m);
void srlri_d(MSARegister wd, MSARegister ws, uint32_t m);
// Check the code size generated from label to here.
int SizeOfCodeGeneratedSince(Label* label) {
return pc_offset() - label->pos();
......@@ -1433,6 +2096,75 @@ class Assembler : public AssemblerBase {
void GenInstrJump(Opcode opcode,
uint32_t address);
// MSA
void GenInstrMsaI8(SecondaryField operation, uint32_t imm8, MSARegister ws,
MSARegister wd);
void GenInstrMsaI5(SecondaryField operation, SecondaryField df, int32_t imm5,
MSARegister ws, MSARegister wd);
void GenInstrMsaBit(SecondaryField operation, SecondaryField df, uint32_t m,
MSARegister ws, MSARegister wd);
void GenInstrMsaI10(SecondaryField operation, SecondaryField df,
int32_t imm10, MSARegister wd);
template <typename RegType>
void GenInstrMsa3R(SecondaryField operation, SecondaryField df, RegType t,
MSARegister ws, MSARegister wd);
template <typename DstType, typename SrcType>
void GenInstrMsaElm(SecondaryField operation, SecondaryField df, uint32_t n,
SrcType src, DstType dst);
void GenInstrMsa3RF(SecondaryField operation, uint32_t df, MSARegister wt,
MSARegister ws, MSARegister wd);
void GenInstrMsaVec(SecondaryField operation, MSARegister wt, MSARegister ws,
MSARegister wd);
void GenInstrMsaMI10(SecondaryField operation, int32_t s10, Register rs,
MSARegister wd);
void GenInstrMsa2R(SecondaryField operation, SecondaryField df,
MSARegister ws, MSARegister wd);
void GenInstrMsa2RF(SecondaryField operation, SecondaryField df,
MSARegister ws, MSARegister wd);
void GenInstrMsaBranch(SecondaryField operation, MSARegister wt,
int32_t offset16);
inline bool is_valid_msa_df_m(SecondaryField bit_df, uint32_t m) {
switch (bit_df) {
case BIT_DF_b:
return is_uint3(m);
case BIT_DF_h:
return is_uint4(m);
case BIT_DF_w:
return is_uint5(m);
case BIT_DF_d:
return is_uint6(m);
default:
return false;
}
}
inline bool is_valid_msa_df_n(SecondaryField elm_df, uint32_t n) {
switch (elm_df) {
case ELM_DF_B:
return is_uint4(n);
case ELM_DF_H:
return is_uint3(n);
case ELM_DF_W:
return is_uint2(n);
case ELM_DF_D:
return is_uint1(n);
default:
return false;
}
}
// Labels.
void print(Label* L);
void bind_to(Label* L, int pos);
......
......@@ -121,6 +121,46 @@ int FPURegisters::Number(const char* name) {
// No Cregister with the reguested name found.
return kInvalidFPURegister;
}
const char* MSARegisters::names_[kNumMSARegisters] = {
"w0", "w1", "w2", "w3", "w4", "w5", "w6", "w7", "w8", "w9", "w10",
"w11", "w12", "w13", "w14", "w15", "w16", "w17", "w18", "w19", "w20", "w21",
"w22", "w23", "w24", "w25", "w26", "w27", "w28", "w29", "w30", "w31"};
const MSARegisters::RegisterAlias MSARegisters::aliases_[] = {
{kInvalidRegister, NULL}};
const char* MSARegisters::Name(int creg) {
const char* result;
if ((0 <= creg) && (creg < kNumMSARegisters)) {
result = names_[creg];
} else {
result = "nocreg";
}
return result;
}
int MSARegisters::Number(const char* name) {
// Look through the canonical names.
for (int i = 0; i < kNumMSARegisters; i++) {
if (strcmp(names_[i], name) == 0) {
return i;
}
}
// Look through the alias names.
int i = 0;
while (aliases_[i].creg != kInvalidRegister) {
if (strcmp(aliases_[i].name, name) == 0) {
return aliases_[i].creg;
}
i++;
}
// No Cregister with the reguested name found.
return kInvalidMSARegister;
}
} // namespace internal
} // namespace v8
......
......@@ -115,6 +115,14 @@ const int kPCRegister = 34;
const int kNumFPURegisters = 32;
const int kInvalidFPURegister = -1;
// Number of MSA registers
const int kNumMSARegisters = 32;
const int kInvalidMSARegister = -1;
const int kInvalidMSAControlRegister = -1;
const int kMSAIRRegister = 0;
const int kMSACSRRegister = 1;
// FPU (coprocessor 1) control registers. Currently only FCSR is implemented.
const int kFCSRRegister = 31;
const int kInvalidFPUControlRegister = -1;
......@@ -200,6 +208,24 @@ class FPURegisters {
static const RegisterAlias aliases_[];
};
// Helper functions for converting between register numbers and names.
class MSARegisters {
public:
// Return the name of the register.
static const char* Name(int reg);
// Lookup the register number for the name provided.
static int Number(const char* name);
struct RegisterAlias {
int creg;
const char* name;
};
private:
static const char* names_[kNumMSARegisters];
static const RegisterAlias aliases_[];
};
// -----------------------------------------------------------------------------
// Instructions encoding constants.
......@@ -260,6 +286,14 @@ const int kImm28Shift = 0;
const int kImm28Bits = 28;
const int kImm32Shift = 0;
const int kImm32Bits = 32;
const int kMsaImm8Shift = 16;
const int kMsaImm8Bits = 8;
const int kMsaImm5Shift = 16;
const int kMsaImm5Bits = 5;
const int kMsaImm10Shift = 11;
const int kMsaImm10Bits = 10;
const int kMsaImmMI10Shift = 16;
const int kMsaImmMI10Bits = 10;
// In branches and jumps immediate fields point to words, not bytes,
// and are therefore shifted by 2.
......@@ -279,6 +313,12 @@ const int kFBccShift = 18;
const int kFBccBits = 3;
const int kFBtrueShift = 16;
const int kFBtrueBits = 1;
const int kWtBits = 5;
const int kWtShift = 16;
const int kWsBits = 5;
const int kWsShift = 11;
const int kWdBits = 5;
const int kWdShift = 6;
// ----- Miscellaneous useful masks.
// Instruction bit masks.
......@@ -289,6 +329,10 @@ const int kImm19Mask = ((1 << kImm19Bits) - 1) << kImm19Shift;
const int kImm21Mask = ((1 << kImm21Bits) - 1) << kImm21Shift;
const int kImm26Mask = ((1 << kImm26Bits) - 1) << kImm26Shift;
const int kImm28Mask = ((1 << kImm28Bits) - 1) << kImm28Shift;
const int kImm5Mask = ((1 << 5) - 1);
const int kImm8Mask = ((1 << 8) - 1);
const int kImm10Mask = ((1 << 10) - 1);
const int kMsaI5I10Mask = ((7U << 23) | ((1 << 6) - 1));
const int kRsFieldMask = ((1 << kRsBits) - 1) << kRsShift;
const int kRtFieldMask = ((1 << kRtBits) - 1) << kRtShift;
const int kRdFieldMask = ((1 << kRdBits) - 1) << kRdShift;
......@@ -342,6 +386,7 @@ enum Opcode : uint32_t {
LDL = ((3U << 3) + 2) << kOpcodeShift,
LDR = ((3U << 3) + 3) << kOpcodeShift,
SPECIAL2 = ((3U << 3) + 4) << kOpcodeShift,
MSA = ((3U << 3) + 6) << kOpcodeShift,
SPECIAL3 = ((3U << 3) + 7) << kOpcodeShift,
LB = ((4U << 3) + 0) << kOpcodeShift,
......@@ -672,9 +717,267 @@ enum SecondaryField : uint32_t {
// POP76 Encoding of rs Field.
JIALC = ((0U << 5) + 0),
// COP1 Encoding of rs Field for MSA Branch Instructions
BZ_V = (((1U << 3) + 3) << kRsShift),
BNZ_V = (((1U << 3) + 7) << kRsShift),
BZ_B = (((3U << 3) + 0) << kRsShift),
BZ_H = (((3U << 3) + 1) << kRsShift),
BZ_W = (((3U << 3) + 2) << kRsShift),
BZ_D = (((3U << 3) + 3) << kRsShift),
BNZ_B = (((3U << 3) + 4) << kRsShift),
BNZ_H = (((3U << 3) + 5) << kRsShift),
BNZ_W = (((3U << 3) + 6) << kRsShift),
BNZ_D = (((3U << 3) + 7) << kRsShift),
// MSA: Operation Field for MI10 Instruction Formats
MSA_LD = (8U << 2),
MSA_ST = (9U << 2),
LD_B = ((8U << 2) + 0),
LD_H = ((8U << 2) + 1),
LD_W = ((8U << 2) + 2),
LD_D = ((8U << 2) + 3),
ST_B = ((9U << 2) + 0),
ST_H = ((9U << 2) + 1),
ST_W = ((9U << 2) + 2),
ST_D = ((9U << 2) + 3),
// MSA: Operation Field for I5 Instruction Format
ADDVI = ((0U << 23) + 6),
SUBVI = ((1U << 23) + 6),
MAXI_S = ((2U << 23) + 6),
MAXI_U = ((3U << 23) + 6),
MINI_S = ((4U << 23) + 6),
MINI_U = ((5U << 23) + 6),
CEQI = ((0U << 23) + 7),
CLTI_S = ((2U << 23) + 7),
CLTI_U = ((3U << 23) + 7),
CLEI_S = ((4U << 23) + 7),
CLEI_U = ((5U << 23) + 7),
LDI = ((6U << 23) + 7), // I10 instruction format
I5_DF_b = (0U << 21),
I5_DF_h = (1U << 21),
I5_DF_w = (2U << 21),
I5_DF_d = (3U << 21),
// MSA: Operation Field for I8 Instruction Format
ANDI_B = ((0U << 24) + 0),
ORI_B = ((1U << 24) + 0),
NORI_B = ((2U << 24) + 0),
XORI_B = ((3U << 24) + 0),
BMNZI_B = ((0U << 24) + 1),
BMZI_B = ((1U << 24) + 1),
BSELI_B = ((2U << 24) + 1),
SHF_B = ((0U << 24) + 2),
SHF_H = ((1U << 24) + 2),
SHF_W = ((2U << 24) + 2),
MSA_VEC_2R_2RF_MINOR = ((3U << 3) + 6),
// MSA: Operation Field for VEC Instruction Formats
AND_V = (((0U << 2) + 0) << 21),
OR_V = (((0U << 2) + 1) << 21),
NOR_V = (((0U << 2) + 2) << 21),
XOR_V = (((0U << 2) + 3) << 21),
BMNZ_V = (((1U << 2) + 0) << 21),
BMZ_V = (((1U << 2) + 1) << 21),
BSEL_V = (((1U << 2) + 2) << 21),
// MSA: Operation Field for 2R Instruction Formats
MSA_2R_FORMAT = (((6U << 2) + 0) << 21),
FILL = (0U << 18),
PCNT = (1U << 18),
NLOC = (2U << 18),
NLZC = (3U << 18),
MSA_2R_DF_b = (0U << 16),
MSA_2R_DF_h = (1U << 16),
MSA_2R_DF_w = (2U << 16),
MSA_2R_DF_d = (3U << 16),
// MSA: Operation Field for 2RF Instruction Formats
MSA_2RF_FORMAT = (((6U << 2) + 1) << 21),
FCLASS = (0U << 17),
FTRUNC_S = (1U << 17),
FTRUNC_U = (2U << 17),
FSQRT = (3U << 17),
FRSQRT = (4U << 17),
FRCP = (5U << 17),
FRINT = (6U << 17),
FLOG2 = (7U << 17),
FEXUPL = (8U << 17),
FEXUPR = (9U << 17),
FFQL = (10U << 17),
FFQR = (11U << 17),
FTINT_S = (12U << 17),
FTINT_U = (13U << 17),
FFINT_S = (14U << 17),
FFINT_U = (15U << 17),
MSA_2RF_DF_w = (0U << 16),
MSA_2RF_DF_d = (1U << 16),
// MSA: Operation Field for 3R Instruction Format
SLL_MSA = ((0U << 23) + 13),
SRA_MSA = ((1U << 23) + 13),
SRL_MSA = ((2U << 23) + 13),
BCLR = ((3U << 23) + 13),
BSET = ((4U << 23) + 13),
BNEG = ((5U << 23) + 13),
BINSL = ((6U << 23) + 13),
BINSR = ((7U << 23) + 13),
ADDV = ((0U << 23) + 14),
SUBV = ((1U << 23) + 14),
MAX_S = ((2U << 23) + 14),
MAX_U = ((3U << 23) + 14),
MIN_S = ((4U << 23) + 14),
MIN_U = ((5U << 23) + 14),
MAX_A = ((6U << 23) + 14),
MIN_A = ((7U << 23) + 14),
CEQ = ((0U << 23) + 15),
CLT_S = ((2U << 23) + 15),
CLT_U = ((3U << 23) + 15),
CLE_S = ((4U << 23) + 15),
CLE_U = ((5U << 23) + 15),
ADD_A = ((0U << 23) + 16),
ADDS_A = ((1U << 23) + 16),
ADDS_S = ((2U << 23) + 16),
ADDS_U = ((3U << 23) + 16),
AVE_S = ((4U << 23) + 16),
AVE_U = ((5U << 23) + 16),
AVER_S = ((6U << 23) + 16),
AVER_U = ((7U << 23) + 16),
SUBS_S = ((0U << 23) + 17),
SUBS_U = ((1U << 23) + 17),
SUBSUS_U = ((2U << 23) + 17),
SUBSUU_S = ((3U << 23) + 17),
ASUB_S = ((4U << 23) + 17),
ASUB_U = ((5U << 23) + 17),
MULV = ((0U << 23) + 18),
MADDV = ((1U << 23) + 18),
MSUBV = ((2U << 23) + 18),
DIV_S_MSA = ((4U << 23) + 18),
DIV_U = ((5U << 23) + 18),
MOD_S = ((6U << 23) + 18),
MOD_U = ((7U << 23) + 18),
DOTP_S = ((0U << 23) + 19),
DOTP_U = ((1U << 23) + 19),
DPADD_S = ((2U << 23) + 19),
DPADD_U = ((3U << 23) + 19),
DPSUB_S = ((4U << 23) + 19),
DPSUB_U = ((5U << 23) + 19),
SLD = ((0U << 23) + 20),
SPLAT = ((1U << 23) + 20),
PCKEV = ((2U << 23) + 20),
PCKOD = ((3U << 23) + 20),
ILVL = ((4U << 23) + 20),
ILVR = ((5U << 23) + 20),
ILVEV = ((6U << 23) + 20),
ILVOD = ((7U << 23) + 20),
VSHF = ((0U << 23) + 21),
SRAR = ((1U << 23) + 21),
SRLR = ((2U << 23) + 21),
HADD_S = ((4U << 23) + 21),
HADD_U = ((5U << 23) + 21),
HSUB_S = ((6U << 23) + 21),
HSUB_U = ((7U << 23) + 21),
MSA_3R_DF_b = (0U << 21),
MSA_3R_DF_h = (1U << 21),
MSA_3R_DF_w = (2U << 21),
MSA_3R_DF_d = (3U << 21),
// MSA: Operation Field for 3RF Instruction Format
FCAF = ((0U << 22) + 26),
FCUN = ((1U << 22) + 26),
FCEQ = ((2U << 22) + 26),
FCUEQ = ((3U << 22) + 26),
FCLT = ((4U << 22) + 26),
FCULT = ((5U << 22) + 26),
FCLE = ((6U << 22) + 26),
FCULE = ((7U << 22) + 26),
FSAF = ((8U << 22) + 26),
FSUN = ((9U << 22) + 26),
FSEQ = ((10U << 22) + 26),
FSUEQ = ((11U << 22) + 26),
FSLT = ((12U << 22) + 26),
FSULT = ((13U << 22) + 26),
FSLE = ((14U << 22) + 26),
FSULE = ((15U << 22) + 26),
FADD = ((0U << 22) + 27),
FSUB = ((1U << 22) + 27),
FMUL = ((2U << 22) + 27),
FDIV = ((3U << 22) + 27),
FMADD = ((4U << 22) + 27),
FMSUB = ((5U << 22) + 27),
FEXP2 = ((7U << 22) + 27),
FEXDO = ((8U << 22) + 27),
FTQ = ((10U << 22) + 27),
FMIN = ((12U << 22) + 27),
FMIN_A = ((13U << 22) + 27),
FMAX = ((14U << 22) + 27),
FMAX_A = ((15U << 22) + 27),
FCOR = ((1U << 22) + 28),
FCUNE = ((2U << 22) + 28),
FCNE = ((3U << 22) + 28),
MUL_Q = ((4U << 22) + 28),
MADD_Q = ((5U << 22) + 28),
MSUB_Q = ((6U << 22) + 28),
FSOR = ((9U << 22) + 28),
FSUNE = ((10U << 22) + 28),
FSNE = ((11U << 22) + 28),
MULR_Q = ((12U << 22) + 28),
MADDR_Q = ((13U << 22) + 28),
MSUBR_Q = ((14U << 22) + 28),
// MSA: Operation Field for ELM Instruction Format
MSA_ELM_MINOR = ((3U << 3) + 1),
SLDI = (0U << 22),
CTCMSA = ((0U << 22) | (62U << 16)),
SPLATI = (1U << 22),
CFCMSA = ((1U << 22) | (62U << 16)),
COPY_S = (2U << 22),
MOVE_V = ((2U << 22) | (62U << 16)),
COPY_U = (3U << 22),
INSERT = (4U << 22),
INSVE = (5U << 22),
ELM_DF_B = ((0U << 4) << 16),
ELM_DF_H = ((4U << 3) << 16),
ELM_DF_W = ((12U << 2) << 16),
ELM_DF_D = ((28U << 1) << 16),
// MSA: Operation Field for BIT Instruction Format
SLLI = ((0U << 23) + 9),
SRAI = ((1U << 23) + 9),
SRLI = ((2U << 23) + 9),
BCLRI = ((3U << 23) + 9),
BSETI = ((4U << 23) + 9),
BNEGI = ((5U << 23) + 9),
BINSLI = ((6U << 23) + 9),
BINSRI = ((7U << 23) + 9),
SAT_S = ((0U << 23) + 10),
SAT_U = ((1U << 23) + 10),
SRARI = ((2U << 23) + 10),
SRLRI = ((3U << 23) + 10),
BIT_DF_b = ((14U << 3) << 16),
BIT_DF_h = ((6U << 4) << 16),
BIT_DF_w = ((2U << 5) << 16),
BIT_DF_d = ((0U << 6) << 16),
NULLSF = 0U
};
enum MSAMinorOpcode : uint32_t {
kMsaMinorUndefined = 0,
kMsaMinorI8,
kMsaMinorI5,
kMsaMinorI10,
kMsaMinorBIT,
kMsaMinor3R,
kMsaMinor3RF,
kMsaMinorELM,
kMsaMinorVEC,
kMsaMinor2R,
kMsaMinor2RF,
kMsaMinorMI10
};
// ----- Emulated conditions.
// On MIPS we use this enum to abstract from conditional branch instructions.
// The 'U' prefix is used to specify unsigned comparisons.
......@@ -1014,6 +1317,62 @@ class InstructionBase {
// Get the encoding type of the instruction.
inline Type InstructionType() const;
inline MSAMinorOpcode MSAMinorOpcodeField() const {
int op = this->FunctionFieldRaw();
switch (op) {
case 0:
case 1:
case 2:
return kMsaMinorI8;
case 6:
return kMsaMinorI5;
case 7:
return (((this->InstructionBits() & kMsaI5I10Mask) == LDI)
? kMsaMinorI10
: kMsaMinorI5);
case 9:
case 10:
return kMsaMinorBIT;
case 13:
case 14:
case 15:
case 16:
case 17:
case 18:
case 19:
case 20:
case 21:
return kMsaMinor3R;
case 25:
return kMsaMinorELM;
case 26:
case 27:
case 28:
return kMsaMinor3RF;
case 30:
switch (this->RsFieldRawNoAssert()) {
case MSA_2R_FORMAT:
return kMsaMinor2R;
case MSA_2RF_FORMAT:
return kMsaMinor2RF;
default:
return kMsaMinorVEC;
}
break;
case 32:
case 33:
case 34:
case 35:
case 36:
case 37:
case 38:
case 39:
return kMsaMinorMI10;
default:
return kMsaMinorUndefined;
}
}
protected:
InstructionBase() {}
};
......@@ -1070,6 +1429,18 @@ class InstructionGetters : public T {
return this->Bits(kFrShift + kFrBits - 1, kFrShift);
}
inline int WdValue() const {
return this->Bits(kWdShift + kWdBits - 1, kWdShift);
}
inline int WsValue() const {
return this->Bits(kWsShift + kWsBits - 1, kWsShift);
}
inline int WtValue() const {
return this->Bits(kWtShift + kWtBits - 1, kWtShift);
}
inline int Bp2Value() const {
DCHECK(this->InstructionType() == InstructionBase::kRegisterType);
return this->Bits(kBp2Shift + kBp2Bits - 1, kBp2Shift);
......@@ -1177,6 +1548,68 @@ class InstructionGetters : public T {
return this->Bits(kImm26Shift + kImm26Bits - 1, kImm26Shift);
}
inline int32_t MsaImm8Value() const {
DCHECK(this->InstructionType() == InstructionBase::kImmediateType);
return this->Bits(kMsaImm8Shift + kMsaImm8Bits - 1, kMsaImm8Shift);
}
inline int32_t MsaImm5Value() const {
DCHECK(this->InstructionType() == InstructionBase::kImmediateType);
return this->Bits(kMsaImm5Shift + kMsaImm5Bits - 1, kMsaImm5Shift);
}
inline int32_t MsaImm10Value() const {
DCHECK(this->InstructionType() == InstructionBase::kImmediateType);
return this->Bits(kMsaImm10Shift + kMsaImm10Bits - 1, kMsaImm10Shift);
}
inline int32_t MsaImmMI10Value() const {
DCHECK(this->InstructionType() == InstructionBase::kImmediateType);
return this->Bits(kMsaImmMI10Shift + kMsaImmMI10Bits - 1, kMsaImmMI10Shift);
}
inline int32_t MsaBitDf() const {
DCHECK(this->InstructionType() == InstructionBase::kImmediateType);
int32_t df_m = this->Bits(22, 16);
if (((df_m >> 6) & 1U) == 0) {
return 3;
} else if (((df_m >> 5) & 3U) == 2) {
return 2;
} else if (((df_m >> 4) & 7U) == 6) {
return 1;
} else if (((df_m >> 3) & 15U) == 14) {
return 0;
} else {
return -1;
}
}
inline int32_t MsaBitMValue() const {
DCHECK(this->InstructionType() == InstructionBase::kImmediateType);
return this->Bits(16 + this->MsaBitDf() + 3, 16);
}
inline int32_t MsaElmDf() const {
DCHECK(this->InstructionType() == InstructionBase::kImmediateType);
int32_t df_n = this->Bits(21, 16);
if (((df_n >> 4) & 3U) == 0) {
return 0;
} else if (((df_n >> 3) & 7U) == 4) {
return 1;
} else if (((df_n >> 2) & 15U) == 12) {
return 2;
} else if (((df_n >> 1) & 31U) == 28) {
return 3;
} else {
return -1;
}
}
inline int32_t MsaElmNValue() const {
DCHECK(this->InstructionType() == InstructionBase::kImmediateType);
return this->Bits(16 + 4 - this->MsaElmDf(), 16);
}
static bool IsForbiddenAfterBranchInstr(Instr instr);
// Say if the instruction should not be used in a branch delay slot or
......@@ -1193,6 +1626,33 @@ class InstructionGetters : public T {
bool IsLinkingInstruction() const;
// Say if the instruction is a break or a trap.
bool IsTrap() const;
inline bool IsMSABranchInstr() const {
if (this->OpcodeFieldRaw() == COP1) {
switch (this->RsFieldRaw()) {
case BZ_V:
case BZ_B:
case BZ_H:
case BZ_W:
case BZ_D:
case BNZ_V:
case BNZ_B:
case BNZ_H:
case BNZ_W:
case BNZ_D:
return true;
default:
return false;
}
}
return false;
}
inline bool IsMSAInstr() const {
if (this->IsMSABranchInstr() || (this->OpcodeFieldRaw() == MSA))
return true;
return false;
}
};
class Instruction : public InstructionGetters<InstructionBase> {
......@@ -1295,6 +1755,18 @@ InstructionBase::Type InstructionBase::InstructionType() const {
case BC1EQZ:
case BC1NEZ:
return kImmediateType;
// MSA Branch instructions
case BZ_V:
case BNZ_V:
case BZ_B:
case BZ_H:
case BZ_W:
case BZ_D:
case BNZ_B:
case BNZ_H:
case BNZ_W:
case BNZ_D:
return kImmediateType;
default:
return kRegisterType;
}
......@@ -1307,6 +1779,18 @@ InstructionBase::Type InstructionBase::InstructionType() const {
case JAL:
return kJumpType;
case MSA:
switch (MSAMinorOpcodeField()) {
case kMsaMinor3R:
case kMsaMinor3RF:
case kMsaMinorVEC:
case kMsaMinor2R:
case kMsaMinor2RF:
return kRegisterType;
default:
return kImmediateType;
}
default:
return kImmediateType;
}
......
......@@ -60,6 +60,17 @@ class Decoder {
int InstructionDecode(byte* instruction);
private:
const uint32_t kMsaI8Mask = ((3U << 24) | ((1 << 6) - 1));
const uint32_t kMsaI5Mask = ((7U << 23) | ((1 << 6) - 1));
const uint32_t kMsaMI10Mask = (15U << 2);
const uint32_t kMsaBITMask = ((7U << 23) | ((1 << 6) - 1));
const uint32_t kMsaELMMask = (15U << 22);
const uint32_t kMsa3RMask = ((7U << 23) | ((1 << 6) - 1));
const uint32_t kMsa3RFMask = ((15U << 22) | ((1 << 6) - 1));
const uint32_t kMsaVECMask = (23U << 21);
const uint32_t kMsa2RMask = (7U << 18);
const uint32_t kMsa2RFMask = (15U << 17);
// Bottleneck functions to print into the out_buffer.
void PrintChar(const char ch);
void Print(const char* str);
......@@ -67,7 +78,9 @@ class Decoder {
// Printing of common values.
void PrintRegister(int reg);
void PrintFPURegister(int freg);
void PrintMSARegister(int wreg);
void PrintFPUStatusRegister(int freg);
void PrintMSAControlRegister(int creg);
void PrintRs(Instruction* instr);
void PrintRt(Instruction* instr);
void PrintRd(Instruction* instr);
......@@ -102,12 +115,22 @@ class Decoder {
void PrintFormat(Instruction* instr); // For floating format postfix.
void PrintBp2(Instruction* instr);
void PrintBp3(Instruction* instr);
void PrintMsaDataFormat(Instruction* instr);
void PrintMsaXImm8(Instruction* instr);
void PrintMsaImm8(Instruction* instr);
void PrintMsaImm5(Instruction* instr);
void PrintMsaSImm5(Instruction* instr);
void PrintMsaSImm10(Instruction* instr, bool is_mi10 = false);
void PrintMsaImmBit(Instruction* instr);
void PrintMsaImmElm(Instruction* instr);
void PrintMsaCopy(Instruction* instr);
// Printing of instruction name.
void PrintInstructionName(Instruction* instr);
// Handle formatting of instructions and their options.
int FormatRegister(Instruction* instr, const char* option);
int FormatFPURegister(Instruction* instr, const char* option);
int FormatMSARegister(Instruction* instr, const char* option);
int FormatOption(Instruction* instr, const char* option);
void Format(Instruction* instr, const char* format);
void Unknown(Instruction* instr);
......@@ -132,6 +155,18 @@ class Decoder {
void DecodeTypeJump(Instruction* instr);
void DecodeTypeMsaI8(Instruction* instr);
void DecodeTypeMsaI5(Instruction* instr);
void DecodeTypeMsaI10(Instruction* instr);
void DecodeTypeMsaELM(Instruction* instr);
void DecodeTypeMsaBIT(Instruction* instr);
void DecodeTypeMsaMI10(Instruction* instr);
void DecodeTypeMsa3R(Instruction* instr);
void DecodeTypeMsa3RF(Instruction* instr);
void DecodeTypeMsaVec(Instruction* instr);
void DecodeTypeMsa2R(Instruction* instr);
void DecodeTypeMsa2RF(Instruction* instr);
const disasm::NameConverter& converter_;
v8::internal::Vector<char> out_buffer_;
int out_buffer_pos_;
......@@ -191,6 +226,7 @@ void Decoder::PrintFPURegister(int freg) {
Print(converter_.NameOfXMMRegister(freg));
}
void Decoder::PrintMSARegister(int wreg) { Print(MSARegisters::Name(wreg)); }
void Decoder::PrintFPUStatusRegister(int freg) {
switch (freg) {
......@@ -202,6 +238,18 @@ void Decoder::PrintFPUStatusRegister(int freg) {
}
}
void Decoder::PrintMSAControlRegister(int creg) {
switch (creg) {
case kMSAIRRegister:
Print("MSAIR");
break;
case kMSACSRRegister:
Print("MSACSR");
break;
default:
Print("no_msacreg");
}
}
void Decoder::PrintFs(Instruction* instr) {
int freg = instr->RsValue();
......@@ -457,6 +505,53 @@ void Decoder::PrintCode(Instruction* instr) {
}
}
void Decoder::PrintMsaXImm8(Instruction* instr) {
int32_t imm = instr->MsaImm8Value();
out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "0x%x", imm);
}
void Decoder::PrintMsaImm8(Instruction* instr) {
int32_t imm = instr->MsaImm8Value();
out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "%u", imm);
}
void Decoder::PrintMsaImm5(Instruction* instr) {
int32_t imm = instr->MsaImm5Value();
out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "%u", imm);
}
void Decoder::PrintMsaSImm5(Instruction* instr) {
int32_t imm = instr->MsaImm5Value();
imm <<= (32 - kMsaImm5Bits);
imm >>= (32 - kMsaImm5Bits);
out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "%d", imm);
}
void Decoder::PrintMsaSImm10(Instruction* instr, bool is_mi10) {
int32_t imm = is_mi10 ? instr->MsaImmMI10Value() : instr->MsaImm10Value();
imm <<= (32 - kMsaImm10Bits);
imm >>= (32 - kMsaImm10Bits);
out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "%d", imm);
}
void Decoder::PrintMsaImmBit(Instruction* instr) {
int32_t m = instr->MsaBitMValue();
out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "%u", m);
}
void Decoder::PrintMsaImmElm(Instruction* instr) {
int32_t n = instr->MsaElmNValue();
out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "%u", n);
}
void Decoder::PrintMsaCopy(Instruction* instr) {
int32_t rd = instr->WdValue();
int32_t ws = instr->WsValue();
int32_t n = instr->MsaElmNValue();
out_buffer_pos_ +=
SNPrintF(out_buffer_ + out_buffer_pos_, "%s, %s[%u]",
converter_.NameOfCPURegister(rd), MSARegisters::Name(ws), n);
}
void Decoder::PrintFormat(Instruction* instr) {
char formatLetter = ' ';
......@@ -480,6 +575,84 @@ void Decoder::PrintFormat(Instruction* instr) {
PrintChar(formatLetter);
}
void Decoder::PrintMsaDataFormat(Instruction* instr) {
DCHECK(instr->IsMSAInstr());
char df = ' ';
if (instr->IsMSABranchInstr()) {
switch (instr->RsFieldRaw()) {
case BZ_V:
case BNZ_V:
df = 'v';
break;
case BZ_B:
case BNZ_B:
df = 'b';
break;
case BZ_H:
case BNZ_H:
df = 'h';
break;
case BZ_W:
case BNZ_W:
df = 'w';
break;
case BZ_D:
case BNZ_D:
df = 'd';
break;
default:
UNREACHABLE();
break;
}
} else {
char DF[] = {'b', 'h', 'w', 'd'};
switch (instr->MSAMinorOpcodeField()) {
case kMsaMinorI5:
case kMsaMinorI10:
case kMsaMinor3R:
df = DF[instr->Bits(22, 21)];
break;
case kMsaMinorMI10:
df = DF[instr->Bits(1, 0)];
break;
case kMsaMinorBIT:
df = DF[instr->MsaBitDf()];
break;
case kMsaMinorELM:
df = DF[instr->MsaElmDf()];
break;
case kMsaMinor3RF: {
uint32_t opcode = instr->InstructionBits() & kMsa3RFMask;
switch (opcode) {
case FEXDO:
case FTQ:
case MUL_Q:
case MADD_Q:
case MSUB_Q:
case MULR_Q:
case MADDR_Q:
case MSUBR_Q:
df = DF[1 + instr->Bit(21)];
break;
default:
df = DF[2 + instr->Bit(21)];
break;
}
} break;
case kMsaMinor2R:
df = DF[instr->Bits(17, 16)];
break;
case kMsaMinor2RF:
df = DF[2 + instr->Bit(16)];
break;
default:
UNREACHABLE();
break;
}
}
PrintChar(df);
}
// Printing of instruction name.
void Decoder::PrintInstructionName(Instruction* instr) {
......@@ -553,6 +726,27 @@ int Decoder::FormatFPURegister(Instruction* instr, const char* format) {
return -1;
}
// Handle all MSARegister based formatting in this function to reduce the
// complexity of FormatOption.
int Decoder::FormatMSARegister(Instruction* instr, const char* format) {
DCHECK(format[0] == 'w');
if (format[1] == 's') {
int reg = instr->WsValue();
PrintMSARegister(reg);
return 2;
} else if (format[1] == 't') {
int reg = instr->WtValue();
PrintMSARegister(reg);
return 2;
} else if (format[1] == 'd') {
int reg = instr->WdValue();
PrintMSARegister(reg);
return 2;
}
UNREACHABLE();
return -1;
}
// FormatOption takes a formatting string and interprets it based on
// the current instructions. The format string points to the first
......@@ -629,6 +823,16 @@ int Decoder::FormatOption(Instruction* instr, const char* format) {
break;
}
return 6;
} else if (format[4] == '0' && format[5] == 's') {
DCHECK(STRING_STARTS_WITH(format, "imm10s"));
if (format[6] == '1') {
DCHECK(STRING_STARTS_WITH(format, "imm10s1"));
PrintMsaSImm10(instr, false);
} else if (format[6] == '2') {
DCHECK(STRING_STARTS_WITH(format, "imm10s2"));
PrintMsaSImm10(instr, true);
}
return 7;
}
} else if (format[3] == '2' && format[4] == '1') {
DCHECK(STRING_STARTS_WITH(format, "imm21"));
......@@ -697,6 +901,28 @@ int Decoder::FormatOption(Instruction* instr, const char* format) {
}
}
return 6;
} else if (format[3] == '5') {
DCHECK(STRING_STARTS_WITH(format, "imm5"));
if (format[4] == 'u') {
DCHECK(STRING_STARTS_WITH(format, "imm5u"));
PrintMsaImm5(instr);
} else if (format[4] == 's') {
DCHECK(STRING_STARTS_WITH(format, "imm5s"));
PrintMsaSImm5(instr);
}
return 5;
} else if (format[3] == '8') {
DCHECK(STRING_STARTS_WITH(format, "imm8"));
PrintMsaImm8(instr);
return 4;
} else if (format[3] == 'b') {
DCHECK(STRING_STARTS_WITH(format, "immb"));
PrintMsaImmBit(instr);
return 4;
} else if (format[3] == 'e') {
DCHECK(STRING_STARTS_WITH(format, "imme"));
PrintMsaImmElm(instr);
return 4;
}
}
case 'r': { // 'r: registers.
......@@ -705,6 +931,9 @@ int Decoder::FormatOption(Instruction* instr, const char* format) {
case 'f': { // 'f: FPUregisters.
return FormatFPURegister(instr, format);
}
case 'w': { // 'w: MSA Register
return FormatMSARegister(instr, format);
}
case 's': { // 'sa.
switch (format[1]) {
case 'a':
......@@ -765,7 +994,11 @@ int Decoder::FormatOption(Instruction* instr, const char* format) {
return 2;
}
case 't':
PrintFormat(instr);
if (instr->IsMSAInstr()) {
PrintMsaDataFormat(instr);
} else {
PrintFormat(instr);
}
return 1;
}
UNREACHABLE();
......@@ -1587,6 +1820,27 @@ int Decoder::DecodeTypeRegister(Instruction* instr) {
case SPECIAL3:
DecodeTypeRegisterSPECIAL3(instr);
break;
case MSA:
switch (instr->MSAMinorOpcodeField()) {
case kMsaMinor3R:
DecodeTypeMsa3R(instr);
break;
case kMsaMinor3RF:
DecodeTypeMsa3RF(instr);
break;
case kMsaMinorVEC:
DecodeTypeMsaVec(instr);
break;
case kMsaMinor2R:
DecodeTypeMsa2R(instr);
break;
case kMsaMinor2RF:
DecodeTypeMsa2RF(instr);
break;
default:
UNREACHABLE();
}
break;
default:
UNREACHABLE();
}
......@@ -1609,6 +1863,20 @@ void Decoder::DecodeTypeImmediateCOP1(Instruction* instr) {
case BC1NEZ:
Format(instr, "bc1nez 'ft, 'imm16u -> 'imm16p4s2");
break;
case BZ_V:
case BZ_B:
case BZ_H:
case BZ_W:
case BZ_D:
Format(instr, "bz.'t 'wt, 'imm16s -> 'imm16p4s2");
break;
case BNZ_V:
case BNZ_B:
case BNZ_H:
case BNZ_W:
case BNZ_D:
Format(instr, "bnz.'t 'wt, 'imm16s -> 'imm16p4s2");
break;
default:
UNREACHABLE();
}
......@@ -1922,6 +2190,31 @@ void Decoder::DecodeTypeImmediate(Instruction* instr) {
}
break;
}
case MSA:
switch (instr->MSAMinorOpcodeField()) {
case kMsaMinorI8:
DecodeTypeMsaI8(instr);
break;
case kMsaMinorI5:
DecodeTypeMsaI5(instr);
break;
case kMsaMinorI10:
DecodeTypeMsaI10(instr);
break;
case kMsaMinorELM:
DecodeTypeMsaELM(instr);
break;
case kMsaMinorBIT:
DecodeTypeMsaBIT(instr);
break;
case kMsaMinorMI10:
DecodeTypeMsaMI10(instr);
break;
default:
UNREACHABLE();
break;
}
break;
default:
printf("a 0x%x \n", instr->OpcodeFieldRaw());
UNREACHABLE();
......@@ -1943,6 +2236,637 @@ void Decoder::DecodeTypeJump(Instruction* instr) {
}
}
void Decoder::DecodeTypeMsaI8(Instruction* instr) {
uint32_t opcode = instr->InstructionBits() & kMsaI8Mask;
switch (opcode) {
case ANDI_B:
Format(instr, "andi.b 'wd, 'ws, 'imm8");
break;
case ORI_B:
Format(instr, "ori.b 'wd, 'ws, 'imm8");
break;
case NORI_B:
Format(instr, "nori.b 'wd, 'ws, 'imm8");
break;
case XORI_B:
Format(instr, "xori.b 'wd, 'ws, 'imm8");
break;
case BMNZI_B:
Format(instr, "bmnzi.b 'wd, 'ws, 'imm8");
break;
case BMZI_B:
Format(instr, "bmzi.b 'wd, 'ws, 'imm8");
break;
case BSELI_B:
Format(instr, "bseli.b 'wd, 'ws, 'imm8");
break;
case SHF_B:
Format(instr, "shf.b 'wd, 'ws, 'imm8");
break;
case SHF_H:
Format(instr, "shf.h 'wd, 'ws, 'imm8");
break;
case SHF_W:
Format(instr, "shf.w 'wd, 'ws, 'imm8");
break;
default:
UNREACHABLE();
}
}
void Decoder::DecodeTypeMsaI5(Instruction* instr) {
uint32_t opcode = instr->InstructionBits() & kMsaI5Mask;
switch (opcode) {
case ADDVI:
Format(instr, "addvi.'t 'wd, 'ws, 'imm5u");
break;
case SUBVI:
Format(instr, "subvi.'t 'wd, 'ws, 'imm5u");
break;
case MAXI_S:
Format(instr, "maxi_s.'t 'wd, 'ws, 'imm5s");
break;
case MAXI_U:
Format(instr, "maxi_u.'t 'wd, 'ws, 'imm5u");
break;
case MINI_S:
Format(instr, "mini_s.'t 'wd, 'ws, 'imm5s");
break;
case MINI_U:
Format(instr, "mini_u.'t 'wd, 'ws, 'imm5u");
break;
case CEQI:
Format(instr, "ceqi.'t 'wd, 'ws, 'imm5s");
break;
case CLTI_S:
Format(instr, "clti_s.'t 'wd, 'ws, 'imm5s");
break;
case CLTI_U:
Format(instr, "clti_u.'t 'wd, 'ws, 'imm5u");
break;
case CLEI_S:
Format(instr, "clei_s.'t 'wd, 'ws, 'imm5s");
break;
case CLEI_U:
Format(instr, "clei_u.'t 'wd, 'ws, 'imm5u");
break;
default:
UNREACHABLE();
}
}
void Decoder::DecodeTypeMsaI10(Instruction* instr) {
uint32_t opcode = instr->InstructionBits() & kMsaI5Mask;
if (opcode == LDI) {
Format(instr, "ldi.'t 'wd, 'imm10s1");
} else {
UNREACHABLE();
}
}
void Decoder::DecodeTypeMsaELM(Instruction* instr) {
uint32_t opcode = instr->InstructionBits() & kMsaELMMask;
switch (opcode) {
case SLDI:
if (instr->Bits(21, 16) == 0x3E) {
Format(instr, "ctcmsa ");
PrintMSAControlRegister(instr->WdValue());
Print(", ");
PrintRegister(instr->WsValue());
} else {
Format(instr, "sldi.'t 'wd, 'ws['imme]");
}
break;
case SPLATI:
if (instr->Bits(21, 16) == 0x3E) {
Format(instr, "cfcmsa ");
PrintRegister(instr->WdValue());
Print(", ");
PrintMSAControlRegister(instr->WsValue());
} else {
Format(instr, "splati.'t 'wd, 'ws['imme]");
}
break;
case COPY_S:
if (instr->Bits(21, 16) == 0x3E) {
Format(instr, "move.v 'wd, 'ws");
} else {
Format(instr, "copy_s.'t ");
PrintMsaCopy(instr);
}
break;
case COPY_U:
Format(instr, "copy_u.'t ");
PrintMsaCopy(instr);
break;
case INSERT:
Format(instr, "insert.'t 'wd['imme], ");
PrintRegister(instr->WsValue());
break;
case INSVE:
Format(instr, "insve.'t 'wd['imme], 'ws[0]");
break;
default:
UNREACHABLE();
}
}
void Decoder::DecodeTypeMsaBIT(Instruction* instr) {
uint32_t opcode = instr->InstructionBits() & kMsaBITMask;
switch (opcode) {
case SLLI:
Format(instr, "slli.'t 'wd, 'ws, 'immb");
break;
case SRAI:
Format(instr, "srai.'t 'wd, 'ws, 'immb");
break;
case SRLI:
Format(instr, "srli.'t 'wd, 'ws, 'immb");
break;
case BCLRI:
Format(instr, "bclri.'t 'wd, 'ws, 'immb");
break;
case BSETI:
Format(instr, "bseti.'t 'wd, 'ws, 'immb");
break;
case BNEGI:
Format(instr, "bnegi.'t 'wd, 'ws, 'immb");
break;
case BINSLI:
Format(instr, "binsli.'t 'wd, 'ws, 'immb");
break;
case BINSRI:
Format(instr, "binsri.'t 'wd, 'ws, 'immb");
break;
case SAT_S:
Format(instr, "sat_s.'t 'wd, 'ws, 'immb");
break;
case SAT_U:
Format(instr, "sat_u.'t 'wd, 'ws, 'immb");
break;
case SRARI:
Format(instr, "srari.'t 'wd, 'ws, 'immb");
break;
case SRLRI:
Format(instr, "srlri.'t 'wd, 'ws, 'immb");
break;
default:
UNREACHABLE();
}
}
void Decoder::DecodeTypeMsaMI10(Instruction* instr) {
uint32_t opcode = instr->InstructionBits() & kMsaMI10Mask;
if (opcode == MSA_LD) {
Format(instr, "ld.'t 'wd, 'imm10s2(");
PrintRegister(instr->WsValue());
Print(")");
} else if (opcode == MSA_ST) {
Format(instr, "st.'t 'wd, 'imm10s2(");
PrintRegister(instr->WsValue());
Print(")");
} else {
UNREACHABLE();
}
}
void Decoder::DecodeTypeMsa3R(Instruction* instr) {
uint32_t opcode = instr->InstructionBits() & kMsa3RMask;
switch (opcode) {
case SLL_MSA:
Format(instr, "sll.'t 'wd, 'ws, 'wt");
break;
case SRA_MSA:
Format(instr, "sra.'t 'wd, 'ws, 'wt");
break;
case SRL_MSA:
Format(instr, "srl.'t 'wd, 'ws, 'wt");
break;
case BCLR:
Format(instr, "bclr.'t 'wd, 'ws, 'wt");
break;
case BSET:
Format(instr, "bset.'t 'wd, 'ws, 'wt");
break;
case BNEG:
Format(instr, "bneg.'t 'wd, 'ws, 'wt");
break;
case BINSL:
Format(instr, "binsl.'t 'wd, 'ws, 'wt");
break;
case BINSR:
Format(instr, "binsr.'t 'wd, 'ws, 'wt");
break;
case ADDV:
Format(instr, "addv.'t 'wd, 'ws, 'wt");
break;
case SUBV:
Format(instr, "subv.'t 'wd, 'ws, 'wt");
break;
case MAX_S:
Format(instr, "max_s.'t 'wd, 'ws, 'wt");
break;
case MAX_U:
Format(instr, "max_u.'t 'wd, 'ws, 'wt");
break;
case MIN_S:
Format(instr, "min_s.'t 'wd, 'ws, 'wt");
break;
case MIN_U:
Format(instr, "min_u.'t 'wd, 'ws, 'wt");
break;
case MAX_A:
Format(instr, "max_a.'t 'wd, 'ws, 'wt");
break;
case MIN_A:
Format(instr, "min_a.'t 'wd, 'ws, 'wt");
break;
case CEQ:
Format(instr, "ceq.'t 'wd, 'ws, 'wt");
break;
case CLT_S:
Format(instr, "clt_s.'t 'wd, 'ws, 'wt");
break;
case CLT_U:
Format(instr, "clt_u.'t 'wd, 'ws, 'wt");
break;
case CLE_S:
Format(instr, "cle_s.'t 'wd, 'ws, 'wt");
break;
case CLE_U:
Format(instr, "cle_u.'t 'wd, 'ws, 'wt");
break;
case ADD_A:
Format(instr, "add_a.'t 'wd, 'ws, 'wt");
break;
case ADDS_A:
Format(instr, "adds_a.'t 'wd, 'ws, 'wt");
break;
case ADDS_S:
Format(instr, "adds_s.'t 'wd, 'ws, 'wt");
break;
case ADDS_U:
Format(instr, "adds_u.'t 'wd, 'ws, 'wt");
break;
case AVE_S:
Format(instr, "ave_s.'t 'wd, 'ws, 'wt");
break;
case AVE_U:
Format(instr, "ave_u.'t 'wd, 'ws, 'wt");
break;
case AVER_S:
Format(instr, "aver_s.'t 'wd, 'ws, 'wt");
break;
case AVER_U:
Format(instr, "aver_u.'t 'wd, 'ws, 'wt");
break;
case SUBS_S:
Format(instr, "subs_s.'t 'wd, 'ws, 'wt");
break;
case SUBS_U:
Format(instr, "subs_u.'t 'wd, 'ws, 'wt");
break;
case SUBSUS_U:
Format(instr, "subsus_u.'t 'wd, 'ws, 'wt");
break;
case SUBSUU_S:
Format(instr, "subsuu_s.'t 'wd, 'ws, 'wt");
break;
case ASUB_S:
Format(instr, "asub_s.'t 'wd, 'ws, 'wt");
break;
case ASUB_U:
Format(instr, "asub_u.'t 'wd, 'ws, 'wt");
break;
case MULV:
Format(instr, "mulv.'t 'wd, 'ws, 'wt");
break;
case MADDV:
Format(instr, "maddv.'t 'wd, 'ws, 'wt");
break;
case MSUBV:
Format(instr, "msubv.'t 'wd, 'ws, 'wt");
break;
case DIV_S_MSA:
Format(instr, "div_s.'t 'wd, 'ws, 'wt");
break;
case DIV_U:
Format(instr, "div_u.'t 'wd, 'ws, 'wt");
break;
case MOD_S:
Format(instr, "mod_s.'t 'wd, 'ws, 'wt");
break;
case MOD_U:
Format(instr, "mod_u.'t 'wd, 'ws, 'wt");
break;
case DOTP_S:
Format(instr, "dotp_s.'t 'wd, 'ws, 'wt");
break;
case DOTP_U:
Format(instr, "dotp_u.'t 'wd, 'ws, 'wt");
break;
case DPADD_S:
Format(instr, "dpadd_s.'t 'wd, 'ws, 'wt");
break;
case DPADD_U:
Format(instr, "dpadd_u.'t 'wd, 'ws, 'wt");
break;
case DPSUB_S:
Format(instr, "dpsub_s.'t 'wd, 'ws, 'wt");
break;
case DPSUB_U:
Format(instr, "dpsub_u.'t 'wd, 'ws, 'wt");
break;
case SLD:
Format(instr, "sld.'t 'wd, 'ws['rt]");
break;
case SPLAT:
Format(instr, "splat.'t 'wd, 'ws['rt]");
break;
case PCKEV:
Format(instr, "pckev.'t 'wd, 'ws, 'wt");
break;
case PCKOD:
Format(instr, "pckod.'t 'wd, 'ws, 'wt");
break;
case ILVL:
Format(instr, "ilvl.'t 'wd, 'ws, 'wt");
break;
case ILVR:
Format(instr, "ilvr.'t 'wd, 'ws, 'wt");
break;
case ILVEV:
Format(instr, "ilvev.'t 'wd, 'ws, 'wt");
break;
case ILVOD:
Format(instr, "ilvod.'t 'wd, 'ws, 'wt");
break;
case VSHF:
Format(instr, "vshf.'t 'wd, 'ws, 'wt");
break;
case SRAR:
Format(instr, "srar.'t 'wd, 'ws, 'wt");
break;
case SRLR:
Format(instr, "srlr.'t 'wd, 'ws, 'wt");
break;
case HADD_S:
Format(instr, "hadd_s.'t 'wd, 'ws, 'wt");
break;
case HADD_U:
Format(instr, "hadd_u.'t 'wd, 'ws, 'wt");
break;
case HSUB_S:
Format(instr, "hsub_s.'t 'wd, 'ws, 'wt");
break;
case HSUB_U:
Format(instr, "hsub_u.'t 'wd, 'ws, 'wt");
break;
default:
UNREACHABLE();
}
}
void Decoder::DecodeTypeMsa3RF(Instruction* instr) {
uint32_t opcode = instr->InstructionBits() & kMsa3RFMask;
switch (opcode) {
case FCAF:
Format(instr, "fcaf.'t 'wd, 'ws, 'wt");
break;
case FCUN:
Format(instr, "fcun.'t 'wd, 'ws, 'wt");
break;
case FCEQ:
Format(instr, "fceq.'t 'wd, 'ws, 'wt");
break;
case FCUEQ:
Format(instr, "fcueq.'t 'wd, 'ws, 'wt");
break;
case FCLT:
Format(instr, "fclt.'t 'wd, 'ws, 'wt");
break;
case FCULT:
Format(instr, "fcult.'t 'wd, 'ws, 'wt");
break;
case FCLE:
Format(instr, "fcle.'t 'wd, 'ws, 'wt");
break;
case FCULE:
Format(instr, "fcule.'t 'wd, 'ws, 'wt");
break;
case FSAF:
Format(instr, "fsaf.'t 'wd, 'ws, 'wt");
break;
case FSUN:
Format(instr, "fsun.'t 'wd, 'ws, 'wt");
break;
case FSEQ:
Format(instr, "fseq.'t 'wd, 'ws, 'wt");
break;
case FSUEQ:
Format(instr, "fsueq.'t 'wd, 'ws, 'wt");
break;
case FSLT:
Format(instr, "fslt.'t 'wd, 'ws, 'wt");
break;
case FSULT:
Format(instr, "fsult.'t 'wd, 'ws, 'wt");
break;
case FSLE:
Format(instr, "fsle.'t 'wd, 'ws, 'wt");
break;
case FSULE:
Format(instr, "fsule.'t 'wd, 'ws, 'wt");
break;
case FADD:
Format(instr, "fadd.'t 'wd, 'ws, 'wt");
break;
case FSUB:
Format(instr, "fsub.'t 'wd, 'ws, 'wt");
break;
case FMUL:
Format(instr, "fmul.'t 'wd, 'ws, 'wt");
break;
case FDIV:
Format(instr, "fdiv.'t 'wd, 'ws, 'wt");
break;
case FMADD:
Format(instr, "fmadd.'t 'wd, 'ws, 'wt");
break;
case FMSUB:
Format(instr, "fmsub.'t 'wd, 'ws, 'wt");
break;
case FEXP2:
Format(instr, "fexp2.'t 'wd, 'ws, 'wt");
break;
case FEXDO:
Format(instr, "fexdo.'t 'wd, 'ws, 'wt");
break;
case FTQ:
Format(instr, "ftq.'t 'wd, 'ws, 'wt");
break;
case FMIN:
Format(instr, "fmin.'t 'wd, 'ws, 'wt");
break;
case FMIN_A:
Format(instr, "fmin_a.'t 'wd, 'ws, 'wt");
break;
case FMAX:
Format(instr, "fmax.'t 'wd, 'ws, 'wt");
break;
case FMAX_A:
Format(instr, "fmax_a.'t 'wd, 'ws, 'wt");
break;
case FCOR:
Format(instr, "fcor.'t 'wd, 'ws, 'wt");
break;
case FCUNE:
Format(instr, "fcune.'t 'wd, 'ws, 'wt");
break;
case FCNE:
Format(instr, "fcne.'t 'wd, 'ws, 'wt");
break;
case MUL_Q:
Format(instr, "mul_q.'t 'wd, 'ws, 'wt");
break;
case MADD_Q:
Format(instr, "madd_q.'t 'wd, 'ws, 'wt");
break;
case MSUB_Q:
Format(instr, "msub_q.'t 'wd, 'ws, 'wt");
break;
case FSOR:
Format(instr, "fsor.'t 'wd, 'ws, 'wt");
break;
case FSUNE:
Format(instr, "fsune.'t 'wd, 'ws, 'wt");
break;
case FSNE:
Format(instr, "fsne.'t 'wd, 'ws, 'wt");
break;
case MULR_Q:
Format(instr, "mulr_q.'t 'wd, 'ws, 'wt");
break;
case MADDR_Q:
Format(instr, "maddr_q.'t 'wd, 'ws, 'wt");
break;
case MSUBR_Q:
Format(instr, "msubr_q.'t 'wd, 'ws, 'wt");
break;
default:
UNREACHABLE();
}
}
void Decoder::DecodeTypeMsaVec(Instruction* instr) {
uint32_t opcode = instr->InstructionBits() & kMsaVECMask;
switch (opcode) {
case AND_V:
Format(instr, "and.v 'wd, 'ws, 'wt");
break;
case OR_V:
Format(instr, "or.v 'wd, 'ws, 'wt");
break;
case NOR_V:
Format(instr, "nor.v 'wd, 'ws, 'wt");
break;
case XOR_V:
Format(instr, "xor.v 'wd, 'ws, 'wt");
break;
case BMNZ_V:
Format(instr, "bmnz.v 'wd, 'ws, 'wt");
break;
case BMZ_V:
Format(instr, "bmz.v 'wd, 'ws, 'wt");
break;
case BSEL_V:
Format(instr, "bsel.v 'wd, 'ws, 'wt");
break;
default:
UNREACHABLE();
}
}
void Decoder::DecodeTypeMsa2R(Instruction* instr) {
uint32_t opcode = instr->InstructionBits() & kMsa2RMask;
switch (opcode) {
case FILL: {
Format(instr, "fill.'t 'wd, ");
PrintRegister(instr->WsValue()); // rs value is in ws field
} break;
case PCNT:
Format(instr, "pcnt.'t 'wd, 'ws");
break;
case NLOC:
Format(instr, "nloc.'t 'wd, 'ws");
break;
case NLZC:
Format(instr, "nlzc.'t 'wd, 'ws");
break;
default:
UNREACHABLE();
}
}
void Decoder::DecodeTypeMsa2RF(Instruction* instr) {
uint32_t opcode = instr->InstructionBits() & kMsa2RFMask;
switch (opcode) {
case FCLASS:
Format(instr, "fclass.'t 'wd, 'ws");
break;
case FTRUNC_S:
Format(instr, "ftrunc_s.'t 'wd, 'ws");
break;
case FTRUNC_U:
Format(instr, "ftrunc_u.'t 'wd, 'ws");
break;
case FSQRT:
Format(instr, "fsqrt.'t 'wd, 'ws");
break;
case FRSQRT:
Format(instr, "frsqrt.'t 'wd, 'ws");
break;
case FRCP:
Format(instr, "frcp.'t 'wd, 'ws");
break;
case FRINT:
Format(instr, "frint.'t 'wd, 'ws");
break;
case FLOG2:
Format(instr, "flog2.'t 'wd, 'ws");
break;
case FEXUPL:
Format(instr, "fexupl.'t 'wd, 'ws");
break;
case FEXUPR:
Format(instr, "fexupr.'t 'wd, 'ws");
break;
case FFQL:
Format(instr, "ffql.'t 'wd, 'ws");
break;
case FFQR:
Format(instr, "ffqr.'t 'wd, 'ws");
break;
case FTINT_S:
Format(instr, "ftint_s.'t 'wd, 'ws");
break;
case FTINT_U:
Format(instr, "ftint_u.'t 'wd, 'ws");
break;
case FFINT_S:
Format(instr, "ffint_s.'t 'wd, 'ws");
break;
case FFINT_U:
Format(instr, "ffint_u.'t 'wd, 'ws");
break;
default:
UNREACHABLE();
}
}
// Disassemble the instruction at *instr_ptr into the output buffer.
// All instructions are one word long, except for the simulator
......
......@@ -127,6 +127,18 @@ if (failure) { \
if (!DisassembleAndCompare(progcounter, str_with_address)) failure = true; \
}
#define COMPARE_MSA_BRANCH(asm_, compare_string, offset) \
{ \
int pc_offset = assm.pc_offset(); \
byte* progcounter = &buffer[pc_offset]; \
char str_with_address[100]; \
snprintf(str_with_address, sizeof(str_with_address), "%s -> %p", \
compare_string, \
static_cast<void*>(progcounter + 4 + (offset * 4))); \
assm.asm_; \
if (!DisassembleAndCompare(progcounter, str_with_address)) failure = true; \
}
#define COMPARE_PC_JUMP(asm_, compare_string, target) \
{ \
int pc_offset = assm.pc_offset(); \
......@@ -1107,3 +1119,683 @@ TEST(madd_msub_maddf_msubf) {
}
VERIFY_RUN();
}
TEST(MSA_BRANCH) {
SET_UP();
if (IsMipsArchVariant(kMips32r6) && CpuFeatures::IsSupported(MIPS_SIMD)) {
CpuFeatureScope fscope(&assm, MIPS_SIMD);
COMPARE_MSA_BRANCH(bnz_b(w0, 1), "47800001 bnz.b w0, 1", 1);
COMPARE_MSA_BRANCH(bnz_h(w1, -1), "47a1ffff bnz.h w1, -1", -1);
COMPARE_MSA_BRANCH(bnz_w(w2, 32767), "47c27fff bnz.w w2, 32767",
32767);
COMPARE_MSA_BRANCH(bnz_d(w3, -32768), "47e38000 bnz.d w3, -32768",
-32768);
COMPARE_MSA_BRANCH(bnz_v(w0, 0), "45e00000 bnz.v w0, 0", 0);
COMPARE_MSA_BRANCH(bz_b(w0, 1), "47000001 bz.b w0, 1", 1);
COMPARE_MSA_BRANCH(bz_h(w1, -1), "4721ffff bz.h w1, -1", -1);
COMPARE_MSA_BRANCH(bz_w(w2, 32767), "47427fff bz.w w2, 32767",
32767);
COMPARE_MSA_BRANCH(bz_d(w3, -32768), "47638000 bz.d w3, -32768",
-32768);
COMPARE_MSA_BRANCH(bz_v(w0, 0), "45600000 bz.v w0, 0", 0);
}
VERIFY_RUN();
}
TEST(MSA_MI10) {
SET_UP();
if (IsMipsArchVariant(kMips32r6) && CpuFeatures::IsSupported(MIPS_SIMD)) {
CpuFeatureScope fscope(&assm, MIPS_SIMD);
COMPARE(ld_b(w0, MemOperand(at, -512)),
"7a000820 ld.b w0, -512(at)");
COMPARE(ld_b(w1, MemOperand(v0, 0)), "78001060 ld.b w1, 0(v0)");
COMPARE(ld_b(w2, MemOperand(v1, 511)), "79ff18a0 ld.b w2, 511(v1)");
COMPARE(ld_h(w4, MemOperand(a1, -512)),
"7a002921 ld.h w4, -512(a1)");
COMPARE(ld_h(w5, MemOperand(a2, 64)), "78403161 ld.h w5, 64(a2)");
COMPARE(ld_h(w6, MemOperand(a3, 511)), "79ff39a1 ld.h w6, 511(a3)");
COMPARE(ld_w(w10, MemOperand(t3, -512)),
"7a005aa2 ld.w w10, -512(t3)");
COMPARE(ld_w(w11, MemOperand(t4, 511)),
"79ff62e2 ld.w w11, 511(t4)");
COMPARE(ld_w(w12, MemOperand(t5, -128)),
"7b806b22 ld.w w12, -128(t5)");
COMPARE(ld_d(w17, MemOperand(s2, -512)),
"7a009463 ld.d w17, -512(s2)");
COMPARE(ld_d(w18, MemOperand(s3, 128)),
"78809ca3 ld.d w18, 128(s3)");
COMPARE(ld_d(w19, MemOperand(s4, 511)),
"79ffa4e3 ld.d w19, 511(s4)");
COMPARE(st_b(w0, MemOperand(at, -512)),
"7a000824 st.b w0, -512(at)");
COMPARE(st_b(w1, MemOperand(v0, 0)), "78001064 st.b w1, 0(v0)");
COMPARE(st_b(w2, MemOperand(v1, 511)), "79ff18a4 st.b w2, 511(v1)");
COMPARE(st_h(w4, MemOperand(a1, -512)),
"7a002925 st.h w4, -512(a1)");
COMPARE(st_h(w5, MemOperand(a2, 64)), "78403165 st.h w5, 64(a2)");
COMPARE(st_h(w6, MemOperand(a3, 511)), "79ff39a5 st.h w6, 511(a3)");
COMPARE(st_w(w10, MemOperand(t3, -512)),
"7a005aa6 st.w w10, -512(t3)");
COMPARE(st_w(w11, MemOperand(t4, 511)),
"79ff62e6 st.w w11, 511(t4)");
COMPARE(st_w(w12, MemOperand(t5, -128)),
"7b806b26 st.w w12, -128(t5)");
COMPARE(st_d(w17, MemOperand(s2, -512)),
"7a009467 st.d w17, -512(s2)");
COMPARE(st_d(w18, MemOperand(s3, 128)),
"78809ca7 st.d w18, 128(s3)");
COMPARE(st_d(w19, MemOperand(s4, 511)),
"79ffa4e7 st.d w19, 511(s4)");
}
VERIFY_RUN();
}
TEST(MSA_I5) {
SET_UP();
if (IsMipsArchVariant(kMips32r6) && CpuFeatures::IsSupported(MIPS_SIMD)) {
CpuFeatureScope fscope(&assm, MIPS_SIMD);
COMPARE(addvi_b(w3, w31, 30), "781ef8c6 addvi.b w3, w31, 30");
COMPARE(addvi_h(w24, w13, 26), "783a6e06 addvi.h w24, w13, 26");
COMPARE(addvi_w(w26, w20, 26), "785aa686 addvi.w w26, w20, 26");
COMPARE(addvi_d(w16, w1, 21), "78750c06 addvi.d w16, w1, 21");
COMPARE(ceqi_b(w24, w21, -8), "7818ae07 ceqi.b w24, w21, -8");
COMPARE(ceqi_h(w31, w15, 2), "78227fc7 ceqi.h w31, w15, 2");
COMPARE(ceqi_w(w12, w1, -1), "785f0b07 ceqi.w w12, w1, -1");
COMPARE(ceqi_d(w24, w22, 7), "7867b607 ceqi.d w24, w22, 7");
COMPARE(clei_s_b(w12, w16, 1), "7a018307 clei_s.b w12, w16, 1");
COMPARE(clei_s_h(w2, w10, -9), "7a375087 clei_s.h w2, w10, -9");
COMPARE(clei_s_w(w4, w11, -10), "7a565907 clei_s.w w4, w11, -10");
COMPARE(clei_s_d(w0, w29, -10), "7a76e807 clei_s.d w0, w29, -10");
COMPARE(clei_u_b(w21, w17, 3), "7a838d47 clei_u.b w21, w17, 3");
COMPARE(clei_u_h(w29, w7, 17), "7ab13f47 clei_u.h w29, w7, 17");
COMPARE(clei_u_w(w1, w1, 2), "7ac20847 clei_u.w w1, w1, 2");
COMPARE(clei_u_d(w27, w27, 29), "7afddec7 clei_u.d w27, w27, 29");
COMPARE(clti_s_b(w19, w13, -7), "79196cc7 clti_s.b w19, w13, -7");
COMPARE(clti_s_h(w15, w10, -12), "793453c7 clti_s.h w15, w10, -12");
COMPARE(clti_s_w(w12, w12, 11), "794b6307 clti_s.w w12, w12, 11");
COMPARE(clti_s_d(w29, w20, -15), "7971a747 clti_s.d w29, w20, -15");
COMPARE(clti_u_b(w14, w9, 29), "799d4b87 clti_u.b w14, w9, 29");
COMPARE(clti_u_h(w24, w25, 25), "79b9ce07 clti_u.h w24, w25, 25");
COMPARE(clti_u_w(w1, w1, 22), "79d60847 clti_u.w w1, w1, 22");
COMPARE(clti_u_d(w21, w25, 1), "79e1cd47 clti_u.d w21, w25, 1");
COMPARE(maxi_s_b(w22, w21, 1), "7901ad86 maxi_s.b w22, w21, 1");
COMPARE(maxi_s_h(w29, w5, -8), "79382f46 maxi_s.h w29, w5, -8");
COMPARE(maxi_s_w(w1, w10, -12), "79545046 maxi_s.w w1, w10, -12");
COMPARE(maxi_s_d(w13, w29, -16), "7970eb46 maxi_s.d w13, w29, -16");
COMPARE(maxi_u_b(w20, w0, 12), "798c0506 maxi_u.b w20, w0, 12");
COMPARE(maxi_u_h(w1, w14, 3), "79a37046 maxi_u.h w1, w14, 3");
COMPARE(maxi_u_w(w27, w22, 11), "79cbb6c6 maxi_u.w w27, w22, 11");
COMPARE(maxi_u_d(w26, w6, 4), "79e43686 maxi_u.d w26, w6, 4");
COMPARE(mini_s_b(w4, w1, 1), "7a010906 mini_s.b w4, w1, 1");
COMPARE(mini_s_h(w27, w27, -9), "7a37dec6 mini_s.h w27, w27, -9");
COMPARE(mini_s_w(w28, w11, 9), "7a495f06 mini_s.w w28, w11, 9");
COMPARE(mini_s_d(w11, w10, 10), "7a6a52c6 mini_s.d w11, w10, 10");
COMPARE(mini_u_b(w18, w23, 27), "7a9bbc86 mini_u.b w18, w23, 27");
COMPARE(mini_u_h(w7, w26, 18), "7ab2d1c6 mini_u.h w7, w26, 18");
COMPARE(mini_u_w(w11, w12, 26), "7ada62c6 mini_u.w w11, w12, 26");
COMPARE(mini_u_d(w11, w15, 2), "7ae27ac6 mini_u.d w11, w15, 2");
COMPARE(subvi_b(w24, w20, 19), "7893a606 subvi.b w24, w20, 19");
COMPARE(subvi_h(w11, w19, 4), "78a49ac6 subvi.h w11, w19, 4");
COMPARE(subvi_w(w12, w10, 11), "78cb5306 subvi.w w12, w10, 11");
COMPARE(subvi_d(w19, w16, 7), "78e784c6 subvi.d w19, w16, 7");
}
VERIFY_RUN();
}
TEST(MSA_I10) {
SET_UP();
if (IsMipsArchVariant(kMips32r6) && CpuFeatures::IsSupported(MIPS_SIMD)) {
CpuFeatureScope fscope(&assm, MIPS_SIMD);
COMPARE(ldi_b(w8, 198), "7b063207 ldi.b w8, 198");
COMPARE(ldi_h(w20, 313), "7b29cd07 ldi.h w20, 313");
COMPARE(ldi_w(w24, 492), "7b4f6607 ldi.w w24, 492");
COMPARE(ldi_d(w27, -180), "7b7a66c7 ldi.d w27, -180");
}
VERIFY_RUN();
}
TEST(MSA_I8) {
SET_UP();
if (IsMipsArchVariant(kMips32r6) && CpuFeatures::IsSupported(MIPS_SIMD)) {
CpuFeatureScope fscope(&assm, MIPS_SIMD);
COMPARE(andi_b(w2, w29, 48), "7830e880 andi.b w2, w29, 48");
COMPARE(bmnzi_b(w6, w22, 126), "787eb181 bmnzi.b w6, w22, 126");
COMPARE(bmzi_b(w27, w1, 88), "79580ec1 bmzi.b w27, w1, 88");
COMPARE(bseli_b(w29, w3, 189), "7abd1f41 bseli.b w29, w3, 189");
COMPARE(nori_b(w1, w17, 56), "7a388840 nori.b w1, w17, 56");
COMPARE(ori_b(w26, w20, 135), "7987a680 ori.b w26, w20, 135");
COMPARE(shf_b(w19, w30, 105), "7869f4c2 shf.b w19, w30, 105");
COMPARE(shf_h(w17, w8, 76), "794c4442 shf.h w17, w8, 76");
COMPARE(shf_w(w14, w3, 93), "7a5d1b82 shf.w w14, w3, 93");
COMPARE(xori_b(w16, w10, 20), "7b145400 xori.b w16, w10, 20");
}
VERIFY_RUN();
}
TEST(MSA_VEC) {
SET_UP();
if (IsMipsArchVariant(kMips32r6) && CpuFeatures::IsSupported(MIPS_SIMD)) {
CpuFeatureScope fscope(&assm, MIPS_SIMD);
COMPARE(and_v(w25, w20, w27), "781ba65e and.v w25, w20, w27");
COMPARE(bmnz_v(w17, w6, w7), "7887345e bmnz.v w17, w6, w7");
COMPARE(bmz_v(w3, w17, w9), "78a988de bmz.v w3, w17, w9");
COMPARE(bsel_v(w8, w0, w14), "78ce021e bsel.v w8, w0, w14");
COMPARE(nor_v(w7, w31, w0), "7840f9de nor.v w7, w31, w0");
COMPARE(or_v(w24, w26, w30), "783ed61e or.v w24, w26, w30");
COMPARE(xor_v(w7, w27, w15), "786fd9de xor.v w7, w27, w15");
}
VERIFY_RUN();
}
TEST(MSA_2R) {
SET_UP();
if (IsMipsArchVariant(kMips32r6) && CpuFeatures::IsSupported(MIPS_SIMD)) {
CpuFeatureScope fscope(&assm, MIPS_SIMD);
COMPARE(fill_b(w30, t1), "7b004f9e fill.b w30, t1");
COMPARE(fill_h(w31, s7), "7b01bfde fill.h w31, s7");
COMPARE(fill_w(w16, t8), "7b02c41e fill.w w16, t8");
COMPARE(nloc_b(w21, w0), "7b08055e nloc.b w21, w0");
COMPARE(nloc_h(w18, w31), "7b09fc9e nloc.h w18, w31");
COMPARE(nloc_w(w2, w23), "7b0ab89e nloc.w w2, w23");
COMPARE(nloc_d(w4, w10), "7b0b511e nloc.d w4, w10");
COMPARE(nlzc_b(w31, w2), "7b0c17de nlzc.b w31, w2");
COMPARE(nlzc_h(w27, w22), "7b0db6de nlzc.h w27, w22");
COMPARE(nlzc_w(w10, w29), "7b0eea9e nlzc.w w10, w29");
COMPARE(nlzc_d(w25, w9), "7b0f4e5e nlzc.d w25, w9");
COMPARE(pcnt_b(w20, w18), "7b04951e pcnt.b w20, w18");
COMPARE(pcnt_h(w0, w8), "7b05401e pcnt.h w0, w8");
COMPARE(pcnt_w(w23, w9), "7b064dde pcnt.w w23, w9");
COMPARE(pcnt_d(w21, w24), "7b07c55e pcnt.d w21, w24");
}
VERIFY_RUN();
}
TEST(MSA_2RF) {
SET_UP();
if (IsMipsArchVariant(kMips32r6) && CpuFeatures::IsSupported(MIPS_SIMD)) {
CpuFeatureScope fscope(&assm, MIPS_SIMD);
COMPARE(fclass_w(w26, w12), "7b20669e fclass.w w26, w12");
COMPARE(fclass_d(w24, w17), "7b218e1e fclass.d w24, w17");
COMPARE(fexupl_w(w8, w0), "7b30021e fexupl.w w8, w0");
COMPARE(fexupl_d(w17, w29), "7b31ec5e fexupl.d w17, w29");
COMPARE(fexupr_w(w13, w4), "7b32235e fexupr.w w13, w4");
COMPARE(fexupr_d(w5, w2), "7b33115e fexupr.d w5, w2");
COMPARE(ffint_s_w(w20, w29), "7b3ced1e ffint_s.w w20, w29");
COMPARE(ffint_s_d(w12, w15), "7b3d7b1e ffint_s.d w12, w15");
COMPARE(ffint_u_w(w7, w27), "7b3ed9de ffint_u.w w7, w27");
COMPARE(ffint_u_d(w19, w16), "7b3f84de ffint_u.d w19, w16");
COMPARE(ffql_w(w31, w13), "7b346fde ffql.w w31, w13");
COMPARE(ffql_d(w12, w13), "7b356b1e ffql.d w12, w13");
COMPARE(ffqr_w(w27, w30), "7b36f6de ffqr.w w27, w30");
COMPARE(ffqr_d(w30, w15), "7b377f9e ffqr.d w30, w15");
COMPARE(flog2_w(w25, w31), "7b2efe5e flog2.w w25, w31");
COMPARE(flog2_d(w18, w10), "7b2f549e flog2.d w18, w10");
COMPARE(frint_w(w7, w15), "7b2c79de frint.w w7, w15");
COMPARE(frint_d(w21, w22), "7b2db55e frint.d w21, w22");
COMPARE(frcp_w(w19, w0), "7b2a04de frcp.w w19, w0");
COMPARE(frcp_d(w4, w14), "7b2b711e frcp.d w4, w14");
COMPARE(frsqrt_w(w12, w17), "7b288b1e frsqrt.w w12, w17");
COMPARE(frsqrt_d(w23, w11), "7b295dde frsqrt.d w23, w11");
COMPARE(fsqrt_w(w0, w11), "7b26581e fsqrt.w w0, w11");
COMPARE(fsqrt_d(w15, w12), "7b2763de fsqrt.d w15, w12");
COMPARE(ftint_s_w(w30, w5), "7b382f9e ftint_s.w w30, w5");
COMPARE(ftint_s_d(w5, w23), "7b39b95e ftint_s.d w5, w23");
COMPARE(ftint_u_w(w20, w14), "7b3a751e ftint_u.w w20, w14");
COMPARE(ftint_u_d(w23, w21), "7b3badde ftint_u.d w23, w21");
COMPARE(ftrunc_s_w(w29, w17), "7b228f5e ftrunc_s.w w29, w17");
COMPARE(ftrunc_s_d(w12, w27), "7b23db1e ftrunc_s.d w12, w27");
COMPARE(ftrunc_u_w(w17, w15), "7b247c5e ftrunc_u.w w17, w15");
COMPARE(ftrunc_u_d(w5, w27), "7b25d95e ftrunc_u.d w5, w27");
}
VERIFY_RUN();
}
TEST(MSA_3R) {
SET_UP();
if (IsMipsArchVariant(kMips32r6) && CpuFeatures::IsSupported(MIPS_SIMD)) {
CpuFeatureScope fscope(&assm, MIPS_SIMD);
COMPARE(add_a_b(w26, w9, w4), "78044e90 add_a.b w26, w9, w4");
COMPARE(add_a_h(w23, w27, w31), "783fddd0 add_a.h w23, w27, w31");
COMPARE(add_a_w(w11, w6, w22), "785632d0 add_a.w w11, w6, w22");
COMPARE(add_a_d(w6, w10, w0), "78605190 add_a.d w6, w10, w0");
COMPARE(adds_a_b(w19, w24, w19), "7893c4d0 adds_a.b w19, w24, w19");
COMPARE(adds_a_h(w25, w6, w4), "78a43650 adds_a.h w25, w6, w4");
COMPARE(adds_a_w(w25, w17, w27), "78db8e50 adds_a.w w25, w17, w27");
COMPARE(adds_a_d(w15, w18, w26), "78fa93d0 adds_a.d w15, w18, w26");
COMPARE(adds_s_b(w29, w11, w19), "79135f50 adds_s.b w29, w11, w19");
COMPARE(adds_s_h(w5, w23, w26), "793ab950 adds_s.h w5, w23, w26");
COMPARE(adds_s_w(w16, w14, w13), "794d7410 adds_s.w w16, w14, w13");
COMPARE(adds_s_d(w2, w14, w28), "797c7090 adds_s.d w2, w14, w28");
COMPARE(adds_u_b(w3, w17, w14), "798e88d0 adds_u.b w3, w17, w14");
COMPARE(adds_u_h(w10, w30, w4), "79a4f290 adds_u.h w10, w30, w4");
COMPARE(adds_u_w(w15, w18, w20), "79d493d0 adds_u.w w15, w18, w20");
COMPARE(adds_u_d(w30, w10, w9), "79e95790 adds_u.d w30, w10, w9");
COMPARE(addv_b(w24, w20, w21), "7815a60e addv.b w24, w20, w21");
COMPARE(addv_h(w4, w13, w27), "783b690e addv.h w4, w13, w27");
COMPARE(addv_w(w19, w11, w14), "784e5cce addv.w w19, w11, w14");
COMPARE(addv_d(w2, w21, w31), "787fa88e addv.d w2, w21, w31");
COMPARE(asub_s_b(w23, w16, w3), "7a0385d1 asub_s.b w23, w16, w3");
COMPARE(asub_s_h(w22, w17, w25), "7a398d91 asub_s.h w22, w17, w25");
COMPARE(asub_s_w(w24, w1, w9), "7a490e11 asub_s.w w24, w1, w9");
COMPARE(asub_s_d(w13, w12, w12), "7a6c6351 asub_s.d w13, w12, w12");
COMPARE(asub_u_b(w10, w29, w11), "7a8bea91 asub_u.b w10, w29, w11");
COMPARE(asub_u_h(w18, w9, w15), "7aaf4c91 asub_u.h w18, w9, w15");
COMPARE(asub_u_w(w10, w19, w31), "7adf9a91 asub_u.w w10, w19, w31");
COMPARE(asub_u_d(w17, w10, w0), "7ae05451 asub_u.d w17, w10, w0");
COMPARE(ave_s_b(w2, w5, w1), "7a012890 ave_s.b w2, w5, w1");
COMPARE(ave_s_h(w16, w19, w9), "7a299c10 ave_s.h w16, w19, w9");
COMPARE(ave_s_w(w17, w31, w5), "7a45fc50 ave_s.w w17, w31, w5");
COMPARE(ave_s_d(w27, w25, w10), "7a6aced0 ave_s.d w27, w25, w10");
COMPARE(ave_u_b(w16, w19, w9), "7a899c10 ave_u.b w16, w19, w9");
COMPARE(ave_u_h(w28, w28, w11), "7aabe710 ave_u.h w28, w28, w11");
COMPARE(ave_u_w(w11, w12, w11), "7acb62d0 ave_u.w w11, w12, w11");
COMPARE(ave_u_d(w30, w19, w28), "7afc9f90 ave_u.d w30, w19, w28");
COMPARE(aver_s_b(w26, w16, w2), "7b028690 aver_s.b w26, w16, w2");
COMPARE(aver_s_h(w31, w27, w27), "7b3bdfd0 aver_s.h w31, w27, w27");
COMPARE(aver_s_w(w28, w18, w25), "7b599710 aver_s.w w28, w18, w25");
COMPARE(aver_s_d(w29, w21, w27), "7b7baf50 aver_s.d w29, w21, w27");
COMPARE(aver_u_b(w29, w26, w3), "7b83d750 aver_u.b w29, w26, w3");
COMPARE(aver_u_h(w18, w18, w9), "7ba99490 aver_u.h w18, w18, w9");
COMPARE(aver_u_w(w17, w25, w29), "7bddcc50 aver_u.w w17, w25, w29");
COMPARE(aver_u_d(w22, w22, w19), "7bf3b590 aver_u.d w22, w22, w19");
COMPARE(bclr_b(w2, w15, w29), "799d788d bclr.b w2, w15, w29");
COMPARE(bclr_h(w16, w21, w28), "79bcac0d bclr.h w16, w21, w28");
COMPARE(bclr_w(w19, w2, w9), "79c914cd bclr.w w19, w2, w9");
COMPARE(bclr_d(w27, w31, w4), "79e4fecd bclr.d w27, w31, w4");
COMPARE(binsl_b(w5, w16, w24), "7b18814d binsl.b w5, w16, w24");
COMPARE(binsl_h(w30, w5, w10), "7b2a2f8d binsl.h w30, w5, w10");
COMPARE(binsl_w(w14, w15, w13), "7b4d7b8d binsl.w w14, w15, w13");
COMPARE(binsl_d(w23, w20, w12), "7b6ca5cd binsl.d w23, w20, w12");
COMPARE(binsr_b(w22, w11, w2), "7b825d8d binsr.b w22, w11, w2");
COMPARE(binsr_h(w0, w26, w6), "7ba6d00d binsr.h w0, w26, w6");
COMPARE(binsr_w(w26, w3, w28), "7bdc1e8d binsr.w w26, w3, w28");
COMPARE(binsr_d(w0, w0, w21), "7bf5000d binsr.d w0, w0, w21");
COMPARE(bneg_b(w0, w11, w24), "7a98580d bneg.b w0, w11, w24");
COMPARE(bneg_h(w28, w16, w4), "7aa4870d bneg.h w28, w16, w4");
COMPARE(bneg_w(w3, w26, w19), "7ad3d0cd bneg.w w3, w26, w19");
COMPARE(bneg_d(w13, w29, w15), "7aefeb4d bneg.d w13, w29, w15");
COMPARE(bset_b(w31, w5, w31), "7a1f2fcd bset.b w31, w5, w31");
COMPARE(bset_h(w14, w12, w6), "7a26638d bset.h w14, w12, w6");
COMPARE(bset_w(w31, w9, w12), "7a4c4fcd bset.w w31, w9, w12");
COMPARE(bset_d(w5, w22, w5), "7a65b14d bset.d w5, w22, w5");
COMPARE(ceq_b(w31, w31, w18), "7812ffcf ceq.b w31, w31, w18");
COMPARE(ceq_h(w10, w27, w9), "7829da8f ceq.h w10, w27, w9");
COMPARE(ceq_w(w9, w5, w14), "784e2a4f ceq.w w9, w5, w14");
COMPARE(ceq_d(w5, w17, w0), "7860894f ceq.d w5, w17, w0");
COMPARE(cle_s_b(w23, w4, w9), "7a0925cf cle_s.b w23, w4, w9");
COMPARE(cle_s_h(w22, w27, w19), "7a33dd8f cle_s.h w22, w27, w19");
COMPARE(cle_s_w(w30, w26, w10), "7a4ad78f cle_s.w w30, w26, w10");
COMPARE(cle_s_d(w18, w5, w10), "7a6a2c8f cle_s.d w18, w5, w10");
COMPARE(cle_u_b(w1, w25, w0), "7a80c84f cle_u.b w1, w25, w0");
COMPARE(cle_u_h(w7, w0, w29), "7abd01cf cle_u.h w7, w0, w29");
COMPARE(cle_u_w(w25, w18, w1), "7ac1964f cle_u.w w25, w18, w1");
COMPARE(cle_u_d(w6, w0, w30), "7afe018f cle_u.d w6, w0, w30");
COMPARE(clt_s_b(w25, w2, w21), "7915164f clt_s.b w25, w2, w21");
COMPARE(clt_s_h(w2, w19, w9), "7929988f clt_s.h w2, w19, w9");
COMPARE(clt_s_w(w23, w8, w16), "795045cf clt_s.w w23, w8, w16");
COMPARE(clt_s_d(w7, w30, w12), "796cf1cf clt_s.d w7, w30, w12");
COMPARE(clt_u_b(w2, w31, w13), "798df88f clt_u.b w2, w31, w13");
COMPARE(clt_u_h(w16, w31, w23), "79b7fc0f clt_u.h w16, w31, w23");
COMPARE(clt_u_w(w3, w24, w9), "79c9c0cf clt_u.w w3, w24, w9");
COMPARE(clt_u_d(w7, w0, w1), "79e101cf clt_u.d w7, w0, w1");
COMPARE(div_s_b(w29, w3, w18), "7a121f52 div_s.b w29, w3, w18");
COMPARE(div_s_h(w17, w16, w13), "7a2d8452 div_s.h w17, w16, w13");
COMPARE(div_s_w(w4, w25, w30), "7a5ec912 div_s.w w4, w25, w30");
COMPARE(div_s_d(w31, w9, w20), "7a744fd2 div_s.d w31, w9, w20");
COMPARE(div_u_b(w6, w29, w10), "7a8ae992 div_u.b w6, w29, w10");
COMPARE(div_u_h(w24, w21, w14), "7aaeae12 div_u.h w24, w21, w14");
COMPARE(div_u_w(w29, w14, w25), "7ad97752 div_u.w w29, w14, w25");
COMPARE(div_u_d(w31, w1, w21), "7af50fd2 div_u.d w31, w1, w21");
COMPARE(dotp_s_h(w23, w22, w25), "7839b5d3 dotp_s.h w23, w22, w25");
COMPARE(dotp_s_w(w20, w14, w5), "78457513 dotp_s.w w20, w14, w5");
COMPARE(dotp_s_d(w17, w2, w22), "78761453 dotp_s.d w17, w2, w22");
COMPARE(dotp_u_h(w13, w2, w6), "78a61353 dotp_u.h w13, w2, w6");
COMPARE(dotp_u_w(w15, w22, w21), "78d5b3d3 dotp_u.w w15, w22, w21");
COMPARE(dotp_u_d(w4, w16, w26), "78fa8113 dotp_u.d w4, w16, w26");
COMPARE(dpadd_s_h(w1, w28, w22), "7936e053 dpadd_s.h w1, w28, w22");
COMPARE(dpadd_s_w(w10, w1, w12), "794c0a93 dpadd_s.w w10, w1, w12");
COMPARE(dpadd_s_d(w3, w21, w27), "797ba8d3 dpadd_s.d w3, w21, w27");
COMPARE(dpadd_u_h(w17, w5, w20), "79b42c53 dpadd_u.h w17, w5, w20");
COMPARE(dpadd_u_w(w24, w8, w16), "79d04613 dpadd_u.w w24, w8, w16");
COMPARE(dpadd_u_d(w15, w29, w16),
"79f0ebd3 dpadd_u.d w15, w29, w16");
COMPARE(dpsub_s_h(w4, w11, w12), "7a2c5913 dpsub_s.h w4, w11, w12");
COMPARE(dpsub_s_w(w4, w7, w6), "7a463913 dpsub_s.w w4, w7, w6");
COMPARE(dpsub_s_d(w31, w12, w28),
"7a7c67d3 dpsub_s.d w31, w12, w28");
COMPARE(dpsub_u_h(w4, w25, w17), "7ab1c913 dpsub_u.h w4, w25, w17");
COMPARE(dpsub_u_w(w19, w25, w16),
"7ad0ccd3 dpsub_u.w w19, w25, w16");
COMPARE(dpsub_u_d(w7, w10, w26), "7afa51d3 dpsub_u.d w7, w10, w26");
COMPARE(hadd_s_h(w28, w24, w2), "7a22c715 hadd_s.h w28, w24, w2");
COMPARE(hadd_s_w(w24, w17, w11), "7a4b8e15 hadd_s.w w24, w17, w11");
COMPARE(hadd_s_d(w17, w15, w20), "7a747c55 hadd_s.d w17, w15, w20");
COMPARE(hadd_u_h(w12, w29, w17), "7ab1eb15 hadd_u.h w12, w29, w17");
COMPARE(hadd_u_w(w9, w5, w6), "7ac62a55 hadd_u.w w9, w5, w6");
COMPARE(hadd_u_d(w1, w20, w6), "7ae6a055 hadd_u.d w1, w20, w6");
COMPARE(hsub_s_h(w16, w14, w29), "7b3d7415 hsub_s.h w16, w14, w29");
COMPARE(hsub_s_w(w9, w13, w11), "7b4b6a55 hsub_s.w w9, w13, w11");
COMPARE(hsub_s_d(w30, w18, w14), "7b6e9795 hsub_s.d w30, w18, w14");
COMPARE(hsub_u_h(w7, w12, w14), "7bae61d5 hsub_u.h w7, w12, w14");
COMPARE(hsub_u_w(w21, w5, w5), "7bc52d55 hsub_u.w w21, w5, w5");
COMPARE(hsub_u_d(w11, w12, w31), "7bff62d5 hsub_u.d w11, w12, w31");
COMPARE(ilvev_b(w18, w16, w30), "7b1e8494 ilvev.b w18, w16, w30");
COMPARE(ilvev_h(w14, w0, w13), "7b2d0394 ilvev.h w14, w0, w13");
COMPARE(ilvev_w(w12, w25, w22), "7b56cb14 ilvev.w w12, w25, w22");
COMPARE(ilvev_d(w30, w27, w3), "7b63df94 ilvev.d w30, w27, w3");
COMPARE(ilvl_b(w29, w3, w21), "7a151f54 ilvl.b w29, w3, w21");
COMPARE(ilvl_h(w27, w10, w17), "7a3156d4 ilvl.h w27, w10, w17");
COMPARE(ilvl_w(w6, w1, w0), "7a400994 ilvl.w w6, w1, w0");
COMPARE(ilvl_d(w3, w16, w24), "7a7880d4 ilvl.d w3, w16, w24");
COMPARE(ilvod_b(w11, w5, w20), "7b942ad4 ilvod.b w11, w5, w20");
COMPARE(ilvod_h(w18, w13, w31), "7bbf6c94 ilvod.h w18, w13, w31");
COMPARE(ilvod_w(w29, w16, w24), "7bd88754 ilvod.w w29, w16, w24");
COMPARE(ilvod_d(w22, w12, w29), "7bfd6594 ilvod.d w22, w12, w29");
COMPARE(ilvr_b(w4, w30, w6), "7a86f114 ilvr.b w4, w30, w6");
COMPARE(ilvr_h(w28, w19, w29), "7abd9f14 ilvr.h w28, w19, w29");
COMPARE(ilvr_w(w18, w20, w21), "7ad5a494 ilvr.w w18, w20, w21");
COMPARE(ilvr_d(w23, w30, w12), "7aecf5d4 ilvr.d w23, w30, w12");
COMPARE(maddv_b(w17, w31, w29), "789dfc52 maddv.b w17, w31, w29");
COMPARE(maddv_h(w7, w24, w9), "78a9c1d2 maddv.h w7, w24, w9");
COMPARE(maddv_w(w22, w22, w20), "78d4b592 maddv.w w22, w22, w20");
COMPARE(maddv_d(w30, w26, w20), "78f4d792 maddv.d w30, w26, w20");
COMPARE(max_a_b(w23, w11, w23), "7b175dce max_a.b w23, w11, w23");
COMPARE(max_a_h(w20, w5, w30), "7b3e2d0e max_a.h w20, w5, w30");
COMPARE(max_a_w(w7, w18, w30), "7b5e91ce max_a.w w7, w18, w30");
COMPARE(max_a_d(w8, w8, w31), "7b7f420e max_a.d w8, w8, w31");
COMPARE(max_s_b(w10, w1, w19), "79130a8e max_s.b w10, w1, w19");
COMPARE(max_s_h(w15, w29, w17), "7931ebce max_s.h w15, w29, w17");
COMPARE(max_s_w(w15, w29, w14), "794eebce max_s.w w15, w29, w14");
COMPARE(max_s_d(w25, w24, w3), "7963c64e max_s.d w25, w24, w3");
COMPARE(max_u_b(w12, w24, w5), "7985c30e max_u.b w12, w24, w5");
COMPARE(max_u_h(w5, w6, w7), "79a7314e max_u.h w5, w6, w7");
COMPARE(max_u_w(w16, w4, w7), "79c7240e max_u.w w16, w4, w7");
COMPARE(max_u_d(w26, w12, w24), "79f8668e max_u.d w26, w12, w24");
COMPARE(min_a_b(w4, w26, w1), "7b81d10e min_a.b w4, w26, w1");
COMPARE(min_a_h(w12, w13, w31), "7bbf6b0e min_a.h w12, w13, w31");
COMPARE(min_a_w(w28, w20, w0), "7bc0a70e min_a.w w28, w20, w0");
COMPARE(min_a_d(w12, w20, w19), "7bf3a30e min_a.d w12, w20, w19");
COMPARE(min_s_b(w19, w3, w14), "7a0e1cce min_s.b w19, w3, w14");
COMPARE(min_s_h(w27, w21, w8), "7a28aece min_s.h w27, w21, w8");
COMPARE(min_s_w(w0, w14, w30), "7a5e700e min_s.w w0, w14, w30");
COMPARE(min_s_d(w6, w8, w21), "7a75418e min_s.d w6, w8, w21");
COMPARE(min_u_b(w22, w26, w8), "7a88d58e min_u.b w22, w26, w8");
COMPARE(min_u_h(w7, w27, w12), "7aacd9ce min_u.h w7, w27, w12");
COMPARE(min_u_w(w8, w20, w14), "7acea20e min_u.w w8, w20, w14");
COMPARE(min_u_d(w26, w14, w15), "7aef768e min_u.d w26, w14, w15");
COMPARE(mod_s_b(w18, w1, w26), "7b1a0c92 mod_s.b w18, w1, w26");
COMPARE(mod_s_h(w31, w30, w28), "7b3cf7d2 mod_s.h w31, w30, w28");
COMPARE(mod_s_w(w2, w6, w13), "7b4d3092 mod_s.w w2, w6, w13");
COMPARE(mod_s_d(w21, w27, w22), "7b76dd52 mod_s.d w21, w27, w22");
COMPARE(mod_u_b(w16, w7, w13), "7b8d3c12 mod_u.b w16, w7, w13");
COMPARE(mod_u_h(w24, w8, w7), "7ba74612 mod_u.h w24, w8, w7");
COMPARE(mod_u_w(w30, w2, w17), "7bd11792 mod_u.w w30, w2, w17");
COMPARE(mod_u_d(w31, w2, w25), "7bf917d2 mod_u.d w31, w2, w25");
COMPARE(msubv_b(w14, w5, w12), "790c2b92 msubv.b w14, w5, w12");
COMPARE(msubv_h(w6, w7, w30), "793e3992 msubv.h w6, w7, w30");
COMPARE(msubv_w(w13, w2, w21), "79551352 msubv.w w13, w2, w21");
COMPARE(msubv_d(w16, w14, w27), "797b7412 msubv.d w16, w14, w27");
COMPARE(mulv_b(w20, w3, w13), "780d1d12 mulv.b w20, w3, w13");
COMPARE(mulv_h(w27, w26, w14), "782ed6d2 mulv.h w27, w26, w14");
COMPARE(mulv_w(w10, w29, w3), "7843ea92 mulv.w w10, w29, w3");
COMPARE(mulv_d(w7, w19, w29), "787d99d2 mulv.d w7, w19, w29");
COMPARE(pckev_b(w5, w27, w7), "7907d954 pckev.b w5, w27, w7");
COMPARE(pckev_h(w1, w4, w27), "793b2054 pckev.h w1, w4, w27");
COMPARE(pckev_w(w30, w20, w0), "7940a794 pckev.w w30, w20, w0");
COMPARE(pckev_d(w6, w1, w15), "796f0994 pckev.d w6, w1, w15");
COMPARE(pckod_b(w18, w28, w30), "799ee494 pckod.b w18, w28, w30");
COMPARE(pckod_h(w26, w5, w8), "79a82e94 pckod.h w26, w5, w8");
COMPARE(pckod_w(w9, w4, w2), "79c22254 pckod.w w9, w4, w2");
COMPARE(pckod_d(w30, w22, w20), "79f4b794 pckod.d w30, w22, w20");
COMPARE(sld_b(w5, w23, t4), "780cb954 sld.b w5, w23[t4]");
COMPARE(sld_h(w1, w23, v1), "7823b854 sld.h w1, w23[v1]");
COMPARE(sld_w(w20, w8, t1), "78494514 sld.w w20, w8[t1]");
COMPARE(sld_d(w7, w23, fp), "787eb9d4 sld.d w7, w23[fp]");
COMPARE(sll_b(w3, w0, w17), "781100cd sll.b w3, w0, w17");
COMPARE(sll_h(w17, w27, w3), "7823dc4d sll.h w17, w27, w3");
COMPARE(sll_w(w16, w7, w6), "78463c0d sll.w w16, w7, w6");
COMPARE(sll_d(w9, w0, w26), "787a024d sll.d w9, w0, w26");
COMPARE(splat_b(w28, w1, at), "78810f14 splat.b w28, w1[at]");
COMPARE(splat_h(w2, w11, t3), "78ab5894 splat.h w2, w11[t3]");
COMPARE(splat_w(w22, w0, t3), "78cb0594 splat.w w22, w0[t3]");
COMPARE(splat_d(w0, w0, v0), "78e20014 splat.d w0, w0[v0]");
COMPARE(sra_b(w28, w4, w17), "7891270d sra.b w28, w4, w17");
COMPARE(sra_h(w13, w9, w3), "78a34b4d sra.h w13, w9, w3");
COMPARE(sra_w(w27, w21, w19), "78d3aecd sra.w w27, w21, w19");
COMPARE(sra_d(w30, w8, w23), "78f7478d sra.d w30, w8, w23");
COMPARE(srar_b(w19, w18, w18), "789294d5 srar.b w19, w18, w18");
COMPARE(srar_h(w7, w23, w8), "78a8b9d5 srar.h w7, w23, w8");
COMPARE(srar_w(w1, w12, w2), "78c26055 srar.w w1, w12, w2");
COMPARE(srar_d(w21, w7, w14), "78ee3d55 srar.d w21, w7, w14");
COMPARE(srl_b(w12, w3, w19), "79131b0d srl.b w12, w3, w19");
COMPARE(srl_h(w23, w31, w20), "7934fdcd srl.h w23, w31, w20");
COMPARE(srl_w(w18, w27, w11), "794bdc8d srl.w w18, w27, w11");
COMPARE(srl_d(w3, w12, w26), "797a60cd srl.d w3, w12, w26");
COMPARE(srlr_b(w15, w21, w11), "790babd5 srlr.b w15, w21, w11");
COMPARE(srlr_h(w21, w13, w19), "79336d55 srlr.h w21, w13, w19");
COMPARE(srlr_w(w6, w30, w3), "7943f195 srlr.w w6, w30, w3");
COMPARE(srlr_d(w1, w2, w14), "796e1055 srlr.d w1, w2, w14");
COMPARE(subs_s_b(w25, w15, w1), "78017e51 subs_s.b w25, w15, w1");
COMPARE(subs_s_h(w28, w25, w22), "7836cf11 subs_s.h w28, w25, w22");
COMPARE(subs_s_w(w10, w12, w21), "78556291 subs_s.w w10, w12, w21");
COMPARE(subs_s_d(w4, w20, w18), "7872a111 subs_s.d w4, w20, w18");
COMPARE(subs_u_b(w21, w6, w25), "78993551 subs_u.b w21, w6, w25");
COMPARE(subs_u_h(w3, w10, w7), "78a750d1 subs_u.h w3, w10, w7");
COMPARE(subs_u_w(w9, w15, w10), "78ca7a51 subs_u.w w9, w15, w10");
COMPARE(subs_u_d(w7, w19, w10), "78ea99d1 subs_u.d w7, w19, w10");
COMPARE(subsus_u_b(w6, w7, w12), "790c3991 subsus_u.b w6, w7, w12");
COMPARE(subsus_u_h(w6, w29, w19),
"7933e991 subsus_u.h w6, w29, w19");
COMPARE(subsus_u_w(w7, w15, w7), "794779d1 subsus_u.w w7, w15, w7");
COMPARE(subsus_u_d(w9, w3, w15), "796f1a51 subsus_u.d w9, w3, w15");
COMPARE(subsuu_s_b(w22, w3, w31),
"799f1d91 subsuu_s.b w22, w3, w31");
COMPARE(subsuu_s_h(w19, w23, w22),
"79b6bcd1 subsuu_s.h w19, w23, w22");
COMPARE(subsuu_s_w(w9, w10, w13),
"79cd5251 subsuu_s.w w9, w10, w13");
COMPARE(subsuu_s_d(w5, w6, w0), "79e03151 subsuu_s.d w5, w6, w0");
COMPARE(subv_b(w6, w13, w19), "7893698e subv.b w6, w13, w19");
COMPARE(subv_h(w4, w25, w12), "78acc90e subv.h w4, w25, w12");
COMPARE(subv_w(w27, w27, w11), "78cbdece subv.w w27, w27, w11");
COMPARE(subv_d(w9, w24, w10), "78eac24e subv.d w9, w24, w10");
COMPARE(vshf_b(w3, w16, w5), "780580d5 vshf.b w3, w16, w5");
COMPARE(vshf_h(w20, w19, w8), "78289d15 vshf.h w20, w19, w8");
COMPARE(vshf_w(w16, w30, w25), "7859f415 vshf.w w16, w30, w25");
COMPARE(vshf_d(w19, w11, w15), "786f5cd5 vshf.d w19, w11, w15");
}
VERIFY_RUN();
}
TEST(MSA_3RF) {
SET_UP();
if (IsMipsArchVariant(kMips32r6) && CpuFeatures::IsSupported(MIPS_SIMD)) {
CpuFeatureScope fscope(&assm, MIPS_SIMD);
COMPARE(fadd_w(w28, w19, w28), "781c9f1b fadd.w w28, w19, w28");
COMPARE(fadd_d(w13, w2, w29), "783d135b fadd.d w13, w2, w29");
COMPARE(fcaf_w(w14, w11, w25), "78195b9a fcaf.w w14, w11, w25");
COMPARE(fcaf_d(w1, w1, w19), "7833085a fcaf.d w1, w1, w19");
COMPARE(fceq_w(w1, w23, w16), "7890b85a fceq.w w1, w23, w16");
COMPARE(fceq_d(w0, w8, w16), "78b0401a fceq.d w0, w8, w16");
COMPARE(fcle_w(w16, w9, w24), "79984c1a fcle.w w16, w9, w24");
COMPARE(fcle_d(w27, w14, w1), "79a176da fcle.d w27, w14, w1");
COMPARE(fclt_w(w28, w8, w8), "7908471a fclt.w w28, w8, w8");
COMPARE(fclt_d(w30, w25, w11), "792bcf9a fclt.d w30, w25, w11");
COMPARE(fcne_w(w2, w18, w23), "78d7909c fcne.w w2, w18, w23");
COMPARE(fcne_d(w14, w20, w15), "78efa39c fcne.d w14, w20, w15");
COMPARE(fcor_w(w10, w18, w25), "7859929c fcor.w w10, w18, w25");
COMPARE(fcor_d(w17, w25, w11), "786bcc5c fcor.d w17, w25, w11");
COMPARE(fcueq_w(w14, w2, w21), "78d5139a fcueq.w w14, w2, w21");
COMPARE(fcueq_d(w29, w3, w7), "78e71f5a fcueq.d w29, w3, w7");
COMPARE(fcule_w(w17, w5, w3), "79c32c5a fcule.w w17, w5, w3");
COMPARE(fcule_d(w31, w1, w30), "79fe0fda fcule.d w31, w1, w30");
COMPARE(fcult_w(w6, w25, w9), "7949c99a fcult.w w6, w25, w9");
COMPARE(fcult_d(w27, w8, w17), "797146da fcult.d w27, w8, w17");
COMPARE(fcun_w(w4, w20, w8), "7848a11a fcun.w w4, w20, w8");
COMPARE(fcun_d(w29, w11, w3), "78635f5a fcun.d w29, w11, w3");
COMPARE(fcune_w(w13, w18, w19), "7893935c fcune.w w13, w18, w19");
COMPARE(fcune_d(w16, w26, w21), "78b5d41c fcune.d w16, w26, w21");
COMPARE(fdiv_w(w13, w24, w2), "78c2c35b fdiv.w w13, w24, w2");
COMPARE(fdiv_d(w19, w4, w25), "78f924db fdiv.d w19, w4, w25");
COMPARE(fexdo_h(w8, w0, w16), "7a10021b fexdo.h w8, w0, w16");
COMPARE(fexdo_w(w0, w13, w27), "7a3b681b fexdo.w w0, w13, w27");
COMPARE(fexp2_w(w17, w0, w3), "79c3045b fexp2.w w17, w0, w3");
COMPARE(fexp2_d(w22, w0, w10), "79ea059b fexp2.d w22, w0, w10");
COMPARE(fmadd_w(w29, w6, w23), "7917375b fmadd.w w29, w6, w23");
COMPARE(fmadd_d(w11, w28, w21), "7935e2db fmadd.d w11, w28, w21");
COMPARE(fmax_w(w0, w23, w13), "7b8db81b fmax.w w0, w23, w13");
COMPARE(fmax_d(w26, w18, w8), "7ba8969b fmax.d w26, w18, w8");
COMPARE(fmax_a_w(w10, w16, w10), "7bca829b fmax_a.w w10, w16, w10");
COMPARE(fmax_a_d(w30, w9, w22), "7bf64f9b fmax_a.d w30, w9, w22");
COMPARE(fmin_w(w24, w1, w30), "7b1e0e1b fmin.w w24, w1, w30");
COMPARE(fmin_d(w27, w27, w10), "7b2adedb fmin.d w27, w27, w10");
COMPARE(fmin_a_w(w10, w29, w20), "7b54ea9b fmin_a.w w10, w29, w20");
COMPARE(fmin_a_d(w13, w30, w24), "7b78f35b fmin_a.d w13, w30, w24");
COMPARE(fmsub_w(w17, w25, w0), "7940cc5b fmsub.w w17, w25, w0");
COMPARE(fmsub_d(w8, w18, w16), "7970921b fmsub.d w8, w18, w16");
COMPARE(fmul_w(w3, w15, w15), "788f78db fmul.w w3, w15, w15");
COMPARE(fmul_d(w9, w30, w10), "78aaf25b fmul.d w9, w30, w10");
COMPARE(fsaf_w(w25, w5, w10), "7a0a2e5a fsaf.w w25, w5, w10");
COMPARE(fsaf_d(w25, w3, w29), "7a3d1e5a fsaf.d w25, w3, w29");
COMPARE(fseq_w(w11, w17, w13), "7a8d8ada fseq.w w11, w17, w13");
COMPARE(fseq_d(w29, w0, w31), "7abf075a fseq.d w29, w0, w31");
COMPARE(fsle_w(w30, w31, w31), "7b9fff9a fsle.w w30, w31, w31");
COMPARE(fsle_d(w18, w23, w24), "7bb8bc9a fsle.d w18, w23, w24");
COMPARE(fslt_w(w12, w5, w6), "7b062b1a fslt.w w12, w5, w6");
COMPARE(fslt_d(w16, w26, w21), "7b35d41a fslt.d w16, w26, w21");
COMPARE(fsne_w(w30, w1, w12), "7acc0f9c fsne.w w30, w1, w12");
COMPARE(fsne_d(w14, w13, w23), "7af76b9c fsne.d w14, w13, w23");
COMPARE(fsor_w(w27, w13, w27), "7a5b6edc fsor.w w27, w13, w27");
COMPARE(fsor_d(w12, w24, w11), "7a6bc31c fsor.d w12, w24, w11");
COMPARE(fsub_w(w31, w26, w1), "7841d7db fsub.w w31, w26, w1");
COMPARE(fsub_d(w19, w17, w27), "787b8cdb fsub.d w19, w17, w27");
COMPARE(fsueq_w(w16, w24, w25), "7ad9c41a fsueq.w w16, w24, w25");
COMPARE(fsueq_d(w18, w14, w14), "7aee749a fsueq.d w18, w14, w14");
COMPARE(fsule_w(w23, w30, w13), "7bcdf5da fsule.w w23, w30, w13");
COMPARE(fsule_d(w2, w11, w26), "7bfa589a fsule.d w2, w11, w26");
COMPARE(fsult_w(w11, w26, w22), "7b56d2da fsult.w w11, w26, w22");
COMPARE(fsult_d(w6, w23, w30), "7b7eb99a fsult.d w6, w23, w30");
COMPARE(fsun_w(w3, w18, w28), "7a5c90da fsun.w w3, w18, w28");
COMPARE(fsun_d(w18, w11, w19), "7a735c9a fsun.d w18, w11, w19");
COMPARE(fsune_w(w16, w31, w2), "7a82fc1c fsune.w w16, w31, w2");
COMPARE(fsune_d(w3, w26, w17), "7ab1d0dc fsune.d w3, w26, w17");
COMPARE(ftq_h(w16, w4, w24), "7a98241b ftq.h w16, w4, w24");
COMPARE(ftq_w(w5, w5, w25), "7ab9295b ftq.w w5, w5, w25");
COMPARE(madd_q_h(w16, w20, w10), "794aa41c madd_q.h w16, w20, w10");
COMPARE(madd_q_w(w28, w2, w9), "7969171c madd_q.w w28, w2, w9");
COMPARE(maddr_q_h(w8, w18, w9), "7b49921c maddr_q.h w8, w18, w9");
COMPARE(maddr_q_w(w29, w12, w16),
"7b70675c maddr_q.w w29, w12, w16");
COMPARE(msub_q_h(w24, w26, w10), "798ad61c msub_q.h w24, w26, w10");
COMPARE(msub_q_w(w13, w30, w28), "79bcf35c msub_q.w w13, w30, w28");
COMPARE(msubr_q_h(w12, w21, w11),
"7b8bab1c msubr_q.h w12, w21, w11");
COMPARE(msubr_q_w(w1, w14, w20), "7bb4705c msubr_q.w w1, w14, w20");
COMPARE(mul_q_h(w6, w16, w30), "791e819c mul_q.h w6, w16, w30");
COMPARE(mul_q_w(w16, w1, w4), "79240c1c mul_q.w w16, w1, w4");
COMPARE(mulr_q_h(w6, w20, w19), "7b13a19c mulr_q.h w6, w20, w19");
COMPARE(mulr_q_w(w27, w1, w20), "7b340edc mulr_q.w w27, w1, w20");
}
VERIFY_RUN();
}
TEST(MSA_ELM) {
SET_UP();
if (IsMipsArchVariant(kMips32r6) && CpuFeatures::IsSupported(MIPS_SIMD)) {
CpuFeatureScope fscope(&assm, MIPS_SIMD);
COMPARE(copy_s_b(t5, w8, 2), "78824359 copy_s.b t5, w8[2]");
COMPARE(copy_s_h(at, w25, 0), "78a0c859 copy_s.h at, w25[0]");
COMPARE(copy_s_w(s6, w5, 1), "78b12d99 copy_s.w s6, w5[1]");
COMPARE(copy_u_b(s6, w20, 4), "78c4a599 copy_u.b s6, w20[4]");
COMPARE(copy_u_h(s4, w4, 0), "78e02519 copy_u.h s4, w4[0]");
COMPARE(sldi_b(w0, w29, 4), "7804e819 sldi.b w0, w29[4]");
COMPARE(sldi_h(w8, w17, 0), "78208a19 sldi.h w8, w17[0]");
COMPARE(sldi_w(w20, w27, 2), "7832dd19 sldi.w w20, w27[2]");
COMPARE(sldi_d(w4, w12, 0), "78386119 sldi.d w4, w12[0]");
COMPARE(splati_b(w25, w3, 2), "78421e59 splati.b w25, w3[2]");
COMPARE(splati_h(w24, w28, 1), "7861e619 splati.h w24, w28[1]");
COMPARE(splati_w(w13, w18, 0), "78709359 splati.w w13, w18[0]");
COMPARE(splati_d(w28, w1, 0), "78780f19 splati.d w28, w1[0]");
COMPARE(move_v(w23, w24), "78bec5d9 move.v w23, w24");
COMPARE(insert_b(w23, 3, sp), "7903edd9 insert.b w23[3], sp");
COMPARE(insert_h(w20, 2, a1), "79222d19 insert.h w20[2], a1");
COMPARE(insert_w(w8, 2, s0), "79328219 insert.w w8[2], s0");
COMPARE(insve_b(w25, 3, w9), "79434e59 insve.b w25[3], w9[0]");
COMPARE(insve_h(w24, 2, w2), "79621619 insve.h w24[2], w2[0]");
COMPARE(insve_w(w0, 2, w13), "79726819 insve.w w0[2], w13[0]");
COMPARE(insve_d(w3, 0, w18), "797890d9 insve.d w3[0], w18[0]");
COMPARE(cfcmsa(at, MSAIR), "787e0059 cfcmsa at, MSAIR");
COMPARE(cfcmsa(v0, MSACSR), "787e0899 cfcmsa v0, MSACSR");
COMPARE(ctcmsa(MSAIR, at), "783e0819 ctcmsa MSAIR, at");
COMPARE(ctcmsa(MSACSR, v0), "783e1059 ctcmsa MSACSR, v0");
}
VERIFY_RUN();
}
TEST(MSA_BIT) {
SET_UP();
if (IsMipsArchVariant(kMips32r6) && CpuFeatures::IsSupported(MIPS_SIMD)) {
CpuFeatureScope fscope(&assm, MIPS_SIMD);
COMPARE(bclri_b(w21, w30, 2), "79f2f549 bclri.b w21, w30, 2");
COMPARE(bclri_h(w24, w21, 0), "79e0ae09 bclri.h w24, w21, 0");
COMPARE(bclri_w(w23, w30, 3), "79c3f5c9 bclri.w w23, w30, 3");
COMPARE(bclri_d(w9, w11, 0), "79805a49 bclri.d w9, w11, 0");
COMPARE(binsli_b(w25, w12, 1), "7b716649 binsli.b w25, w12, 1");
COMPARE(binsli_h(w21, w22, 0), "7b60b549 binsli.h w21, w22, 0");
COMPARE(binsli_w(w22, w4, 0), "7b402589 binsli.w w22, w4, 0");
COMPARE(binsli_d(w6, w2, 6), "7b061189 binsli.d w6, w2, 6");
COMPARE(binsri_b(w15, w19, 0), "7bf09bc9 binsri.b w15, w19, 0");
COMPARE(binsri_h(w8, w30, 1), "7be1f209 binsri.h w8, w30, 1");
COMPARE(binsri_w(w2, w19, 5), "7bc59889 binsri.w w2, w19, 5");
COMPARE(binsri_d(w18, w20, 1), "7b81a489 binsri.d w18, w20, 1");
COMPARE(bnegi_b(w24, w19, 0), "7af09e09 bnegi.b w24, w19, 0");
COMPARE(bnegi_h(w28, w11, 3), "7ae35f09 bnegi.h w28, w11, 3");
COMPARE(bnegi_w(w1, w27, 5), "7ac5d849 bnegi.w w1, w27, 5");
COMPARE(bnegi_d(w4, w21, 1), "7a81a909 bnegi.d w4, w21, 1");
COMPARE(bseti_b(w18, w8, 0), "7a704489 bseti.b w18, w8, 0");
COMPARE(bseti_h(w24, w14, 2), "7a627609 bseti.h w24, w14, 2");
COMPARE(bseti_w(w9, w18, 4), "7a449249 bseti.w w9, w18, 4");
COMPARE(bseti_d(w7, w15, 1), "7a0179c9 bseti.d w7, w15, 1");
COMPARE(sat_s_b(w31, w31, 2), "7872ffca sat_s.b w31, w31, 2");
COMPARE(sat_s_h(w19, w19, 0), "78609cca sat_s.h w19, w19, 0");
COMPARE(sat_s_w(w19, w29, 0), "7840ecca sat_s.w w19, w29, 0");
COMPARE(sat_s_d(w11, w22, 0), "7800b2ca sat_s.d w11, w22, 0");
COMPARE(sat_u_b(w1, w13, 3), "78f3684a sat_u.b w1, w13, 3");
COMPARE(sat_u_h(w30, w24, 4), "78e4c78a sat_u.h w30, w24, 4");
COMPARE(sat_u_w(w31, w13, 0), "78c06fca sat_u.w w31, w13, 0");
COMPARE(sat_u_d(w29, w16, 5), "7885874a sat_u.d w29, w16, 5");
COMPARE(slli_b(w23, w10, 1), "787155c9 slli.b w23, w10, 1");
COMPARE(slli_h(w9, w18, 1), "78619249 slli.h w9, w18, 1");
COMPARE(slli_w(w11, w29, 4), "7844eac9 slli.w w11, w29, 4");
COMPARE(slli_d(w25, w20, 1), "7801a649 slli.d w25, w20, 1");
COMPARE(srai_b(w24, w29, 1), "78f1ee09 srai.b w24, w29, 1");
COMPARE(srai_h(w1, w6, 0), "78e03049 srai.h w1, w6, 0");
COMPARE(srai_w(w7, w26, 1), "78c1d1c9 srai.w w7, w26, 1");
COMPARE(srai_d(w20, w25, 3), "7883cd09 srai.d w20, w25, 3");
COMPARE(srari_b(w5, w25, 0), "7970c94a srari.b w5, w25, 0");
COMPARE(srari_h(w7, w6, 4), "796431ca srari.h w7, w6, 4");
COMPARE(srari_w(w17, w11, 5), "79455c4a srari.w w17, w11, 5");
COMPARE(srari_d(w21, w25, 5), "7905cd4a srari.d w21, w25, 5");
COMPARE(srli_b(w2, w0, 2), "79720089 srli.b w2, w0, 2");
COMPARE(srli_h(w31, w31, 2), "7962ffc9 srli.h w31, w31, 2");
COMPARE(srli_w(w5, w9, 4), "79444949 srli.w w5, w9, 4");
COMPARE(srli_d(w27, w26, 5), "7905d6c9 srli.d w27, w26, 5");
COMPARE(srlri_b(w18, w3, 0), "79f01c8a srlri.b w18, w3, 0");
COMPARE(srlri_h(w1, w2, 3), "79e3104a srlri.h w1, w2, 3");
COMPARE(srlri_w(w11, w22, 2), "79c2b2ca srlri.w w11, w22, 2");
COMPARE(srlri_d(w24, w10, 6), "7986560a srlri.d w24, w10, 6");
}
VERIFY_RUN();
}
......@@ -127,6 +127,18 @@ if (failure) { \
if (!DisassembleAndCompare(progcounter, str_with_address)) failure = true; \
}
#define COMPARE_MSA_BRANCH(asm_, compare_string, offset) \
{ \
int pc_offset = assm.pc_offset(); \
byte* progcounter = &buffer[pc_offset]; \
char str_with_address[100]; \
snprintf(str_with_address, sizeof(str_with_address), "%s -> %p", \
compare_string, \
static_cast<void*>(progcounter + 4 + (offset * 4))); \
assm.asm_; \
if (!DisassembleAndCompare(progcounter, str_with_address)) failure = true; \
}
#define COMPARE_PC_JUMP(asm_, compare_string, target) \
{ \
int pc_offset = assm.pc_offset(); \
......@@ -1293,3 +1305,687 @@ TEST(madd_msub_maddf_msubf) {
}
VERIFY_RUN();
}
TEST(MSA_BRANCH) {
SET_UP();
if ((kArchVariant == kMips64r6) && CpuFeatures::IsSupported(MIPS_SIMD)) {
CpuFeatureScope fscope(&assm, MIPS_SIMD);
COMPARE_MSA_BRANCH(bnz_b(w0, 1), "47800001 bnz.b w0, 1", 1);
COMPARE_MSA_BRANCH(bnz_h(w1, -1), "47a1ffff bnz.h w1, -1", -1);
COMPARE_MSA_BRANCH(bnz_w(w2, 32767), "47c27fff bnz.w w2, 32767",
32767);
COMPARE_MSA_BRANCH(bnz_d(w3, -32768), "47e38000 bnz.d w3, -32768",
-32768);
COMPARE_MSA_BRANCH(bnz_v(w0, 0), "45e00000 bnz.v w0, 0", 0);
COMPARE_MSA_BRANCH(bz_b(w0, 1), "47000001 bz.b w0, 1", 1);
COMPARE_MSA_BRANCH(bz_h(w1, -1), "4721ffff bz.h w1, -1", -1);
COMPARE_MSA_BRANCH(bz_w(w2, 32767), "47427fff bz.w w2, 32767",
32767);
COMPARE_MSA_BRANCH(bz_d(w3, -32768), "47638000 bz.d w3, -32768",
-32768);
COMPARE_MSA_BRANCH(bz_v(w0, 0), "45600000 bz.v w0, 0", 0);
}
VERIFY_RUN();
}
TEST(MSA_MI10) {
SET_UP();
if ((kArchVariant == kMips64r6) && CpuFeatures::IsSupported(MIPS_SIMD)) {
CpuFeatureScope fscope(&assm, MIPS_SIMD);
COMPARE(ld_b(w0, MemOperand(at, -512)),
"7a000820 ld.b w0, -512(at)");
COMPARE(ld_b(w1, MemOperand(v0, 0)), "78001060 ld.b w1, 0(v0)");
COMPARE(ld_b(w2, MemOperand(v1, 511)), "79ff18a0 ld.b w2, 511(v1)");
COMPARE(ld_h(w4, MemOperand(a1, -512)),
"7a002921 ld.h w4, -512(a1)");
COMPARE(ld_h(w5, MemOperand(a2, 64)), "78403161 ld.h w5, 64(a2)");
COMPARE(ld_h(w6, MemOperand(a3, 511)), "79ff39a1 ld.h w6, 511(a3)");
COMPARE(ld_w(w10, MemOperand(a7, -512)),
"7a005aa2 ld.w w10, -512(a7)");
COMPARE(ld_w(w11, MemOperand(t0, 511)),
"79ff62e2 ld.w w11, 511(t0)");
COMPARE(ld_w(w12, MemOperand(t1, -128)),
"7b806b22 ld.w w12, -128(t1)");
COMPARE(ld_d(w17, MemOperand(s2, -512)),
"7a009463 ld.d w17, -512(s2)");
COMPARE(ld_d(w18, MemOperand(s3, 128)),
"78809ca3 ld.d w18, 128(s3)");
COMPARE(ld_d(w19, MemOperand(s4, 511)),
"79ffa4e3 ld.d w19, 511(s4)");
COMPARE(st_b(w0, MemOperand(at, -512)),
"7a000824 st.b w0, -512(at)");
COMPARE(st_b(w1, MemOperand(v0, 0)), "78001064 st.b w1, 0(v0)");
COMPARE(st_b(w2, MemOperand(v1, 511)), "79ff18a4 st.b w2, 511(v1)");
COMPARE(st_h(w4, MemOperand(a1, -512)),
"7a002925 st.h w4, -512(a1)");
COMPARE(st_h(w5, MemOperand(a2, 64)), "78403165 st.h w5, 64(a2)");
COMPARE(st_h(w6, MemOperand(a3, 511)), "79ff39a5 st.h w6, 511(a3)");
COMPARE(st_w(w10, MemOperand(a7, -512)),
"7a005aa6 st.w w10, -512(a7)");
COMPARE(st_w(w11, MemOperand(t0, 511)),
"79ff62e6 st.w w11, 511(t0)");
COMPARE(st_w(w12, MemOperand(t1, -128)),
"7b806b26 st.w w12, -128(t1)");
COMPARE(st_d(w17, MemOperand(s2, -512)),
"7a009467 st.d w17, -512(s2)");
COMPARE(st_d(w18, MemOperand(s3, 128)),
"78809ca7 st.d w18, 128(s3)");
COMPARE(st_d(w19, MemOperand(s4, 511)),
"79ffa4e7 st.d w19, 511(s4)");
}
VERIFY_RUN();
}
TEST(MSA_I5) {
SET_UP();
if ((kArchVariant == kMips64r6) && CpuFeatures::IsSupported(MIPS_SIMD)) {
CpuFeatureScope fscope(&assm, MIPS_SIMD);
COMPARE(addvi_b(w3, w31, 30), "781ef8c6 addvi.b w3, w31, 30");
COMPARE(addvi_h(w24, w13, 26), "783a6e06 addvi.h w24, w13, 26");
COMPARE(addvi_w(w26, w20, 26), "785aa686 addvi.w w26, w20, 26");
COMPARE(addvi_d(w16, w1, 21), "78750c06 addvi.d w16, w1, 21");
COMPARE(ceqi_b(w24, w21, -8), "7818ae07 ceqi.b w24, w21, -8");
COMPARE(ceqi_h(w31, w15, 2), "78227fc7 ceqi.h w31, w15, 2");
COMPARE(ceqi_w(w12, w1, -1), "785f0b07 ceqi.w w12, w1, -1");
COMPARE(ceqi_d(w24, w22, 7), "7867b607 ceqi.d w24, w22, 7");
COMPARE(clei_s_b(w12, w16, 1), "7a018307 clei_s.b w12, w16, 1");
COMPARE(clei_s_h(w2, w10, -9), "7a375087 clei_s.h w2, w10, -9");
COMPARE(clei_s_w(w4, w11, -10), "7a565907 clei_s.w w4, w11, -10");
COMPARE(clei_s_d(w0, w29, -10), "7a76e807 clei_s.d w0, w29, -10");
COMPARE(clei_u_b(w21, w17, 3), "7a838d47 clei_u.b w21, w17, 3");
COMPARE(clei_u_h(w29, w7, 17), "7ab13f47 clei_u.h w29, w7, 17");
COMPARE(clei_u_w(w1, w1, 2), "7ac20847 clei_u.w w1, w1, 2");
COMPARE(clei_u_d(w27, w27, 29), "7afddec7 clei_u.d w27, w27, 29");
COMPARE(clti_s_b(w19, w13, -7), "79196cc7 clti_s.b w19, w13, -7");
COMPARE(clti_s_h(w15, w10, -12), "793453c7 clti_s.h w15, w10, -12");
COMPARE(clti_s_w(w12, w12, 11), "794b6307 clti_s.w w12, w12, 11");
COMPARE(clti_s_d(w29, w20, -15), "7971a747 clti_s.d w29, w20, -15");
COMPARE(clti_u_b(w14, w9, 29), "799d4b87 clti_u.b w14, w9, 29");
COMPARE(clti_u_h(w24, w25, 25), "79b9ce07 clti_u.h w24, w25, 25");
COMPARE(clti_u_w(w1, w1, 22), "79d60847 clti_u.w w1, w1, 22");
COMPARE(clti_u_d(w21, w25, 1), "79e1cd47 clti_u.d w21, w25, 1");
COMPARE(maxi_s_b(w22, w21, 1), "7901ad86 maxi_s.b w22, w21, 1");
COMPARE(maxi_s_h(w29, w5, -8), "79382f46 maxi_s.h w29, w5, -8");
COMPARE(maxi_s_w(w1, w10, -12), "79545046 maxi_s.w w1, w10, -12");
COMPARE(maxi_s_d(w13, w29, -16), "7970eb46 maxi_s.d w13, w29, -16");
COMPARE(maxi_u_b(w20, w0, 12), "798c0506 maxi_u.b w20, w0, 12");
COMPARE(maxi_u_h(w1, w14, 3), "79a37046 maxi_u.h w1, w14, 3");
COMPARE(maxi_u_w(w27, w22, 11), "79cbb6c6 maxi_u.w w27, w22, 11");
COMPARE(maxi_u_d(w26, w6, 4), "79e43686 maxi_u.d w26, w6, 4");
COMPARE(mini_s_b(w4, w1, 1), "7a010906 mini_s.b w4, w1, 1");
COMPARE(mini_s_h(w27, w27, -9), "7a37dec6 mini_s.h w27, w27, -9");
COMPARE(mini_s_w(w28, w11, 9), "7a495f06 mini_s.w w28, w11, 9");
COMPARE(mini_s_d(w11, w10, 10), "7a6a52c6 mini_s.d w11, w10, 10");
COMPARE(mini_u_b(w18, w23, 27), "7a9bbc86 mini_u.b w18, w23, 27");
COMPARE(mini_u_h(w7, w26, 18), "7ab2d1c6 mini_u.h w7, w26, 18");
COMPARE(mini_u_w(w11, w12, 26), "7ada62c6 mini_u.w w11, w12, 26");
COMPARE(mini_u_d(w11, w15, 2), "7ae27ac6 mini_u.d w11, w15, 2");
COMPARE(subvi_b(w24, w20, 19), "7893a606 subvi.b w24, w20, 19");
COMPARE(subvi_h(w11, w19, 4), "78a49ac6 subvi.h w11, w19, 4");
COMPARE(subvi_w(w12, w10, 11), "78cb5306 subvi.w w12, w10, 11");
COMPARE(subvi_d(w19, w16, 7), "78e784c6 subvi.d w19, w16, 7");
}
VERIFY_RUN();
}
TEST(MSA_I10) {
SET_UP();
if ((kArchVariant == kMips64r6) && CpuFeatures::IsSupported(MIPS_SIMD)) {
CpuFeatureScope fscope(&assm, MIPS_SIMD);
COMPARE(ldi_b(w8, 198), "7b063207 ldi.b w8, 198");
COMPARE(ldi_h(w20, 313), "7b29cd07 ldi.h w20, 313");
COMPARE(ldi_w(w24, 492), "7b4f6607 ldi.w w24, 492");
COMPARE(ldi_d(w27, -180), "7b7a66c7 ldi.d w27, -180");
}
VERIFY_RUN();
}
TEST(MSA_I8) {
SET_UP();
if ((kArchVariant == kMips64r6) && CpuFeatures::IsSupported(MIPS_SIMD)) {
CpuFeatureScope fscope(&assm, MIPS_SIMD);
COMPARE(andi_b(w2, w29, 48), "7830e880 andi.b w2, w29, 48");
COMPARE(bmnzi_b(w6, w22, 126), "787eb181 bmnzi.b w6, w22, 126");
COMPARE(bmzi_b(w27, w1, 88), "79580ec1 bmzi.b w27, w1, 88");
COMPARE(bseli_b(w29, w3, 189), "7abd1f41 bseli.b w29, w3, 189");
COMPARE(nori_b(w1, w17, 56), "7a388840 nori.b w1, w17, 56");
COMPARE(ori_b(w26, w20, 135), "7987a680 ori.b w26, w20, 135");
COMPARE(shf_b(w19, w30, 105), "7869f4c2 shf.b w19, w30, 105");
COMPARE(shf_h(w17, w8, 76), "794c4442 shf.h w17, w8, 76");
COMPARE(shf_w(w14, w3, 93), "7a5d1b82 shf.w w14, w3, 93");
COMPARE(xori_b(w16, w10, 20), "7b145400 xori.b w16, w10, 20");
}
VERIFY_RUN();
}
TEST(MSA_VEC) {
SET_UP();
if ((kArchVariant == kMips64r6) && CpuFeatures::IsSupported(MIPS_SIMD)) {
CpuFeatureScope fscope(&assm, MIPS_SIMD);
COMPARE(and_v(w25, w20, w27), "781ba65e and.v w25, w20, w27");
COMPARE(bmnz_v(w17, w6, w7), "7887345e bmnz.v w17, w6, w7");
COMPARE(bmz_v(w3, w17, w9), "78a988de bmz.v w3, w17, w9");
COMPARE(bsel_v(w8, w0, w14), "78ce021e bsel.v w8, w0, w14");
COMPARE(nor_v(w7, w31, w0), "7840f9de nor.v w7, w31, w0");
COMPARE(or_v(w24, w26, w30), "783ed61e or.v w24, w26, w30");
COMPARE(xor_v(w7, w27, w15), "786fd9de xor.v w7, w27, w15");
}
VERIFY_RUN();
}
TEST(MSA_2R) {
SET_UP();
if ((kArchVariant == kMips64r6) && CpuFeatures::IsSupported(MIPS_SIMD)) {
CpuFeatureScope fscope(&assm, MIPS_SIMD);
COMPARE(fill_b(w30, a5), "7b004f9e fill.b w30, a5");
COMPARE(fill_h(w31, s7), "7b01bfde fill.h w31, s7");
COMPARE(fill_w(w16, t8), "7b02c41e fill.w w16, t8");
COMPARE(fill_d(w27, a5), "7b034ede fill.d w27, a5");
COMPARE(nloc_b(w21, w0), "7b08055e nloc.b w21, w0");
COMPARE(nloc_h(w18, w31), "7b09fc9e nloc.h w18, w31");
COMPARE(nloc_w(w2, w23), "7b0ab89e nloc.w w2, w23");
COMPARE(nloc_d(w4, w10), "7b0b511e nloc.d w4, w10");
COMPARE(nlzc_b(w31, w2), "7b0c17de nlzc.b w31, w2");
COMPARE(nlzc_h(w27, w22), "7b0db6de nlzc.h w27, w22");
COMPARE(nlzc_w(w10, w29), "7b0eea9e nlzc.w w10, w29");
COMPARE(nlzc_d(w25, w9), "7b0f4e5e nlzc.d w25, w9");
COMPARE(pcnt_b(w20, w18), "7b04951e pcnt.b w20, w18");
COMPARE(pcnt_h(w0, w8), "7b05401e pcnt.h w0, w8");
COMPARE(pcnt_w(w23, w9), "7b064dde pcnt.w w23, w9");
COMPARE(pcnt_d(w21, w24), "7b07c55e pcnt.d w21, w24");
}
VERIFY_RUN();
}
TEST(MSA_2RF) {
SET_UP();
if ((kArchVariant == kMips64r6) && CpuFeatures::IsSupported(MIPS_SIMD)) {
CpuFeatureScope fscope(&assm, MIPS_SIMD);
COMPARE(fclass_w(w26, w12), "7b20669e fclass.w w26, w12");
COMPARE(fclass_d(w24, w17), "7b218e1e fclass.d w24, w17");
COMPARE(fexupl_w(w8, w0), "7b30021e fexupl.w w8, w0");
COMPARE(fexupl_d(w17, w29), "7b31ec5e fexupl.d w17, w29");
COMPARE(fexupr_w(w13, w4), "7b32235e fexupr.w w13, w4");
COMPARE(fexupr_d(w5, w2), "7b33115e fexupr.d w5, w2");
COMPARE(ffint_s_w(w20, w29), "7b3ced1e ffint_s.w w20, w29");
COMPARE(ffint_s_d(w12, w15), "7b3d7b1e ffint_s.d w12, w15");
COMPARE(ffint_u_w(w7, w27), "7b3ed9de ffint_u.w w7, w27");
COMPARE(ffint_u_d(w19, w16), "7b3f84de ffint_u.d w19, w16");
COMPARE(ffql_w(w31, w13), "7b346fde ffql.w w31, w13");
COMPARE(ffql_d(w12, w13), "7b356b1e ffql.d w12, w13");
COMPARE(ffqr_w(w27, w30), "7b36f6de ffqr.w w27, w30");
COMPARE(ffqr_d(w30, w15), "7b377f9e ffqr.d w30, w15");
COMPARE(flog2_w(w25, w31), "7b2efe5e flog2.w w25, w31");
COMPARE(flog2_d(w18, w10), "7b2f549e flog2.d w18, w10");
COMPARE(frint_w(w7, w15), "7b2c79de frint.w w7, w15");
COMPARE(frint_d(w21, w22), "7b2db55e frint.d w21, w22");
COMPARE(frcp_w(w19, w0), "7b2a04de frcp.w w19, w0");
COMPARE(frcp_d(w4, w14), "7b2b711e frcp.d w4, w14");
COMPARE(frsqrt_w(w12, w17), "7b288b1e frsqrt.w w12, w17");
COMPARE(frsqrt_d(w23, w11), "7b295dde frsqrt.d w23, w11");
COMPARE(fsqrt_w(w0, w11), "7b26581e fsqrt.w w0, w11");
COMPARE(fsqrt_d(w15, w12), "7b2763de fsqrt.d w15, w12");
COMPARE(ftint_s_w(w30, w5), "7b382f9e ftint_s.w w30, w5");
COMPARE(ftint_s_d(w5, w23), "7b39b95e ftint_s.d w5, w23");
COMPARE(ftint_u_w(w20, w14), "7b3a751e ftint_u.w w20, w14");
COMPARE(ftint_u_d(w23, w21), "7b3badde ftint_u.d w23, w21");
COMPARE(ftrunc_s_w(w29, w17), "7b228f5e ftrunc_s.w w29, w17");
COMPARE(ftrunc_s_d(w12, w27), "7b23db1e ftrunc_s.d w12, w27");
COMPARE(ftrunc_u_w(w17, w15), "7b247c5e ftrunc_u.w w17, w15");
COMPARE(ftrunc_u_d(w5, w27), "7b25d95e ftrunc_u.d w5, w27");
}
VERIFY_RUN();
}
TEST(MSA_3R) {
SET_UP();
if ((kArchVariant == kMips64r6) && CpuFeatures::IsSupported(MIPS_SIMD)) {
CpuFeatureScope fscope(&assm, MIPS_SIMD);
COMPARE(add_a_b(w26, w9, w4), "78044e90 add_a.b w26, w9, w4");
COMPARE(add_a_h(w23, w27, w31), "783fddd0 add_a.h w23, w27, w31");
COMPARE(add_a_w(w11, w6, w22), "785632d0 add_a.w w11, w6, w22");
COMPARE(add_a_d(w6, w10, w0), "78605190 add_a.d w6, w10, w0");
COMPARE(adds_a_b(w19, w24, w19), "7893c4d0 adds_a.b w19, w24, w19");
COMPARE(adds_a_h(w25, w6, w4), "78a43650 adds_a.h w25, w6, w4");
COMPARE(adds_a_w(w25, w17, w27), "78db8e50 adds_a.w w25, w17, w27");
COMPARE(adds_a_d(w15, w18, w26), "78fa93d0 adds_a.d w15, w18, w26");
COMPARE(adds_s_b(w29, w11, w19), "79135f50 adds_s.b w29, w11, w19");
COMPARE(adds_s_h(w5, w23, w26), "793ab950 adds_s.h w5, w23, w26");
COMPARE(adds_s_w(w16, w14, w13), "794d7410 adds_s.w w16, w14, w13");
COMPARE(adds_s_d(w2, w14, w28), "797c7090 adds_s.d w2, w14, w28");
COMPARE(adds_u_b(w3, w17, w14), "798e88d0 adds_u.b w3, w17, w14");
COMPARE(adds_u_h(w10, w30, w4), "79a4f290 adds_u.h w10, w30, w4");
COMPARE(adds_u_w(w15, w18, w20), "79d493d0 adds_u.w w15, w18, w20");
COMPARE(adds_u_d(w30, w10, w9), "79e95790 adds_u.d w30, w10, w9");
COMPARE(addv_b(w24, w20, w21), "7815a60e addv.b w24, w20, w21");
COMPARE(addv_h(w4, w13, w27), "783b690e addv.h w4, w13, w27");
COMPARE(addv_w(w19, w11, w14), "784e5cce addv.w w19, w11, w14");
COMPARE(addv_d(w2, w21, w31), "787fa88e addv.d w2, w21, w31");
COMPARE(asub_s_b(w23, w16, w3), "7a0385d1 asub_s.b w23, w16, w3");
COMPARE(asub_s_h(w22, w17, w25), "7a398d91 asub_s.h w22, w17, w25");
COMPARE(asub_s_w(w24, w1, w9), "7a490e11 asub_s.w w24, w1, w9");
COMPARE(asub_s_d(w13, w12, w12), "7a6c6351 asub_s.d w13, w12, w12");
COMPARE(asub_u_b(w10, w29, w11), "7a8bea91 asub_u.b w10, w29, w11");
COMPARE(asub_u_h(w18, w9, w15), "7aaf4c91 asub_u.h w18, w9, w15");
COMPARE(asub_u_w(w10, w19, w31), "7adf9a91 asub_u.w w10, w19, w31");
COMPARE(asub_u_d(w17, w10, w0), "7ae05451 asub_u.d w17, w10, w0");
COMPARE(ave_s_b(w2, w5, w1), "7a012890 ave_s.b w2, w5, w1");
COMPARE(ave_s_h(w16, w19, w9), "7a299c10 ave_s.h w16, w19, w9");
COMPARE(ave_s_w(w17, w31, w5), "7a45fc50 ave_s.w w17, w31, w5");
COMPARE(ave_s_d(w27, w25, w10), "7a6aced0 ave_s.d w27, w25, w10");
COMPARE(ave_u_b(w16, w19, w9), "7a899c10 ave_u.b w16, w19, w9");
COMPARE(ave_u_h(w28, w28, w11), "7aabe710 ave_u.h w28, w28, w11");
COMPARE(ave_u_w(w11, w12, w11), "7acb62d0 ave_u.w w11, w12, w11");
COMPARE(ave_u_d(w30, w19, w28), "7afc9f90 ave_u.d w30, w19, w28");
COMPARE(aver_s_b(w26, w16, w2), "7b028690 aver_s.b w26, w16, w2");
COMPARE(aver_s_h(w31, w27, w27), "7b3bdfd0 aver_s.h w31, w27, w27");
COMPARE(aver_s_w(w28, w18, w25), "7b599710 aver_s.w w28, w18, w25");
COMPARE(aver_s_d(w29, w21, w27), "7b7baf50 aver_s.d w29, w21, w27");
COMPARE(aver_u_b(w29, w26, w3), "7b83d750 aver_u.b w29, w26, w3");
COMPARE(aver_u_h(w18, w18, w9), "7ba99490 aver_u.h w18, w18, w9");
COMPARE(aver_u_w(w17, w25, w29), "7bddcc50 aver_u.w w17, w25, w29");
COMPARE(aver_u_d(w22, w22, w19), "7bf3b590 aver_u.d w22, w22, w19");
COMPARE(bclr_b(w2, w15, w29), "799d788d bclr.b w2, w15, w29");
COMPARE(bclr_h(w16, w21, w28), "79bcac0d bclr.h w16, w21, w28");
COMPARE(bclr_w(w19, w2, w9), "79c914cd bclr.w w19, w2, w9");
COMPARE(bclr_d(w27, w31, w4), "79e4fecd bclr.d w27, w31, w4");
COMPARE(binsl_b(w5, w16, w24), "7b18814d binsl.b w5, w16, w24");
COMPARE(binsl_h(w30, w5, w10), "7b2a2f8d binsl.h w30, w5, w10");
COMPARE(binsl_w(w14, w15, w13), "7b4d7b8d binsl.w w14, w15, w13");
COMPARE(binsl_d(w23, w20, w12), "7b6ca5cd binsl.d w23, w20, w12");
COMPARE(binsr_b(w22, w11, w2), "7b825d8d binsr.b w22, w11, w2");
COMPARE(binsr_h(w0, w26, w6), "7ba6d00d binsr.h w0, w26, w6");
COMPARE(binsr_w(w26, w3, w28), "7bdc1e8d binsr.w w26, w3, w28");
COMPARE(binsr_d(w0, w0, w21), "7bf5000d binsr.d w0, w0, w21");
COMPARE(bneg_b(w0, w11, w24), "7a98580d bneg.b w0, w11, w24");
COMPARE(bneg_h(w28, w16, w4), "7aa4870d bneg.h w28, w16, w4");
COMPARE(bneg_w(w3, w26, w19), "7ad3d0cd bneg.w w3, w26, w19");
COMPARE(bneg_d(w13, w29, w15), "7aefeb4d bneg.d w13, w29, w15");
COMPARE(bset_b(w31, w5, w31), "7a1f2fcd bset.b w31, w5, w31");
COMPARE(bset_h(w14, w12, w6), "7a26638d bset.h w14, w12, w6");
COMPARE(bset_w(w31, w9, w12), "7a4c4fcd bset.w w31, w9, w12");
COMPARE(bset_d(w5, w22, w5), "7a65b14d bset.d w5, w22, w5");
COMPARE(ceq_b(w31, w31, w18), "7812ffcf ceq.b w31, w31, w18");
COMPARE(ceq_h(w10, w27, w9), "7829da8f ceq.h w10, w27, w9");
COMPARE(ceq_w(w9, w5, w14), "784e2a4f ceq.w w9, w5, w14");
COMPARE(ceq_d(w5, w17, w0), "7860894f ceq.d w5, w17, w0");
COMPARE(cle_s_b(w23, w4, w9), "7a0925cf cle_s.b w23, w4, w9");
COMPARE(cle_s_h(w22, w27, w19), "7a33dd8f cle_s.h w22, w27, w19");
COMPARE(cle_s_w(w30, w26, w10), "7a4ad78f cle_s.w w30, w26, w10");
COMPARE(cle_s_d(w18, w5, w10), "7a6a2c8f cle_s.d w18, w5, w10");
COMPARE(cle_u_b(w1, w25, w0), "7a80c84f cle_u.b w1, w25, w0");
COMPARE(cle_u_h(w7, w0, w29), "7abd01cf cle_u.h w7, w0, w29");
COMPARE(cle_u_w(w25, w18, w1), "7ac1964f cle_u.w w25, w18, w1");
COMPARE(cle_u_d(w6, w0, w30), "7afe018f cle_u.d w6, w0, w30");
COMPARE(clt_s_b(w25, w2, w21), "7915164f clt_s.b w25, w2, w21");
COMPARE(clt_s_h(w2, w19, w9), "7929988f clt_s.h w2, w19, w9");
COMPARE(clt_s_w(w23, w8, w16), "795045cf clt_s.w w23, w8, w16");
COMPARE(clt_s_d(w7, w30, w12), "796cf1cf clt_s.d w7, w30, w12");
COMPARE(clt_u_b(w2, w31, w13), "798df88f clt_u.b w2, w31, w13");
COMPARE(clt_u_h(w16, w31, w23), "79b7fc0f clt_u.h w16, w31, w23");
COMPARE(clt_u_w(w3, w24, w9), "79c9c0cf clt_u.w w3, w24, w9");
COMPARE(clt_u_d(w7, w0, w1), "79e101cf clt_u.d w7, w0, w1");
COMPARE(div_s_b(w29, w3, w18), "7a121f52 div_s.b w29, w3, w18");
COMPARE(div_s_h(w17, w16, w13), "7a2d8452 div_s.h w17, w16, w13");
COMPARE(div_s_w(w4, w25, w30), "7a5ec912 div_s.w w4, w25, w30");
COMPARE(div_s_d(w31, w9, w20), "7a744fd2 div_s.d w31, w9, w20");
COMPARE(div_u_b(w6, w29, w10), "7a8ae992 div_u.b w6, w29, w10");
COMPARE(div_u_h(w24, w21, w14), "7aaeae12 div_u.h w24, w21, w14");
COMPARE(div_u_w(w29, w14, w25), "7ad97752 div_u.w w29, w14, w25");
COMPARE(div_u_d(w31, w1, w21), "7af50fd2 div_u.d w31, w1, w21");
COMPARE(dotp_s_h(w23, w22, w25), "7839b5d3 dotp_s.h w23, w22, w25");
COMPARE(dotp_s_w(w20, w14, w5), "78457513 dotp_s.w w20, w14, w5");
COMPARE(dotp_s_d(w17, w2, w22), "78761453 dotp_s.d w17, w2, w22");
COMPARE(dotp_u_h(w13, w2, w6), "78a61353 dotp_u.h w13, w2, w6");
COMPARE(dotp_u_w(w15, w22, w21), "78d5b3d3 dotp_u.w w15, w22, w21");
COMPARE(dotp_u_d(w4, w16, w26), "78fa8113 dotp_u.d w4, w16, w26");
COMPARE(dpadd_s_h(w1, w28, w22), "7936e053 dpadd_s.h w1, w28, w22");
COMPARE(dpadd_s_w(w10, w1, w12), "794c0a93 dpadd_s.w w10, w1, w12");
COMPARE(dpadd_s_d(w3, w21, w27), "797ba8d3 dpadd_s.d w3, w21, w27");
COMPARE(dpadd_u_h(w17, w5, w20), "79b42c53 dpadd_u.h w17, w5, w20");
COMPARE(dpadd_u_w(w24, w8, w16), "79d04613 dpadd_u.w w24, w8, w16");
COMPARE(dpadd_u_d(w15, w29, w16),
"79f0ebd3 dpadd_u.d w15, w29, w16");
COMPARE(dpsub_s_h(w4, w11, w12), "7a2c5913 dpsub_s.h w4, w11, w12");
COMPARE(dpsub_s_w(w4, w7, w6), "7a463913 dpsub_s.w w4, w7, w6");
COMPARE(dpsub_s_d(w31, w12, w28),
"7a7c67d3 dpsub_s.d w31, w12, w28");
COMPARE(dpsub_u_h(w4, w25, w17), "7ab1c913 dpsub_u.h w4, w25, w17");
COMPARE(dpsub_u_w(w19, w25, w16),
"7ad0ccd3 dpsub_u.w w19, w25, w16");
COMPARE(dpsub_u_d(w7, w10, w26), "7afa51d3 dpsub_u.d w7, w10, w26");
COMPARE(hadd_s_h(w28, w24, w2), "7a22c715 hadd_s.h w28, w24, w2");
COMPARE(hadd_s_w(w24, w17, w11), "7a4b8e15 hadd_s.w w24, w17, w11");
COMPARE(hadd_s_d(w17, w15, w20), "7a747c55 hadd_s.d w17, w15, w20");
COMPARE(hadd_u_h(w12, w29, w17), "7ab1eb15 hadd_u.h w12, w29, w17");
COMPARE(hadd_u_w(w9, w5, w6), "7ac62a55 hadd_u.w w9, w5, w6");
COMPARE(hadd_u_d(w1, w20, w6), "7ae6a055 hadd_u.d w1, w20, w6");
COMPARE(hsub_s_h(w16, w14, w29), "7b3d7415 hsub_s.h w16, w14, w29");
COMPARE(hsub_s_w(w9, w13, w11), "7b4b6a55 hsub_s.w w9, w13, w11");
COMPARE(hsub_s_d(w30, w18, w14), "7b6e9795 hsub_s.d w30, w18, w14");
COMPARE(hsub_u_h(w7, w12, w14), "7bae61d5 hsub_u.h w7, w12, w14");
COMPARE(hsub_u_w(w21, w5, w5), "7bc52d55 hsub_u.w w21, w5, w5");
COMPARE(hsub_u_d(w11, w12, w31), "7bff62d5 hsub_u.d w11, w12, w31");
COMPARE(ilvev_b(w18, w16, w30), "7b1e8494 ilvev.b w18, w16, w30");
COMPARE(ilvev_h(w14, w0, w13), "7b2d0394 ilvev.h w14, w0, w13");
COMPARE(ilvev_w(w12, w25, w22), "7b56cb14 ilvev.w w12, w25, w22");
COMPARE(ilvev_d(w30, w27, w3), "7b63df94 ilvev.d w30, w27, w3");
COMPARE(ilvl_b(w29, w3, w21), "7a151f54 ilvl.b w29, w3, w21");
COMPARE(ilvl_h(w27, w10, w17), "7a3156d4 ilvl.h w27, w10, w17");
COMPARE(ilvl_w(w6, w1, w0), "7a400994 ilvl.w w6, w1, w0");
COMPARE(ilvl_d(w3, w16, w24), "7a7880d4 ilvl.d w3, w16, w24");
COMPARE(ilvod_b(w11, w5, w20), "7b942ad4 ilvod.b w11, w5, w20");
COMPARE(ilvod_h(w18, w13, w31), "7bbf6c94 ilvod.h w18, w13, w31");
COMPARE(ilvod_w(w29, w16, w24), "7bd88754 ilvod.w w29, w16, w24");
COMPARE(ilvod_d(w22, w12, w29), "7bfd6594 ilvod.d w22, w12, w29");
COMPARE(ilvr_b(w4, w30, w6), "7a86f114 ilvr.b w4, w30, w6");
COMPARE(ilvr_h(w28, w19, w29), "7abd9f14 ilvr.h w28, w19, w29");
COMPARE(ilvr_w(w18, w20, w21), "7ad5a494 ilvr.w w18, w20, w21");
COMPARE(ilvr_d(w23, w30, w12), "7aecf5d4 ilvr.d w23, w30, w12");
COMPARE(maddv_b(w17, w31, w29), "789dfc52 maddv.b w17, w31, w29");
COMPARE(maddv_h(w7, w24, w9), "78a9c1d2 maddv.h w7, w24, w9");
COMPARE(maddv_w(w22, w22, w20), "78d4b592 maddv.w w22, w22, w20");
COMPARE(maddv_d(w30, w26, w20), "78f4d792 maddv.d w30, w26, w20");
COMPARE(max_a_b(w23, w11, w23), "7b175dce max_a.b w23, w11, w23");
COMPARE(max_a_h(w20, w5, w30), "7b3e2d0e max_a.h w20, w5, w30");
COMPARE(max_a_w(w7, w18, w30), "7b5e91ce max_a.w w7, w18, w30");
COMPARE(max_a_d(w8, w8, w31), "7b7f420e max_a.d w8, w8, w31");
COMPARE(max_s_b(w10, w1, w19), "79130a8e max_s.b w10, w1, w19");
COMPARE(max_s_h(w15, w29, w17), "7931ebce max_s.h w15, w29, w17");
COMPARE(max_s_w(w15, w29, w14), "794eebce max_s.w w15, w29, w14");
COMPARE(max_s_d(w25, w24, w3), "7963c64e max_s.d w25, w24, w3");
COMPARE(max_u_b(w12, w24, w5), "7985c30e max_u.b w12, w24, w5");
COMPARE(max_u_h(w5, w6, w7), "79a7314e max_u.h w5, w6, w7");
COMPARE(max_u_w(w16, w4, w7), "79c7240e max_u.w w16, w4, w7");
COMPARE(max_u_d(w26, w12, w24), "79f8668e max_u.d w26, w12, w24");
COMPARE(min_a_b(w4, w26, w1), "7b81d10e min_a.b w4, w26, w1");
COMPARE(min_a_h(w12, w13, w31), "7bbf6b0e min_a.h w12, w13, w31");
COMPARE(min_a_w(w28, w20, w0), "7bc0a70e min_a.w w28, w20, w0");
COMPARE(min_a_d(w12, w20, w19), "7bf3a30e min_a.d w12, w20, w19");
COMPARE(min_s_b(w19, w3, w14), "7a0e1cce min_s.b w19, w3, w14");
COMPARE(min_s_h(w27, w21, w8), "7a28aece min_s.h w27, w21, w8");
COMPARE(min_s_w(w0, w14, w30), "7a5e700e min_s.w w0, w14, w30");
COMPARE(min_s_d(w6, w8, w21), "7a75418e min_s.d w6, w8, w21");
COMPARE(min_u_b(w22, w26, w8), "7a88d58e min_u.b w22, w26, w8");
COMPARE(min_u_h(w7, w27, w12), "7aacd9ce min_u.h w7, w27, w12");
COMPARE(min_u_w(w8, w20, w14), "7acea20e min_u.w w8, w20, w14");
COMPARE(min_u_d(w26, w14, w15), "7aef768e min_u.d w26, w14, w15");
COMPARE(mod_s_b(w18, w1, w26), "7b1a0c92 mod_s.b w18, w1, w26");
COMPARE(mod_s_h(w31, w30, w28), "7b3cf7d2 mod_s.h w31, w30, w28");
COMPARE(mod_s_w(w2, w6, w13), "7b4d3092 mod_s.w w2, w6, w13");
COMPARE(mod_s_d(w21, w27, w22), "7b76dd52 mod_s.d w21, w27, w22");
COMPARE(mod_u_b(w16, w7, w13), "7b8d3c12 mod_u.b w16, w7, w13");
COMPARE(mod_u_h(w24, w8, w7), "7ba74612 mod_u.h w24, w8, w7");
COMPARE(mod_u_w(w30, w2, w17), "7bd11792 mod_u.w w30, w2, w17");
COMPARE(mod_u_d(w31, w2, w25), "7bf917d2 mod_u.d w31, w2, w25");
COMPARE(msubv_b(w14, w5, w12), "790c2b92 msubv.b w14, w5, w12");
COMPARE(msubv_h(w6, w7, w30), "793e3992 msubv.h w6, w7, w30");
COMPARE(msubv_w(w13, w2, w21), "79551352 msubv.w w13, w2, w21");
COMPARE(msubv_d(w16, w14, w27), "797b7412 msubv.d w16, w14, w27");
COMPARE(mulv_b(w20, w3, w13), "780d1d12 mulv.b w20, w3, w13");
COMPARE(mulv_h(w27, w26, w14), "782ed6d2 mulv.h w27, w26, w14");
COMPARE(mulv_w(w10, w29, w3), "7843ea92 mulv.w w10, w29, w3");
COMPARE(mulv_d(w7, w19, w29), "787d99d2 mulv.d w7, w19, w29");
COMPARE(pckev_b(w5, w27, w7), "7907d954 pckev.b w5, w27, w7");
COMPARE(pckev_h(w1, w4, w27), "793b2054 pckev.h w1, w4, w27");
COMPARE(pckev_w(w30, w20, w0), "7940a794 pckev.w w30, w20, w0");
COMPARE(pckev_d(w6, w1, w15), "796f0994 pckev.d w6, w1, w15");
COMPARE(pckod_b(w18, w28, w30), "799ee494 pckod.b w18, w28, w30");
COMPARE(pckod_h(w26, w5, w8), "79a82e94 pckod.h w26, w5, w8");
COMPARE(pckod_w(w9, w4, w2), "79c22254 pckod.w w9, w4, w2");
COMPARE(pckod_d(w30, w22, w20), "79f4b794 pckod.d w30, w22, w20");
COMPARE(sld_b(w5, w23, t0), "780cb954 sld.b w5, w23[t0]");
COMPARE(sld_h(w1, w23, v1), "7823b854 sld.h w1, w23[v1]");
COMPARE(sld_w(w20, w8, a5), "78494514 sld.w w20, w8[a5]");
COMPARE(sld_d(w7, w23, fp), "787eb9d4 sld.d w7, w23[fp]");
COMPARE(sll_b(w3, w0, w17), "781100cd sll.b w3, w0, w17");
COMPARE(sll_h(w17, w27, w3), "7823dc4d sll.h w17, w27, w3");
COMPARE(sll_w(w16, w7, w6), "78463c0d sll.w w16, w7, w6");
COMPARE(sll_d(w9, w0, w26), "787a024d sll.d w9, w0, w26");
COMPARE(splat_b(w28, w1, at), "78810f14 splat.b w28, w1[at]");
COMPARE(splat_h(w2, w11, a7), "78ab5894 splat.h w2, w11[a7]");
COMPARE(splat_w(w22, w0, a7), "78cb0594 splat.w w22, w0[a7]");
COMPARE(splat_d(w0, w0, v0), "78e20014 splat.d w0, w0[v0]");
COMPARE(sra_b(w28, w4, w17), "7891270d sra.b w28, w4, w17");
COMPARE(sra_h(w13, w9, w3), "78a34b4d sra.h w13, w9, w3");
COMPARE(sra_w(w27, w21, w19), "78d3aecd sra.w w27, w21, w19");
COMPARE(sra_d(w30, w8, w23), "78f7478d sra.d w30, w8, w23");
COMPARE(srar_b(w19, w18, w18), "789294d5 srar.b w19, w18, w18");
COMPARE(srar_h(w7, w23, w8), "78a8b9d5 srar.h w7, w23, w8");
COMPARE(srar_w(w1, w12, w2), "78c26055 srar.w w1, w12, w2");
COMPARE(srar_d(w21, w7, w14), "78ee3d55 srar.d w21, w7, w14");
COMPARE(srl_b(w12, w3, w19), "79131b0d srl.b w12, w3, w19");
COMPARE(srl_h(w23, w31, w20), "7934fdcd srl.h w23, w31, w20");
COMPARE(srl_w(w18, w27, w11), "794bdc8d srl.w w18, w27, w11");
COMPARE(srl_d(w3, w12, w26), "797a60cd srl.d w3, w12, w26");
COMPARE(srlr_b(w15, w21, w11), "790babd5 srlr.b w15, w21, w11");
COMPARE(srlr_h(w21, w13, w19), "79336d55 srlr.h w21, w13, w19");
COMPARE(srlr_w(w6, w30, w3), "7943f195 srlr.w w6, w30, w3");
COMPARE(srlr_d(w1, w2, w14), "796e1055 srlr.d w1, w2, w14");
COMPARE(subs_s_b(w25, w15, w1), "78017e51 subs_s.b w25, w15, w1");
COMPARE(subs_s_h(w28, w25, w22), "7836cf11 subs_s.h w28, w25, w22");
COMPARE(subs_s_w(w10, w12, w21), "78556291 subs_s.w w10, w12, w21");
COMPARE(subs_s_d(w4, w20, w18), "7872a111 subs_s.d w4, w20, w18");
COMPARE(subs_u_b(w21, w6, w25), "78993551 subs_u.b w21, w6, w25");
COMPARE(subs_u_h(w3, w10, w7), "78a750d1 subs_u.h w3, w10, w7");
COMPARE(subs_u_w(w9, w15, w10), "78ca7a51 subs_u.w w9, w15, w10");
COMPARE(subs_u_d(w7, w19, w10), "78ea99d1 subs_u.d w7, w19, w10");
COMPARE(subsus_u_b(w6, w7, w12), "790c3991 subsus_u.b w6, w7, w12");
COMPARE(subsus_u_h(w6, w29, w19),
"7933e991 subsus_u.h w6, w29, w19");
COMPARE(subsus_u_w(w7, w15, w7), "794779d1 subsus_u.w w7, w15, w7");
COMPARE(subsus_u_d(w9, w3, w15), "796f1a51 subsus_u.d w9, w3, w15");
COMPARE(subsuu_s_b(w22, w3, w31),
"799f1d91 subsuu_s.b w22, w3, w31");
COMPARE(subsuu_s_h(w19, w23, w22),
"79b6bcd1 subsuu_s.h w19, w23, w22");
COMPARE(subsuu_s_w(w9, w10, w13),
"79cd5251 subsuu_s.w w9, w10, w13");
COMPARE(subsuu_s_d(w5, w6, w0), "79e03151 subsuu_s.d w5, w6, w0");
COMPARE(subv_b(w6, w13, w19), "7893698e subv.b w6, w13, w19");
COMPARE(subv_h(w4, w25, w12), "78acc90e subv.h w4, w25, w12");
COMPARE(subv_w(w27, w27, w11), "78cbdece subv.w w27, w27, w11");
COMPARE(subv_d(w9, w24, w10), "78eac24e subv.d w9, w24, w10");
COMPARE(vshf_b(w3, w16, w5), "780580d5 vshf.b w3, w16, w5");
COMPARE(vshf_h(w20, w19, w8), "78289d15 vshf.h w20, w19, w8");
COMPARE(vshf_w(w16, w30, w25), "7859f415 vshf.w w16, w30, w25");
COMPARE(vshf_d(w19, w11, w15), "786f5cd5 vshf.d w19, w11, w15");
}
VERIFY_RUN();
}
TEST(MSA_3RF) {
SET_UP();
if ((kArchVariant == kMips64r6) && CpuFeatures::IsSupported(MIPS_SIMD)) {
CpuFeatureScope fscope(&assm, MIPS_SIMD);
COMPARE(fadd_w(w28, w19, w28), "781c9f1b fadd.w w28, w19, w28");
COMPARE(fadd_d(w13, w2, w29), "783d135b fadd.d w13, w2, w29");
COMPARE(fcaf_w(w14, w11, w25), "78195b9a fcaf.w w14, w11, w25");
COMPARE(fcaf_d(w1, w1, w19), "7833085a fcaf.d w1, w1, w19");
COMPARE(fceq_w(w1, w23, w16), "7890b85a fceq.w w1, w23, w16");
COMPARE(fceq_d(w0, w8, w16), "78b0401a fceq.d w0, w8, w16");
COMPARE(fcle_w(w16, w9, w24), "79984c1a fcle.w w16, w9, w24");
COMPARE(fcle_d(w27, w14, w1), "79a176da fcle.d w27, w14, w1");
COMPARE(fclt_w(w28, w8, w8), "7908471a fclt.w w28, w8, w8");
COMPARE(fclt_d(w30, w25, w11), "792bcf9a fclt.d w30, w25, w11");
COMPARE(fcne_w(w2, w18, w23), "78d7909c fcne.w w2, w18, w23");
COMPARE(fcne_d(w14, w20, w15), "78efa39c fcne.d w14, w20, w15");
COMPARE(fcor_w(w10, w18, w25), "7859929c fcor.w w10, w18, w25");
COMPARE(fcor_d(w17, w25, w11), "786bcc5c fcor.d w17, w25, w11");
COMPARE(fcueq_w(w14, w2, w21), "78d5139a fcueq.w w14, w2, w21");
COMPARE(fcueq_d(w29, w3, w7), "78e71f5a fcueq.d w29, w3, w7");
COMPARE(fcule_w(w17, w5, w3), "79c32c5a fcule.w w17, w5, w3");
COMPARE(fcule_d(w31, w1, w30), "79fe0fda fcule.d w31, w1, w30");
COMPARE(fcult_w(w6, w25, w9), "7949c99a fcult.w w6, w25, w9");
COMPARE(fcult_d(w27, w8, w17), "797146da fcult.d w27, w8, w17");
COMPARE(fcun_w(w4, w20, w8), "7848a11a fcun.w w4, w20, w8");
COMPARE(fcun_d(w29, w11, w3), "78635f5a fcun.d w29, w11, w3");
COMPARE(fcune_w(w13, w18, w19), "7893935c fcune.w w13, w18, w19");
COMPARE(fcune_d(w16, w26, w21), "78b5d41c fcune.d w16, w26, w21");
COMPARE(fdiv_w(w13, w24, w2), "78c2c35b fdiv.w w13, w24, w2");
COMPARE(fdiv_d(w19, w4, w25), "78f924db fdiv.d w19, w4, w25");
COMPARE(fexdo_h(w8, w0, w16), "7a10021b fexdo.h w8, w0, w16");
COMPARE(fexdo_w(w0, w13, w27), "7a3b681b fexdo.w w0, w13, w27");
COMPARE(fexp2_w(w17, w0, w3), "79c3045b fexp2.w w17, w0, w3");
COMPARE(fexp2_d(w22, w0, w10), "79ea059b fexp2.d w22, w0, w10");
COMPARE(fmadd_w(w29, w6, w23), "7917375b fmadd.w w29, w6, w23");
COMPARE(fmadd_d(w11, w28, w21), "7935e2db fmadd.d w11, w28, w21");
COMPARE(fmax_w(w0, w23, w13), "7b8db81b fmax.w w0, w23, w13");
COMPARE(fmax_d(w26, w18, w8), "7ba8969b fmax.d w26, w18, w8");
COMPARE(fmax_a_w(w10, w16, w10), "7bca829b fmax_a.w w10, w16, w10");
COMPARE(fmax_a_d(w30, w9, w22), "7bf64f9b fmax_a.d w30, w9, w22");
COMPARE(fmin_w(w24, w1, w30), "7b1e0e1b fmin.w w24, w1, w30");
COMPARE(fmin_d(w27, w27, w10), "7b2adedb fmin.d w27, w27, w10");
COMPARE(fmin_a_w(w10, w29, w20), "7b54ea9b fmin_a.w w10, w29, w20");
COMPARE(fmin_a_d(w13, w30, w24), "7b78f35b fmin_a.d w13, w30, w24");
COMPARE(fmsub_w(w17, w25, w0), "7940cc5b fmsub.w w17, w25, w0");
COMPARE(fmsub_d(w8, w18, w16), "7970921b fmsub.d w8, w18, w16");
COMPARE(fmul_w(w3, w15, w15), "788f78db fmul.w w3, w15, w15");
COMPARE(fmul_d(w9, w30, w10), "78aaf25b fmul.d w9, w30, w10");
COMPARE(fsaf_w(w25, w5, w10), "7a0a2e5a fsaf.w w25, w5, w10");
COMPARE(fsaf_d(w25, w3, w29), "7a3d1e5a fsaf.d w25, w3, w29");
COMPARE(fseq_w(w11, w17, w13), "7a8d8ada fseq.w w11, w17, w13");
COMPARE(fseq_d(w29, w0, w31), "7abf075a fseq.d w29, w0, w31");
COMPARE(fsle_w(w30, w31, w31), "7b9fff9a fsle.w w30, w31, w31");
COMPARE(fsle_d(w18, w23, w24), "7bb8bc9a fsle.d w18, w23, w24");
COMPARE(fslt_w(w12, w5, w6), "7b062b1a fslt.w w12, w5, w6");
COMPARE(fslt_d(w16, w26, w21), "7b35d41a fslt.d w16, w26, w21");
COMPARE(fsne_w(w30, w1, w12), "7acc0f9c fsne.w w30, w1, w12");
COMPARE(fsne_d(w14, w13, w23), "7af76b9c fsne.d w14, w13, w23");
COMPARE(fsor_w(w27, w13, w27), "7a5b6edc fsor.w w27, w13, w27");
COMPARE(fsor_d(w12, w24, w11), "7a6bc31c fsor.d w12, w24, w11");
COMPARE(fsub_w(w31, w26, w1), "7841d7db fsub.w w31, w26, w1");
COMPARE(fsub_d(w19, w17, w27), "787b8cdb fsub.d w19, w17, w27");
COMPARE(fsueq_w(w16, w24, w25), "7ad9c41a fsueq.w w16, w24, w25");
COMPARE(fsueq_d(w18, w14, w14), "7aee749a fsueq.d w18, w14, w14");
COMPARE(fsule_w(w23, w30, w13), "7bcdf5da fsule.w w23, w30, w13");
COMPARE(fsule_d(w2, w11, w26), "7bfa589a fsule.d w2, w11, w26");
COMPARE(fsult_w(w11, w26, w22), "7b56d2da fsult.w w11, w26, w22");
COMPARE(fsult_d(w6, w23, w30), "7b7eb99a fsult.d w6, w23, w30");
COMPARE(fsun_w(w3, w18, w28), "7a5c90da fsun.w w3, w18, w28");
COMPARE(fsun_d(w18, w11, w19), "7a735c9a fsun.d w18, w11, w19");
COMPARE(fsune_w(w16, w31, w2), "7a82fc1c fsune.w w16, w31, w2");
COMPARE(fsune_d(w3, w26, w17), "7ab1d0dc fsune.d w3, w26, w17");
COMPARE(ftq_h(w16, w4, w24), "7a98241b ftq.h w16, w4, w24");
COMPARE(ftq_w(w5, w5, w25), "7ab9295b ftq.w w5, w5, w25");
COMPARE(madd_q_h(w16, w20, w10), "794aa41c madd_q.h w16, w20, w10");
COMPARE(madd_q_w(w28, w2, w9), "7969171c madd_q.w w28, w2, w9");
COMPARE(maddr_q_h(w8, w18, w9), "7b49921c maddr_q.h w8, w18, w9");
COMPARE(maddr_q_w(w29, w12, w16),
"7b70675c maddr_q.w w29, w12, w16");
COMPARE(msub_q_h(w24, w26, w10), "798ad61c msub_q.h w24, w26, w10");
COMPARE(msub_q_w(w13, w30, w28), "79bcf35c msub_q.w w13, w30, w28");
COMPARE(msubr_q_h(w12, w21, w11),
"7b8bab1c msubr_q.h w12, w21, w11");
COMPARE(msubr_q_w(w1, w14, w20), "7bb4705c msubr_q.w w1, w14, w20");
COMPARE(mul_q_h(w6, w16, w30), "791e819c mul_q.h w6, w16, w30");
COMPARE(mul_q_w(w16, w1, w4), "79240c1c mul_q.w w16, w1, w4");
COMPARE(mulr_q_h(w6, w20, w19), "7b13a19c mulr_q.h w6, w20, w19");
COMPARE(mulr_q_w(w27, w1, w20), "7b340edc mulr_q.w w27, w1, w20");
}
VERIFY_RUN();
}
TEST(MSA_ELM) {
SET_UP();
if ((kArchVariant == kMips64r6) && CpuFeatures::IsSupported(MIPS_SIMD)) {
CpuFeatureScope fscope(&assm, MIPS_SIMD);
COMPARE(copy_s_b(t1, w8, 2), "78824359 copy_s.b t1, w8[2]");
COMPARE(copy_s_h(at, w25, 0), "78a0c859 copy_s.h at, w25[0]");
COMPARE(copy_s_w(s6, w5, 1), "78b12d99 copy_s.w s6, w5[1]");
COMPARE(copy_s_d(s3, w31, 0), "78b8fcd9 copy_s.d s3, w31[0]");
COMPARE(copy_u_b(s6, w20, 4), "78c4a599 copy_u.b s6, w20[4]");
COMPARE(copy_u_h(s4, w4, 0), "78e02519 copy_u.h s4, w4[0]");
COMPARE(copy_u_w(t1, w0, 1), "78f10359 copy_u.w t1, w0[1]");
COMPARE(sldi_b(w0, w29, 4), "7804e819 sldi.b w0, w29[4]");
COMPARE(sldi_h(w8, w17, 0), "78208a19 sldi.h w8, w17[0]");
COMPARE(sldi_w(w20, w27, 2), "7832dd19 sldi.w w20, w27[2]");
COMPARE(sldi_d(w4, w12, 0), "78386119 sldi.d w4, w12[0]");
COMPARE(splati_b(w25, w3, 2), "78421e59 splati.b w25, w3[2]");
COMPARE(splati_h(w24, w28, 1), "7861e619 splati.h w24, w28[1]");
COMPARE(splati_w(w13, w18, 0), "78709359 splati.w w13, w18[0]");
COMPARE(splati_d(w28, w1, 0), "78780f19 splati.d w28, w1[0]");
COMPARE(move_v(w23, w24), "78bec5d9 move.v w23, w24");
COMPARE(insert_b(w23, 3, sp), "7903edd9 insert.b w23[3], sp");
COMPARE(insert_h(w20, 2, a1), "79222d19 insert.h w20[2], a1");
COMPARE(insert_w(w8, 2, s0), "79328219 insert.w w8[2], s0");
COMPARE(insert_d(w1, 1, sp), "7939e859 insert.d w1[1], sp");
COMPARE(insve_b(w25, 3, w9), "79434e59 insve.b w25[3], w9[0]");
COMPARE(insve_h(w24, 2, w2), "79621619 insve.h w24[2], w2[0]");
COMPARE(insve_w(w0, 2, w13), "79726819 insve.w w0[2], w13[0]");
COMPARE(insve_d(w3, 0, w18), "797890d9 insve.d w3[0], w18[0]");
COMPARE(cfcmsa(at, MSAIR), "787e0059 cfcmsa at, MSAIR");
COMPARE(cfcmsa(v0, MSACSR), "787e0899 cfcmsa v0, MSACSR");
COMPARE(ctcmsa(MSAIR, at), "783e0819 ctcmsa MSAIR, at");
COMPARE(ctcmsa(MSACSR, v0), "783e1059 ctcmsa MSACSR, v0");
}
VERIFY_RUN();
}
TEST(MSA_BIT) {
SET_UP();
if ((kArchVariant == kMips64r6) && CpuFeatures::IsSupported(MIPS_SIMD)) {
CpuFeatureScope fscope(&assm, MIPS_SIMD);
COMPARE(bclri_b(w21, w30, 2), "79f2f549 bclri.b w21, w30, 2");
COMPARE(bclri_h(w24, w21, 0), "79e0ae09 bclri.h w24, w21, 0");
COMPARE(bclri_w(w23, w30, 3), "79c3f5c9 bclri.w w23, w30, 3");
COMPARE(bclri_d(w9, w11, 0), "79805a49 bclri.d w9, w11, 0");
COMPARE(binsli_b(w25, w12, 1), "7b716649 binsli.b w25, w12, 1");
COMPARE(binsli_h(w21, w22, 0), "7b60b549 binsli.h w21, w22, 0");
COMPARE(binsli_w(w22, w4, 0), "7b402589 binsli.w w22, w4, 0");
COMPARE(binsli_d(w6, w2, 6), "7b061189 binsli.d w6, w2, 6");
COMPARE(binsri_b(w15, w19, 0), "7bf09bc9 binsri.b w15, w19, 0");
COMPARE(binsri_h(w8, w30, 1), "7be1f209 binsri.h w8, w30, 1");
COMPARE(binsri_w(w2, w19, 5), "7bc59889 binsri.w w2, w19, 5");
COMPARE(binsri_d(w18, w20, 1), "7b81a489 binsri.d w18, w20, 1");
COMPARE(bnegi_b(w24, w19, 0), "7af09e09 bnegi.b w24, w19, 0");
COMPARE(bnegi_h(w28, w11, 3), "7ae35f09 bnegi.h w28, w11, 3");
COMPARE(bnegi_w(w1, w27, 5), "7ac5d849 bnegi.w w1, w27, 5");
COMPARE(bnegi_d(w4, w21, 1), "7a81a909 bnegi.d w4, w21, 1");
COMPARE(bseti_b(w18, w8, 0), "7a704489 bseti.b w18, w8, 0");
COMPARE(bseti_h(w24, w14, 2), "7a627609 bseti.h w24, w14, 2");
COMPARE(bseti_w(w9, w18, 4), "7a449249 bseti.w w9, w18, 4");
COMPARE(bseti_d(w7, w15, 1), "7a0179c9 bseti.d w7, w15, 1");
COMPARE(sat_s_b(w31, w31, 2), "7872ffca sat_s.b w31, w31, 2");
COMPARE(sat_s_h(w19, w19, 0), "78609cca sat_s.h w19, w19, 0");
COMPARE(sat_s_w(w19, w29, 0), "7840ecca sat_s.w w19, w29, 0");
COMPARE(sat_s_d(w11, w22, 0), "7800b2ca sat_s.d w11, w22, 0");
COMPARE(sat_u_b(w1, w13, 3), "78f3684a sat_u.b w1, w13, 3");
COMPARE(sat_u_h(w30, w24, 4), "78e4c78a sat_u.h w30, w24, 4");
COMPARE(sat_u_w(w31, w13, 0), "78c06fca sat_u.w w31, w13, 0");
COMPARE(sat_u_d(w29, w16, 5), "7885874a sat_u.d w29, w16, 5");
COMPARE(slli_b(w23, w10, 1), "787155c9 slli.b w23, w10, 1");
COMPARE(slli_h(w9, w18, 1), "78619249 slli.h w9, w18, 1");
COMPARE(slli_w(w11, w29, 4), "7844eac9 slli.w w11, w29, 4");
COMPARE(slli_d(w25, w20, 1), "7801a649 slli.d w25, w20, 1");
COMPARE(srai_b(w24, w29, 1), "78f1ee09 srai.b w24, w29, 1");
COMPARE(srai_h(w1, w6, 0), "78e03049 srai.h w1, w6, 0");
COMPARE(srai_w(w7, w26, 1), "78c1d1c9 srai.w w7, w26, 1");
COMPARE(srai_d(w20, w25, 3), "7883cd09 srai.d w20, w25, 3");
COMPARE(srari_b(w5, w25, 0), "7970c94a srari.b w5, w25, 0");
COMPARE(srari_h(w7, w6, 4), "796431ca srari.h w7, w6, 4");
COMPARE(srari_w(w17, w11, 5), "79455c4a srari.w w17, w11, 5");
COMPARE(srari_d(w21, w25, 5), "7905cd4a srari.d w21, w25, 5");
COMPARE(srli_b(w2, w0, 2), "79720089 srli.b w2, w0, 2");
COMPARE(srli_h(w31, w31, 2), "7962ffc9 srli.h w31, w31, 2");
COMPARE(srli_w(w5, w9, 4), "79444949 srli.w w5, w9, 4");
COMPARE(srli_d(w27, w26, 5), "7905d6c9 srli.d w27, w26, 5");
COMPARE(srlri_b(w18, w3, 0), "79f01c8a srlri.b w18, w3, 0");
COMPARE(srlri_h(w1, w2, 3), "79e3104a srlri.h w1, w2, 3");
COMPARE(srlri_w(w11, w22, 2), "79c2b2ca srlri.w w11, w22, 2");
COMPARE(srlri_d(w24, w10, 6), "7986560a srlri.d w24, w10, 6");
}
VERIFY_RUN();
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment