Commit 838d0b4b authored by Miran.Karic's avatar Miran.Karic Committed by Commit bot

MIPS64: Add/fix bit insertion/extraction instrs.

Added support for DINSM and DINSU bit insertion instructions. Also fixed
errors with bit extraction instructions, added disassembler tests and
adjusted the code to make it more compact.

BUG=
TEST=cctest/test-assembler-mips/Dins
     cctest/test-disasm-mips/Type0

Review-Url: https://codereview.chromium.org/2871663002
Cr-Commit-Position: refs/heads/master@{#45226}
parent 755a809e
......@@ -1216,19 +1216,8 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
}
break;
case kMips64Dext: {
int16_t pos = i.InputInt8(1);
int16_t size = i.InputInt8(2);
if (size > 0 && size <= 32 && pos >= 0 && pos < 32) {
__ Dext(i.OutputRegister(), i.InputRegister(0), i.InputInt8(1),
i.InputInt8(2));
} else if (size > 32 && size <= 64 && pos >= 0 && pos < 32) {
__ Dextm(i.OutputRegister(), i.InputRegister(0), i.InputInt8(1),
i.InputInt8(2));
} else {
DCHECK(size > 0 && size <= 32 && pos >= 32 && pos < 64);
__ Dextu(i.OutputRegister(), i.InputRegister(0), i.InputInt8(1),
i.InputInt8(2));
}
__ Dext(i.OutputRegister(), i.InputRegister(0), i.InputInt8(1),
i.InputInt8(2));
break;
}
case kMips64Dins:
......@@ -2516,7 +2505,7 @@ void CodeGenerator::AssembleArchBoolean(Instruction* instr,
base::bits::IsPowerOfTwo64(i.InputOperand(1).immediate())) {
uint16_t pos =
base::bits::CountTrailingZeros64(i.InputOperand(1).immediate());
__ ExtractBits(result, i.InputRegister(0), pos, 1);
__ Dext(result, i.InputRegister(0), pos, 1);
} else {
__ And(kScratchReg, i.InputRegister(0), i.InputOperand(1));
__ Sltu(result, zero_reg, kScratchReg);
......
......@@ -2497,7 +2497,7 @@ void Assembler::selnez(Register rd, Register rs, Register rt) {
// Bit twiddling.
void Assembler::clz(Register rd, Register rs) {
if (kArchVariant != kMips64r6) {
// Clz instr requires same GPR number in 'rd' and 'rt' fields.
// clz instr requires same GPR number in 'rd' and 'rt' fields.
GenInstrRegister(SPECIAL2, rs, rd, rd, 0, CLZ);
} else {
GenInstrRegister(SPECIAL, rs, zero_reg, rd, 1, CLZ_R6);
......@@ -2517,7 +2517,7 @@ void Assembler::dclz(Register rd, Register rs) {
void Assembler::ins_(Register rt, Register rs, uint16_t pos, uint16_t size) {
// Should be called via MacroAssembler::Ins.
// Ins instr has 'rt' field as dest, and two uint5: msb, lsb.
// ins instr has 'rt' field as dest, and two uint5: msb, lsb.
DCHECK((kArchVariant == kMips64r2) || (kArchVariant == kMips64r6));
GenInstrRegister(SPECIAL3, rs, rt, pos + size - 1, pos, INS);
}
......@@ -2525,15 +2525,28 @@ void Assembler::ins_(Register rt, Register rs, uint16_t pos, uint16_t size) {
void Assembler::dins_(Register rt, Register rs, uint16_t pos, uint16_t size) {
// Should be called via MacroAssembler::Dins.
// Dext instr has 'rt' field as dest, and two uint5: msb, lsb.
// dins instr has 'rt' field as dest, and two uint5: msb, lsb.
DCHECK(kArchVariant == kMips64r2 || kArchVariant == kMips64r6);
GenInstrRegister(SPECIAL3, rs, rt, pos + size - 1, pos, DINS);
}
void Assembler::dinsm_(Register rt, Register rs, uint16_t pos, uint16_t size) {
// Should be called via MacroAssembler::Dins.
// dinsm instr has 'rt' field as dest, and two uint5: msbminus32, lsb.
DCHECK(kArchVariant == kMips64r2 || kArchVariant == kMips64r6);
GenInstrRegister(SPECIAL3, rs, rt, pos + size - 1 - 32, pos, DINSM);
}
void Assembler::dinsu_(Register rt, Register rs, uint16_t pos, uint16_t size) {
// Should be called via MacroAssembler::Dins.
// dinsu instr has 'rt' field as dest, and two uint5: msbminus32, lsbminus32.
DCHECK(kArchVariant == kMips64r2 || kArchVariant == kMips64r6);
GenInstrRegister(SPECIAL3, rs, rt, pos + size - 1 - 32, pos - 32, DINSU);
}
void Assembler::ext_(Register rt, Register rs, uint16_t pos, uint16_t size) {
// Should be called via MacroAssembler::Ext.
// Ext instr has 'rt' field as dest, and two uint5: msb, lsb.
// ext instr has 'rt' field as dest, and two uint5: msbd, lsb.
DCHECK(kArchVariant == kMips64r2 || kArchVariant == kMips64r6);
GenInstrRegister(SPECIAL3, rs, rt, size - 1, pos, EXT);
}
......@@ -2541,23 +2554,21 @@ void Assembler::ext_(Register rt, Register rs, uint16_t pos, uint16_t size) {
void Assembler::dext_(Register rt, Register rs, uint16_t pos, uint16_t size) {
// Should be called via MacroAssembler::Dext.
// Dext instr has 'rt' field as dest, and two uint5: msb, lsb.
// dext instr has 'rt' field as dest, and two uint5: msbd, lsb.
DCHECK(kArchVariant == kMips64r2 || kArchVariant == kMips64r6);
GenInstrRegister(SPECIAL3, rs, rt, size - 1, pos, DEXT);
}
void Assembler::dextm(Register rt, Register rs, uint16_t pos, uint16_t size) {
void Assembler::dextm_(Register rt, Register rs, uint16_t pos, uint16_t size) {
// Should be called via MacroAssembler::Dextm.
// Dextm instr has 'rt' field as dest, and two uint5: msb, lsb.
// dextm instr has 'rt' field as dest, and two uint5: msbdminus32, lsb.
DCHECK(kArchVariant == kMips64r2 || kArchVariant == kMips64r6);
GenInstrRegister(SPECIAL3, rs, rt, size - 1 - 32, pos, DEXTM);
}
void Assembler::dextu(Register rt, Register rs, uint16_t pos, uint16_t size) {
void Assembler::dextu_(Register rt, Register rs, uint16_t pos, uint16_t size) {
// Should be called via MacroAssembler::Dextu.
// Dext instr has 'rt' field as dest, and two uint5: msb, lsb.
// dextu instr has 'rt' field as dest, and two uint5: msbd, lsbminus32.
DCHECK(kArchVariant == kMips64r2 || kArchVariant == kMips64r6);
GenInstrRegister(SPECIAL3, rs, rt, size - 1, pos - 32, DEXTU);
}
......
......@@ -1005,9 +1005,11 @@ class Assembler : public AssemblerBase {
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 dext_(Register rt, Register rs, uint16_t pos, uint16_t size);
void dextm(Register rt, Register rs, uint16_t pos, uint16_t size);
void dextu(Register rt, Register rs, uint16_t pos, uint16_t size);
void dextm_(Register rt, Register rs, uint16_t pos, uint16_t size);
void dextu_(Register rt, Register rs, uint16_t pos, uint16_t size);
void dins_(Register rt, Register rs, uint16_t pos, uint16_t size);
void dinsm_(Register rt, Register rs, uint16_t pos, uint16_t size);
void dinsu_(Register rt, Register rs, uint16_t pos, uint16_t size);
void bitswap(Register rd, Register rt);
void dbitswap(Register rd, Register rt);
void align(Register rd, Register rs, Register rt, uint8_t bp);
......
......@@ -1708,6 +1708,8 @@ InstructionBase::Type InstructionBase::InstructionType() const {
switch (FunctionFieldRaw()) {
case INS:
case DINS:
case DINSM:
case DINSU:
case EXT:
case DEXT:
case DEXTM:
......
......@@ -92,6 +92,9 @@ class Decoder {
void PrintSd(Instruction* instr);
void PrintSs1(Instruction* instr);
void PrintSs2(Instruction* instr);
void PrintSs3(Instruction* instr);
void PrintSs4(Instruction* instr);
void PrintSs5(Instruction* instr);
void PrintBc(Instruction* instr);
void PrintCc(Instruction* instr);
void PrintFunction(Instruction* instr);
......@@ -289,20 +292,41 @@ void Decoder::PrintSd(Instruction* instr) {
out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "%d", sd);
}
// Print the integer value of the rd field, when used as 'ext' size.
// Print the integer value of ext/dext/dextu size from the msbd field.
void Decoder::PrintSs1(Instruction* instr) {
int ss = instr->RdValue();
out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "%d", ss + 1);
int msbd = instr->RdValue();
out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "%d", msbd + 1);
}
// Print the integer value of the rd field, when used as 'ins' size.
// Print the integer value of ins/dins/dinsu size from the msb and lsb fields
// (for dinsu it is msbminus32 and lsbminus32 fields).
void Decoder::PrintSs2(Instruction* instr) {
int ss = instr->RdValue();
int pos = instr->SaValue();
int msb = instr->RdValue();
int lsb = instr->SaValue();
out_buffer_pos_ +=
SNPrintF(out_buffer_ + out_buffer_pos_, "%d", ss - pos + 1);
SNPrintF(out_buffer_ + out_buffer_pos_, "%d", msb - lsb + 1);
}
// Print the integer value of dextm size from the msbdminus32 field.
void Decoder::PrintSs3(Instruction* instr) {
int msbdminus32 = instr->RdValue();
out_buffer_pos_ +=
SNPrintF(out_buffer_ + out_buffer_pos_, "%d", msbdminus32 + 32 + 1);
}
// Print the integer value of dinsm size from the msbminus32 and lsb fields.
void Decoder::PrintSs4(Instruction* instr) {
int msbminus32 = instr->RdValue();
int lsb = instr->SaValue();
out_buffer_pos_ +=
SNPrintF(out_buffer_ + out_buffer_pos_, "%d", msbminus32 + 32 - lsb + 1);
}
// Print the integer value of dextu/dinsu pos from the lsbminus32 field.
void Decoder::PrintSs5(Instruction* instr) {
int lsbminus32 = instr->SaValue();
out_buffer_pos_ +=
SNPrintF(out_buffer_ + out_buffer_pos_, "%d", lsbminus32 + 32);
}
......@@ -954,14 +978,22 @@ int Decoder::FormatOption(Instruction* instr, const char* format) {
}
case 's': {
if (format[2] == '1') {
DCHECK(STRING_STARTS_WITH(format, "ss1")); /* ext size */
PrintSs1(instr);
return 3;
DCHECK(STRING_STARTS_WITH(format, "ss1")); // ext, dext, dextu size
PrintSs1(instr);
} else if (format[2] == '2') {
DCHECK(STRING_STARTS_WITH(format, "ss2")); // ins, dins, dinsu size
PrintSs2(instr);
} else if (format[2] == '3') {
DCHECK(STRING_STARTS_WITH(format, "ss3")); // dextm size
PrintSs3(instr);
} else if (format[2] == '4') {
DCHECK(STRING_STARTS_WITH(format, "ss4")); // dinsm size
PrintSs4(instr);
} else {
DCHECK(STRING_STARTS_WITH(format, "ss2")); /* ins size */
PrintSs2(instr);
return 3;
DCHECK(STRING_STARTS_WITH(format, "ss5")); // dextu, dinsu pos
PrintSs5(instr);
}
return 3;
}
}
}
......@@ -1694,10 +1726,6 @@ void Decoder::DecodeTypeRegisterSPECIAL2(Instruction* instr) {
void Decoder::DecodeTypeRegisterSPECIAL3(Instruction* instr) {
switch (instr->FunctionFieldRaw()) {
case INS: {
Format(instr, "ins 'rt, 'rs, 'sa, 'ss2");
break;
}
case EXT: {
Format(instr, "ext 'rt, 'rs, 'sa, 'ss1");
break;
......@@ -1707,11 +1735,27 @@ void Decoder::DecodeTypeRegisterSPECIAL3(Instruction* instr) {
break;
}
case DEXTM: {
Format(instr, "dextm 'rt, 'rs, 'sa, 'ss1");
Format(instr, "dextm 'rt, 'rs, 'sa, 'ss3");
break;
}
case DEXTU: {
Format(instr, "dextu 'rt, 'rs, 'sa, 'ss1");
Format(instr, "dextu 'rt, 'rs, 'ss5, 'ss1");
break;
}
case INS: {
Format(instr, "ins 'rt, 'rs, 'sa, 'ss2");
break;
}
case DINS: {
Format(instr, "dins 'rt, 'rs, 'sa, 'ss2");
break;
}
case DINSM: {
Format(instr, "dinsm 'rt, 'rs, 'sa, 'ss4");
break;
}
case DINSU: {
Format(instr, "dinsu 'rt, 'rs, 'ss5, 'ss2");
break;
}
case BSHFL: {
......@@ -1749,10 +1793,6 @@ void Decoder::DecodeTypeRegisterSPECIAL3(Instruction* instr) {
}
break;
}
case DINS: {
Format(instr, "dins 'rt, 'rs, 'sa, 'ss2");
break;
}
case DBSHFL: {
int sa = instr->SaFieldRaw() >> kSaShift;
switch (sa) {
......
......@@ -1950,55 +1950,18 @@ void MacroAssembler::Ext(Register rt,
ext_(rt, rs, pos, size);
}
void MacroAssembler::ExtractBits(Register rt, Register rs, uint16_t pos,
uint16_t size) {
DCHECK(pos < 64);
DCHECK(size > 0 && size <= 64);
DCHECK(pos + size <= 64);
if (pos < 32) {
if (size <= 32) {
Dext(rt, rs, pos, size);
} else {
Dextm(rt, rs, pos, size);
}
} else if (pos < 64) {
DCHECK(size <= 32);
Dextu(rt, rs, pos, size);
}
}
void MacroAssembler::Dext(Register rt, Register rs, uint16_t pos,
uint16_t size) {
DCHECK(pos < 32);
DCHECK(size > 0 && size <= 32);
dext_(rt, rs, pos, size);
}
void MacroAssembler::Dextm(Register rt, Register rs, uint16_t pos,
uint16_t size) {
DCHECK(pos < 32);
DCHECK(size > 32 && size <= 64);
DCHECK((pos + size) > 32 && (pos + size) <= 64);
dextm(rt, rs, pos, size);
}
void MacroAssembler::Dextu(Register rt, Register rs, uint16_t pos,
uint16_t size) {
DCHECK(pos >= 32 && pos < 64);
DCHECK(size > 0 && size <= 32);
DCHECK((pos + size) > 32 && (pos + size) <= 64);
dextu(rt, rs, pos, size);
}
void MacroAssembler::Dins(Register rt, Register rs, uint16_t pos,
uint16_t size) {
DCHECK(pos < 32);
DCHECK(pos + size <= 32);
DCHECK(size != 0);
dins_(rt, rs, pos, size);
DCHECK(pos < 64 && 0 < size && size <= 64 && 0 < pos + size &&
pos + size <= 64);
if (size > 32) {
dextm_(rt, rs, pos, size);
} else if (pos >= 32) {
dextu_(rt, rs, pos, size);
} else {
dext_(rt, rs, pos, size);
}
}
......@@ -2012,6 +1975,19 @@ void MacroAssembler::Ins(Register rt,
ins_(rt, rs, pos, size);
}
void MacroAssembler::Dins(Register rt, Register rs, uint16_t pos,
uint16_t size) {
DCHECK(pos < 64 && 0 < size && size <= 64 && 0 < pos + size &&
pos + size <= 64);
if (pos + size <= 32) {
dins_(rt, rs, pos, size);
} else if (pos < 32) {
dinsm_(rt, rs, pos, size);
} else {
dinsu_(rt, rs, pos, size);
}
}
void MacroAssembler::Neg_s(FPURegister fd, FPURegister fs) {
if (kArchVariant == kMips64r6) {
// r6 neg_s changes the sign for NaN-like operands as well.
......
......@@ -863,15 +863,10 @@ class MacroAssembler: public Assembler {
void LoadFromSafepointRegisterSlot(Register dst, Register src);
// MIPS64 R2 instruction macro.
void Ins(Register rt, Register rs, uint16_t pos, uint16_t size);
void Dins(Register rt, Register rs, uint16_t pos, uint16_t size);
void Ext(Register rt, Register rs, uint16_t pos, uint16_t size);
void ExtractBits(Register rt, Register rs, uint16_t pos, uint16_t size);
void Dext(Register rt, Register rs, uint16_t pos, uint16_t size);
void Dextm(Register rt, Register rs, uint16_t pos, uint16_t size);
void Dextu(Register rt, Register rs, uint16_t pos, uint16_t size);
void Ins(Register rt, Register rs, uint16_t pos, uint16_t size);
void Dins(Register rt, Register rs, uint16_t pos, uint16_t size);
void Neg_s(FPURegister fd, FPURegister fs);
void Neg_d(FPURegister fd, FPURegister fs);
......
......@@ -4037,73 +4037,101 @@ void Simulator::DecodeTypeRegisterSPECIAL2() {
void Simulator::DecodeTypeRegisterSPECIAL3() {
int64_t alu_out;
switch (instr_.FunctionFieldRaw()) {
case INS: { // Mips64r2 instruction.
// Interpret rd field as 5-bit msb of insert.
uint16_t msb = rd_reg();
// Interpret sa field as 5-bit lsb of insert.
uint16_t lsb = sa();
uint16_t size = msb - lsb + 1;
uint64_t mask = (1ULL << size) - 1;
alu_out = static_cast<int32_t>((rt_u() & ~(mask << lsb)) |
((rs_u() & mask) << lsb));
SetResult(rt_reg(), alu_out);
break;
}
case DINS: { // Mips64r2 instruction.
// Interpret rd field as 5-bit msb of insert.
uint16_t msb = rd_reg();
// Interpret sa field as 5-bit lsb of insert.
uint16_t lsb = sa();
uint16_t size = msb - lsb + 1;
uint64_t mask = (1ULL << size) - 1;
alu_out = (rt_u() & ~(mask << lsb)) | ((rs_u() & mask) << lsb);
SetResult(rt_reg(), alu_out);
break;
}
case EXT: { // Mips64r2 instruction.
// Interpret rd field as 5-bit msb of extract.
uint16_t msb = rd_reg();
case EXT: { // Mips32r2 instruction.
// Interpret rd field as 5-bit msbd of extract.
uint16_t msbd = rd_reg();
// Interpret sa field as 5-bit lsb of extract.
uint16_t lsb = sa();
uint16_t size = msb + 1;
uint16_t size = msbd + 1;
uint64_t mask = (1ULL << size) - 1;
alu_out = static_cast<int32_t>((rs_u() & (mask << lsb)) >> lsb);
SetResult(rt_reg(), alu_out);
break;
}
case DEXT: { // Mips64r2 instruction.
// Interpret rd field as 5-bit msb of extract.
uint16_t msb = rd_reg();
// Interpret rd field as 5-bit msbd of extract.
uint16_t msbd = rd_reg();
// Interpret sa field as 5-bit lsb of extract.
uint16_t lsb = sa();
uint16_t size = msb + 1;
uint16_t size = msbd + 1;
uint64_t mask = (size == 64) ? UINT64_MAX : (1ULL << size) - 1;
alu_out = static_cast<int64_t>((rs_u() & (mask << lsb)) >> lsb);
SetResult(rt_reg(), alu_out);
break;
}
case DEXTM: {
// Interpret rd field as 5-bit msb of extract.
uint16_t msb = rd_reg();
// Interpret rd field as 5-bit msbdminus32 of extract.
uint16_t msbdminus32 = rd_reg();
// Interpret sa field as 5-bit lsb of extract.
uint16_t lsb = sa();
uint16_t size = msb + 33;
uint16_t size = msbdminus32 + 1 + 32;
uint64_t mask = (size == 64) ? UINT64_MAX : (1ULL << size) - 1;
alu_out = static_cast<int64_t>((rs_u() & (mask << lsb)) >> lsb);
SetResult(rt_reg(), alu_out);
break;
}
case DEXTU: {
// Interpret rd field as 5-bit msb of extract.
uint16_t msb = rd_reg();
// Interpret sa field as 5-bit lsb of extract.
// Interpret rd field as 5-bit msbd of extract.
uint16_t msbd = rd_reg();
// Interpret sa field as 5-bit lsbminus32 of extract and add 32 to get
// lsb.
uint16_t lsb = sa() + 32;
uint16_t size = msb + 1;
uint16_t size = msbd + 1;
uint64_t mask = (size == 64) ? UINT64_MAX : (1ULL << size) - 1;
alu_out = static_cast<int64_t>((rs_u() & (mask << lsb)) >> lsb);
SetResult(rt_reg(), alu_out);
break;
}
case INS: { // Mips32r2 instruction.
// Interpret rd field as 5-bit msb of insert.
uint16_t msb = rd_reg();
// Interpret sa field as 5-bit lsb of insert.
uint16_t lsb = sa();
uint16_t size = msb - lsb + 1;
uint64_t mask = (1ULL << size) - 1;
alu_out = static_cast<int32_t>((rt_u() & ~(mask << lsb)) |
((rs_u() & mask) << lsb));
SetResult(rt_reg(), alu_out);
break;
}
case DINS: { // Mips64r2 instruction.
// Interpret rd field as 5-bit msb of insert.
uint16_t msb = rd_reg();
// Interpret sa field as 5-bit lsb of insert.
uint16_t lsb = sa();
uint16_t size = msb - lsb + 1;
uint64_t mask = (1ULL << size) - 1;
alu_out = (rt_u() & ~(mask << lsb)) | ((rs_u() & mask) << lsb);
SetResult(rt_reg(), alu_out);
break;
}
case DINSM: { // Mips64r2 instruction.
// Interpret rd field as 5-bit msbminus32 of insert.
uint16_t msbminus32 = rd_reg();
// Interpret sa field as 5-bit lsb of insert.
uint16_t lsb = sa();
uint16_t size = msbminus32 + 32 - lsb + 1;
uint64_t mask;
if (size < 64)
mask = (1ULL << size) - 1;
else
mask = std::numeric_limits<uint64_t>::max();
alu_out = (rt_u() & ~(mask << lsb)) | ((rs_u() & mask) << lsb);
SetResult(rt_reg(), alu_out);
break;
}
case DINSU: { // Mips64r2 instruction.
// Interpret rd field as 5-bit msbminus32 of insert.
uint16_t msbminus32 = rd_reg();
// Interpret rd field as 5-bit lsbminus32 of insert.
uint16_t lsbminus32 = sa();
uint16_t lsb = lsbminus32 + 32;
uint16_t size = msbminus32 + 32 - lsb + 1;
uint64_t mask = (1ULL << size) - 1;
alu_out = (rt_u() & ~(mask << lsb)) | ((rs_u() & mask) << lsb);
SetResult(rt_reg(), alu_out);
break;
}
case BSHFL: {
int32_t sa = instr_.SaFieldRaw() >> kSaShift;
switch (sa) {
......
......@@ -6057,4 +6057,63 @@ TEST(maddf_msubf_d) {
});
}
uint64_t run_Dins(uint64_t imm, uint64_t source, uint16_t pos, uint16_t size) {
Isolate* isolate = CcTest::i_isolate();
HandleScope scope(isolate);
MacroAssembler assm(isolate, NULL, 0, v8::internal::CodeObjectRequired::kYes);
__ li(v0, imm);
__ li(t0, source);
__ Dins(v0, t0, pos, size);
__ jr(ra);
__ nop();
CodeDesc desc;
assm.GetCode(&desc);
Handle<Code> code = isolate->factory()->NewCode(
desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
F2 f = FUNCTION_CAST<F2>(code->entry());
uint64_t res = reinterpret_cast<uint64_t>(
CALL_GENERATED_CODE(isolate, f, 0, 0, 0, 0, 0));
return res;
}
TEST(Dins) {
CcTest::InitializeVM();
// Test Dins macro-instruction.
struct TestCaseDins {
uint64_t imm;
uint64_t source;
uint16_t pos;
uint16_t size;
uint64_t expected_res;
};
// We load imm to v0 and source to t0 and then call
// Dins(v0, t0, pos, size) to test cases listed below.
struct TestCaseDins tc[] = {
// imm, source, pos, size, expected_res
{0x5555555555555555, 0x1ABCDEF01, 31, 1, 0x55555555D5555555},
{0x5555555555555555, 0x1ABCDEF02, 30, 2, 0x5555555595555555},
{0x201234567, 0x1FABCDEFF, 0, 32, 0x2FABCDEFF},
{0x201234567, 0x7FABCDEFF, 31, 2, 0x381234567},
{0x800000000, 0x7FABCDEFF, 0, 33, 0x9FABCDEFF},
{0x1234, 0xABCDABCDABCDABCD, 0, 64, 0xABCDABCDABCDABCD},
{0xABCD, 0xABCEABCF, 32, 1, 0x10000ABCD},
{0xABCD, 0xABCEABCF, 63, 1, 0x800000000000ABCD},
{0xABCD, 0xABC1ABC2ABC3ABC4, 32, 32, 0xABC3ABC40000ABCD},
};
size_t nr_test_cases = sizeof(tc) / sizeof(TestCaseDins);
for (size_t i = 0; i < nr_test_cases; ++i) {
CHECK_EQ(tc[i].expected_res,
run_Dins(tc[i].imm, tc[i].source, tc[i].pos, tc[i].size));
}
}
#undef __
......@@ -711,26 +711,41 @@ TEST(Type0) {
COMPARE(dsbh(s6, s7), "7c17b0a4 dsbh s6, s7");
COMPARE(dsbh(v0, v1), "7c0310a4 dsbh v0, v1");
COMPARE(dshd(a0, a1), "7c052164 dshd a0, a1");
COMPARE(dshd(s6, s7), "7c17b164 dshd s6, s7");
COMPARE(dshd(v0, v1), "7c031164 dshd v0, v1");
COMPARE(ext_(a0, a1, 31, 1), "7ca407c0 ext a0, a1, 31, 1");
COMPARE(ext_(s6, s7, 30, 2), "7ef60f80 ext s6, s7, 30, 2");
COMPARE(ext_(v0, v1, 0, 32), "7c62f800 ext v0, v1, 0, 32");
COMPARE(dext_(a0, a1, 31, 1), "7ca407c3 dext a0, a1, 31, 1");
COMPARE(dext_(s6, s7, 30, 2), "7ef60f83 dext s6, s7, 30, 2");
COMPARE(dext_(v0, v1, 0, 32), "7c62f803 dext v0, v1, 0, 32");
COMPARE(dextm_(a0, a1, 31, 33), "7ca407c1 dextm a0, a1, 31, 33");
COMPARE(dextm_(s6, s7, 0, 33), "7ef60001 dextm s6, s7, 0, 33");
COMPARE(dextm_(v0, v1, 0, 64), "7c62f801 dextm v0, v1, 0, 64");
COMPARE(dextu_(a0, a1, 32, 1), "7ca40002 dextu a0, a1, 32, 1");
COMPARE(dextu_(s6, s7, 63, 1), "7ef607c2 dextu s6, s7, 63, 1");
COMPARE(dextu_(v0, v1, 32, 32), "7c62f802 dextu v0, v1, 32, 32");
COMPARE(ins_(a0, a1, 31, 1), "7ca4ffc4 ins a0, a1, 31, 1");
COMPARE(ins_(s6, s7, 30, 2), "7ef6ff84 ins s6, s7, 30, 2");
COMPARE(ins_(v0, v1, 0, 32), "7c62f804 ins v0, v1, 0, 32");
COMPARE(dins_(a0, a1, 31, 1), "7ca4ffc7 dins a0, a1, 31, 1");
COMPARE(dins_(s6, s7, 30, 2), "7ef6ff87 dins s6, s7, 30, 2");
COMPARE(dins_(v0, v1, 0, 32), "7c62f807 dins v0, v1, 0, 32");
COMPARE(dshd(a0, a1), "7c052164 dshd a0, a1");
COMPARE(dshd(s6, s7), "7c17b164 dshd s6, s7");
COMPARE(dshd(v0, v1), "7c031164 dshd v0, v1");
COMPARE(dinsm_(a0, a1, 31, 2), "7ca407c5 dinsm a0, a1, 31, 2");
COMPARE(dinsm_(s6, s7, 0, 33), "7ef60005 dinsm s6, s7, 0, 33");
COMPARE(dinsm_(v0, v1, 0, 64), "7c62f805 dinsm v0, v1, 0, 64");
COMPARE(ins_(a0, a1, 31, 1),
"7ca4ffc4 ins a0, a1, 31, 1");
COMPARE(ins_(s6, s7, 30, 2),
"7ef6ff84 ins s6, s7, 30, 2");
COMPARE(ins_(v0, v1, 0, 32),
"7c62f804 ins v0, v1, 0, 32");
COMPARE(ext_(a0, a1, 31, 1),
"7ca407c0 ext a0, a1, 31, 1");
COMPARE(ext_(s6, s7, 30, 2),
"7ef60f80 ext s6, s7, 30, 2");
COMPARE(ext_(v0, v1, 0, 32),
"7c62f800 ext v0, v1, 0, 32");
COMPARE(dinsu_(a0, a1, 32, 1), "7ca40006 dinsu a0, a1, 32, 1");
COMPARE(dinsu_(s6, s7, 63, 1), "7ef6ffc6 dinsu s6, s7, 63, 1");
COMPARE(dinsu_(v0, v1, 32, 32), "7c62f806 dinsu v0, v1, 32, 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");
......
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