From d0b3d6159d46314067c2686580d868f243cbc41a Mon Sep 17 00:00:00 2001 From: Zoran Jovanovic Date: Mon, 5 Oct 2015 14:00:09 +0000 Subject: [PATCH] [mips][microMIPS] Implement JALRC16, JRCADDIUSP and JRC16 instructions Differential Revision: http://reviews.llvm.org/D11219 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@249317 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/Mips/AsmParser/MipsAsmParser.cpp | 12 ++++-- lib/Target/Mips/MicroMips32r6InstrFormats.td | 20 ++++++++++ lib/Target/Mips/MicroMips32r6InstrInfo.td | 39 ++++++++++++++++++++ lib/Target/Mips/MicroMipsInstrInfo.td | 13 ++++++- lib/Target/Mips/MipsInstrInfo.td | 3 ++ test/MC/Disassembler/Mips/micromips32r6.txt | 6 +++ test/MC/Disassembler/Mips/micromips64r6.txt | 6 +++ test/MC/Mips/micromips-invalid.s | 9 +++++ test/MC/Mips/micromips32r6/invalid.s | 9 +++++ test/MC/Mips/micromips32r6/valid.s | 3 ++ test/MC/Mips/micromips64r6/invalid.s | 9 +++++ test/MC/Mips/micromips64r6/valid.s | 3 ++ 12 files changed, 127 insertions(+), 5 deletions(-) diff --git a/lib/Target/Mips/AsmParser/MipsAsmParser.cpp b/lib/Target/Mips/AsmParser/MipsAsmParser.cpp index 76cca79741b..551d7643e14 100644 --- a/lib/Target/Mips/AsmParser/MipsAsmParser.cpp +++ b/lib/Target/Mips/AsmParser/MipsAsmParser.cpp @@ -980,6 +980,9 @@ public: && (getConstantMemOff() % 4 == 0) && getMemBase()->isRegIdx() && (getMemBase()->getGPR32Reg() == Mips::SP); } + bool isUImm5Lsl2() const { + return (isImm() && isConstantImm() && isShiftedUInt<5, 2>(getConstantImm())); + } bool isRegList16() const { if (!isRegList()) return false; @@ -2085,7 +2088,7 @@ bool MipsAsmParser::expandJalWithRegs(MCInst &Inst, SMLoc IDLoc, JalrInst.setOpcode(Mips::JALRS16_MM); JalrInst.addOperand(FirstRegOp); } else if (inMicroMipsMode()) { - JalrInst.setOpcode(Mips::JALR16_MM); + JalrInst.setOpcode(hasMips32r6() ? Mips::JALRC16_MMR6 : Mips::JALR16_MM); JalrInst.addOperand(FirstRegOp); } else { JalrInst.setOpcode(Mips::JALR); @@ -2104,9 +2107,12 @@ bool MipsAsmParser::expandJalWithRegs(MCInst &Inst, SMLoc IDLoc, } Instructions.push_back(JalrInst); - // If .set reorder is active, emit a NOP after it. - if (AssemblerOptions.back()->isReorder()) + // If .set reorder is active and branch instruction has a delay slot, + // emit a NOP after it. + const MCInstrDesc &MCID = getInstDesc(JalrInst.getOpcode()); + if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder()) { createNop(hasShortDelaySlot(JalrInst.getOpcode()), IDLoc, Instructions); + } return false; } diff --git a/lib/Target/Mips/MicroMips32r6InstrFormats.td b/lib/Target/Mips/MicroMips32r6InstrFormats.td index 0d7b3e01fc3..242037f5941 100644 --- a/lib/Target/Mips/MicroMips32r6InstrFormats.td +++ b/lib/Target/Mips/MicroMips32r6InstrFormats.td @@ -42,6 +42,26 @@ class BEQZC_BNEZC_FM_MM16R6 op> : MicroMipsR6Inst16 { let Inst{6-0} = offset; } +class POOL16C_JALRC_FM_MM16R6 op> { + bits<5> rs; + + bits<16> Inst; + + let Inst{15-10} = 0x11; + let Inst{9-5} = rs; + let Inst{4-0} = op; +} + +class POOL16C_JRCADDIUSP_FM_MM16R6 op> { + bits<5> imm; + + bits<16> Inst; + + let Inst{15-10} = 0x11; + let Inst{9-5} = imm; + let Inst{4-0} = op; +} + class POOL32A_BITSWAP_FM_MMR6 funct> : MipsR6Inst { bits<5> rd; bits<5> rt; diff --git a/lib/Target/Mips/MicroMips32r6InstrInfo.td b/lib/Target/Mips/MicroMips32r6InstrInfo.td index d944894da77..44e4e56e0a7 100644 --- a/lib/Target/Mips/MicroMips32r6InstrInfo.td +++ b/lib/Target/Mips/MicroMips32r6InstrInfo.td @@ -48,8 +48,11 @@ class EHB_MMR6_ENC : BARRIER_MMR6_ENC<"ehb", 0x3>; class EI_MMR6_ENC : EIDI_MMR6_ENC<"ei", 0x15d>; class ERET_MMR6_ENC : ERET_FM_MMR6<"eret">; class ERETNC_MMR6_ENC : ERETNC_FM_MMR6<"eretnc">; +class JALRC16_MMR6_ENC : POOL16C_JALRC_FM_MM16R6<0xb>; class JIALC_MMR6_ENC : JMP_IDX_COMPACT_FM<0b100000>; class JIC_MMR6_ENC : JMP_IDX_COMPACT_FM<0b101000>; +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 MOD_MMR6_ENC : ARITH_FM_MMR6<"mod", 0x158>; @@ -292,6 +295,16 @@ class EI_MMR6_DESC : DEI_FT<"ei", GPR32Opnd>; class ERET_MMR6_DESC : ER_FT<"eret">; class ERETNC_MMR6_DESC : ER_FT<"eretnc">; +class JALRC16_MMR6_DESC_BASE + : MicroMipsInst16<(outs), (ins RO:$rs), !strconcat(opstr, "\t$rs"), + [(MipsJmpLink RO:$rs)], II_JALR, FrmR>, + MMR6Arch, MicroMipsR6Inst16 { + let isCall = 1; + let hasDelaySlot = 0; + let Defs = [RA]; +} +class JALRC16_MMR6_DESC : JALRC16_MMR6_DESC_BASE<"jalr", GPR32Opnd>; + class JMP_MMR6_IDX_COMPACT_DESC_BASE : MMR6Arch { @@ -314,6 +327,27 @@ class JIC_MMR6_DESC : JMP_MMR6_IDX_COMPACT_DESC_BASE<"jic", jmpoffset16, list Defs = [AT]; } +class JRC16_MMR6_DESC_BASE + : MicroMipsInst16<(outs), (ins RO:$rs), !strconcat(opstr, "\t$rs"), + [], II_JR, FrmR>, + MMR6Arch, MicroMipsR6Inst16 { + let hasDelaySlot = 0; + let isBranch = 1; + let isIndirectBranch = 1; +} +class JRC16_MMR6_DESC : JRC16_MMR6_DESC_BASE<"jrc16", GPR32Opnd>; + +class JRCADDIUSP_MMR6_DESC + : MicroMipsInst16<(outs), (ins uimm5_lsl2:$imm), "jrcaddiusp\t$imm", + [], II_JRADDIUSP, FrmR>, + MMR6Arch<"jrcaddiusp">, MicroMipsR6Inst16 { + let hasDelaySlot = 0; + let isTerminator = 1; + let isBarrier = 1; + let isBranch = 1; + let isIndirectBranch = 1; +} + class ALIGN_MMR6_DESC_BASE : MMR6Arch { dag OutOperandList = (outs GPROpnd:$rd); @@ -745,8 +779,13 @@ def EI_MMR6 : StdMMR6Rel, EI_MMR6_DESC, EI_MMR6_ENC, ISA_MICROMIPS32R6; def ERET_MMR6 : R6MMR6Rel, ERET_MMR6_DESC, ERET_MMR6_ENC, ISA_MICROMIPS32R6; def ERETNC_MMR6 : R6MMR6Rel, ERETNC_MMR6_DESC, ERETNC_MMR6_ENC, ISA_MICROMIPS32R6; +def JALRC16_MMR6 : R6MMR6Rel, JALRC16_MMR6_DESC, JALRC16_MMR6_ENC, + ISA_MICROMIPS32R6; def JIALC_MMR6 : R6MMR6Rel, JIALC_MMR6_ENC, JIALC_MMR6_DESC, ISA_MICROMIPS32R6; def JIC_MMR6 : R6MMR6Rel, JIC_MMR6_ENC, JIC_MMR6_DESC, ISA_MICROMIPS32R6; +def JRC16_MMR6 : R6MMR6Rel, JRC16_MMR6_DESC, JRC16_MMR6_ENC, ISA_MICROMIPS32R6; +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 MOD_MMR6 : R6MMR6Rel, MOD_MMR6_DESC, MOD_MMR6_ENC, ISA_MICROMIPS32R6; diff --git a/lib/Target/Mips/MicroMipsInstrInfo.td b/lib/Target/Mips/MicroMipsInstrInfo.td index 35958bd7c6e..4e7a1776014 100644 --- a/lib/Target/Mips/MicroMipsInstrInfo.td +++ b/lib/Target/Mips/MicroMipsInstrInfo.td @@ -13,9 +13,17 @@ def simm12 : Operand { let DecoderMethod = "DecodeSimm12"; } +def MipsUimm5Lsl2AsmOperand : AsmOperandClass { + let Name = "Uimm5Lsl2"; + let RenderMethod = "addImmOperands"; + let ParserMethod = "parseImm"; + let PredicateMethod = "isUImm5Lsl2"; +} + def uimm5_lsl2 : Operand { let EncoderMethod = "getUImm5Lsl2Encoding"; let DecoderMethod = "DecodeUImm5lsl2"; + let ParserMatchClass = MipsUimm5Lsl2AsmOperand; } def uimm6_lsl2 : Operand { @@ -401,7 +409,7 @@ class LoadImmMM16 : // 16-bit Jump and Link (Call) class JumpLinkRegMM16 : MicroMipsInst16<(outs), (ins RO:$rs), !strconcat(opstr, "\t$rs"), - [(MipsJmpLink RO:$rs)], II_JALR, FrmR> { + [(MipsJmpLink RO:$rs)], II_JALR, FrmR>, PredicateControl { let isCall = 1; let hasDelaySlot = 1; let Defs = [RA]; @@ -613,7 +621,8 @@ def MOVE16_MM : MoveMM16<"move", GPR32Opnd>, MOVE_FM_MM16<0x03>; def MOVEP_MM : MovePMM16<"movep", GPRMM16OpndMoveP>, MOVEP_FM_MM16; def LI16_MM : LoadImmMM16<"li16", li_simm7, GPRMM16Opnd>, LI_FM_MM16, IsAsCheapAsAMove; -def JALR16_MM : JumpLinkRegMM16<"jalr", GPR32Opnd>, JALR_FM_MM16<0x0e>; +def JALR16_MM : JumpLinkRegMM16<"jalr", GPR32Opnd>, JALR_FM_MM16<0x0e>, + ISA_MICROMIPS32_NOT_MIPS32R6; def JALRS16_MM : JumpLinkRegSMM16<"jalrs16", GPR32Opnd>, JALR_FM_MM16<0x0f>; def JRC16_MM : JumpRegCMM16<"jrc", GPR32Opnd>, JALR_FM_MM16<0x0d>; def JRADDIUSP : JumpRAddiuStackMM16, JRADDIUSP_FM_MM16<0x18>; diff --git a/lib/Target/Mips/MipsInstrInfo.td b/lib/Target/Mips/MipsInstrInfo.td index d15b785517c..1bd352453e2 100644 --- a/lib/Target/Mips/MipsInstrInfo.td +++ b/lib/Target/Mips/MipsInstrInfo.td @@ -267,6 +267,9 @@ class ISA_MICROMIPS32R6 { class ISA_MICROMIPS64R6 { list InsnPredicates = [HasMicroMips64r6]; } +class ISA_MICROMIPS32_NOT_MIPS32R6 { + list InsnPredicates = [InMicroMips, NotMips32r6]; +} class INSN_EVA { list InsnPredicates = [HasEVA]; } class INSN_EVA_NOT_32R6_64R6 { diff --git a/test/MC/Disassembler/Mips/micromips32r6.txt b/test/MC/Disassembler/Mips/micromips32r6.txt index 0d6123ea3df..5440642dfc5 100644 --- a/test/MC/Disassembler/Mips/micromips32r6.txt +++ b/test/MC/Disassembler/Mips/micromips32r6.txt @@ -88,10 +88,16 @@ 0x00 0x01 0xf3 0x7c # CHECK: eretnc +0x45 0x2b # CHECK: jalr $9 + 0x80 0x05 0x01 0x00 # CHECK: jialc $5, 256 0xa0 0x05 0x01 0x00 # CHECK: jic $5, 256 +0x45 0x23 # CHECK: jrc16 $9 + +0x44 0xb3 # CHECK: jrcaddiusp 20 + 0x78 0x48 0x00 0x43 # CHECK: lwpc $2, 268 0x00 0x43 0x26 0x0f # CHECK: lsa $2, $3, $4, 3 diff --git a/test/MC/Disassembler/Mips/micromips64r6.txt b/test/MC/Disassembler/Mips/micromips64r6.txt index 606b6fbb203..10c9304138d 100644 --- a/test/MC/Disassembler/Mips/micromips64r6.txt +++ b/test/MC/Disassembler/Mips/micromips64r6.txt @@ -255,3 +255,9 @@ 0x00 0x64 0xf1 0x7c # CHECK: wrpgpr $3, $4 0x00 0x64 0x7b 0x3c # CHECK: wsbh $3, $4 + +0x45 0x2b # CHECK: jalr $9 + +0x45 0x23 # CHECK: jrc16 $9 + +0x44 0xb3 # CHECK: jrcaddiusp 20 diff --git a/test/MC/Mips/micromips-invalid.s b/test/MC/Mips/micromips-invalid.s index 1cf792eec55..99e9eb4fa43 100644 --- a/test/MC/Mips/micromips-invalid.s +++ b/test/MC/Mips/micromips-invalid.s @@ -79,3 +79,12 @@ break 1024, 1024 # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction wait 1024 # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction prefx 33, $8($5) # CHECK: :[[@LINE]]:{{[0-9]+}}: error: immediate operand value out of range + jraddiusp 1 # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction + jraddiusp 2 # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction + jraddiusp 3 # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction + jraddiusp 10 # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction + jraddiusp 18 # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction + jraddiusp 31 # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction + jraddiusp 33 # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction + jraddiusp 125 # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction + jraddiusp 132 # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction diff --git a/test/MC/Mips/micromips32r6/invalid.s b/test/MC/Mips/micromips32r6/invalid.s index 6b844ec2f57..d6458997c49 100644 --- a/test/MC/Mips/micromips32r6/invalid.s +++ b/test/MC/Mips/micromips32r6/invalid.s @@ -60,3 +60,12 @@ wrpgpr $3, $33 # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction wsbh $34, $4 # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction wsbh $3, $33 # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction + jrcaddiusp 1 # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction + jrcaddiusp 2 # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction + jrcaddiusp 3 # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction + jrcaddiusp 10 # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction + jrcaddiusp 18 # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction + jrcaddiusp 31 # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction + 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 diff --git a/test/MC/Mips/micromips32r6/valid.s b/test/MC/Mips/micromips32r6/valid.s index d4ab500f9e4..e8f9c85bc99 100644 --- a/test/MC/Mips/micromips32r6/valid.s +++ b/test/MC/Mips/micromips32r6/valid.s @@ -47,8 +47,11 @@ ei $10 # CHECK: ei $10 # encoding: [0x00,0x0a,0x57,0x7c] eret # CHECK: eret # encoding: [0x00,0x00,0xf3,0x7c] eretnc # CHECK: eretnc # encoding: [0x00,0x01,0xf3,0x7c] + jalr $9 # CHECK: jalr $9 # encoding: [0x45,0x2b] jialc $5, 256 # CHECK: jialc $5, 256 # encoding: [0x80,0x05,0x01,0x00] jic $5, 256 # CHECK: jic $5, 256 # encoding: [0xa0,0x05,0x01,0x00] + jrc16 $9 # CHECK: jrc16 $9 # encoding: [0x45,0x23] + jrcaddiusp 20 # CHECK: jrcaddiusp 20 # encoding: [0x44,0xb3] lsa $2, $3, $4, 3 # CHECK: lsa $2, $3, $4, 3 # encoding: [0x00,0x43,0x26,0x0f] lwpc $2,268 # CHECK: lwpc $2, 268 # encoding: [0x78,0x48,0x00,0x43] mod $3, $4, $5 # CHECK: mod $3, $4, $5 # encoding: [0x00,0xa4,0x19,0x58] diff --git a/test/MC/Mips/micromips64r6/invalid.s b/test/MC/Mips/micromips64r6/invalid.s index fea7a3754f9..59e7cd61243 100644 --- a/test/MC/Mips/micromips64r6/invalid.s +++ b/test/MC/Mips/micromips64r6/invalid.s @@ -66,3 +66,12 @@ wrpgpr $3, $33 # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction wsbh $34, $4 # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction wsbh $3, $33 # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction + jrcaddiusp 1 # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction + jrcaddiusp 2 # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction + jrcaddiusp 3 # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction + jrcaddiusp 10 # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction + jrcaddiusp 18 # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction + jrcaddiusp 31 # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction + 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 diff --git a/test/MC/Mips/micromips64r6/valid.s b/test/MC/Mips/micromips64r6/valid.s index 346ab484a35..9567601680e 100644 --- a/test/MC/Mips/micromips64r6/valid.s +++ b/test/MC/Mips/micromips64r6/valid.s @@ -112,5 +112,8 @@ a: cachee 1, 8($5) # CHECK: cachee 1, 8($5) # encoding: [0x60,0x25,0xa6,0x08] wrpgpr $3, $4 # CHECK: wrpgpr $3, $4 # encoding: [0x00,0x64,0xf1,0x7c] wsbh $3, $4 # CHECK: wsbh $3, $4 # encoding: [0x00,0x64,0x7b,0x3c] + jalr $9 # CHECK: jalr $9 # encoding: [0x45,0x2b] + jrc16 $9 # CHECK: jrc16 $9 # encoding: [0x45,0x23] + jrcaddiusp 20 # CHECK: jrcaddiusp 20 # encoding: [0x44,0xb3] 1: -- 2.34.1