From dbe4d96b4f7e6ee8b4d05f4a6df6891fb28b3d9b Mon Sep 17 00:00:00 2001 From: Hrvoje Varga Date: Thu, 8 Sep 2016 07:41:43 +0000 Subject: [PATCH] [mips][microMIPS] Implement DBITSWAP, DLSA and LWUPC and add tests for AUI instructions Differential Revision: https://reviews.llvm.org/D16452 llvm-svn: 280909 --- llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp | 17 ++++++-- llvm/lib/Target/Mips/MCTargetDesc/MipsBaseInfo.h | 5 ++- llvm/lib/Target/Mips/MicroMips64r6InstrFormats.td | 46 ++++++++++++++++++++++ llvm/lib/Target/Mips/MicroMips64r6InstrInfo.td | 35 ++++++++++++++++ llvm/lib/Target/Mips/Mips32r6InstrInfo.td | 2 +- llvm/lib/Target/Mips/Mips64r6InstrInfo.td | 8 +--- llvm/lib/Target/Mips/MipsInstrFormats.td | 4 ++ llvm/lib/Target/Mips/MipsInstrInfo.td | 21 +++++++++- .../MC/Disassembler/Mips/micromips64r6/valid.txt | 4 ++ llvm/test/MC/Mips/micromips64r6/invalid.s | 10 +++++ llvm/test/MC/Mips/micromips64r6/valid.s | 6 +++ 11 files changed, 146 insertions(+), 12 deletions(-) diff --git a/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp b/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp index 58ae3aa..cdbf4a6 100644 --- a/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp +++ b/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp @@ -13,6 +13,7 @@ #include "MipsRegisterInfo.h" #include "MipsTargetObjectFile.h" #include "MipsTargetStreamer.h" +#include "MCTargetDesc/MipsBaseInfo.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringSwitch.h" #include "llvm/MC/MCContext.h" @@ -1166,8 +1167,14 @@ public: } template bool isScaledSImm() const { - return isConstantImm() && - isShiftedInt(getConstantImm()); + if (isConstantImm() && isShiftedInt(getConstantImm())) + return true; + // Operand can also be a symbol or symbol plus offset in case of relocations. + if (Kind != k_Immediate) + return false; + MCValue Res; + bool Success = getImm()->evaluateAsRelocatable(Res, nullptr, nullptr); + return Success && isShiftedInt(Res.getConstant()); } bool isRegList16() const { if (!isRegList()) @@ -1839,7 +1846,8 @@ bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc, ExpandedJalSym = true; } - if (MCID.mayLoad() || MCID.mayStore()) { + bool IsPCRelativeLoad = (MCID.TSFlags & MipsII::IsPCRelativeLoad) != 0; + if ((MCID.mayLoad() || MCID.mayStore()) && !IsPCRelativeLoad) { // Check the offset of memory operand, if it is a symbol // reference or immediate we may have to expand instructions. for (unsigned i = 0; i < MCID.getNumOperands(); i++) { @@ -4030,6 +4038,9 @@ bool MipsAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, case Match_SImm16_Relaxed: return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), "expected 16-bit signed immediate"); + case Match_SImm19_Lsl2: + return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), + "expected both 19-bit signed immediate and multiple of 4"); case Match_UImm20_0: return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), "expected 20-bit unsigned immediate"); diff --git a/llvm/lib/Target/Mips/MCTargetDesc/MipsBaseInfo.h b/llvm/lib/Target/Mips/MCTargetDesc/MipsBaseInfo.h index 2bcff88..35de7b2 100644 --- a/llvm/lib/Target/Mips/MCTargetDesc/MipsBaseInfo.h +++ b/llvm/lib/Target/Mips/MCTargetDesc/MipsBaseInfo.h @@ -120,7 +120,10 @@ namespace MipsII { /// IsCTI - Instruction is a Control Transfer Instruction. IsCTI = 1 << 4, /// HasForbiddenSlot - Instruction has a forbidden slot. - HasForbiddenSlot = 1 << 5 + HasForbiddenSlot = 1 << 5, + /// IsPCRelativeLoad - A Load instruction with implicit source register + /// ($pc) with explicit offset and destination register + IsPCRelativeLoad = 1 << 6 }; } diff --git a/llvm/lib/Target/Mips/MicroMips64r6InstrFormats.td b/llvm/lib/Target/Mips/MicroMips64r6InstrFormats.td index 4add305..26062bf 100644 --- a/llvm/lib/Target/Mips/MicroMips64r6InstrFormats.td +++ b/llvm/lib/Target/Mips/MicroMips64r6InstrFormats.td @@ -219,3 +219,49 @@ class POOL32S_3R_FM_MMR6 funct> let Inst{10-9} = 0b00; let Inst{8-0} = funct; } + +class POOL32S_DBITSWAP_FM_MMR6 : MMR6Arch, + MipsR6Inst { + bits<5> rt; + bits<5> rd; + + bits<32> Inst; + + let Inst{31-26} = 0b010110; + let Inst{25-21} = rt; + let Inst{20-16} = rd; + let Inst{15-12} = 0b0000; + let Inst{11-6} = 0b101100; + let Inst{5-0} = 0b111100; +} + +class POOL32S_3RSA_FM_MMR6 : MMR6Arch, + MipsR6Inst { + bits<5> rt; + bits<5> rs; + bits<5> rd; + bits<2> sa; + + bits<32> Inst; + + let Inst{31-26} = 0b010110; + let Inst{25-21} = rt; + let Inst{20-16} = rs; + let Inst{15-11} = rd; + let Inst{10-9} = sa; + let Inst{8-6} = 0b100; + let Inst{5-0} = 0b000100; +} + +class PCREL_1ROFFSET19_FM_MMR6 : MMR6Arch, + MipsR6Inst { + bits<5> rt; + bits<19> offset; + + bits<32> Inst; + + let Inst{31-26} = 0b011110; + let Inst{25-21} = rt; + let Inst{20-19} = 0b10; + let Inst{18-0} = offset; +} diff --git a/llvm/lib/Target/Mips/MicroMips64r6InstrInfo.td b/llvm/lib/Target/Mips/MicroMips64r6InstrInfo.td index 27b39f9..508b342 100644 --- a/llvm/lib/Target/Mips/MicroMips64r6InstrInfo.td +++ b/llvm/lib/Target/Mips/MicroMips64r6InstrInfo.td @@ -67,6 +67,9 @@ class SD_MM64R6_ENC : LD_SD_32_2R_OFFSET16_FM_MMR6<"sd", 0b110110>; class DSRL_MM64R6_ENC : POOL32S_2RSA5B0_FM_MMR6<"dsrl", 0b001000000>; class DSRL32_MM64R6_ENC : POOL32S_2RSA5B0_FM_MMR6<"dsrl32", 0b001001000>; class DSRLV_MM64R6_ENC : POOL32S_3R_FM_MMR6<"dsrlv", 0b001010000>; +class DBITSWAP_MM64R6_ENC : POOL32S_DBITSWAP_FM_MMR6<"dbitswap">; +class DLSA_MM64R6_ENC : POOL32S_3RSA_FM_MMR6<"dlsa">; +class LWUPC_MM64R6_ENC : PCREL_1ROFFSET19_FM_MMR6<"lwupc">; //===----------------------------------------------------------------------===// // @@ -323,6 +326,32 @@ class SD_MM64R6_DESC { string DecoderMethod = "DecodeMemMMImm16"; } +class DBITSWAP_MM64R6_DESC { + dag OutOperandList = (outs GPR64Opnd:$rd); + dag InOperandList = (ins GPR64Opnd:$rt); + string AsmString = !strconcat("dbitswap", "\t$rd, $rt"); + list Pattern = []; + InstrItinClass Itinerary = II_DBITSWAP; +} + +class DLSA_MM64R6_DESC { + dag OutOperandList = (outs GPR64Opnd:$rd); + dag InOperandList = (ins GPR64Opnd:$rt, GPR64Opnd:$rs, uimm2_plus1:$sa); + string AsmString = "dlsa\t$rt, $rs, $rd, $sa"; + list Pattern = []; + InstrItinClass Itinerary = II_DLSA; +} + +class LWUPC_MM64R6_DESC { + dag OutOperandList = (outs GPR64Opnd:$rt); + dag InOperandList = (ins simm19_lsl2:$offset); + string AsmString = "lwupc\t$rt, $offset"; + list Pattern = []; + InstrItinClass Itinerary = II_LWUPC; + bit mayLoad = 1; + bit IsPCRelativeLoad = 1; +} + //===----------------------------------------------------------------------===// // // Instruction Definitions @@ -427,6 +456,12 @@ let DecoderNamespace = "MicroMipsR6" in { ISA_MICROMIPS64R6; def DSRLV_MM64R6 : StdMMR6Rel, DSRLV_MM64R6_ENC, DSRLV_MM64R6_DESC, ISA_MICROMIPS64R6; + def DBITSWAP_MM64R6 : R6MMR6Rel, DBITSWAP_MM64R6_ENC, DBITSWAP_MM64R6_DESC, + ISA_MICROMIPS64R6; + def DLSA_MM64R6 : R6MMR6Rel, DLSA_MM64R6_ENC, DLSA_MM64R6_DESC, + ISA_MICROMIPS64R6; + def LWUPC_MM64R6 : R6MMR6Rel, LWUPC_MM64R6_ENC, LWUPC_MM64R6_DESC, + ISA_MICROMIPS64R6; } let AdditionalPredicates = [InMicroMips] in diff --git a/llvm/lib/Target/Mips/Mips32r6InstrInfo.td b/llvm/lib/Target/Mips/Mips32r6InstrInfo.td index 9d7377e..e818695 100644 --- a/llvm/lib/Target/Mips/Mips32r6InstrInfo.td +++ b/llvm/lib/Target/Mips/Mips32r6InstrInfo.td @@ -831,8 +831,8 @@ let AdditionalPredicates = [NotInMicroMips] in { def LWC2_R6 : LWC2_R6_ENC, LWC2_R6_DESC, ISA_MIPS32R6; } def LWPC : R6MMR6Rel, LWPC_ENC, LWPC_DESC, ISA_MIPS32R6; -def LWUPC : LWUPC_ENC, LWUPC_DESC, ISA_MIPS32R6; let AdditionalPredicates = [NotInMicroMips] in { + def LWUPC : R6MMR6Rel, LWUPC_ENC, LWUPC_DESC, ISA_MIPS32R6; def MADDF_S : MADDF_S_ENC, MADDF_S_DESC, ISA_MIPS32R6, HARDFLOAT; def MADDF_D : MADDF_D_ENC, MADDF_D_DESC, ISA_MIPS32R6, HARDFLOAT; def MAXA_D : MAXA_D_ENC, MAXA_D_DESC, ISA_MIPS32R6, HARDFLOAT; diff --git a/llvm/lib/Target/Mips/Mips64r6InstrInfo.td b/llvm/lib/Target/Mips/Mips64r6InstrInfo.td index b45e427..c380dfd 100644 --- a/llvm/lib/Target/Mips/Mips64r6InstrInfo.td +++ b/llvm/lib/Target/Mips/Mips64r6InstrInfo.td @@ -115,18 +115,14 @@ let AdditionalPredicates = [NotInMicroMips] in { def DAHI : DAHI_ENC, DAHI_DESC, ISA_MIPS64R6; def DAUI : DAUI_ENC, DAUI_DESC, ISA_MIPS64R6; def DALIGN : DALIGN_ENC, DALIGN_DESC, ISA_MIPS64R6; -} -def DBITSWAP : DBITSWAP_ENC, DBITSWAP_DESC, ISA_MIPS64R6; -let AdditionalPredicates = [NotInMicroMips] in { + def DBITSWAP : R6MMR6Rel, DBITSWAP_ENC, DBITSWAP_DESC, ISA_MIPS64R6; def DCLO_R6 : R6MMR6Rel, DCLO_R6_ENC, DCLO_R6_DESC, ISA_MIPS64R6; def DCLZ_R6 : R6MMR6Rel, DCLZ_R6_ENC, DCLZ_R6_DESC, ISA_MIPS64R6; def DDIV : DDIV_ENC, DDIV_DESC, ISA_MIPS64R6; def DDIVU : DDIVU_ENC, DDIVU_DESC, ISA_MIPS64R6; def DMOD : DMOD_ENC, DMOD_DESC, ISA_MIPS64R6; def DMODU : DMODU_ENC, DMODU_DESC, ISA_MIPS64R6; -} -def DLSA_R6 : DLSA_R6_ENC, DLSA_R6_DESC, ISA_MIPS64R6; -let AdditionalPredicates = [NotInMicroMips] in { + def DLSA_R6 : R6MMR6Rel, DLSA_R6_ENC, DLSA_R6_DESC, ISA_MIPS64R6; def DMUH: DMUH_ENC, DMUH_DESC, ISA_MIPS64R6; def DMUHU: DMUHU_ENC, DMUHU_DESC, ISA_MIPS64R6; def DMUL_R6: DMUL_R6_ENC, DMUL_R6_DESC, ISA_MIPS64R6; diff --git a/llvm/lib/Target/Mips/MipsInstrFormats.td b/llvm/lib/Target/Mips/MipsInstrFormats.td index 0bbb49b..1437fb7 100644 --- a/llvm/lib/Target/Mips/MipsInstrFormats.td +++ b/llvm/lib/Target/Mips/MipsInstrFormats.td @@ -98,11 +98,15 @@ class MipsInst pattern, bit isCTI = 0; // Any form of Control Transfer Instruction. // Required for MIPSR6 bit hasForbiddenSlot = 0; // Instruction has a forbidden slot. + bit IsPCRelativeLoad = 0; // Load instruction with implicit source register + // ($pc) and with explicit offset and destination + // register // TSFlags layout should be kept in sync with MipsInstrInfo.h. let TSFlags{3-0} = FormBits; let TSFlags{4} = isCTI; let TSFlags{5} = hasForbiddenSlot; + let TSFlags{6} = IsPCRelativeLoad; let DecoderNamespace = "Mips"; diff --git a/llvm/lib/Target/Mips/MipsInstrInfo.td b/llvm/lib/Target/Mips/MipsInstrInfo.td index 4dd8a5c..39b3107 100644 --- a/llvm/lib/Target/Mips/MipsInstrInfo.td +++ b/llvm/lib/Target/Mips/MipsInstrInfo.td @@ -413,6 +413,15 @@ class ConstantSImmAsmOperandClass Supers = [], let DiagnosticType = "SImm" # Bits # "_" # Offset; } +class SimmLslAsmOperandClass Supers = [], + int Shift = 0> : AsmOperandClass { + let Name = "Simm" # Bits # "_Lsl" # Shift; + let RenderMethod = "addImmOperands"; + let PredicateMethod = "isScaledSImm<" # Bits # ", " # Shift # ">"; + let SuperClasses = Supers; + let DiagnosticType = "SImm" # Bits # "_Lsl" # Shift; +} + class ConstantUImmAsmOperandClass Supers = [], int Offset = 0> : AsmOperandClass { let Name = "ConstantUImm" # Bits # "_" # Offset; @@ -485,6 +494,13 @@ def ConstantUImm26AsmOperandClass : ConstantUImmAsmOperandClass<26, [SImm32AsmOperandClass]>; def ConstantUImm20AsmOperandClass : ConstantUImmAsmOperandClass<20, [ConstantUImm26AsmOperandClass]>; +def ConstantSImm19Lsl2AsmOperandClass : AsmOperandClass { + let Name = "SImm19Lsl2"; + let RenderMethod = "addImmOperands"; + let PredicateMethod = "isScaledSImm<19, 2>"; + let SuperClasses = [ConstantUImm20AsmOperandClass]; + let DiagnosticType = "SImm19_Lsl2"; +} def UImm16RelaxedAsmOperandClass : UImmAsmOperandClass<16, [ConstantUImm20AsmOperandClass]> { let Name = "UImm16_Relaxed"; @@ -611,6 +627,9 @@ def ConstantImmzAsmOperandClass : AsmOperandClass { let DiagnosticType = "Immz"; } +def Simm19Lsl2AsmOperand + : SimmLslAsmOperandClass<19, [], 2>; + def MipsJumpTargetAsmOperand : AsmOperandClass { let Name = "JumpTarget"; let ParserMethod = "parseJumpTarget"; @@ -645,7 +664,7 @@ def imm64: Operand; def simm19_lsl2 : Operand { let EncoderMethod = "getSimm19Lsl2Encoding"; let DecoderMethod = "DecodeSimm19Lsl2"; - let ParserMatchClass = MipsJumpTargetAsmOperand; + let ParserMatchClass = Simm19Lsl2AsmOperand; } def simm18_lsl3 : Operand { diff --git a/llvm/test/MC/Disassembler/Mips/micromips64r6/valid.txt b/llvm/test/MC/Disassembler/Mips/micromips64r6/valid.txt index 5e80b55..d291330 100644 --- a/llvm/test/MC/Disassembler/Mips/micromips64r6/valid.txt +++ b/llvm/test/MC/Disassembler/Mips/micromips64r6/valid.txt @@ -314,3 +314,7 @@ 0xf4 0x40 0x00 0x40 # CHECK: blezc $2, 260 0xf6 0x10 0x00 0x80 # CHECK: bgezc $16, 516 0xd5 0x80 0x01 0x00 # CHECK: bgtzc $12, 1028 +0x10 0x64 0x01 0x00 # CHECK: aui $3, $4, 256 +0x58 0x83 0x0b 0x3c # CHECK: dbitswap $3, $4 +0x58 0x64 0x2d 0x04 # CHECK: dlsa $3, $4, $5, 3 +0x78 0x50 0x00 0x43 # CHECK: lwupc $2, 268 diff --git a/llvm/test/MC/Mips/micromips64r6/invalid.s b/llvm/test/MC/Mips/micromips64r6/invalid.s index 4516294..a6aa534 100644 --- a/llvm/test/MC/Mips/micromips64r6/invalid.s +++ b/llvm/test/MC/Mips/micromips64r6/invalid.s @@ -391,3 +391,13 @@ bnezc $2, -4194303 # CHECK: :[[@LINE]]:{{[0-9]+}}: error: branch to misaligned address bnezc $2, 4194304 # CHECK: :[[@LINE]]:{{[0-9]+}}: error: branch target out of range bnezc $2, 4194303 # CHECK: :[[@LINE]]:{{[0-9]+}}: error: branch to misaligned address + dlsa $3, $4, $5, 5 # CHECK: :[[@LINE]]:{{[0-9]+}}: error: expected immediate in range 1 .. 4 + dlsa $3, $4, $5, -1 # CHECK: :[[@LINE]]:{{[0-9]+}}: error: expected immediate in range 1 .. 4 + dlsa $3, $4, $5, 0 # CHECK: :[[@LINE]]:{{[0-9]+}}: error: expected immediate in range 1 .. 4 + lwupc $2, 262145 # CHECK: :[[@LINE]]:13: error: expected both 19-bit signed immediate and multiple of 4 + lwupc $2, 5 # CHECK: :[[@LINE]]:13: error: expected both 19-bit signed immediate and multiple of 4 + lwupc $2, -262145 # CHECK: :[[@LINE]]:13: error: expected both 19-bit signed immediate and multiple of 4 + lwupc $2, $2 # CHECK: :[[@LINE]]:13: error: expected both 19-bit signed immediate and multiple of 4 + lwupc $2, bar+267 # CHECK: :[[@LINE]]:13: error: expected both 19-bit signed immediate and multiple of 4 + aui $3, $4, 32768 # CHECK: :[[@LINE]]:15: error: expected 16-bit signed immediate + aui $3, $4, -32769 # CHECK: :[[@LINE]]:15: error: expected 16-bit signed immediate diff --git a/llvm/test/MC/Mips/micromips64r6/valid.s b/llvm/test/MC/Mips/micromips64r6/valid.s index d3c09a9..e04bee4 100644 --- a/llvm/test/MC/Mips/micromips64r6/valid.s +++ b/llvm/test/MC/Mips/micromips64r6/valid.s @@ -330,5 +330,11 @@ a: blezc $2, 256 # CHECK: blezc $2, 256 # encoding: [0xf4,0x40,0x00,0x40] bgezc $16, 512 # CHECK: bgezc $16, 512 # encoding: [0xf6,0x10,0x00,0x80] bgtzc $12, 1024 # CHECK: bgtzc $12, 1024 # encoding: [0xd5,0x80,0x01,0x00] + aui $3, $4, 256 # CHECK: aui $3, $4, 256 # encoding: [0x10,0x64,0x01,0x00] + dbitswap $3, $4 # CHECK: dbitswap $3, $4 # encoding: [0x58,0x83,0x0b,0x3c] + dlsa $3, $4, $5, 3 # CHECK: dlsa $3, $4, $5, 3 # encoding: [0x58,0x64,0x2d,0x04] + lwupc $2, 268 # CHECK: lwupc $2, 268 # encoding: [0x78,0x50,0x00,0x43] + lwupc $2, bar # CHECK: lwupc $2, bar # encoding: [0x78,0b01010AAA,A,A] + lwupc $2, bar+268 # CHECK: lwupc $2, bar+268 # encoding: [0x78,0b01010AAA,A,A] 1: -- 2.7.4