Skip to content

Commit

Permalink
MIPS: Major fixes and clean-up in asm. for instruction encoding.
Browse files Browse the repository at this point in the history
- Fixed single float register type instruction en[de]coding in assembler and disassembler.
- Added max and min instructions for r6 and corresponding tests.
- Fixed selection instruction for boundary cases in simulator.
- Update assembler tests to be more thorough wrt boundary cases.

TEST=cctest/test-assembler-mips64/MIPS17, MIPS18
     cctest/test-disasm-mips64/Type1
     cctest/test-assembler-mips/MIPS16, MIPS17
     cctest/test-disasm-mips/Type1
BUG=

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

Cr-Commit-Position: refs/heads/master@{#27601}
  • Loading branch information
dusan.milosavljevic authored and Commit bot committed Apr 6, 2015
1 parent 2fbfc9f commit 4b5af7b
Show file tree
Hide file tree
Showing 14 changed files with 527 additions and 506 deletions.
39 changes: 25 additions & 14 deletions src/mips/assembler-mips.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1903,28 +1903,39 @@ void Assembler::movf(Register rd, Register rs, uint16_t cc) {
}


void Assembler::seleqz(Register rs, Register rt, Register rd) {
void Assembler::sel(SecondaryField fmt, FPURegister fd, FPURegister fs,
FPURegister ft) {
DCHECK(IsMipsArchVariant(kMips32r6));
DCHECK((fmt == D) || (fmt == S));

Instr instr = COP1 | fmt << kRsShift | ft.code() << kFtShift |
fs.code() << kFsShift | fd.code() << kFdShift | SEL;
emit(instr);
}


void Assembler::seleqz(Register rd, Register rs, Register rt) {
DCHECK(IsMipsArchVariant(kMips32r6));
GenInstrRegister(SPECIAL, rs, rt, rd, 0, SELEQZ_S);
}


void Assembler::seleqz(SecondaryField fmt, FPURegister fd, FPURegister ft,
FPURegister fs) {
void Assembler::seleqz(SecondaryField fmt, FPURegister fd, FPURegister fs,
FPURegister ft) {
DCHECK(IsMipsArchVariant(kMips32r6));
DCHECK((fmt == D) || (fmt == S));
GenInstrRegister(COP1, fmt, ft, fs, fd, SELEQZ_C);
}


void Assembler::selnez(Register rs, Register rt, Register rd) {
void Assembler::selnez(Register rd, Register rs, Register rt) {
DCHECK(IsMipsArchVariant(kMips32r6));
GenInstrRegister(SPECIAL, rs, rt, rd, 0, SELNEZ_S);
}


void Assembler::selnez(SecondaryField fmt, FPURegister fd, FPURegister ft,
FPURegister fs) {
void Assembler::selnez(SecondaryField fmt, FPURegister fd, FPURegister fs,
FPURegister ft) {
DCHECK(IsMipsArchVariant(kMips32r6));
DCHECK((fmt == D) || (fmt == S));
GenInstrRegister(COP1, fmt, ft, fs, fd, SELNEZ_C);
Expand Down Expand Up @@ -2244,32 +2255,32 @@ void Assembler::ceil_l_d(FPURegister fd, FPURegister fs) {
}


void Assembler::min(SecondaryField fmt, FPURegister fd, FPURegister ft,
FPURegister fs) {
void Assembler::min(SecondaryField fmt, FPURegister fd, FPURegister fs,
FPURegister ft) {
DCHECK(IsMipsArchVariant(kMips32r6));
DCHECK((fmt == D) || (fmt == S));
GenInstrRegister(COP1, fmt, ft, fs, fd, MIN);
}


void Assembler::mina(SecondaryField fmt, FPURegister fd, FPURegister ft,
FPURegister fs) {
void Assembler::mina(SecondaryField fmt, FPURegister fd, FPURegister fs,
FPURegister ft) {
DCHECK(IsMipsArchVariant(kMips32r6));
DCHECK((fmt == D) || (fmt == S));
GenInstrRegister(COP1, fmt, ft, fs, fd, MINA);
}


void Assembler::max(SecondaryField fmt, FPURegister fd, FPURegister ft,
FPURegister fs) {
void Assembler::max(SecondaryField fmt, FPURegister fd, FPURegister fs,
FPURegister ft) {
DCHECK(IsMipsArchVariant(kMips32r6));
DCHECK((fmt == D) || (fmt == S));
GenInstrRegister(COP1, fmt, ft, fs, fd, MAX);
}


void Assembler::maxa(SecondaryField fmt, FPURegister fd, FPURegister ft,
FPURegister fs) {
void Assembler::maxa(SecondaryField fmt, FPURegister fd, FPURegister fs,
FPURegister ft) {
DCHECK(IsMipsArchVariant(kMips32r6));
DCHECK((fmt == D) || (fmt == S));
GenInstrRegister(COP1, fmt, ft, fs, fd, MAXA);
Expand Down
23 changes: 11 additions & 12 deletions src/mips/assembler-mips.h
Original file line number Diff line number Diff line change
Expand Up @@ -852,14 +852,13 @@ class Assembler : public AssemblerBase {
void movt(Register rd, Register rs, uint16_t cc = 0);
void movf(Register rd, Register rs, uint16_t cc = 0);

void sel(SecondaryField fmt, FPURegister fd, FPURegister ft,
FPURegister fs, uint8_t sel);
void seleqz(Register rs, Register rt, Register rd);
void seleqz(SecondaryField fmt, FPURegister fd, FPURegister ft,
FPURegister fs);
void selnez(Register rs, Register rt, Register rd);
void selnez(SecondaryField fmt, FPURegister fd, FPURegister ft,
FPURegister fs);
void sel(SecondaryField fmt, FPURegister fd, FPURegister fs, FPURegister ft);
void seleqz(Register rd, Register rs, Register rt);
void seleqz(SecondaryField fmt, FPURegister fd, FPURegister fs,
FPURegister ft);
void selnez(Register rd, Register rs, Register rt);
void selnez(SecondaryField fmt, FPURegister fd, FPURegister fs,
FPURegister ft);

// Bit twiddling.
void clz(Register rd, Register rs);
Expand Down Expand Up @@ -924,10 +923,10 @@ class Assembler : public AssemblerBase {
void ceil_l_s(FPURegister fd, FPURegister fs);
void ceil_l_d(FPURegister fd, FPURegister fs);

void min(SecondaryField fmt, FPURegister fd, FPURegister ft, FPURegister fs);
void mina(SecondaryField fmt, FPURegister fd, FPURegister ft, FPURegister fs);
void max(SecondaryField fmt, FPURegister fd, FPURegister ft, FPURegister fs);
void maxa(SecondaryField fmt, FPURegister fd, FPURegister ft, FPURegister fs);
void min(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 maxa(SecondaryField fmt, FPURegister fd, FPURegister fs, FPURegister ft);

void cvt_s_w(FPURegister fd, FPURegister fs);
void cvt_s_l(FPURegister fd, FPURegister fs);
Expand Down
2 changes: 0 additions & 2 deletions src/mips/constants-mips.cc
Original file line number Diff line number Diff line change
Expand Up @@ -282,8 +282,6 @@ Instruction::Type Instruction::InstructionType() const {
case BC1: // Branch on coprocessor condition.
case BC1EQZ:
case BC1NEZ:
case SELEQZ_C:
case SELNEZ_C:
return kImmediateType;
default:
return kRegisterType;
Expand Down
220 changes: 74 additions & 146 deletions src/mips/disasm-mips.cc
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@ class Decoder {
void DecodeTypeRegisterSRsType(Instruction* instr);
void DecodeTypeRegisterDRsType(Instruction* instr);
void DecodeTypeRegisterLRsType(Instruction* instr);
void DecodeTypeRegisterWRsType(Instruction* instr);
void DecodeTypeRegisterSPECIAL(Instruction* instr);
void DecodeTypeRegisterSPECIAL2(Instruction* instr);
void DecodeTypeRegisterSPECIAL3(Instruction* instr);
Expand Down Expand Up @@ -486,6 +487,27 @@ void Decoder::Unknown(Instruction* instr) {

bool Decoder::DecodeTypeRegisterRsType(Instruction* instr) {
switch (instr->FunctionFieldRaw()) {
case MIN:
Format(instr, "min.'t 'fd, 'fs, 'ft");
break;
case MAX:
Format(instr, "max.'t 'fd, 'fs, 'ft");
break;
case MINA:
Format(instr, "mina.'t 'fd, 'fs, 'ft");
break;
case MAXA:
Format(instr, "maxa.'t 'fd, 'fs, 'ft");
break;
case SEL:
Format(instr, "sel.'t 'fd, 'fs, 'ft");
break;
case SELEQZ_C:
Format(instr, "seleqz.'t 'fd, 'fs, 'ft");
break;
case SELNEZ_C:
Format(instr, "selnez.'t 'fd, 'fs, 'ft");
break;
case ADD_D:
Format(instr, "add.'t 'fd, 'fs, 'ft");
break;
Expand Down Expand Up @@ -630,6 +652,53 @@ void Decoder::DecodeTypeRegisterLRsType(Instruction* instr) {
}


void Decoder::DecodeTypeRegisterWRsType(Instruction* instr) {
switch (instr->FunctionValue()) {
case CVT_S_W: // Convert word to float (single).
Format(instr, "cvt.s.w 'fd, 'fs");
break;
case CVT_D_W: // Convert word to double.
Format(instr, "cvt.d.w 'fd, 'fs");
break;
case CMP_AF:
Format(instr, "cmp.af.s 'fd, 'fs, 'ft");
break;
case CMP_UN:
Format(instr, "cmp.un.s 'fd, 'fs, 'ft");
break;
case CMP_EQ:
Format(instr, "cmp.eq.s 'fd, 'fs, 'ft");
break;
case CMP_UEQ:
Format(instr, "cmp.ueq.s 'fd, 'fs, 'ft");
break;
case CMP_LT:
Format(instr, "cmp.lt.s 'fd, 'fs, 'ft");
break;
case CMP_ULT:
Format(instr, "cmp.ult.s 'fd, 'fs, 'ft");
break;
case CMP_LE:
Format(instr, "cmp.le.s 'fd, 'fs, 'ft");
break;
case CMP_ULE:
Format(instr, "cmp.ule.s 'fd, 'fs, 'ft");
break;
case CMP_OR:
Format(instr, "cmp.or.s 'fd, 'fs, 'ft");
break;
case CMP_UNE:
Format(instr, "cmp.une.s 'fd, 'fs, 'ft");
break;
case CMP_NE:
Format(instr, "cmp.ne.s 'fd, 'fs, 'ft");
break;
default:
UNREACHABLE();
}
}


void Decoder::DecodeTypeRegisterSPECIAL(Instruction* instr) {
switch (instr->FunctionFieldRaw()) {
case JR:
Expand Down Expand Up @@ -805,10 +874,10 @@ void Decoder::DecodeTypeRegisterSPECIAL(Instruction* instr) {
}
break;
case SELEQZ_S:
Format(instr, "seleqz 'rs, 'rt, 'rd");
Format(instr, "seleqz 'rd, 'rs, 'rt");
break;
case SELNEZ_S:
Format(instr, "selnez 'rs, 'rt, 'rd");
Format(instr, "selnez 'rd, 'rs, 'rt");
break;
default:
UNREACHABLE();
Expand Down Expand Up @@ -888,21 +957,12 @@ void Decoder::DecodeTypeRegister(Instruction* instr) {
case D:
DecodeTypeRegisterDRsType(instr);
break;
case W:
switch (instr->FunctionFieldRaw()) {
case CVT_S_W: // Convert word to float (single).
Format(instr, "cvt.s.w 'fd, 'fs");
break;
case CVT_D_W: // Convert word to double.
Format(instr, "cvt.d.w 'fd, 'fs");
break;
default:
UNREACHABLE();
}
break;
case L:
DecodeTypeRegisterLRsType(instr);
break;
case W:
DecodeTypeRegisterWRsType(instr);
break;
case PS:
UNIMPLEMENTED_MIPS();
break;
Expand Down Expand Up @@ -951,138 +1011,6 @@ void Decoder::DecodeTypeImmediate(Instruction* instr) {
case BC1NEZ:
Format(instr, "bc1nez 'ft, 'imm16u");
break;
case W: // CMP.S instruction.
switch (instr->FunctionValue()) {
case CMP_AF:
Format(instr, "cmp.af.S 'ft, 'fs, 'fd");
break;
case CMP_UN:
Format(instr, "cmp.un.S 'ft, 'fs, 'fd");
break;
case CMP_EQ:
Format(instr, "cmp.eq.S 'ft, 'fs, 'fd");
break;
case CMP_UEQ:
Format(instr, "cmp.ueq.S 'ft, 'fs, 'fd");
break;
case CMP_LT:
Format(instr, "cmp.lt.S 'ft, 'fs, 'fd");
break;
case CMP_ULT:
Format(instr, "cmp.ult.S 'ft, 'fs, 'fd");
break;
case CMP_LE:
Format(instr, "cmp.le.S 'ft, 'fs, 'fd");
break;
case CMP_ULE:
Format(instr, "cmp.ule.S 'ft, 'fs, 'fd");
break;
case CMP_OR:
Format(instr, "cmp.or.S 'ft, 'fs, 'fd");
break;
case CMP_UNE:
Format(instr, "cmp.une.S 'ft, 'fs, 'fd");
break;
case CMP_NE:
Format(instr, "cmp.ne.S 'ft, 'fs, 'fd");
break;
default:
UNREACHABLE();
}
break;
case L: // CMP.D instruction.
switch (instr->FunctionValue()) {
case CMP_AF:
Format(instr, "cmp.af.D 'ft, 'fs, 'fd");
break;
case CMP_UN:
Format(instr, "cmp.un.D 'ft, 'fs, 'fd");
break;
case CMP_EQ:
Format(instr, "cmp.eq.D 'ft, 'fs, 'fd");
break;
case CMP_UEQ:
Format(instr, "cmp.ueq.D 'ft, 'fs, 'fd");
break;
case CMP_LT:
Format(instr, "cmp.lt.D 'ft, 'fs, 'fd");
break;
case CMP_ULT:
Format(instr, "cmp.ult.D 'ft, 'fs, 'fd");
break;
case CMP_LE:
Format(instr, "cmp.le.D 'ft, 'fs, 'fd");
break;
case CMP_ULE:
Format(instr, "cmp.ule.D 'ft, 'fs, 'fd");
break;
case CMP_OR:
Format(instr, "cmp.or.D 'ft, 'fs, 'fd");
break;
case CMP_UNE:
Format(instr, "cmp.une.D 'ft, 'fs, 'fd");
break;
case CMP_NE:
Format(instr, "cmp.ne.D 'ft, 'fs, 'fd");
break;
default:
UNREACHABLE();
}
break;
case S:
switch (instr->FunctionValue()) {
case SEL:
Format(instr, "sel.S 'ft, 'fs, 'fd");
break;
case SELEQZ_C:
Format(instr, "seleqz.S 'ft, 'fs, 'fd");
break;
case SELNEZ_C:
Format(instr, "selnez.S 'ft, 'fs, 'fd");
break;
case MIN:
Format(instr, "min.S 'ft, 'fs, 'fd");
break;
case MINA:
Format(instr, "mina.S 'ft, 'fs, 'fd");
break;
case MAX:
Format(instr, "max.S 'ft, 'fs, 'fd");
break;
case MAXA:
Format(instr, "maxa.S 'ft, 'fs, 'fd");
break;
default:
UNREACHABLE();
}
break;
case D:
switch (instr->FunctionValue()) {
case SEL:
Format(instr, "sel.D 'ft, 'fs, 'fd");
break;
case SELEQZ_C:
Format(instr, "seleqz.D 'ft, 'fs, 'fd");
break;
case SELNEZ_C:
Format(instr, "selnez.D 'ft, 'fs, 'fd");
break;
case MIN:
Format(instr, "min.D 'ft, 'fs, 'fd");
break;
case MINA:
Format(instr, "mina.D 'ft, 'fs, 'fd");
break;
case MAX:
Format(instr, "max.D 'ft, 'fs, 'fd");
break;
case MAXA:
Format(instr, "maxa.D 'ft, 'fs, 'fd");
break;
default:
UNREACHABLE();
}
break;
default:
UNREACHABLE();
}
Expand Down
Loading

0 comments on commit 4b5af7b

Please sign in to comment.