Skip to content

Commit

Permalink
Reland "[mips][mt][6/7] Add support for mftr, mttr instructions.""
Browse files Browse the repository at this point in the history
Unlike many other instructions, these instructions have aliases which
take coprocessor registers, gpr register, accumulator (and dsp accumulator)
registers, floating point registers, floating point control registers and
coprocessor 2 data and control operands.

For the moment, these aliases are treated as pseudo instructions which are
expanded into the underlying instruction. As a result, disassembling these
instructions shows the underlying instruction and not the alias.

Reviewers: slthakur, atanasyan

Differential Revision: https://reviews.llvm.org/D35253

The last version of this patch broke one of the expensive checks buildbots,
this version changes the failing test/MC/Mips/mt/invalid.s and other invalid
tests to write the errors to a file and run FileCheck on that, rather than
relying on the 'not llvm-mc ... <%s 2>&1 | Filecheck %s' idiom.

Hopefully this will sarisfy the buildbot.

llvm-svn: 308023
  • Loading branch information
Simon Dardis committed Jul 14, 2017
1 parent 5aae773 commit b352984
Show file tree
Hide file tree
Showing 16 changed files with 573 additions and 27 deletions.
219 changes: 219 additions & 0 deletions llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp
Expand Up @@ -304,6 +304,9 @@ class MipsAsmParser : public MCTargetAsmParser {
bool expandSeqI(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
const MCSubtargetInfo *STI);

bool expandMXTRAlias(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
const MCSubtargetInfo *STI);

bool reportParseError(Twine ErrorMsg);
bool reportParseError(SMLoc Loc, Twine ErrorMsg);

Expand Down Expand Up @@ -2511,6 +2514,16 @@ MipsAsmParser::tryExpandInstruction(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
return expandSeq(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
case Mips::SEQIMacro:
return expandSeqI(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
case Mips::MFTC0: case Mips::MTTC0:
case Mips::MFTGPR: case Mips::MTTGPR:
case Mips::MFTLO: case Mips::MTTLO:
case Mips::MFTHI: case Mips::MTTHI:
case Mips::MFTACX: case Mips::MTTACX:
case Mips::MFTDSP: case Mips::MTTDSP:
case Mips::MFTC1: case Mips::MTTC1:
case Mips::MFTHC1: case Mips::MTTHC1:
case Mips::CFTC1: case Mips::CTTC1:
return expandMXTRAlias(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
}
}

Expand Down Expand Up @@ -4882,6 +4895,212 @@ bool MipsAsmParser::expandSeqI(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
return false;
}

// Map the DSP accumulator and control register to the corresponding gpr
// operand. Unlike the other alias, the m(f|t)t(lo|hi|acx) instructions
// do not map the DSP registers contigously to gpr registers.
static unsigned getRegisterForMxtrDSP(MCInst &Inst, bool IsMFDSP) {
switch (Inst.getOpcode()) {
case Mips::MFTLO:
case Mips::MTTLO:
switch (Inst.getOperand(IsMFDSP ? 1 : 0).getReg()) {
case Mips::AC0:
return Mips::ZERO;
case Mips::AC1:
return Mips::A0;
case Mips::AC2:
return Mips::T0;
case Mips::AC3:
return Mips::T4;
default:
llvm_unreachable("Unknown register for 'mttr' alias!");
}
case Mips::MFTHI:
case Mips::MTTHI:
switch (Inst.getOperand(IsMFDSP ? 1 : 0).getReg()) {
case Mips::AC0:
return Mips::AT;
case Mips::AC1:
return Mips::A1;
case Mips::AC2:
return Mips::T1;
case Mips::AC3:
return Mips::T5;
default:
llvm_unreachable("Unknown register for 'mttr' alias!");
}
case Mips::MFTACX:
case Mips::MTTACX:
switch (Inst.getOperand(IsMFDSP ? 1 : 0).getReg()) {
case Mips::AC0:
return Mips::V0;
case Mips::AC1:
return Mips::A2;
case Mips::AC2:
return Mips::T2;
case Mips::AC3:
return Mips::T6;
default:
llvm_unreachable("Unknown register for 'mttr' alias!");
}
case Mips::MFTDSP:
case Mips::MTTDSP:
return Mips::S0;
default:
llvm_unreachable("Unknown instruction for 'mttr' dsp alias!");
}
}

// Map the floating point register operand to the corresponding register
// operand.
static unsigned getRegisterForMxtrFP(MCInst &Inst, bool IsMFTC1) {
switch (Inst.getOperand(IsMFTC1 ? 1 : 0).getReg()) {
case Mips::F0: return Mips::ZERO;
case Mips::F1: return Mips::AT;
case Mips::F2: return Mips::V0;
case Mips::F3: return Mips::V1;
case Mips::F4: return Mips::A0;
case Mips::F5: return Mips::A1;
case Mips::F6: return Mips::A2;
case Mips::F7: return Mips::A3;
case Mips::F8: return Mips::T0;
case Mips::F9: return Mips::T1;
case Mips::F10: return Mips::T2;
case Mips::F11: return Mips::T3;
case Mips::F12: return Mips::T4;
case Mips::F13: return Mips::T5;
case Mips::F14: return Mips::T6;
case Mips::F15: return Mips::T7;
case Mips::F16: return Mips::S0;
case Mips::F17: return Mips::S1;
case Mips::F18: return Mips::S2;
case Mips::F19: return Mips::S3;
case Mips::F20: return Mips::S4;
case Mips::F21: return Mips::S5;
case Mips::F22: return Mips::S6;
case Mips::F23: return Mips::S7;
case Mips::F24: return Mips::T8;
case Mips::F25: return Mips::T9;
case Mips::F26: return Mips::K0;
case Mips::F27: return Mips::K1;
case Mips::F28: return Mips::GP;
case Mips::F29: return Mips::SP;
case Mips::F30: return Mips::FP;
case Mips::F31: return Mips::RA;
default: llvm_unreachable("Unknown register for mttc1 alias!");
}
}

// Map the coprocessor operand the corresponding gpr register operand.
static unsigned getRegisterForMxtrC0(MCInst &Inst, bool IsMFTC0) {
switch (Inst.getOperand(IsMFTC0 ? 1 : 0).getReg()) {
case Mips::COP00: return Mips::ZERO;
case Mips::COP01: return Mips::AT;
case Mips::COP02: return Mips::V0;
case Mips::COP03: return Mips::V1;
case Mips::COP04: return Mips::A0;
case Mips::COP05: return Mips::A1;
case Mips::COP06: return Mips::A2;
case Mips::COP07: return Mips::A3;
case Mips::COP08: return Mips::T0;
case Mips::COP09: return Mips::T1;
case Mips::COP010: return Mips::T2;
case Mips::COP011: return Mips::T3;
case Mips::COP012: return Mips::T4;
case Mips::COP013: return Mips::T5;
case Mips::COP014: return Mips::T6;
case Mips::COP015: return Mips::T7;
case Mips::COP016: return Mips::S0;
case Mips::COP017: return Mips::S1;
case Mips::COP018: return Mips::S2;
case Mips::COP019: return Mips::S3;
case Mips::COP020: return Mips::S4;
case Mips::COP021: return Mips::S5;
case Mips::COP022: return Mips::S6;
case Mips::COP023: return Mips::S7;
case Mips::COP024: return Mips::T8;
case Mips::COP025: return Mips::T9;
case Mips::COP026: return Mips::K0;
case Mips::COP027: return Mips::K1;
case Mips::COP028: return Mips::GP;
case Mips::COP029: return Mips::SP;
case Mips::COP030: return Mips::FP;
case Mips::COP031: return Mips::RA;
default: llvm_unreachable("Unknown register for mttc0 alias!");
}
}

/// Expand an alias of 'mftr' or 'mttr' into the full instruction, by producing
/// an mftr or mttr with the correctly mapped gpr register, u, sel and h bits.
bool MipsAsmParser::expandMXTRAlias(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
const MCSubtargetInfo *STI) {
MipsTargetStreamer &TOut = getTargetStreamer();
unsigned rd = 0;
unsigned u = 1;
unsigned sel = 0;
unsigned h = 0;
bool IsMFTR = false;
switch (Inst.getOpcode()) {
case Mips::MFTC0:
IsMFTR = true;
LLVM_FALLTHROUGH;
case Mips::MTTC0:
u = 0;
rd = getRegisterForMxtrC0(Inst, IsMFTR);
sel = Inst.getOperand(2).getImm();
break;
case Mips::MFTGPR:
IsMFTR = true;
LLVM_FALLTHROUGH;
case Mips::MTTGPR:
rd = Inst.getOperand(IsMFTR ? 1 : 0).getReg();
break;
case Mips::MFTLO:
case Mips::MFTHI:
case Mips::MFTACX:
case Mips::MFTDSP:
IsMFTR = true;
LLVM_FALLTHROUGH;
case Mips::MTTLO:
case Mips::MTTHI:
case Mips::MTTACX:
case Mips::MTTDSP:
rd = getRegisterForMxtrDSP(Inst, IsMFTR);
sel = 1;
break;
case Mips::MFTHC1:
h = 1;
LLVM_FALLTHROUGH;
case Mips::MFTC1:
IsMFTR = true;
rd = getRegisterForMxtrFP(Inst, IsMFTR);
sel = 2;
break;
case Mips::MTTHC1:
h = 1;
LLVM_FALLTHROUGH;
case Mips::MTTC1:
rd = getRegisterForMxtrFP(Inst, IsMFTR);
sel = 2;
break;
case Mips::CFTC1:
IsMFTR = true;
LLVM_FALLTHROUGH;
case Mips::CTTC1:
rd = getRegisterForMxtrFP(Inst, IsMFTR);
sel = 3;
break;
}
unsigned Op0 = IsMFTR ? Inst.getOperand(0).getReg() : rd;
unsigned Op1 =
IsMFTR ? rd
: (Inst.getOpcode() != Mips::MTTDSP ? Inst.getOperand(1).getReg()
: Inst.getOperand(0).getReg());

TOut.emitRRIII(IsMFTR ? Mips::MFTR : Mips::MTTR, Op0, Op1, u, sel, h, IDLoc,
STI);
return false;
}

unsigned
MipsAsmParser::checkEarlyTargetMatchPredicate(MCInst &Inst,
const OperandVector &Operands) {
Expand Down
15 changes: 15 additions & 0 deletions llvm/lib/Target/Mips/MCTargetDesc/MipsTargetStreamer.cpp
Expand Up @@ -193,6 +193,21 @@ void MipsTargetStreamer::emitRRI(unsigned Opcode, unsigned Reg0, unsigned Reg1,
emitRRX(Opcode, Reg0, Reg1, MCOperand::createImm(Imm), IDLoc, STI);
}

void MipsTargetStreamer::emitRRIII(unsigned Opcode, unsigned Reg0,
unsigned Reg1, int16_t Imm0, int16_t Imm1,
int16_t Imm2, SMLoc IDLoc,
const MCSubtargetInfo *STI) {
MCInst TmpInst;
TmpInst.setOpcode(Opcode);
TmpInst.addOperand(MCOperand::createReg(Reg0));
TmpInst.addOperand(MCOperand::createReg(Reg1));
TmpInst.addOperand(MCOperand::createImm(Imm0));
TmpInst.addOperand(MCOperand::createImm(Imm1));
TmpInst.addOperand(MCOperand::createImm(Imm2));
TmpInst.setLoc(IDLoc);
getStreamer().EmitInstruction(TmpInst, *STI);
}

void MipsTargetStreamer::emitAddu(unsigned DstReg, unsigned SrcReg,
unsigned TrgReg, bool Is64Bit,
const MCSubtargetInfo *STI) {
Expand Down
21 changes: 21 additions & 0 deletions llvm/lib/Target/Mips/MipsMTInstrFormats.td
Expand Up @@ -35,6 +35,8 @@ class FIELD5<bits<5> Val> {
def FIELD5_1_DMT_EMT : FIELD5<0b00001>;
def FIELD5_2_DMT_EMT : FIELD5<0b01111>;
def FIELD5_1_2_DVPE_EVPE : FIELD5<0b00000>;
def FIELD5_MFTR : FIELD5<0b01000>;
def FIELD5_MTTR : FIELD5<0b01100>;

class COP0_MFMC0_MT<FIELD5 Op1, FIELD5 Op2, OPCODE1 sc> : MipsMTInst {
bits<32> Inst;
Expand All @@ -50,6 +52,25 @@ class COP0_MFMC0_MT<FIELD5 Op1, FIELD5 Op2, OPCODE1 sc> : MipsMTInst {
let Inst{2-0} = 0b001;
}

class COP0_MFTTR_MT<FIELD5 Op> : MipsMTInst {
bits<32> Inst;

bits<5> rt;
bits<5> rd;
bits<1> u;
bits<1> h;
bits<3> sel;
let Inst{31-26} = 0b010000; // COP0
let Inst{25-21} = Op.Value; // MFMC0
let Inst{20-16} = rt;
let Inst{15-11} = rd;
let Inst{10-6} = 0b00000; // rx - currently unsupported.
let Inst{5} = u;
let Inst{4} = h;
let Inst{3} = 0b0;
let Inst{2-0} = sel;
}

class SPECIAL3_MT_FORK : MipsMTInst {
bits<32> Inst;

Expand Down

0 comments on commit b352984

Please sign in to comment.