Commit b4d5c651 authored by Simon Dardis's avatar Simon Dardis
Browse files

Merging r318207:

------------------------------------------------------------------------
r318207 | sdardis | 2017-11-14 22:26:42 +0000 (Tue, 14 Nov 2017) | 18 lines

Reland "[mips][mt][6/7] Add support for mftr, mttr instructions."

This adjusts the tests to hopfully pacify the
llvm-clang-x86_64-expensive-checks-win buildbot.

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

------------------------------------------------------------------------

llvm-svn: 318386
parent 5c325eae
Loading
Loading
Loading
Loading
+219 −0
Original line number Diff line number Diff line
@@ -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);

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

@@ -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) {
+15 −0
Original line number Diff line number Diff line
@@ -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) {
+21 −0
Original line number Diff line number Diff line
@@ -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;
@@ -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;

+110 −0
Original line number Diff line number Diff line
@@ -6,6 +6,13 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file describes the MIPS MT ASE as defined by MD00378 1.12.
//
// TODO: Add support for the microMIPS encodings for the MT ASE and add the
//       instruction mappings.
//
//===----------------------------------------------------------------------===//

//===----------------------------------------------------------------------===//
// MIPS MT Instruction Encodings
@@ -27,6 +34,10 @@ class FORK_ENC : SPECIAL3_MT_FORK;

class YIELD_ENC : SPECIAL3_MT_YIELD;

class MFTR_ENC : COP0_MFTTR_MT<FIELD5_MFTR>;

class MTTR_ENC : COP0_MFTTR_MT<FIELD5_MTTR>;

//===----------------------------------------------------------------------===//
// MIPS MT Instruction Descriptions
//===----------------------------------------------------------------------===//
@@ -39,6 +50,22 @@ class MT_1R_DESC_BASE<string instr_asm, InstrItinClass Itin = NoItinerary> {
  InstrItinClass Itinerary = Itin;
}

class MFTR_DESC {
  dag OutOperandList = (outs GPR32Opnd:$rd);
  dag InOperandList = (ins GPR32Opnd:$rt, uimm1:$u, uimm3:$sel, uimm1:$h);
  string AsmString = "mftr\t$rd, $rt, $u, $sel, $h";
  list<dag> Pattern = [];
  InstrItinClass Itinerary = II_MFTR;
}

class MTTR_DESC {
  dag OutOperandList = (outs GPR32Opnd:$rd);
  dag InOperandList = (ins GPR32Opnd:$rt, uimm1:$u, uimm3:$sel, uimm1:$h);
  string AsmString = "mttr\t$rt, $rd, $u, $sel, $h";
  list<dag> Pattern = [];
  InstrItinClass Itinerary = II_MTTR;
}

class FORK_DESC {
  dag OutOperandList = (outs GPR32Opnd:$rs, GPR32Opnd:$rd);
  dag InOperandList = (ins GPR32Opnd:$rt);
@@ -79,8 +106,73 @@ let hasSideEffects = 1, isNotDuplicable = 1,
  def FORK : FORK_ENC, FORK_DESC, ASE_MT;

  def YIELD : YIELD_ENC, YIELD_DESC, ASE_MT;

  def MFTR : MFTR_ENC, MFTR_DESC, ASE_MT;

  def MTTR : MTTR_ENC, MTTR_DESC, ASE_MT;
}

//===----------------------------------------------------------------------===//
// MIPS MT Pseudo Instructions - used to support mtfr & mttr aliases.
//===----------------------------------------------------------------------===//
def MFTC0 : MipsAsmPseudoInst<(outs GPR32Opnd:$rd), (ins COP0Opnd:$rt,
                                                        uimm3:$sel),
                              "mftc0 $rd, $rt, $sel">, ASE_MT;

def MFTGPR : MipsAsmPseudoInst<(outs GPR32Opnd:$rd), (ins GPR32Opnd:$rt,
                                                          uimm3:$sel),
                               "mftgpr $rd, $rt">, ASE_MT;

def MFTLO : MipsAsmPseudoInst<(outs GPR32Opnd:$rt), (ins ACC64DSPOpnd:$ac),
                              "mftlo $rt, $ac">, ASE_MT;

def MFTHI : MipsAsmPseudoInst<(outs GPR32Opnd:$rt), (ins ACC64DSPOpnd:$ac),
                              "mfthi $rt, $ac">, ASE_MT;

def MFTACX : MipsAsmPseudoInst<(outs GPR32Opnd:$rt), (ins ACC64DSPOpnd:$ac),
                               "mftacx $rt, $ac">, ASE_MT;

def MFTDSP : MipsAsmPseudoInst<(outs GPR32Opnd:$rt), (ins),
                               "mftdsp $rt">, ASE_MT;

def MFTC1 : MipsAsmPseudoInst<(outs GPR32Opnd:$rt), (ins FGR32Opnd:$ft),
                              "mftc1 $rt, $ft">, ASE_MT;

def MFTHC1 : MipsAsmPseudoInst<(outs GPR32Opnd:$rt), (ins FGR32Opnd:$ft),
                               "mfthc1 $rt, $ft">, ASE_MT;

def CFTC1 : MipsAsmPseudoInst<(outs GPR32Opnd:$rt), (ins FGRCCOpnd:$ft),
                              "cftc1 $rt, $ft">, ASE_MT;


def MTTC0 : MipsAsmPseudoInst<(outs COP0Opnd:$rd), (ins GPR32Opnd:$rt,
                                                        uimm3:$sel),
                              "mttc0 $rt, $rd, $sel">, ASE_MT;

def MTTGPR : MipsAsmPseudoInst<(outs GPR32Opnd:$rt), (ins GPR32Opnd:$rd),
                               "mttgpr $rd, $rt">, ASE_MT;

def MTTLO : MipsAsmPseudoInst<(outs ACC64DSPOpnd:$ac), (ins GPR32Opnd:$rt),
                              "mttlo $rt, $ac">, ASE_MT;

def MTTHI : MipsAsmPseudoInst<(outs ACC64DSPOpnd:$ac), (ins GPR32Opnd:$rt),
                              "mtthi $rt, $ac">, ASE_MT;

def MTTACX : MipsAsmPseudoInst<(outs ACC64DSPOpnd:$ac), (ins GPR32Opnd:$rt),
                               "mttacx $rt, $ac">, ASE_MT;

def MTTDSP : MipsAsmPseudoInst<(outs), (ins GPR32Opnd:$rt),
                               "mttdsp $rt">, ASE_MT;

def MTTC1 : MipsAsmPseudoInst<(outs FGR32Opnd:$ft), (ins GPR32Opnd:$rt),
                              "mttc1 $rt, $ft">, ASE_MT;

def MTTHC1 : MipsAsmPseudoInst<(outs FGR32Opnd:$ft), (ins GPR32Opnd:$rt),
                               "mtthc1 $rt, $ft">, ASE_MT;

def CTTC1 : MipsAsmPseudoInst<(outs FGRCCOpnd:$ft), (ins GPR32Opnd:$rt),
                              "cttc1 $rt, $ft">, ASE_MT;

//===----------------------------------------------------------------------===//
// MIPS MT Instruction Definitions
//===----------------------------------------------------------------------===//
@@ -95,4 +187,22 @@ let AdditionalPredicates = [NotInMicroMips] in {
  def : MipsInstAlias<"evpe", (EVPE ZERO), 1>, ASE_MT;

  def : MipsInstAlias<"yield $rs", (YIELD ZERO, GPR32Opnd:$rs), 1>, ASE_MT;

  def : MipsInstAlias<"mftc0 $rd, $rt", (MFTC0 GPR32Opnd:$rd, COP0Opnd:$rt, 0),
                      1>, ASE_MT;

  def : MipsInstAlias<"mftlo $rt", (MFTLO GPR32Opnd:$rt, AC0), 1>, ASE_MT;

  def : MipsInstAlias<"mfthi $rt", (MFTHI GPR32Opnd:$rt, AC0), 1>, ASE_MT;

  def : MipsInstAlias<"mftacx $rt", (MFTACX GPR32Opnd:$rt, AC0), 1>, ASE_MT;

  def : MipsInstAlias<"mttc0 $rd, $rt", (MTTC0 COP0Opnd:$rt, GPR32Opnd:$rd, 0),
                      1>, ASE_MT;

  def : MipsInstAlias<"mttlo $rt", (MTTLO AC0, GPR32Opnd:$rt), 1>, ASE_MT;

  def : MipsInstAlias<"mtthi $rt", (MTTHI AC0, GPR32Opnd:$rt), 1>, ASE_MT;

  def : MipsInstAlias<"mttacx $rt", (MTTACX AC0, GPR32Opnd:$rt), 1>, ASE_MT;
}
+4 −0
Original line number Diff line number Diff line
@@ -226,6 +226,7 @@ def II_MFC1 : InstrItinClass;
def II_MFHC1            : InstrItinClass;
def II_MFC2             : InstrItinClass;
def II_MFHI_MFLO        : InstrItinClass; // mfhi and mflo
def II_MFTR             : InstrItinClass;
def II_MOD              : InstrItinClass;
def II_MODU             : InstrItinClass;
def II_MOVE             : InstrItinClass;
@@ -255,6 +256,7 @@ def II_MTC1 : InstrItinClass;
def II_MTHC1            : InstrItinClass;
def II_MTC2             : InstrItinClass;
def II_MTHI_MTLO        : InstrItinClass; // mthi and mtlo
def II_MTTR             : InstrItinClass;
def II_MUL              : InstrItinClass;
def II_MUH              : InstrItinClass;
def II_MUHU             : InstrItinClass;
@@ -664,12 +666,14 @@ def MipsGenericItineraries : ProcessorItineraries<[ALU, IMULDIV], [], [
  InstrItinData<II_MFHC0           , [InstrStage<2,  [ALU]>]>,
  InstrItinData<II_MFC1            , [InstrStage<2,  [ALU]>]>,
  InstrItinData<II_MFC2            , [InstrStage<2,  [ALU]>]>,
  InstrItinData<II_MFTR            , [InstrStage<2,  [ALU]>]>,
  InstrItinData<II_MTC0            , [InstrStage<2,  [ALU]>]>,
  InstrItinData<II_MTHC0           , [InstrStage<2,  [ALU]>]>,
  InstrItinData<II_MTC1            , [InstrStage<2,  [ALU]>]>,
  InstrItinData<II_MTC2            , [InstrStage<2,  [ALU]>]>,
  InstrItinData<II_MFHC1           , [InstrStage<2,  [ALU]>]>,
  InstrItinData<II_MTHC1           , [InstrStage<2,  [ALU]>]>,
  InstrItinData<II_MTTR            , [InstrStage<2,  [ALU]>]>,
  InstrItinData<II_CACHE           , [InstrStage<1,  [ALU]>]>,
  InstrItinData<II_PREF            , [InstrStage<1,  [ALU]>]>,
  InstrItinData<II_CACHEE          , [InstrStage<1,  [ALU]>]>,
Loading