Commit 874c54e0 authored by Djordje.Pesic's avatar Djordje.Pesic Committed by Commit bot

MIPS: Add float instructions and test coverage, part two

Implement assembler, disassembler tests for all instructions for mips32 and mips64. Additionally, add missing single precision float instructions for r2 and r6 architecture variants in assembler, simulator and disassembler with corresponding tests.

Review URL: https://codereview.chromium.org/1145223002

Cr-Commit-Position: refs/heads/master@{#28595}
parent aff8ebb0
...@@ -1936,6 +1936,12 @@ void Assembler::ext_(Register rt, Register rs, uint16_t pos, uint16_t size) { ...@@ -1936,6 +1936,12 @@ void Assembler::ext_(Register rt, Register rs, uint16_t pos, uint16_t size) {
} }
void Assembler::bitswap(Register rd, Register rt) {
DCHECK(kArchVariant == kMips32r6);
GenInstrRegister(SPECIAL3, zero_reg, rt, rd, 0, BITSWAP);
}
void Assembler::pref(int32_t hint, const MemOperand& rs) { void Assembler::pref(int32_t hint, const MemOperand& rs) {
DCHECK(!IsMipsArchVariant(kLoongson)); DCHECK(!IsMipsArchVariant(kLoongson));
DCHECK(is_uint5(hint) && is_uint16(rs.offset_)); DCHECK(is_uint5(hint) && is_uint16(rs.offset_));
...@@ -2422,6 +2428,18 @@ void Assembler::ceil_l_d(FPURegister fd, FPURegister fs) { ...@@ -2422,6 +2428,18 @@ void Assembler::ceil_l_d(FPURegister fd, FPURegister fs) {
} }
void Assembler::class_s(FPURegister fd, FPURegister fs) {
DCHECK(IsMipsArchVariant(kMips32r6));
GenInstrRegister(COP1, S, f0, fs, fd, CLASS_S);
}
void Assembler::class_d(FPURegister fd, FPURegister fs) {
DCHECK(IsMipsArchVariant(kMips32r6));
GenInstrRegister(COP1, D, f0, fs, fd, CLASS_D);
}
void Assembler::min(SecondaryField fmt, FPURegister fd, FPURegister fs, void Assembler::min(SecondaryField fmt, FPURegister fd, FPURegister fs,
FPURegister ft) { FPURegister ft) {
DCHECK(IsMipsArchVariant(kMips32r6)); DCHECK(IsMipsArchVariant(kMips32r6));
...@@ -2500,7 +2518,7 @@ void Assembler::cvt_s_w(FPURegister fd, FPURegister fs) { ...@@ -2500,7 +2518,7 @@ void Assembler::cvt_s_w(FPURegister fd, FPURegister fs) {
void Assembler::cvt_s_l(FPURegister fd, FPURegister fs) { void Assembler::cvt_s_l(FPURegister fd, FPURegister fs) {
DCHECK(IsMipsArchVariant(kMips32r2)); DCHECK(IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6));
GenInstrRegister(COP1, L, f0, fs, fd, CVT_S_L); GenInstrRegister(COP1, L, f0, fs, fd, CVT_S_L);
} }
...@@ -2537,6 +2555,17 @@ void Assembler::cmp(FPUCondition cond, SecondaryField fmt, ...@@ -2537,6 +2555,17 @@ void Assembler::cmp(FPUCondition cond, SecondaryField fmt,
} }
void Assembler::cmp_s(FPUCondition cond, FPURegister fd, FPURegister fs,
FPURegister ft) {
cmp(cond, W, fd, fs, ft);
}
void Assembler::cmp_d(FPUCondition cond, FPURegister fd, FPURegister fs,
FPURegister ft) {
cmp(cond, L, fd, fs, ft);
}
void Assembler::bc1eqz(int16_t offset, FPURegister ft) { void Assembler::bc1eqz(int16_t offset, FPURegister ft) {
DCHECK(IsMipsArchVariant(kMips32r6)); DCHECK(IsMipsArchVariant(kMips32r6));
Instr instr = COP1 | BC1EQZ | ft.code() << kFtShift | (offset & kImm16Mask); Instr instr = COP1 | BC1EQZ | ft.code() << kFtShift | (offset & kImm16Mask);
...@@ -2555,6 +2584,7 @@ void Assembler::bc1nez(int16_t offset, FPURegister ft) { ...@@ -2555,6 +2584,7 @@ void Assembler::bc1nez(int16_t offset, FPURegister ft) {
void Assembler::c(FPUCondition cond, SecondaryField fmt, void Assembler::c(FPUCondition cond, SecondaryField fmt,
FPURegister fs, FPURegister ft, uint16_t cc) { FPURegister fs, FPURegister ft, uint16_t cc) {
DCHECK(is_uint3(cc)); DCHECK(is_uint3(cc));
DCHECK(fmt == S || fmt == D);
DCHECK((fmt & ~(31 << kRsShift)) == 0); DCHECK((fmt & ~(31 << kRsShift)) == 0);
Instr instr = COP1 | fmt | ft.code() << 16 | fs.code() << kFsShift Instr instr = COP1 | fmt | ft.code() << 16 | fs.code() << kFsShift
| cc << 8 | 3 << 4 | cond; | cc << 8 | 3 << 4 | cond;
...@@ -2562,6 +2592,18 @@ void Assembler::c(FPUCondition cond, SecondaryField fmt, ...@@ -2562,6 +2592,18 @@ void Assembler::c(FPUCondition cond, SecondaryField fmt,
} }
void Assembler::c_s(FPUCondition cond, FPURegister fs, FPURegister ft,
uint16_t cc) {
c(cond, S, fs, ft, cc);
}
void Assembler::c_d(FPUCondition cond, FPURegister fs, FPURegister ft,
uint16_t cc) {
c(cond, D, fs, ft, cc);
}
void Assembler::fcmp(FPURegister src1, const double src2, void Assembler::fcmp(FPURegister src1, const double src2,
FPUCondition cond) { FPUCondition cond) {
DCHECK(src2 == 0.0); DCHECK(src2 == 0.0);
......
...@@ -878,6 +878,7 @@ class Assembler : public AssemblerBase { ...@@ -878,6 +878,7 @@ class Assembler : public AssemblerBase {
void clz(Register rd, Register rs); void clz(Register rd, Register rs);
void ins_(Register rt, Register rs, uint16_t pos, uint16_t size); void ins_(Register rt, Register rs, uint16_t pos, uint16_t size);
void ext_(Register rt, Register rs, uint16_t pos, uint16_t size); void ext_(Register rt, Register rs, uint16_t pos, uint16_t size);
void bitswap(Register rd, Register rt);
// --------Coprocessor-instructions---------------- // --------Coprocessor-instructions----------------
...@@ -946,6 +947,9 @@ class Assembler : public AssemblerBase { ...@@ -946,6 +947,9 @@ class Assembler : public AssemblerBase {
void ceil_l_s(FPURegister fd, FPURegister fs); void ceil_l_s(FPURegister fd, FPURegister fs);
void ceil_l_d(FPURegister fd, FPURegister fs); void ceil_l_d(FPURegister fd, FPURegister fs);
void class_s(FPURegister fd, FPURegister fs);
void class_d(FPURegister fd, FPURegister fs);
void min(SecondaryField fmt, FPURegister fd, FPURegister fs, FPURegister ft); void min(SecondaryField fmt, FPURegister fd, FPURegister fs, FPURegister ft);
void mina(SecondaryField fmt, FPURegister fd, FPURegister fs, FPURegister ft); void mina(SecondaryField fmt, FPURegister fd, FPURegister fs, FPURegister ft);
void max(SecondaryField fmt, FPURegister fd, FPURegister fs, FPURegister ft); void max(SecondaryField fmt, FPURegister fd, FPURegister fs, FPURegister ft);
...@@ -970,6 +974,8 @@ class Assembler : public AssemblerBase { ...@@ -970,6 +974,8 @@ class Assembler : public AssemblerBase {
// Conditions and branches for MIPSr6. // Conditions and branches for MIPSr6.
void cmp(FPUCondition cond, SecondaryField fmt, void cmp(FPUCondition cond, SecondaryField fmt,
FPURegister fd, FPURegister ft, FPURegister fs); FPURegister fd, FPURegister ft, FPURegister fs);
void cmp_s(FPUCondition cond, FPURegister fd, FPURegister fs, FPURegister ft);
void cmp_d(FPUCondition cond, FPURegister fd, FPURegister fs, FPURegister ft);
void bc1eqz(int16_t offset, FPURegister ft); void bc1eqz(int16_t offset, FPURegister ft);
void bc1eqz(Label* L, FPURegister ft) { void bc1eqz(Label* L, FPURegister ft) {
...@@ -983,6 +989,8 @@ class Assembler : public AssemblerBase { ...@@ -983,6 +989,8 @@ class Assembler : public AssemblerBase {
// Conditions and branches for non MIPSr6. // Conditions and branches for non MIPSr6.
void c(FPUCondition cond, SecondaryField fmt, void c(FPUCondition cond, SecondaryField fmt,
FPURegister ft, FPURegister fs, uint16_t cc = 0); FPURegister ft, FPURegister fs, uint16_t cc = 0);
void c_s(FPUCondition cond, FPURegister ft, FPURegister fs, uint16_t cc = 0);
void c_d(FPUCondition cond, FPURegister ft, FPURegister fs, uint16_t cc = 0);
void bc1f(int16_t offset, uint16_t cc = 0); void bc1f(int16_t offset, uint16_t cc = 0);
void bc1f(Label* L, uint16_t cc = 0) { bc1f(branch_offset(L, false)>>2, cc); } void bc1f(Label* L, uint16_t cc = 0) { bc1f(branch_offset(L, false)>>2, cc); }
......
...@@ -272,6 +272,7 @@ Instruction::Type Instruction::InstructionType() const { ...@@ -272,6 +272,7 @@ Instruction::Type Instruction::InstructionType() const {
switch (FunctionFieldRaw()) { switch (FunctionFieldRaw()) {
case INS: case INS:
case EXT: case EXT:
case BITSWAP:
return kRegisterType; return kRegisterType;
default: default:
return kUnsupported; return kUnsupported;
......
...@@ -435,6 +435,7 @@ enum SecondaryField { ...@@ -435,6 +435,7 @@ enum SecondaryField {
// SPECIAL3 Encoding of Function Field. // SPECIAL3 Encoding of Function Field.
EXT = ((0 << 3) + 0), EXT = ((0 << 3) + 0),
INS = ((0 << 3) + 4), INS = ((0 << 3) + 4),
BITSWAP = ((4 << 3) + 0),
// REGIMM encoding of rt Field. // REGIMM encoding of rt Field.
BLTZ = ((0 << 3) + 0) << 16, BLTZ = ((0 << 3) + 0) << 16,
...@@ -457,6 +458,7 @@ enum SecondaryField { ...@@ -457,6 +458,7 @@ enum SecondaryField {
L = ((2 << 3) + 5) << 21, L = ((2 << 3) + 5) << 21,
PS = ((2 << 3) + 6) << 21, PS = ((2 << 3) + 6) << 21,
// COP1 Encoding of Function Field When rs=S. // COP1 Encoding of Function Field When rs=S.
ADD_S = ((0 << 3) + 0), ADD_S = ((0 << 3) + 0),
SUB_S = ((0 << 3) + 1), SUB_S = ((0 << 3) + 1),
MUL_S = ((0 << 3) + 2), MUL_S = ((0 << 3) + 2),
...@@ -475,10 +477,12 @@ enum SecondaryField { ...@@ -475,10 +477,12 @@ enum SecondaryField {
FLOOR_W_S = ((1 << 3) + 7), FLOOR_W_S = ((1 << 3) + 7),
RECIP_S = ((2 << 3) + 5), RECIP_S = ((2 << 3) + 5),
RSQRT_S = ((2 << 3) + 6), RSQRT_S = ((2 << 3) + 6),
CLASS_S = ((3 << 3) + 3),
CVT_D_S = ((4 << 3) + 1), CVT_D_S = ((4 << 3) + 1),
CVT_W_S = ((4 << 3) + 4), CVT_W_S = ((4 << 3) + 4),
CVT_L_S = ((4 << 3) + 5), CVT_L_S = ((4 << 3) + 5),
CVT_PS_S = ((4 << 3) + 6), CVT_PS_S = ((4 << 3) + 6),
// COP1 Encoding of Function Field When rs=D. // COP1 Encoding of Function Field When rs=D.
ADD_D = ((0 << 3) + 0), ADD_D = ((0 << 3) + 0),
SUB_D = ((0 << 3) + 1), SUB_D = ((0 << 3) + 1),
...@@ -498,6 +502,11 @@ enum SecondaryField { ...@@ -498,6 +502,11 @@ enum SecondaryField {
FLOOR_W_D = ((1 << 3) + 7), FLOOR_W_D = ((1 << 3) + 7),
RECIP_D = ((2 << 3) + 5), RECIP_D = ((2 << 3) + 5),
RSQRT_D = ((2 << 3) + 6), RSQRT_D = ((2 << 3) + 6),
CLASS_D = ((3 << 3) + 3),
MIN = ((3 << 3) + 4),
MINA = ((3 << 3) + 5),
MAX = ((3 << 3) + 6),
MAXA = ((3 << 3) + 7),
CVT_S_D = ((4 << 3) + 0), CVT_S_D = ((4 << 3) + 0),
CVT_W_D = ((4 << 3) + 4), CVT_W_D = ((4 << 3) + 4),
CVT_L_D = ((4 << 3) + 5), CVT_L_D = ((4 << 3) + 5),
...@@ -509,6 +518,7 @@ enum SecondaryField { ...@@ -509,6 +518,7 @@ enum SecondaryField {
C_ULT_D = ((6 << 3) + 5), C_ULT_D = ((6 << 3) + 5),
C_OLE_D = ((6 << 3) + 6), C_OLE_D = ((6 << 3) + 6),
C_ULE_D = ((6 << 3) + 7), C_ULE_D = ((6 << 3) + 7),
// COP1 Encoding of Function Field When rs=W or L. // COP1 Encoding of Function Field When rs=W or L.
CVT_S_W = ((4 << 3) + 0), CVT_S_W = ((4 << 3) + 0),
CVT_D_W = ((4 << 3) + 1), CVT_D_W = ((4 << 3) + 1),
...@@ -551,10 +561,6 @@ enum SecondaryField { ...@@ -551,10 +561,6 @@ enum SecondaryField {
CMP_SUGT = ((3 << 3) + 6), // Reserved, not implemented. CMP_SUGT = ((3 << 3) + 6), // Reserved, not implemented.
CMP_SOGT = ((3 << 3) + 7), // Reserved, not implemented. CMP_SOGT = ((3 << 3) + 7), // Reserved, not implemented.
MIN = ((3 << 3) + 4),
MINA = ((3 << 3) + 5),
MAX = ((3 << 3) + 6),
MAXA = ((3 << 3) + 7),
SEL = ((2 << 3) + 0), SEL = ((2 << 3) + 0),
MOVZ_C = ((2 << 3) + 2), MOVZ_C = ((2 << 3) + 2),
MOVN_C = ((2 << 3) + 3), MOVN_C = ((2 << 3) + 3),
...@@ -698,14 +704,21 @@ inline Condition CommuteCondition(Condition cc) { ...@@ -698,14 +704,21 @@ inline Condition CommuteCondition(Condition cc) {
enum FPUCondition { enum FPUCondition {
kNoFPUCondition = -1, kNoFPUCondition = -1,
F = 0, // False. F = 0x00, // False.
UN = 1, // Unordered. UN = 0x01, // Unordered.
EQ = 2, // Equal. EQ = 0x02, // Equal.
UEQ = 3, // Unordered or Equal. UEQ = 0x03, // Unordered or Equal.
OLT = 4, // Ordered or Less Than. OLT = 0x04, // Ordered or Less Than, on Mips release < 6.
ULT = 5, // Unordered or Less Than. LT = 0x04, // Ordered or Less Than, on Mips release >= 6.
OLE = 6, // Ordered or Less Than or Equal. ULT = 0x05, // Unordered or Less Than.
ULE = 7 // Unordered or Less Than or Equal. OLE = 0x06, // Ordered or Less Than or Equal, on Mips release < 6.
LE = 0x06, // Ordered or Less Than or Equal, on Mips release >= 6.
ULE = 0x07, // Unordered or Less Than or Equal.
// Following constants are available on Mips release >= 6 only.
ORD = 0x11, // Ordered, on Mips release >= 6.
UNE = 0x12, // Not equal, on Mips release >= 6.
NE = 0x13, // Ordered Greater Than or Less Than. on Mips >= 6 only.
}; };
......
...@@ -581,6 +581,9 @@ bool Decoder::DecodeTypeRegisterRsType(Instruction* instr) { ...@@ -581,6 +581,9 @@ bool Decoder::DecodeTypeRegisterRsType(Instruction* instr) {
case CEIL_W_D: case CEIL_W_D:
Format(instr, "ceil.w.'t 'fd, 'fs"); Format(instr, "ceil.w.'t 'fd, 'fs");
break; break;
case CLASS_D:
Format(instr, "class.'t 'fd, 'fs");
break;
case CEIL_L_D: case CEIL_L_D:
Format(instr, "ceil.l.'t 'fd, 'fs"); Format(instr, "ceil.l.'t 'fd, 'fs");
break; break;
...@@ -647,6 +650,9 @@ void Decoder::DecodeTypeRegisterLRsType(Instruction* instr) { ...@@ -647,6 +650,9 @@ void Decoder::DecodeTypeRegisterLRsType(Instruction* instr) {
case CVT_S_L: case CVT_S_L:
Format(instr, "cvt.s.l 'fd, 'fs"); Format(instr, "cvt.s.l 'fd, 'fs");
break; break;
case CMP_AF:
Format(instr, "cmp.af.d 'fd, 'fs, 'ft");
break;
case CMP_UN: case CMP_UN:
Format(instr, "cmp.un.d 'fd, 'fs, 'ft"); Format(instr, "cmp.un.d 'fd, 'fs, 'ft");
break; break;
...@@ -950,6 +956,14 @@ void Decoder::DecodeTypeRegisterSPECIAL3(Instruction* instr) { ...@@ -950,6 +956,14 @@ void Decoder::DecodeTypeRegisterSPECIAL3(Instruction* instr) {
} }
break; break;
} }
case BITSWAP: {
if (IsMipsArchVariant(kMips32r6)) {
Format(instr, "bitswap 'rd, 'rt");
} else {
Unknown(instr);
}
break;
}
default: default:
UNREACHABLE(); UNREACHABLE();
} }
......
This diff is collapsed.
...@@ -183,6 +183,12 @@ class Simulator { ...@@ -183,6 +183,12 @@ class Simulator {
bool set_fcsr_round64_error(float original, float rounded); bool set_fcsr_round64_error(float original, float rounded);
void round_according_to_fcsr(double toRound, double& rounded, void round_according_to_fcsr(double toRound, double& rounded,
int32_t& rounded_int, double fs); int32_t& rounded_int, double fs);
void round_according_to_fcsr(float toRound, float& rounded,
int32_t& rounded_int, float fs);
void round64_according_to_fcsr(double toRound, double& rounded,
int64_t& rounded_int, double fs);
void round64_according_to_fcsr(float toRound, float& rounded,
int64_t& rounded_int, float fs);
// Special case of set_register and get_register to access the raw PC value. // Special case of set_register and get_register to access the raw PC value.
void set_pc(int32_t value); void set_pc(int32_t value);
int32_t get_pc() const; int32_t get_pc() const;
...@@ -278,7 +284,8 @@ class Simulator { ...@@ -278,7 +284,8 @@ class Simulator {
const int32_t& fs_reg, const int32_t& ft_reg, const int32_t& fs_reg, const int32_t& ft_reg,
const int32_t& fd_reg); const int32_t& fd_reg);
void DecodeTypeRegisterWRsType(Instruction* instr, int32_t& alu_out, void DecodeTypeRegisterWRsType(Instruction* instr, int32_t& alu_out,
const int32_t& fd_reg, const int32_t& fs_reg); const int32_t& fd_reg, const int32_t& fs_reg,
const int32_t& ft_reg);
void DecodeTypeRegisterSRsType(Instruction* instr, const int32_t& ft_reg, void DecodeTypeRegisterSRsType(Instruction* instr, const int32_t& ft_reg,
const int32_t& fs_reg, const int32_t& fd_reg); const int32_t& fs_reg, const int32_t& fd_reg);
void DecodeTypeRegisterLRsType(Instruction* instr, const int32_t& ft_reg, void DecodeTypeRegisterLRsType(Instruction* instr, const int32_t& ft_reg,
...@@ -312,7 +319,7 @@ class Simulator { ...@@ -312,7 +319,7 @@ class Simulator {
int32_t& alu_out); int32_t& alu_out);
void DecodeTypeRegisterSPECIAL3(Instruction* instr, const int32_t& rt_reg, void DecodeTypeRegisterSPECIAL3(Instruction* instr, const int32_t& rt_reg,
int32_t& alu_out); const int32_t& rd_reg, int32_t& alu_out);
// Helper function for DecodeTypeRegister. // Helper function for DecodeTypeRegister.
void ConfigureTypeRegister(Instruction* instr, void ConfigureTypeRegister(Instruction* instr,
......
...@@ -2205,6 +2205,18 @@ void Assembler::dext_(Register rt, Register rs, uint16_t pos, uint16_t size) { ...@@ -2205,6 +2205,18 @@ void Assembler::dext_(Register rt, Register rs, uint16_t pos, uint16_t size) {
} }
void Assembler::bitswap(Register rd, Register rt) {
DCHECK(kArchVariant == kMips64r6);
GenInstrRegister(SPECIAL3, zero_reg, rt, rd, 0, BITSWAP);
}
void Assembler::dbitswap(Register rd, Register rt) {
DCHECK(kArchVariant == kMips64r6);
GenInstrRegister(SPECIAL3, zero_reg, rt, rd, 0, DBITSWAP);
}
void Assembler::pref(int32_t hint, const MemOperand& rs) { void Assembler::pref(int32_t hint, const MemOperand& rs) {
DCHECK(is_uint5(hint) && is_uint16(rs.offset_)); DCHECK(is_uint5(hint) && is_uint16(rs.offset_));
Instr instr = PREF | (rs.rm().code() << kRsShift) | (hint << kRtShift) Instr instr = PREF | (rs.rm().code() << kRsShift) | (hint << kRtShift)
...@@ -2642,6 +2654,18 @@ void Assembler::ceil_l_d(FPURegister fd, FPURegister fs) { ...@@ -2642,6 +2654,18 @@ void Assembler::ceil_l_d(FPURegister fd, FPURegister fs) {
} }
void Assembler::class_s(FPURegister fd, FPURegister fs) {
DCHECK(kArchVariant == kMips64r6);
GenInstrRegister(COP1, S, f0, fs, fd, CLASS_S);
}
void Assembler::class_d(FPURegister fd, FPURegister fs) {
DCHECK(kArchVariant == kMips64r6);
GenInstrRegister(COP1, D, f0, fs, fd, CLASS_D);
}
void Assembler::mina(SecondaryField fmt, FPURegister fd, FPURegister fs, void Assembler::mina(SecondaryField fmt, FPURegister fd, FPURegister fs,
FPURegister ft) { FPURegister ft) {
DCHECK(kArchVariant == kMips64r6); DCHECK(kArchVariant == kMips64r6);
...@@ -2701,6 +2725,17 @@ void Assembler::cmp(FPUCondition cond, SecondaryField fmt, ...@@ -2701,6 +2725,17 @@ void Assembler::cmp(FPUCondition cond, SecondaryField fmt,
} }
void Assembler::cmp_s(FPUCondition cond, FPURegister fd, FPURegister fs,
FPURegister ft) {
cmp(cond, W, fd, fs, ft);
}
void Assembler::cmp_d(FPUCondition cond, FPURegister fd, FPURegister fs,
FPURegister ft) {
cmp(cond, L, fd, fs, ft);
}
void Assembler::bc1eqz(int16_t offset, FPURegister ft) { void Assembler::bc1eqz(int16_t offset, FPURegister ft) {
DCHECK(kArchVariant == kMips64r6); DCHECK(kArchVariant == kMips64r6);
Instr instr = COP1 | BC1EQZ | ft.code() << kFtShift | (offset & kImm16Mask); Instr instr = COP1 | BC1EQZ | ft.code() << kFtShift | (offset & kImm16Mask);
...@@ -2728,6 +2763,18 @@ void Assembler::c(FPUCondition cond, SecondaryField fmt, ...@@ -2728,6 +2763,18 @@ void Assembler::c(FPUCondition cond, SecondaryField fmt,
} }
void Assembler::c_s(FPUCondition cond, FPURegister fs, FPURegister ft,
uint16_t cc) {
c(cond, S, fs, ft, cc);
}
void Assembler::c_d(FPUCondition cond, FPURegister fs, FPURegister ft,
uint16_t cc) {
c(cond, D, fs, ft, cc);
}
void Assembler::fcmp(FPURegister src1, const double src2, void Assembler::fcmp(FPURegister src1, const double src2,
FPUCondition cond) { FPUCondition cond) {
DCHECK(src2 == 0.0); DCHECK(src2 == 0.0);
......
...@@ -907,6 +907,8 @@ class Assembler : public AssemblerBase { ...@@ -907,6 +907,8 @@ class Assembler : public AssemblerBase {
void ins_(Register rt, Register rs, uint16_t pos, uint16_t size); void ins_(Register rt, Register rs, uint16_t pos, uint16_t size);
void ext_(Register rt, Register rs, uint16_t pos, uint16_t size); void ext_(Register rt, Register rs, uint16_t pos, uint16_t size);
void dext_(Register rt, Register rs, uint16_t pos, uint16_t size); void dext_(Register rt, Register rs, uint16_t pos, uint16_t size);
void bitswap(Register rd, Register rt);
void dbitswap(Register rd, Register rt);
// --------Coprocessor-instructions---------------- // --------Coprocessor-instructions----------------
...@@ -978,6 +980,9 @@ class Assembler : public AssemblerBase { ...@@ -978,6 +980,9 @@ class Assembler : public AssemblerBase {
void ceil_l_s(FPURegister fd, FPURegister fs); void ceil_l_s(FPURegister fd, FPURegister fs);
void ceil_l_d(FPURegister fd, FPURegister fs); void ceil_l_d(FPURegister fd, FPURegister fs);
void class_s(FPURegister fd, FPURegister fs);
void class_d(FPURegister fd, FPURegister fs);
void min(SecondaryField fmt, FPURegister fd, FPURegister fs, FPURegister ft); void min(SecondaryField fmt, FPURegister fd, FPURegister fs, FPURegister ft);
void mina(SecondaryField fmt, FPURegister fd, FPURegister fs, FPURegister ft); void mina(SecondaryField fmt, FPURegister fd, FPURegister fs, FPURegister ft);
void max(SecondaryField fmt, FPURegister fd, FPURegister fs, FPURegister ft); void max(SecondaryField fmt, FPURegister fd, FPURegister fs, FPURegister ft);
...@@ -1002,6 +1007,8 @@ class Assembler : public AssemblerBase { ...@@ -1002,6 +1007,8 @@ class Assembler : public AssemblerBase {
// Conditions and branches for MIPSr6. // Conditions and branches for MIPSr6.
void cmp(FPUCondition cond, SecondaryField fmt, void cmp(FPUCondition cond, SecondaryField fmt,
FPURegister fd, FPURegister ft, FPURegister fs); FPURegister fd, FPURegister ft, FPURegister fs);
void cmp_s(FPUCondition cond, FPURegister fd, FPURegister fs, FPURegister ft);
void cmp_d(FPUCondition cond, FPURegister fd, FPURegister fs, FPURegister ft);
void bc1eqz(int16_t offset, FPURegister ft); void bc1eqz(int16_t offset, FPURegister ft);
void bc1eqz(Label* L, FPURegister ft) { void bc1eqz(Label* L, FPURegister ft) {
...@@ -1015,6 +1022,8 @@ class Assembler : public AssemblerBase { ...@@ -1015,6 +1022,8 @@ class Assembler : public AssemblerBase {
// Conditions and branches for non MIPSr6. // Conditions and branches for non MIPSr6.
void c(FPUCondition cond, SecondaryField fmt, void c(FPUCondition cond, SecondaryField fmt,
FPURegister ft, FPURegister fs, uint16_t cc = 0); FPURegister ft, FPURegister fs, uint16_t cc = 0);
void c_s(FPUCondition cond, FPURegister ft, FPURegister fs, uint16_t cc = 0);
void c_d(FPUCondition cond, FPURegister ft, FPURegister fs, uint16_t cc = 0);
void bc1f(int16_t offset, uint16_t cc = 0); void bc1f(int16_t offset, uint16_t cc = 0);
void bc1f(Label* L, uint16_t cc = 0) { void bc1f(Label* L, uint16_t cc = 0) {
......
...@@ -290,6 +290,8 @@ Instruction::Type Instruction::InstructionType() const { ...@@ -290,6 +290,8 @@ Instruction::Type Instruction::InstructionType() const {
case INS: case INS:
case EXT: case EXT:
case DEXT: case DEXT:
case BITSWAP:
case DBITSWAP:
return kRegisterType; return kRegisterType;
default: default:
return kUnsupported; return kUnsupported;
......
...@@ -443,8 +443,13 @@ enum SecondaryField { ...@@ -443,8 +443,13 @@ enum SecondaryField {
DINSU = ((0 << 3) + 6), DINSU = ((0 << 3) + 6),
DINS = ((0 << 3) + 7), DINS = ((0 << 3) + 7),
BITSWAP = ((4 << 3) + 0),
DBITSWAP = ((4 << 3) + 4),
DSBH = ((4 << 3) + 4), DSBH = ((4 << 3) + 4),
// SPECIAL3 Encoding of sa Field.
DBITSWAP_SA = ((0 << 3) + 0) << kSaShift,
// REGIMM encoding of rt Field. // REGIMM encoding of rt Field.
BLTZ = ((0 << 3) + 0) << 16, BLTZ = ((0 << 3) + 0) << 16,
BGEZ = ((0 << 3) + 1) << 16, BGEZ = ((0 << 3) + 1) << 16,
...@@ -470,6 +475,7 @@ enum SecondaryField { ...@@ -470,6 +475,7 @@ enum SecondaryField {
L = ((2 << 3) + 5) << 21, L = ((2 << 3) + 5) << 21,
PS = ((2 << 3) + 6) << 21, PS = ((2 << 3) + 6) << 21,
// COP1 Encoding of Function Field When rs=S. // COP1 Encoding of Function Field When rs=S.
ADD_S = ((0 << 3) + 0), ADD_S = ((0 << 3) + 0),
SUB_S = ((0 << 3) + 1), SUB_S = ((0 << 3) + 1),
MUL_S = ((0 << 3) + 2), MUL_S = ((0 << 3) + 2),
...@@ -488,6 +494,7 @@ enum SecondaryField { ...@@ -488,6 +494,7 @@ enum SecondaryField {
FLOOR_W_S = ((1 << 3) + 7), FLOOR_W_S = ((1 << 3) + 7),
RECIP_S = ((2 << 3) + 5), RECIP_S = ((2 << 3) + 5),
RSQRT_S = ((2 << 3) + 6), RSQRT_S = ((2 << 3) + 6),
CLASS_S = ((3 << 3) + 3),
CVT_D_S = ((4 << 3) + 1), CVT_D_S = ((4 << 3) + 1),
CVT_W_S = ((4 << 3) + 4), CVT_W_S = ((4 << 3) + 4),
CVT_L_S = ((4 << 3) + 5), CVT_L_S = ((4 << 3) + 5),
...@@ -511,6 +518,11 @@ enum SecondaryField { ...@@ -511,6 +518,11 @@ enum SecondaryField {
FLOOR_W_D = ((1 << 3) + 7), FLOOR_W_D = ((1 << 3) + 7),
RECIP_D = ((2 << 3) + 5), RECIP_D = ((2 << 3) + 5),
RSQRT_D = ((2 << 3) + 6), RSQRT_D = ((2 << 3) + 6),
CLASS_D = ((3 << 3) + 3),
MIN = ((3 << 3) + 4),
MINA = ((3 << 3) + 5),
MAX = ((3 << 3) + 6),
MAXA = ((3 << 3) + 7),
CVT_S_D = ((4 << 3) + 0), CVT_S_D = ((4 << 3) + 0),
CVT_W_D = ((4 << 3) + 4), CVT_W_D = ((4 << 3) + 4),
CVT_L_D = ((4 << 3) + 5), CVT_L_D = ((4 << 3) + 5),
...@@ -522,6 +534,7 @@ enum SecondaryField { ...@@ -522,6 +534,7 @@ enum SecondaryField {
C_ULT_D = ((6 << 3) + 5), C_ULT_D = ((6 << 3) + 5),
C_OLE_D = ((6 << 3) + 6), C_OLE_D = ((6 << 3) + 6),
C_ULE_D = ((6 << 3) + 7), C_ULE_D = ((6 << 3) + 7),
// COP1 Encoding of Function Field When rs=W or L. // COP1 Encoding of Function Field When rs=W or L.
CVT_S_W = ((4 << 3) + 0), CVT_S_W = ((4 << 3) + 0),
CVT_D_W = ((4 << 3) + 1), CVT_D_W = ((4 << 3) + 1),
...@@ -564,10 +577,6 @@ enum SecondaryField { ...@@ -564,10 +577,6 @@ enum SecondaryField {
CMP_SUGT = ((3 << 3) + 6), // Reserved, not implemented. CMP_SUGT = ((3 << 3) + 6), // Reserved, not implemented.
CMP_SOGT = ((3 << 3) + 7), // Reserved, not implemented. CMP_SOGT = ((3 << 3) + 7), // Reserved, not implemented.
MIN = ((3 << 3) + 4),
MINA = ((3 << 3) + 5),
MAX = ((3 << 3) + 6),
MAXA = ((3 << 3) + 7),
SEL = ((2 << 3) + 0), SEL = ((2 << 3) + 0),
MOVF = ((2 << 3) + 1), // Function field for MOVT.fmt and MOVF.fmt MOVF = ((2 << 3) + 1), // Function field for MOVT.fmt and MOVF.fmt
MOVZ_C = ((2 << 3) + 2), // COP1 on FPR registers. MOVZ_C = ((2 << 3) + 2), // COP1 on FPR registers.
...@@ -712,14 +721,21 @@ inline Condition CommuteCondition(Condition cc) { ...@@ -712,14 +721,21 @@ inline Condition CommuteCondition(Condition cc) {
enum FPUCondition { enum FPUCondition {
kNoFPUCondition = -1, kNoFPUCondition = -1,
F = 0, // False. F = 0x00, // False.
UN = 1, // Unordered. UN = 0x01, // Unordered.
EQ = 2, // Equal. EQ = 0x02, // Equal.
UEQ = 3, // Unordered or Equal. UEQ = 0x03, // Unordered or Equal.
OLT = 4, // Ordered or Less Than. OLT = 0x04, // Ordered or Less Than, on Mips release < 6.
ULT = 5, // Unordered or Less Than. LT = 0x04, // Ordered or Less Than, on Mips release >= 6.
OLE = 6, // Ordered or Less Than or Equal. ULT = 0x05, // Unordered or Less Than.
ULE = 7 // Unordered or Less Than or Equal. OLE = 0x06, // Ordered or Less Than or Equal, on Mips release < 6.
LE = 0x06, // Ordered or Less Than or Equal, on Mips release >= 6.
ULE = 0x07, // Unordered or Less Than or Equal.
// Following constants are available on Mips release >= 6 only.
ORD = 0x11, // Ordered, on Mips release >= 6.
UNE = 0x12, // Not equal, on Mips release >= 6.
NE = 0x13, // Ordered Greater Than or Less Than. on Mips >= 6 only.
}; };
......
...@@ -614,6 +614,9 @@ bool Decoder::DecodeTypeRegisterRsType(Instruction* instr) { ...@@ -614,6 +614,9 @@ bool Decoder::DecodeTypeRegisterRsType(Instruction* instr) {
case CEIL_L_D: case CEIL_L_D:
Format(instr, "ceil.l.'t 'fd, 'fs"); Format(instr, "ceil.l.'t 'fd, 'fs");
break; break;
case CLASS_D:
Format(instr, "class.'t 'fd, 'fs");
break;
case CVT_S_D: case CVT_S_D:
Format(instr, "cvt.s.'t 'fd, 'fs"); Format(instr, "cvt.s.'t 'fd, 'fs");
break; break;
...@@ -677,6 +680,9 @@ void Decoder::DecodeTypeRegisterLRsType(Instruction* instr) { ...@@ -677,6 +680,9 @@ void Decoder::DecodeTypeRegisterLRsType(Instruction* instr) {
case CVT_S_L: case CVT_S_L:
Format(instr, "cvt.s.l 'fd, 'fs"); Format(instr, "cvt.s.l 'fd, 'fs");
break; break;
case CMP_AF:
Format(instr, "cmp.af.d 'fd, 'fs, 'ft");
break;
case CMP_UN: case CMP_UN:
Format(instr, "cmp.un.d 'fd, 'fs, 'ft"); Format(instr, "cmp.un.d 'fd, 'fs, 'ft");
break; break;
...@@ -1129,6 +1135,20 @@ void Decoder::DecodeTypeRegisterSPECIAL3(Instruction* instr) { ...@@ -1129,6 +1135,20 @@ void Decoder::DecodeTypeRegisterSPECIAL3(Instruction* instr) {
Format(instr, "dext 'rt, 'rs, 'sa, 'ss1"); Format(instr, "dext 'rt, 'rs, 'sa, 'ss1");
break; break;
} }
case BITSWAP: {
Format(instr, "bitswap 'rd, 'rt");
break;
}
case DBITSWAP: {
switch (instr->SaFieldRaw()) {
case DBITSWAP_SA:
Format(instr, "dbitswap 'rd, 'rt");
break;
default:
UNREACHABLE();
}
break;
}
default: default:
UNREACHABLE(); UNREACHABLE();
} }
......
This diff is collapsed.
...@@ -213,6 +213,10 @@ class Simulator { ...@@ -213,6 +213,10 @@ class Simulator {
int32_t& rounded_int, double fs); int32_t& rounded_int, double fs);
void round64_according_to_fcsr(double toRound, double& rounded, void round64_according_to_fcsr(double toRound, double& rounded,
int64_t& rounded_int, double fs); int64_t& rounded_int, double fs);
void round_according_to_fcsr(float toRound, float& rounded,
int32_t& rounded_int, float fs);
void round64_according_to_fcsr(float toRound, float& rounded,
int64_t& rounded_int, float fs);
void set_fcsr_rounding_mode(FPURoundingMode mode); void set_fcsr_rounding_mode(FPURoundingMode mode);
unsigned int get_fcsr_rounding_mode(); unsigned int get_fcsr_rounding_mode();
// Special case of set_register and get_register to access the raw PC value. // Special case of set_register and get_register to access the raw PC value.
...@@ -347,7 +351,7 @@ class Simulator { ...@@ -347,7 +351,7 @@ class Simulator {
int64_t& alu_out); int64_t& alu_out);
void DecodeTypeRegisterSPECIAL3(Instruction* instr, const int64_t& rt_reg, void DecodeTypeRegisterSPECIAL3(Instruction* instr, const int64_t& rt_reg,
int64_t& alu_out); const int64_t& rd_reg, int64_t& alu_out);
void DecodeTypeRegisterSRsType(Instruction* instr, const int32_t& fs_reg, void DecodeTypeRegisterSRsType(Instruction* instr, const int32_t& fs_reg,
const int32_t& ft_reg, const int32_t& fd_reg); const int32_t& ft_reg, const int32_t& fd_reg);
...@@ -356,7 +360,8 @@ class Simulator { ...@@ -356,7 +360,8 @@ class Simulator {
const int32_t& ft_reg, const int32_t& fd_reg); const int32_t& ft_reg, const int32_t& fd_reg);
void DecodeTypeRegisterWRsType(Instruction* instr, const int32_t& fs_reg, void DecodeTypeRegisterWRsType(Instruction* instr, const int32_t& fs_reg,
const int32_t& fd_reg, int64_t& alu_out); const int32_t& ft_reg, const int32_t& fd_reg,
int64_t& alu_out);
void DecodeTypeRegisterLRsType(Instruction* instr, const int32_t& fs_reg, void DecodeTypeRegisterLRsType(Instruction* instr, const int32_t& fs_reg,
const int32_t& fd_reg, const int32_t& ft_reg); const int32_t& fd_reg, const int32_t& ft_reg);
......
This diff is collapsed.
This diff is collapsed.
...@@ -520,6 +520,19 @@ TEST(Type0) { ...@@ -520,6 +520,19 @@ TEST(Type0) {
COMPARE(ext_(v0, v1, 0, 32), COMPARE(ext_(v0, v1, 0, 32),
"7c62f800 ext v0, v1, 0, 32"); "7c62f800 ext v0, v1, 0, 32");
} }
COMPARE(add_s(f4, f6, f8), "46083100 add.s f4, f6, f8");
COMPARE(add_d(f12, f14, f16), "46307300 add.d f12, f14, f16");
if (IsMipsArchVariant(kMips32r6)) {
COMPARE(bitswap(a0, a1), "7c052020 bitswap a0, a1");
COMPARE(bitswap(t8, s0), "7c10c020 bitswap t8, s0");
}
COMPARE(abs_s(f6, f8), "46004185 abs.s f6, f8");
COMPARE(abs_d(f10, f12), "46206285 abs.d f10, f12");
COMPARE(div_s(f2, f4, f6), "46062083 div.s f2, f4, f6");
COMPARE(div_d(f2, f4, f6), "46262083 div.d f2, f4, f6");
VERIFY_RUN(); VERIFY_RUN();
} }
...@@ -616,3 +629,116 @@ TEST(Type1) { ...@@ -616,3 +629,116 @@ TEST(Type1) {
} }
VERIFY_RUN(); VERIFY_RUN();
} }
TEST(Type2) {
if (IsMipsArchVariant(kMips32r6)) {
SET_UP();
COMPARE(class_s(f3, f4), "460020db class.s f3, f4");
COMPARE(class_d(f2, f3), "4620189b class.d f2, f3");
VERIFY_RUN();
}
}
TEST(C_FMT_DISASM) {
if (IsMipsArchVariant(kMips32r1) || IsMipsArchVariant(kMips32r2)) {
SET_UP();
COMPARE(c_s(F, f8, f10, 0), "460a4030 c.f.s f8, f10, cc(0)");
COMPARE(c_d(F, f8, f10, 0), "462a4030 c.f.d f8, f10, cc(0)");
COMPARE(c_s(UN, f8, f10, 2), "460a4231 c.un.s f8, f10, cc(2)");
COMPARE(c_d(UN, f8, f10, 2), "462a4231 c.un.d f8, f10, cc(2)");
COMPARE(c_s(EQ, f8, f10, 4), "460a4432 c.eq.s f8, f10, cc(4)");
COMPARE(c_d(EQ, f8, f10, 4), "462a4432 c.eq.d f8, f10, cc(4)");
COMPARE(c_s(UEQ, f8, f10, 6), "460a4633 c.ueq.s f8, f10, cc(6)");
COMPARE(c_d(UEQ, f8, f10, 6), "462a4633 c.ueq.d f8, f10, cc(6)");
COMPARE(c_s(OLT, f8, f10, 0), "460a4034 c.olt.s f8, f10, cc(0)");
COMPARE(c_d(OLT, f8, f10, 0), "462a4034 c.olt.d f8, f10, cc(0)");
COMPARE(c_s(ULT, f8, f10, 2), "460a4235 c.ult.s f8, f10, cc(2)");
COMPARE(c_d(ULT, f8, f10, 2), "462a4235 c.ult.d f8, f10, cc(2)");
COMPARE(c_s(OLE, f8, f10, 4), "460a4436 c.ole.s f8, f10, cc(4)");
COMPARE(c_d(OLE, f8, f10, 4), "462a4436 c.ole.d f8, f10, cc(4)");
COMPARE(c_s(ULE, f8, f10, 6), "460a4637 c.ule.s f8, f10, cc(6)");
COMPARE(c_d(ULE, f8, f10, 6), "462a4637 c.ule.d f8, f10, cc(6)");
VERIFY_RUN();
}
}
TEST(COND_FMT_DISASM) {
if (IsMipsArchVariant(kMips32r6)) {
SET_UP();
COMPARE(cmp_s(F, f6, f8, f10), "468a4180 cmp.af.s f6, f8, f10");
COMPARE(cmp_d(F, f6, f8, f10), "46aa4180 cmp.af.d f6, f8, f10");
COMPARE(cmp_s(UN, f6, f8, f10), "468a4181 cmp.un.s f6, f8, f10");
COMPARE(cmp_d(UN, f6, f8, f10), "46aa4181 cmp.un.d f6, f8, f10");
COMPARE(cmp_s(EQ, f6, f8, f10), "468a4182 cmp.eq.s f6, f8, f10");
COMPARE(cmp_d(EQ, f6, f8, f10), "46aa4182 cmp.eq.d f6, f8, f10");
COMPARE(cmp_s(UEQ, f6, f8, f10), "468a4183 cmp.ueq.s f6, f8, f10");
COMPARE(cmp_d(UEQ, f6, f8, f10), "46aa4183 cmp.ueq.d f6, f8, f10");
COMPARE(cmp_s(LT, f6, f8, f10), "468a4184 cmp.lt.s f6, f8, f10");
COMPARE(cmp_d(LT, f6, f8, f10), "46aa4184 cmp.lt.d f6, f8, f10");
COMPARE(cmp_s(ULT, f6, f8, f10), "468a4185 cmp.ult.s f6, f8, f10");
COMPARE(cmp_d(ULT, f6, f8, f10), "46aa4185 cmp.ult.d f6, f8, f10");
COMPARE(cmp_s(LE, f6, f8, f10), "468a4186 cmp.le.s f6, f8, f10");
COMPARE(cmp_d(LE, f6, f8, f10), "46aa4186 cmp.le.d f6, f8, f10");
COMPARE(cmp_s(ULE, f6, f8, f10), "468a4187 cmp.ule.s f6, f8, f10");
COMPARE(cmp_d(ULE, f6, f8, f10), "46aa4187 cmp.ule.d f6, f8, f10");
COMPARE(cmp_s(ORD, f6, f8, f10), "468a4191 cmp.or.s f6, f8, f10");
COMPARE(cmp_d(ORD, f6, f8, f10), "46aa4191 cmp.or.d f6, f8, f10");
COMPARE(cmp_s(UNE, f6, f8, f10), "468a4192 cmp.une.s f6, f8, f10");
COMPARE(cmp_d(UNE, f6, f8, f10), "46aa4192 cmp.une.d f6, f8, f10");
COMPARE(cmp_s(NE, f6, f8, f10), "468a4193 cmp.ne.s f6, f8, f10");
COMPARE(cmp_d(NE, f6, f8, f10), "46aa4193 cmp.ne.d f6, f8, f10");
VERIFY_RUN();
}
}
TEST(CVT_DISSASM) {
SET_UP();
COMPARE(cvt_d_s(f22, f24), "4600c5a1 cvt.d.s f22, f24");
COMPARE(cvt_d_w(f22, f24), "4680c5a1 cvt.d.w f22, f24");
if (IsMipsArchVariant(kMips32r6) || IsMipsArchVariant(kMips32r2)) {
COMPARE(cvt_d_l(f22, f24), "46a0c5a1 cvt.d.l f22, f24");
}
if (IsMipsArchVariant(kMips32r6) || IsMipsArchVariant(kMips32r2)) {
COMPARE(cvt_l_s(f22, f24), "4600c5a5 cvt.l.s f22, f24");
COMPARE(cvt_l_d(f22, f24), "4620c5a5 cvt.l.d f22, f24");
}
COMPARE(cvt_s_d(f22, f24), "4620c5a0 cvt.s.d f22, f24");
COMPARE(cvt_s_w(f22, f24), "4680c5a0 cvt.s.w f22, f24");
if (IsMipsArchVariant(kMips32r6) || IsMipsArchVariant(kMips32r2)) {
COMPARE(cvt_s_l(f22, f24), "46a0c5a0 cvt.s.l f22, f24");
}
COMPARE(cvt_s_d(f22, f24), "4620c5a0 cvt.s.d f22, f24");
COMPARE(cvt_s_w(f22, f24), "4680c5a0 cvt.s.w f22, f24");
VERIFY_RUN();
}
...@@ -669,6 +669,22 @@ TEST(Type0) { ...@@ -669,6 +669,22 @@ TEST(Type0) {
COMPARE(ext_(v0, v1, 0, 32), COMPARE(ext_(v0, v1, 0, 32),
"7c62f800 ext v0, v1, 0, 32"); "7c62f800 ext v0, v1, 0, 32");
COMPARE(add_s(f4, f6, f8), "46083100 add.s f4, f6, f8");
COMPARE(add_d(f12, f14, f16), "46307300 add.d f12, f14, f16");
if (kArchVariant == kMips64r6) {
COMPARE(bitswap(a0, a1), "7c052020 bitswap a0, a1");
COMPARE(bitswap(t8, s0), "7c10c020 bitswap t8, s0");
COMPARE(dbitswap(a0, a1), "7c052024 dbitswap a0, a1");
COMPARE(dbitswap(t8, s0), "7c10c024 dbitswap t8, s0");
}
COMPARE(abs_s(f6, f8), "46004185 abs.s f6, f8");
COMPARE(abs_d(f10, f12), "46206285 abs.d f10, f12");
COMPARE(div_s(f2, f4, f6), "46062083 div.s f2, f4, f6");
COMPARE(div_d(f2, f4, f6), "46262083 div.d f2, f4, f6");
VERIFY_RUN(); VERIFY_RUN();
} }
...@@ -763,3 +779,116 @@ TEST(Type1) { ...@@ -763,3 +779,116 @@ TEST(Type1) {
} }
VERIFY_RUN(); VERIFY_RUN();
} }
TEST(Type2) {
if (kArchVariant == kMips64r6) {
SET_UP();
COMPARE(class_s(f3, f4), "460020db class.s f3, f4");
COMPARE(class_d(f2, f3), "4620189b class.d f2, f3");
VERIFY_RUN();
}
}
TEST(C_FMT_DISASM) {
if (kArchVariant == kMips64r2) {
SET_UP();
COMPARE(c_s(F, f8, f10, 0), "460a4030 c.f.s f8, f10, cc(0)");
COMPARE(c_d(F, f8, f10, 0), "462a4030 c.f.d f8, f10, cc(0)");
COMPARE(c_s(UN, f8, f10, 2), "460a4231 c.un.s f8, f10, cc(2)");
COMPARE(c_d(UN, f8, f10, 2), "462a4231 c.un.d f8, f10, cc(2)");
COMPARE(c_s(EQ, f8, f10, 4), "460a4432 c.eq.s f8, f10, cc(4)");
COMPARE(c_d(EQ, f8, f10, 4), "462a4432 c.eq.d f8, f10, cc(4)");
COMPARE(c_s(UEQ, f8, f10, 6), "460a4633 c.ueq.s f8, f10, cc(6)");
COMPARE(c_d(UEQ, f8, f10, 6), "462a4633 c.ueq.d f8, f10, cc(6)");
COMPARE(c_s(OLT, f8, f10, 0), "460a4034 c.olt.s f8, f10, cc(0)");
COMPARE(c_d(OLT, f8, f10, 0), "462a4034 c.olt.d f8, f10, cc(0)");
COMPARE(c_s(ULT, f8, f10, 2), "460a4235 c.ult.s f8, f10, cc(2)");
COMPARE(c_d(ULT, f8, f10, 2), "462a4235 c.ult.d f8, f10, cc(2)");
COMPARE(c_s(OLE, f8, f10, 4), "460a4436 c.ole.s f8, f10, cc(4)");
COMPARE(c_d(OLE, f8, f10, 4), "462a4436 c.ole.d f8, f10, cc(4)");
COMPARE(c_s(ULE, f8, f10, 6), "460a4637 c.ule.s f8, f10, cc(6)");
COMPARE(c_d(ULE, f8, f10, 6), "462a4637 c.ule.d f8, f10, cc(6)");
VERIFY_RUN();
}
}
TEST(COND_FMT_DISASM) {
if (kArchVariant == kMips64r6) {
SET_UP();
COMPARE(cmp_s(F, f6, f8, f10), "468a4180 cmp.af.s f6, f8, f10");
COMPARE(cmp_d(F, f6, f8, f10), "46aa4180 cmp.af.d f6, f8, f10");
COMPARE(cmp_s(UN, f6, f8, f10), "468a4181 cmp.un.s f6, f8, f10");
COMPARE(cmp_d(UN, f6, f8, f10), "46aa4181 cmp.un.d f6, f8, f10");
COMPARE(cmp_s(EQ, f6, f8, f10), "468a4182 cmp.eq.s f6, f8, f10");
COMPARE(cmp_d(EQ, f6, f8, f10), "46aa4182 cmp.eq.d f6, f8, f10");
COMPARE(cmp_s(UEQ, f6, f8, f10), "468a4183 cmp.ueq.s f6, f8, f10");
COMPARE(cmp_d(UEQ, f6, f8, f10), "46aa4183 cmp.ueq.d f6, f8, f10");
COMPARE(cmp_s(LT, f6, f8, f10), "468a4184 cmp.lt.s f6, f8, f10");
COMPARE(cmp_d(LT, f6, f8, f10), "46aa4184 cmp.lt.d f6, f8, f10");
COMPARE(cmp_s(ULT, f6, f8, f10), "468a4185 cmp.ult.s f6, f8, f10");
COMPARE(cmp_d(ULT, f6, f8, f10), "46aa4185 cmp.ult.d f6, f8, f10");
COMPARE(cmp_s(LE, f6, f8, f10), "468a4186 cmp.le.s f6, f8, f10");
COMPARE(cmp_d(LE, f6, f8, f10), "46aa4186 cmp.le.d f6, f8, f10");
COMPARE(cmp_s(ULE, f6, f8, f10), "468a4187 cmp.ule.s f6, f8, f10");
COMPARE(cmp_d(ULE, f6, f8, f10), "46aa4187 cmp.ule.d f6, f8, f10");
COMPARE(cmp_s(ORD, f6, f8, f10), "468a4191 cmp.or.s f6, f8, f10");
COMPARE(cmp_d(ORD, f6, f8, f10), "46aa4191 cmp.or.d f6, f8, f10");
COMPARE(cmp_s(UNE, f6, f8, f10), "468a4192 cmp.une.s f6, f8, f10");
COMPARE(cmp_d(UNE, f6, f8, f10), "46aa4192 cmp.une.d f6, f8, f10");
COMPARE(cmp_s(NE, f6, f8, f10), "468a4193 cmp.ne.s f6, f8, f10");
COMPARE(cmp_d(NE, f6, f8, f10), "46aa4193 cmp.ne.d f6, f8, f10");
VERIFY_RUN();
}
}
TEST(CVT_DISSASM) {
SET_UP();
COMPARE(cvt_d_s(f22, f24), "4600c5a1 cvt.d.s f22, f24");
COMPARE(cvt_d_w(f22, f24), "4680c5a1 cvt.d.w f22, f24");
if (kArchVariant == kMips64r6 || kArchVariant == kMips64r2) {
COMPARE(cvt_d_l(f22, f24), "46a0c5a1 cvt.d.l f22, f24");
}
if (kArchVariant == kMips64r6 || kArchVariant == kMips64r2) {
COMPARE(cvt_l_s(f22, f24), "4600c5a5 cvt.l.s f22, f24");
COMPARE(cvt_l_d(f22, f24), "4620c5a5 cvt.l.d f22, f24");
}
COMPARE(cvt_s_d(f22, f24), "4620c5a0 cvt.s.d f22, f24");
COMPARE(cvt_s_w(f22, f24), "4680c5a0 cvt.s.w f22, f24");
if (kArchVariant == kMips64r6 || kArchVariant == kMips64r2) {
COMPARE(cvt_s_l(f22, f24), "46a0c5a0 cvt.s.l f22, f24");
}
COMPARE(cvt_s_d(f22, f24), "4620c5a0 cvt.s.d f22, f24");
COMPARE(cvt_s_w(f22, f24), "4680c5a0 cvt.s.w f22, f24");
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