Skip to content

Commit

Permalink
MIPS64: Add/fix bit insertion/extraction instrs.
Browse files Browse the repository at this point in the history
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}
  • Loading branch information
Miran.Karic authored and Commit bot committed May 10, 2017
1 parent 755a809 commit 838d0b4
Show file tree
Hide file tree
Showing 10 changed files with 274 additions and 157 deletions.
17 changes: 3 additions & 14 deletions src/compiler/mips64/code-generator-mips64.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down Expand Up @@ -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);
Expand Down
33 changes: 22 additions & 11 deletions src/mips64/assembler-mips64.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -2517,47 +2517,58 @@ 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);
}


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);
}


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);
}
Expand Down
6 changes: 4 additions & 2 deletions src/mips64/assembler-mips64.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
2 changes: 2 additions & 0 deletions src/mips64/constants-mips64.h
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
90 changes: 65 additions & 25 deletions src/mips64/disasm-mips64.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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);
}


Expand Down Expand Up @@ -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;
}
}
}
Expand Down Expand Up @@ -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;
Expand All @@ -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: {
Expand Down Expand Up @@ -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) {
Expand Down
68 changes: 22 additions & 46 deletions src/mips64/macro-assembler-mips64.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
}


Expand All @@ -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.
Expand Down
9 changes: 2 additions & 7 deletions src/mips64/macro-assembler-mips64.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down
Loading

0 comments on commit 838d0b4

Please sign in to comment.