diff options
| author | Zlatko Buljan <Zlatko.Buljan@imgtec.com> | 2015-11-12 13:21:33 +0000 | 
|---|---|---|
| committer | Zlatko Buljan <Zlatko.Buljan@imgtec.com> | 2015-11-12 13:21:33 +0000 | 
| commit | 797c2aec6b776f2efbe5cb49039301329cca11b1 (patch) | |
| tree | 22d9599d66372a5876ec4d43ff8e9fee1cf5d12c | |
| parent | d38860610da955e7013479106075e30c11814bb4 (diff) | |
| download | bcm5719-llvm-797c2aec6b776f2efbe5cb49039301329cca11b1.tar.gz bcm5719-llvm-797c2aec6b776f2efbe5cb49039301329cca11b1.zip  | |
[mips][microMIPS] Implement LWM16, SB16, SH16, SW16, SWSP and SWM16 instructions
Differential Revision: http://reviews.llvm.org/D11406
llvm-svn: 252885
| -rw-r--r-- | llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp | 48 | ||||
| -rw-r--r-- | llvm/lib/Target/Mips/Disassembler/MipsDisassembler.cpp | 28 | ||||
| -rw-r--r-- | llvm/lib/Target/Mips/InstPrinter/MipsInstPrinter.cpp | 2 | ||||
| -rw-r--r-- | llvm/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp | 2 | ||||
| -rw-r--r-- | llvm/lib/Target/Mips/MicroMips32r6InstrFormats.td | 12 | ||||
| -rw-r--r-- | llvm/lib/Target/Mips/MicroMips32r6InstrInfo.td | 67 | ||||
| -rw-r--r-- | llvm/lib/Target/Mips/MicroMipsInstrFormats.td | 2 | ||||
| -rw-r--r-- | llvm/lib/Target/Mips/MicroMipsInstrInfo.td | 10 | ||||
| -rw-r--r-- | llvm/test/MC/Disassembler/Mips/micromips32r6/valid.txt | 7 | ||||
| -rw-r--r-- | llvm/test/MC/Disassembler/Mips/micromips64r6/valid.txt | 7 | ||||
| -rw-r--r-- | llvm/test/MC/Mips/micromips32r6/invalid.s | 28 | ||||
| -rw-r--r-- | llvm/test/MC/Mips/micromips32r6/valid.s | 9 | ||||
| -rw-r--r-- | llvm/test/MC/Mips/micromips64r6/invalid.s | 28 | ||||
| -rw-r--r-- | llvm/test/MC/Mips/micromips64r6/valid.s | 9 | 
14 files changed, 242 insertions, 17 deletions
diff --git a/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp b/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp index d89d6ce8f47..f4710459770 100644 --- a/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp +++ b/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp @@ -1007,8 +1007,13 @@ public:        return false;      int Size = RegList.List->size(); -    if (Size < 2 || Size > 5 || *RegList.List->begin() != Mips::S0 || -        RegList.List->back() != Mips::RA) +    if (Size < 2 || Size > 5) +      return false; + +    unsigned R0 = RegList.List->front(); +    unsigned R1 = RegList.List->back(); +    if (!((R0 == Mips::S0 && R1 == Mips::RA) || +          (R0 == Mips::S0_64 && R1 == Mips::RA_64)))        return false;      int PrevReg = *RegList.List->begin(); @@ -1841,6 +1846,7 @@ bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,        case Mips::TLTU_MM:        case Mips::TNE_MM:        case Mips::SB16_MM: +      case Mips::SB16_MMR6:          Opnd = Inst.getOperand(2);          if (!Opnd.isImm())            return Error(IDLoc, "expected immediate operand kind"); @@ -1850,6 +1856,7 @@ bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,          break;        case Mips::LHU16_MM:        case Mips::SH16_MM: +      case Mips::SH16_MMR6:          Opnd = Inst.getOperand(2);          if (!Opnd.isImm())            return Error(IDLoc, "expected immediate operand kind"); @@ -1859,6 +1866,7 @@ bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,          break;        case Mips::LW16_MM:        case Mips::SW16_MM: +      case Mips::SW16_MMR6:          Opnd = Inst.getOperand(2);          if (!Opnd.isImm())            return Error(IDLoc, "expected immediate operand kind"); @@ -2612,10 +2620,16 @@ MipsAsmParser::expandLoadStoreMultiple(MCInst &Inst, SMLoc IDLoc,    if (OpNum < 8 && Inst.getOperand(OpNum - 1).getImm() <= 60 &&        Inst.getOperand(OpNum - 1).getImm() >= 0 && -      Inst.getOperand(OpNum - 2).getReg() == Mips::SP && -      Inst.getOperand(OpNum - 3).getReg() == Mips::RA) +      (Inst.getOperand(OpNum - 2).getReg() == Mips::SP || +       Inst.getOperand(OpNum - 2).getReg() == Mips::SP_64) && +      (Inst.getOperand(OpNum - 3).getReg() == Mips::RA || +       Inst.getOperand(OpNum - 3).getReg() == Mips::RA_64)) {      // It can be implemented as SWM16 or LWM16 instruction. -    NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM16_MM : Mips::LWM16_MM; +    if (inMicroMipsMode() && hasMips32r6()) +      NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM16_MMR6 : Mips::LWM16_MMR6; +    else +      NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM16_MM : Mips::LWM16_MM; +  }    Inst.setOpcode(NewOpcode);    Instructions.push_back(Inst); @@ -4145,12 +4159,15 @@ MipsAsmParser::parseRegisterList(OperandVector &Operands) {      if (RegRange) {        // Remove last register operand because registers from register range        // should be inserted first. -      if (RegNo == Mips::RA) { +      if ((isGP64bit() && RegNo == Mips::RA_64) || +          (!isGP64bit() && RegNo == Mips::RA)) {          Regs.push_back(RegNo);        } else {          unsigned TmpReg = PrevReg + 1;          while (TmpReg <= RegNo) { -          if ((TmpReg < Mips::S0) || (TmpReg > Mips::S7)) { +          if ((((TmpReg < Mips::S0) || (TmpReg > Mips::S7)) && !isGP64bit()) || +              (((TmpReg < Mips::S0_64) || (TmpReg > Mips::S7_64)) && +               isGP64bit())) {              Error(E, "invalid register operand");              return MatchOperand_ParseFail;            } @@ -4162,16 +4179,23 @@ MipsAsmParser::parseRegisterList(OperandVector &Operands) {        RegRange = false;      } else { -      if ((PrevReg == Mips::NoRegister) && (RegNo != Mips::S0) && -          (RegNo != Mips::RA)) { +      if ((PrevReg == Mips::NoRegister) && +          ((isGP64bit() && (RegNo != Mips::S0_64) && (RegNo != Mips::RA_64)) || +          (!isGP64bit() && (RegNo != Mips::S0) && (RegNo != Mips::RA)))) {          Error(E, "$16 or $31 expected");          return MatchOperand_ParseFail; -      } else if (((RegNo < Mips::S0) || (RegNo > Mips::S7)) && -                 (RegNo != Mips::FP) && (RegNo != Mips::RA)) { +      } else if (!(((RegNo == Mips::FP || RegNo == Mips::RA || +                    (RegNo >= Mips::S0 && RegNo <= Mips::S7)) && +                    !isGP64bit()) || +                   ((RegNo == Mips::FP_64 || RegNo == Mips::RA_64 || +                    (RegNo >= Mips::S0_64 && RegNo <= Mips::S7_64)) && +                    isGP64bit()))) {          Error(E, "invalid register operand");          return MatchOperand_ParseFail;        } else if ((PrevReg != Mips::NoRegister) && (RegNo != PrevReg + 1) && -                 (RegNo != Mips::FP) && (RegNo != Mips::RA)) { +                 ((RegNo != Mips::FP && RegNo != Mips::RA && !isGP64bit()) || +                  (RegNo != Mips::FP_64 && RegNo != Mips::RA_64 && +                   isGP64bit()))) {          Error(E, "consecutive register numbers expected");          return MatchOperand_ParseFail;        } diff --git a/llvm/lib/Target/Mips/Disassembler/MipsDisassembler.cpp b/llvm/lib/Target/Mips/Disassembler/MipsDisassembler.cpp index 6332e1d52c4..f25df1ef715 100644 --- a/llvm/lib/Target/Mips/Disassembler/MipsDisassembler.cpp +++ b/llvm/lib/Target/Mips/Disassembler/MipsDisassembler.cpp @@ -1380,8 +1380,11 @@ static DecodeStatus DecodeMemMMImm4(MCInst &Inst,          return MCDisassembler::Fail;        break;      case Mips::SB16_MM: +    case Mips::SB16_MMR6:      case Mips::SH16_MM: +    case Mips::SH16_MMR6:      case Mips::SW16_MM: +    case Mips::SW16_MMR6:        if (DecodeGPRMM16ZeroRegisterClass(Inst, Reg, Address, Decoder)              == MCDisassembler::Fail)          return MCDisassembler::Fail; @@ -1400,14 +1403,17 @@ static DecodeStatus DecodeMemMMImm4(MCInst &Inst,          Inst.addOperand(MCOperand::createImm(Offset));        break;      case Mips::SB16_MM: +    case Mips::SB16_MMR6:        Inst.addOperand(MCOperand::createImm(Offset));        break;      case Mips::LHU16_MM:      case Mips::SH16_MM: +    case Mips::SH16_MMR6:        Inst.addOperand(MCOperand::createImm(Offset << 1));        break;      case Mips::LW16_MM:      case Mips::SW16_MM: +    case Mips::SW16_MMR6:        Inst.addOperand(MCOperand::createImm(Offset << 2));        break;    } @@ -1451,7 +1457,16 @@ static DecodeStatus DecodeMemMMReglistImm4Lsl2(MCInst &Inst,                                                 unsigned Insn,                                                 uint64_t Address,                                                 const void *Decoder) { -  int Offset = SignExtend32<4>(Insn & 0xf); +  int Offset; +  switch (Inst.getOpcode()) { +  case Mips::LWM16_MMR6: +  case Mips::SWM16_MMR6: +    Offset = fieldFromInstruction(Insn, 4, 4); +    break; +  default: +    Offset = SignExtend32<4>(Insn & 0xf); +    break; +  }    if (DecodeRegListOperand16(Inst, Insn, Address, Decoder)        == MCDisassembler::Fail) @@ -2009,7 +2024,16 @@ static DecodeStatus DecodeRegListOperand16(MCInst &Inst, unsigned Insn,                                             uint64_t Address,                                             const void *Decoder) {    unsigned Regs[] = {Mips::S0, Mips::S1, Mips::S2, Mips::S3}; -  unsigned RegLst = fieldFromInstruction(Insn, 4, 2); +  unsigned RegLst; +  switch(Inst.getOpcode()) { +  default: +    RegLst = fieldFromInstruction(Insn, 4, 2); +    break; +  case Mips::LWM16_MMR6: +  case Mips::SWM16_MMR6: +    RegLst = fieldFromInstruction(Insn, 8, 2); +    break; +  }    unsigned RegNum = RegLst & 0x3;    for (unsigned i = 0; i <= RegNum; i++) diff --git a/llvm/lib/Target/Mips/InstPrinter/MipsInstPrinter.cpp b/llvm/lib/Target/Mips/InstPrinter/MipsInstPrinter.cpp index a5637b16b63..a7b7d2e080e 100644 --- a/llvm/lib/Target/Mips/InstPrinter/MipsInstPrinter.cpp +++ b/llvm/lib/Target/Mips/InstPrinter/MipsInstPrinter.cpp @@ -235,7 +235,9 @@ printMemOperand(const MCInst *MI, int opNum, raw_ostream &O) {    case Mips::SWM32_MM:    case Mips::LWM32_MM:    case Mips::SWM16_MM: +  case Mips::SWM16_MMR6:    case Mips::LWM16_MM: +  case Mips::LWM16_MMR6:      opNum = MI->getNumOperands() - 2;      break;    } diff --git a/llvm/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp b/llvm/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp index 861049f000f..86a5d588218 100644 --- a/llvm/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp +++ b/llvm/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp @@ -832,7 +832,9 @@ getMemEncodingMMImm4sp(const MCInst &MI, unsigned OpNo,    default:      break;    case Mips::SWM16_MM: +  case Mips::SWM16_MMR6:    case Mips::LWM16_MM: +  case Mips::LWM16_MMR6:      OpNo = MI.getNumOperands() - 2;      break;    } diff --git a/llvm/lib/Target/Mips/MicroMips32r6InstrFormats.td b/llvm/lib/Target/Mips/MicroMips32r6InstrFormats.td index 779b00b71a6..c4cdb0c2fad 100644 --- a/llvm/lib/Target/Mips/MicroMips32r6InstrFormats.td +++ b/llvm/lib/Target/Mips/MicroMips32r6InstrFormats.td @@ -62,6 +62,18 @@ class POOL16C_JRCADDIUSP_FM_MM16R6<bits<5> op> {    let Inst{4-0}   = op;  } +class POOL16C_LWM_SWM_FM_MM16R6<bits<4> funct> { +  bits<2> rt; +  bits<4> addr; + +  bits<16> Inst; + +  let Inst{15-10} = 0x11; +  let Inst{9-8}   = rt; +  let Inst{7-4}   = addr; +  let Inst{3-0}   = funct; +} +  class POOL32A_BITSWAP_FM_MMR6<bits<6> funct> : MipsR6Inst {    bits<5> rd;    bits<5> rt; diff --git a/llvm/lib/Target/Mips/MicroMips32r6InstrInfo.td b/llvm/lib/Target/Mips/MicroMips32r6InstrInfo.td index 572ba784c0d..cabaa53b2b1 100644 --- a/llvm/lib/Target/Mips/MicroMips32r6InstrInfo.td +++ b/llvm/lib/Target/Mips/MicroMips32r6InstrInfo.td @@ -55,6 +55,7 @@ class JRC16_MMR6_ENC: POOL16C_JALRC_FM_MM16R6<0x3>;  class JRCADDIUSP_MMR6_ENC : POOL16C_JRCADDIUSP_FM_MM16R6<0x13>;  class LSA_MMR6_ENC : POOL32A_LSA_FM<0b001111>;  class LWPC_MMR6_ENC  : PCREL19_FM_MMR6<0b01>; +class LWM16_MMR6_ENC : POOL16C_LWM_SWM_FM_MM16R6<0x2>;  class MOD_MMR6_ENC : ARITH_FM_MMR6<"mod", 0x158>;  class MODU_MMR6_ENC : ARITH_FM_MMR6<"modu", 0x1d8>;  class MUL_MMR6_ENC : ARITH_FM_MMR6<"mul", 0x18>; @@ -65,15 +66,20 @@ class NOR_MMR6_ENC : ARITH_FM_MMR6<"nor", 0x2d0>;  class OR_MMR6_ENC : ARITH_FM_MMR6<"or", 0x290>;  class ORI_MMR6_ENC : ADDI_FM_MMR6<"ori", 0x14>;  class PREF_MMR6_ENC : CACHE_PREF_FM_MMR6<0b011000, 0b0010>; +class SB16_MMR6_ENC : LOAD_STORE_FM_MM16<0x22>;  class SEB_MMR6_ENC : SIGN_EXTEND_FM_MMR6<"seb", 0b0010101100>;  class SEH_MMR6_ENC : SIGN_EXTEND_FM_MMR6<"seh", 0b0011101100>;  class SELEQZ_MMR6_ENC : POOL32A_FM_MMR6<0b0101000000>;  class SELNEZ_MMR6_ENC : POOL32A_FM_MMR6<0b0110000000>; +class SH16_MMR6_ENC : LOAD_STORE_FM_MM16<0x2a>;  class SLL_MMR6_ENC : SHIFT_MMR6_ENC<"sll", 0x00, 0b0>;  class SUB_MMR6_ENC : ARITH_FM_MMR6<"sub", 0x190>;  class SUBU_MMR6_ENC : ARITH_FM_MMR6<"subu", 0x1d0>;  class SW_MMR6_ENC : SW32_FM_MMR6<"sw", 0x3e>;  class SWE_MMR6_ENC : POOL32C_SWE_FM_MMR6<"swe", 0x18, 0xa, 0x7>; +class SW16_MMR6_ENC : LOAD_STORE_FM_MM16<0x3a>; +class SWM16_MMR6_ENC : POOL16C_LWM_SWM_FM_MM16R6<0xa>; +class SWSP_MMR6_ENC : LOAD_STORE_SP_FM_MM16<0x32>;  class PREFE_MMR6_ENC : POOL32C_ST_EVA_FM_MMR6<0b011000, 0b010>;  class CACHEE_MMR6_ENC : POOL32C_ST_EVA_FM_MMR6<0b011000, 0b011>;  class WRPGPR_MMR6_ENC : POOL32A_WRPGPR_WSBH_FM_MMR6<0x3c5>; @@ -814,6 +820,52 @@ class SDBBP_MMR6_DESC : MipsR6Inst {    list<dag> Pattern = [];  } +class LWM16_MMR6_DESC +    : MicroMipsInst16<(outs reglist16:$rt), (ins mem_mm_4sp:$addr), +                      !strconcat("lwm16", "\t$rt, $addr"), [], +                      NoItinerary, FrmI>, +      MMR6Arch<"lwm16">, MicroMipsR6Inst16 { +  let DecoderMethod = "DecodeMemMMReglistImm4Lsl2"; +  let mayLoad = 1; +  InstrItinClass Itin = NoItinerary; +  ComplexPattern Addr = addr; +} + +class SWM16_MMR6_DESC +    : MicroMipsInst16<(outs), (ins reglist16:$rt, mem_mm_4sp:$addr), +                      !strconcat("swm16", "\t$rt, $addr"), [], +                      NoItinerary, FrmI>, +      MMR6Arch<"swm16">, MicroMipsR6Inst16 { +  let DecoderMethod = "DecodeMemMMReglistImm4Lsl2"; +  let mayStore = 1; +  InstrItinClass Itin = NoItinerary; +  ComplexPattern Addr = addr; +} + +class SB16_MMR6_DESC_BASE<string opstr, DAGOperand RTOpnd, DAGOperand RO, +                          SDPatternOperator OpNode, InstrItinClass Itin, +                          Operand MemOpnd> +    : MicroMipsInst16<(outs), (ins RTOpnd:$rt, MemOpnd:$addr), +                      !strconcat(opstr, "\t$rt, $addr"), [], Itin, FrmI>, +      MMR6Arch<opstr>, MicroMipsR6Inst16 { +  let DecoderMethod = "DecodeMemMMImm4"; +  let mayStore = 1; +} +class SB16_MMR6_DESC : SB16_MMR6_DESC_BASE<"sb16", GPRMM16OpndZero, GPRMM16Opnd, +                                           truncstorei8, II_SB, mem_mm_4>; +class SH16_MMR6_DESC : SB16_MMR6_DESC_BASE<"sh16", GPRMM16OpndZero, GPRMM16Opnd, +                                           truncstorei16, II_SH, mem_mm_4_lsl1>; +class SW16_MMR6_DESC : SB16_MMR6_DESC_BASE<"sw16", GPRMM16OpndZero, GPRMM16Opnd, +                                           store, II_SW, mem_mm_4_lsl2>; + +class SWSP_MMR6_DESC +    : MicroMipsInst16<(outs), (ins GPR32Opnd:$rt, mem_mm_sp_imm5_lsl2:$offset), +                      !strconcat("sw", "\t$rt, $offset"), [], II_SW, FrmI>, +      MMR6Arch<"sw">, MicroMipsR6Inst16 { +  let DecoderMethod = "DecodeMemMMSPImm5Lsl2"; +  let mayStore = 1; +} +  //===----------------------------------------------------------------------===//  //  // Instruction Definitions @@ -874,6 +926,7 @@ def JRCADDIUSP_MMR6 : R6MMR6Rel, JRCADDIUSP_MMR6_DESC, JRCADDIUSP_MMR6_ENC,                        ISA_MICROMIPS32R6;  def LSA_MMR6 : R6MMR6Rel, LSA_MMR6_ENC, LSA_MMR6_DESC, ISA_MICROMIPS32R6;  def LWPC_MMR6 : R6MMR6Rel, LWPC_MMR6_ENC, LWPC_MMR6_DESC, ISA_MICROMIPS32R6; +def LWM16_MMR6 : StdMMR6Rel, LWM16_MMR6_DESC, LWM16_MMR6_ENC, ISA_MICROMIPS32R6;  def MOD_MMR6 : R6MMR6Rel, MOD_MMR6_DESC, MOD_MMR6_ENC, ISA_MICROMIPS32R6;  def MODU_MMR6 : R6MMR6Rel, MODU_MMR6_DESC, MODU_MMR6_ENC, ISA_MICROMIPS32R6;  def MUL_MMR6 : R6MMR6Rel, MUL_MMR6_DESC, MUL_MMR6_ENC, ISA_MICROMIPS32R6; @@ -884,15 +937,20 @@ def NOR_MMR6 : StdMMR6Rel, NOR_MMR6_DESC, NOR_MMR6_ENC, ISA_MICROMIPS32R6;  def OR_MMR6 : StdMMR6Rel, OR_MMR6_DESC, OR_MMR6_ENC, ISA_MICROMIPS32R6;  def ORI_MMR6 : StdMMR6Rel, ORI_MMR6_DESC, ORI_MMR6_ENC, ISA_MICROMIPS32R6;  def PREF_MMR6 : R6MMR6Rel, PREF_MMR6_ENC, PREF_MMR6_DESC, ISA_MICROMIPS32R6; +def SB16_MMR6 : StdMMR6Rel, SB16_MMR6_DESC, SB16_MMR6_ENC, ISA_MICROMIPS32R6;  def SEB_MMR6 : StdMMR6Rel, SEB_MMR6_DESC, SEB_MMR6_ENC, ISA_MICROMIPS32R6;  def SEH_MMR6 : StdMMR6Rel, SEH_MMR6_DESC, SEH_MMR6_ENC, ISA_MICROMIPS32R6;  def SELEQZ_MMR6 : R6MMR6Rel, SELEQZ_MMR6_ENC, SELEQZ_MMR6_DESC,                    ISA_MICROMIPS32R6;  def SELNEZ_MMR6 : R6MMR6Rel, SELNEZ_MMR6_ENC, SELNEZ_MMR6_DESC,                    ISA_MICROMIPS32R6; +def SH16_MMR6 : StdMMR6Rel, SH16_MMR6_DESC, SH16_MMR6_ENC, ISA_MICROMIPS32R6;  def SLL_MMR6 : StdMMR6Rel, SLL_MMR6_DESC, SLL_MMR6_ENC, ISA_MICROMIPS32R6;  def SUB_MMR6 : StdMMR6Rel, SUB_MMR6_DESC, SUB_MMR6_ENC, ISA_MICROMIPS32R6;  def SUBU_MMR6 : StdMMR6Rel, SUBU_MMR6_DESC, SUBU_MMR6_ENC, ISA_MICROMIPS32R6; +def SW16_MMR6 : StdMMR6Rel, SW16_MMR6_DESC, SW16_MMR6_ENC, ISA_MICROMIPS32R6; +def SWM16_MMR6 : StdMMR6Rel, SWM16_MMR6_DESC, SWM16_MMR6_ENC, ISA_MICROMIPS32R6; +def SWSP_MMR6 : StdMMR6Rel, SWSP_MMR6_DESC, SWSP_MMR6_ENC, ISA_MICROMIPS32R6;  def PREFE_MMR6 : StdMMR6Rel, PREFE_MMR6_ENC, PREFE_MMR6_DESC, ISA_MICROMIPS32R6;  def CACHEE_MMR6 : StdMMR6Rel, CACHEE_MMR6_ENC, CACHEE_MMR6_DESC,                    ISA_MICROMIPS32R6; @@ -1075,3 +1133,12 @@ def : MipsInstAlias<"sdbbp", (SDBBP_MMR6 0), 1>, ISA_MICROMIPS32R6;  def : MipsInstAlias<"rdhwr $rt, $rs",                      (RDHWR_MMR6 GPR32Opnd:$rt, HWRegsOpnd:$rs, 0), 1>,                      ISA_MICROMIPS32R6; + +//===----------------------------------------------------------------------===// +// +// MicroMips arbitrary patterns that map to one or more instructions +// +//===----------------------------------------------------------------------===// + +def : MipsPat<(store GPRMM16:$src, addrimm4lsl2:$addr), +              (SW16_MMR6 GPRMM16:$src, addrimm4lsl2:$addr)>, ISA_MICROMIPS32R6; diff --git a/llvm/lib/Target/Mips/MicroMipsInstrFormats.td b/llvm/lib/Target/Mips/MicroMipsInstrFormats.td index e2cf4ca2f4b..b736367ee5f 100644 --- a/llvm/lib/Target/Mips/MicroMipsInstrFormats.td +++ b/llvm/lib/Target/Mips/MicroMipsInstrFormats.td @@ -943,7 +943,7 @@ class LWM_FM_MM<bits<4> funct> : MMArch {    let Inst{11-0}  = addr{11-0};  } -class LWM_FM_MM16<bits<4> funct> : MMArch { +class LWM_FM_MM16<bits<4> funct> : MMArch, PredicateControl {    bits<2> rt;    bits<4> addr; diff --git a/llvm/lib/Target/Mips/MicroMipsInstrInfo.td b/llvm/lib/Target/Mips/MicroMipsInstrInfo.td index 42a346e90c1..5eb5a4d233b 100644 --- a/llvm/lib/Target/Mips/MicroMipsInstrInfo.td +++ b/llvm/lib/Target/Mips/MicroMipsInstrInfo.td @@ -660,6 +660,14 @@ def BREAK16_MM : BrkSdbbp16MM<"break16">, BRKSDBBP16_FM_MM<0x28>,  def SDBBP16_MM : BrkSdbbp16MM<"sdbbp16">, BRKSDBBP16_FM_MM<0x2C>,      ISA_MICROMIPS_NOT_32R6_64R6; +let DecoderNamespace = "MicroMips" in { +  /// Load and Store Instructions - multiple +  def SWM16_MM : StoreMultMM16<"swm16">, LWM_FM_MM16<0x5>, +                 ISA_MICROMIPS32_NOT_MIPS32R6; +  def LWM16_MM : LoadMultMM16<"lwm16">, LWM_FM_MM16<0x4>, +                 ISA_MICROMIPS32_NOT_MIPS32R6; +} +  class WaitMM<string opstr> :    InstSE<(outs), (ins uimm10:$code_), !strconcat(opstr, "\t$code_"), [],           NoItinerary, FrmOther, opstr>; @@ -790,8 +798,6 @@ let DecoderNamespace = "MicroMips", Predicates = [InMicroMips] in {    /// Load and Store Instructions - multiple    def SWM32_MM  : StoreMultMM<"swm32">, LWM_FM_MM<0xd>;    def LWM32_MM  : LoadMultMM<"lwm32">, LWM_FM_MM<0x5>; -  def SWM16_MM : StoreMultMM16<"swm16">, LWM_FM_MM16<0x5>; -  def LWM16_MM : LoadMultMM16<"lwm16">, LWM_FM_MM16<0x4>;    /// Load and Store Pair Instructions    def SWP_MM  : StorePairMM<"swp">, LWM_FM_MM<0x9>; diff --git a/llvm/test/MC/Disassembler/Mips/micromips32r6/valid.txt b/llvm/test/MC/Disassembler/Mips/micromips32r6/valid.txt index 8a65e01cb01..619ce3faeda 100644 --- a/llvm/test/MC/Disassembler/Mips/micromips32r6/valid.txt +++ b/llvm/test/MC/Disassembler/Mips/micromips32r6/valid.txt @@ -230,3 +230,10 @@  0x00 0x69 0xe1 0x7c # CHECK: rdpgpr $3, $9  0x00 0x00 0xdb 0x7c # CHECK: sdbbp  0x00 0x22 0xdb 0x7c # CHECK: sdbbp 34 +0x45 0x22 # CHECK: lwm16 $16, $17, $ra, 8($sp) +0x89 0x84 # CHECK: sb16 $3, 4($16) +0xaa 0x14 # CHECK: sh16 $4, 8($17) +0xc8 0x9f # CHECK: sw $4, 124($sp) +0xea 0x11 # CHECK: sw16 $4, 4($17) +0xe8 0x11 # CHECK: sw16 $zero, 4($17) +0x45 0x2a # CHECK: swm16 $16, $17, $ra, 8($sp) diff --git a/llvm/test/MC/Disassembler/Mips/micromips64r6/valid.txt b/llvm/test/MC/Disassembler/Mips/micromips64r6/valid.txt index 7ed8d62bed0..fb641c06bfb 100644 --- a/llvm/test/MC/Disassembler/Mips/micromips64r6/valid.txt +++ b/llvm/test/MC/Disassembler/Mips/micromips64r6/valid.txt @@ -143,3 +143,10 @@  0x46 0x3b # CHECK: sdbbp16 8  0x04 0x3b # CHECK: subu16 $5, $16, $3  0x44 0xd8 # CHECK: xor16 $17, $5 +0x45 0x22 # CHECK: lwm16 $16, $17, $ra, 8($sp) +0x89 0x84 # CHECK: sb16 $3, 4($16) +0xaa 0x14 # CHECK: sh16 $4, 8($17) +0xc8 0x9f # CHECK: sw $4, 124($sp) +0xea 0x11 # CHECK: sw16 $4, 4($17) +0xe8 0x11 # CHECK: sw16 $zero, 4($17) +0x45 0x2a # CHECK: swm16 $16, $17, $ra, 8($sp) diff --git a/llvm/test/MC/Mips/micromips32r6/invalid.s b/llvm/test/MC/Mips/micromips32r6/invalid.s index 039855e2025..48c770a85a7 100644 --- a/llvm/test/MC/Mips/micromips32r6/invalid.s +++ b/llvm/test/MC/Mips/micromips32r6/invalid.s @@ -73,3 +73,31 @@    jrcaddiusp 33            # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction    jrcaddiusp 125           # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction    jrcaddiusp 132           # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction +  lwm16 $5, $6, $ra, 8($sp)   # CHECK: :[[@LINE]]:{{[0-9]+}}: error: $16 or $31 expected +  lwm16 $16, $19, $ra, 8($sp) # CHECK: :[[@LINE]]:{{[0-9]+}}: error: consecutive register numbers expected +  lwm16 $16-$25, $ra, 8($sp)  # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid register operand +  lwm16 $16, 8($sp)           # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction +  lwm16 $16, $17, 8($sp)      # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction +  lwm16 $16-$20, 8($sp)       # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction +  lwm16 $16, $17, $ra, 8($fp)  # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction +  lwm16 $16, $17, $ra, 64($sp) # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction +  sb16 $9, 4($16)          # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction +  sb16 $3, 64($16)         # CHECK: :[[@LINE]]:{{[0-9]+}}: error: immediate operand value out of range +  sb16 $16, 4($16)         # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction +  sb16 $7, 4($9)           # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction +  sh16  $9, 8($17)         # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction +  sh16  $4, 68($17)        # CHECK: :[[@LINE]]:{{[0-9]+}}: error: immediate operand value out of range +  sh16  $16, 8($17)        # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction +  sh16  $7, 8($9)          # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction +  sw16  $9, 4($17)         # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction +  sw16  $4, 64($17)        # CHECK: :[[@LINE]]:{{[0-9]+}}: error: immediate operand value out of range +  sw16  $16, 4($17)        # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction +  sw16  $7, 4($10)         # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction +  swm16 $5, $6, $ra, 8($sp)   # CHECK: :[[@LINE]]:{{[0-9]+}}: error: $16 or $31 expected +  swm16 $16, $19, $ra, 8($sp) # CHECK: :[[@LINE]]:{{[0-9]+}}: error: consecutive register numbers expected +  swm16 $16-$25, $ra, 8($sp)  # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid register operand +  swm16 $16, 8($sp)           # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction +  swm16 $16, $17, 8($sp)      # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction +  swm16 $16-$20, 8($sp)       # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction +  swm16 $16, $17, $ra, 8($fp)  # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction +  swm16 $16, $17, $ra, 64($sp) # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction diff --git a/llvm/test/MC/Mips/micromips32r6/valid.s b/llvm/test/MC/Mips/micromips32r6/valid.s index a1b1a501880..b2bce840765 100644 --- a/llvm/test/MC/Mips/micromips32r6/valid.s +++ b/llvm/test/MC/Mips/micromips32r6/valid.s @@ -54,6 +54,8 @@    jrcaddiusp 20            # CHECK: jrcaddiusp 20       # encoding: [0x44,0xb3]    lsa $2, $3, $4, 3        # CHECK: lsa  $2, $3, $4, 3  # encoding: [0x00,0x43,0x24,0x0f]    lwpc    $2,268           # CHECK: lwpc $2, 268        # encoding: [0x78,0x48,0x00,0x43] +  lwm $16, $17, $ra, 8($sp)   # CHECK: lwm16 $16, $17, $ra, 8($sp) # encoding: [0x45,0x22] +  lwm16 $16, $17, $ra, 8($sp) # CHECK: lwm16 $16, $17, $ra, 8($sp) # encoding: [0x45,0x22]    mod $3, $4, $5           # CHECK: mod $3, $4, $5      # encoding: [0x00,0xa4,0x19,0x58]    modu $3, $4, $5          # CHECK: modu $3, $4, $5     # encoding: [0x00,0xa4,0x19,0xd8]    mul $3, $4, $5           # CHECK mul $3, $4, $5       # encoding: [0x00,0xa4,0x18,0x18] @@ -65,13 +67,20 @@    or $3, $4, $5            # CHECK: or $3, $4, $5       # encoding: [0x00,0xa4,0x1a,0x90]    ori $3, $4, 1234         # CHECK: ori $3, $4, 1234    # encoding: [0x50,0x64,0x04,0xd2]    pref 1, 8($5)            # CHECK: pref 1, 8($5)       # encoding: [0x60,0x25,0x20,0x08] +  sb16 $3, 4($16)          # CHECK: sb16 $3, 4($16)     # encoding: [0x89,0x84]    seb $3, $4               # CHECK: seb $3, $4          # encoding: [0x00,0x64,0x2b,0x3c]    seh $3, $4               # CHECK: seh $3, $4          # encoding: [0x00,0x64,0x3b,0x3c]    seleqz $2,$3,$4          # CHECK: seleqz $2, $3, $4   # encoding: [0x00,0x83,0x11,0x40]    selnez $2,$3,$4          # CHECK: selnez $2, $3, $4   # encoding: [0x00,0x83,0x11,0x80] +  sh16 $4, 8($17)          # CHECK: sh16 $4, 8($17)     # encoding: [0xaa,0x14]    sll $4, $3, 7            # CHECK: sll $4, $3, 7       # encoding: [0x00,0x83,0x38,0x00]    sub $3, $4, $5           # CHECK: sub $3, $4, $5      # encoding: [0x00,0xa4,0x19,0x90]    subu $3, $4, $5          # CHECK: subu $3, $4, $5     # encoding: [0x00,0xa4,0x19,0xd0] +  sw $4, 124($sp)          # CHECK: sw $4, 124($sp)     # encoding: [0xc8,0x9f] +  sw16 $4, 4($17)          # CHECK: sw16 $4, 4($17)     # encoding: [0xea,0x11] +  sw16 $0, 4($17)          # CHECK: sw16 $zero, 4($17)  # encoding: [0xe8,0x11] +  swm $16, $17, $ra, 8($sp)   # CHECK: swm16 $16, $17, $ra, 8($sp) # encoding: [0x45,0x2a] +  swm16 $16, $17, $ra, 8($sp) # CHECK: swm16 $16, $17, $ra, 8($sp) # encoding: [0x45,0x2a]    wrpgpr $3, $4            # CHECK: wrpgpr $3, $4       # encoding: [0x00,0x64,0xf1,0x7c]    wsbh $3, $4              # CHECK: wsbh $3, $4         # encoding: [0x00,0x64,0x7b,0x3c]    pause                    # CHECK: pause               # encoding: [0x00,0x00,0x28,0x00] diff --git a/llvm/test/MC/Mips/micromips64r6/invalid.s b/llvm/test/MC/Mips/micromips64r6/invalid.s index d9adcf0af78..b71434d33b2 100644 --- a/llvm/test/MC/Mips/micromips64r6/invalid.s +++ b/llvm/test/MC/Mips/micromips64r6/invalid.s @@ -81,3 +81,31 @@    jrcaddiusp 33            # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction    jrcaddiusp 125           # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction    jrcaddiusp 132           # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction +  lwm16 $5, $6, $ra, 8($sp)   # CHECK: :[[@LINE]]:{{[0-9]+}}: error: $16 or $31 expected +  lwm16 $16, $19, $ra, 8($sp) # CHECK: :[[@LINE]]:{{[0-9]+}}: error: consecutive register numbers expected +  lwm16 $16-$25, $ra, 8($sp)  # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid register operand +  lwm16 $16, 8($sp)           # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction +  lwm16 $16, $17, 8($sp)      # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction +  lwm16 $16-$20, 8($sp)       # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction +  lwm16 $16, $17, $ra, 8($fp)  # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction +  lwm16 $16, $17, $ra, 64($sp) # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction +  sb16 $9, 4($16)          # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction +  sb16 $3, 64($16)         # CHECK: :[[@LINE]]:{{[0-9]+}}: error: immediate operand value out of range +  sb16 $16, 4($16)         # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction +  sb16 $7, 4($9)           # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction +  sh16  $9, 8($17)         # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction +  sh16  $4, 68($17)        # CHECK: :[[@LINE]]:{{[0-9]+}}: error: immediate operand value out of range +  sh16  $16, 8($17)        # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction +  sh16  $7, 8($9)          # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction +  sw16  $9, 4($17)         # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction +  sw16  $4, 64($17)        # CHECK: :[[@LINE]]:{{[0-9]+}}: error: immediate operand value out of range +  sw16  $16, 4($17)        # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction +  sw16  $7, 4($10)         # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction +  swm16 $5, $6, $ra, 8($sp)   # CHECK: :[[@LINE]]:{{[0-9]+}}: error: $16 or $31 expected +  swm16 $16, $19, $ra, 8($sp) # CHECK: :[[@LINE]]:{{[0-9]+}}: error: consecutive register numbers expected +  swm16 $16-$25, $ra, 8($sp)  # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid register operand +  swm16 $16, 8($sp)           # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction +  swm16 $16, $17, 8($sp)      # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction +  swm16 $16-$20, 8($sp)       # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction +  swm16 $16, $17, $ra, 8($fp)  # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction +  swm16 $16, $17, $ra, 64($sp) # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction diff --git a/llvm/test/MC/Mips/micromips64r6/valid.s b/llvm/test/MC/Mips/micromips64r6/valid.s index 0fb95d74248..68581074178 100644 --- a/llvm/test/MC/Mips/micromips64r6/valid.s +++ b/llvm/test/MC/Mips/micromips64r6/valid.s @@ -121,5 +121,14 @@ a:          sdbbp16 8                # CHECK: sdbbp16 8                # encoding: [0x46,0x3b]          subu16 $5, $16, $3       # CHECK: subu16 $5, $16, $3       # encoding: [0x04,0x3b]          xor16 $17, $5            # CHECK: xor16 $17, $5            # encoding: [0x44,0xd8] +        lwm $16, $17, $ra, 8($sp)   # CHECK: lwm16 $16, $17, $ra, 8($sp) # encoding: [0x45,0x22] +        lwm16 $16, $17, $ra, 8($sp) # CHECK: lwm16 $16, $17, $ra, 8($sp) # encoding: [0x45,0x22] +        sb16 $3, 4($16)          # CHECK: sb16 $3, 4($16)     # encoding: [0x89,0x84] +        sh16 $4, 8($17)          # CHECK: sh16 $4, 8($17)     # encoding: [0xaa,0x14] +        sw $4, 124($sp)          # CHECK: sw $4, 124($sp)     # encoding: [0xc8,0x9f] +        sw16 $4, 4($17)          # CHECK: sw16 $4, 4($17)     # encoding: [0xea,0x11] +        sw16 $0, 4($17)          # CHECK: sw16 $zero, 4($17)  # encoding: [0xe8,0x11] +        swm $16, $17, $ra, 8($sp)   # CHECK: swm16 $16, $17, $ra, 8($sp) # encoding: [0x45,0x2a] +        swm16 $16, $17, $ra, 8($sp) # CHECK: swm16 $16, $17, $ra, 8($sp) # encoding: [0x45,0x2a]  1:  | 

