diff options
| author | Daniel Sanders <daniel.sanders@imgtec.com> | 2016-03-31 14:34:00 +0000 |
|---|---|---|
| committer | Daniel Sanders <daniel.sanders@imgtec.com> | 2016-03-31 14:34:00 +0000 |
| commit | 85fd10bd932f9d109d674f9553aabdc131cf31e5 (patch) | |
| tree | 3a88c99c39c11f26d266199a7083290c9b75cc85 /llvm/lib | |
| parent | eab314615663cae3b36469cc08fd2a8588e55d5b (diff) | |
| download | bcm5719-llvm-85fd10bd932f9d109d674f9553aabdc131cf31e5.tar.gz bcm5719-llvm-85fd10bd932f9d109d674f9553aabdc131cf31e5.zip | |
[mips] Range check simm16
Summary:
There are too many instructions to exhaustively test so addiu and lwc2 are
used as representative examples.
It should be noted that many memory instructions that should have simm16
range checking do not because it is also necessary to support the macro
of the same name which accepts simm32. The range checks for these occur in
the macro expansion.
Reviewers: vkalintiris
Subscribers: dsanders, llvm-commits
Differential Revision: http://reviews.llvm.org/D18437
llvm-svn: 265019
Diffstat (limited to 'llvm/lib')
| -rw-r--r-- | llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp | 19 | ||||
| -rw-r--r-- | llvm/lib/Target/Mips/Disassembler/MipsDisassembler.cpp | 13 | ||||
| -rw-r--r-- | llvm/lib/Target/Mips/Mips64r6InstrInfo.td | 2 | ||||
| -rw-r--r-- | llvm/lib/Target/Mips/MipsInstrInfo.td | 69 |
4 files changed, 68 insertions, 35 deletions
diff --git a/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp b/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp index 986bb8fc757..2d98fa02e11 100644 --- a/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp +++ b/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp @@ -948,6 +948,15 @@ public: } template <unsigned Bits> + void addSImmOperands(MCInst &Inst, unsigned N) const { + if (isImm() && !isConstantImm()) { + addExpr(Inst, getImm()); + return; + } + addConstantSImmOperands<Bits, 0, 0>(Inst, N); + } + + template <unsigned Bits> void addUImmOperands(MCInst &Inst, unsigned N) const { if (isImm() && !isConstantImm()) { addExpr(Inst, getImm()); @@ -1031,6 +1040,9 @@ public: template <unsigned Bits, int Offset = 0> bool isConstantUImm() const { return isConstantImm() && isUInt<Bits>(getConstantImm() - Offset); } + template <unsigned Bits> bool isSImm() const { + return isConstantImm() ? isInt<Bits>(getConstantImm()) : isImm(); + } template <unsigned Bits> bool isUImm() const { return isConstantImm() ? isUInt<Bits>(getConstantImm()) : isImm(); } @@ -3793,6 +3805,10 @@ bool MipsAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, case Match_UImm16_Relaxed: return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), "expected 16-bit unsigned immediate"); + case Match_SImm16: + case Match_SImm16_Relaxed: + return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), + "expected 16-bit signed immediate"); case Match_UImm20_0: return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), "expected 20-bit unsigned immediate"); @@ -3820,6 +3836,9 @@ bool MipsAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, case Match_MemSImm11: return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), "expected memory with 11-bit signed offset"); + case Match_MemSImm16: + return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), + "expected memory with 16-bit signed offset"); } llvm_unreachable("Implement any new match types added!"); diff --git a/llvm/lib/Target/Mips/Disassembler/MipsDisassembler.cpp b/llvm/lib/Target/Mips/Disassembler/MipsDisassembler.cpp index 81c18683c4a..a8131857cd2 100644 --- a/llvm/lib/Target/Mips/Disassembler/MipsDisassembler.cpp +++ b/llvm/lib/Target/Mips/Disassembler/MipsDisassembler.cpp @@ -373,11 +373,6 @@ static DecodeStatus DecodePOOL16BEncodedField(MCInst &Inst, uint64_t Address, const void *Decoder); -static DecodeStatus DecodeSimm16(MCInst &Inst, - unsigned Insn, - uint64_t Address, - const void *Decoder); - template <unsigned Bits, int Offset, int Scale> static DecodeStatus DecodeUImmWithOffsetAndScale(MCInst &Inst, unsigned Value, uint64_t Address, @@ -1929,14 +1924,6 @@ static DecodeStatus DecodePOOL16BEncodedField(MCInst &Inst, return MCDisassembler::Success; } -static DecodeStatus DecodeSimm16(MCInst &Inst, - unsigned Insn, - uint64_t Address, - const void *Decoder) { - Inst.addOperand(MCOperand::createImm(SignExtend32<16>(Insn))); - return MCDisassembler::Success; -} - template <unsigned Bits, int Offset, int Scale> static DecodeStatus DecodeUImmWithOffsetAndScale(MCInst &Inst, unsigned Value, uint64_t Address, diff --git a/llvm/lib/Target/Mips/Mips64r6InstrInfo.td b/llvm/lib/Target/Mips/Mips64r6InstrInfo.td index b9b248eee1f..087bddc59c3 100644 --- a/llvm/lib/Target/Mips/Mips64r6InstrInfo.td +++ b/llvm/lib/Target/Mips/Mips64r6InstrInfo.td @@ -48,7 +48,7 @@ class SCD_R6_ENC : SPECIAL3_LL_SC_FM<OPCODE6_SCD>; class AHI_ATI_DESC_BASE<string instr_asm, RegisterOperand GPROpnd, InstrItinClass itin> { dag OutOperandList = (outs GPROpnd:$rs); - dag InOperandList = (ins GPROpnd:$rt, simm16:$imm); + dag InOperandList = (ins GPROpnd:$rt, simm16_relaxed:$imm); string AsmString = !strconcat(instr_asm, "\t$rt, $imm"); string Constraints = "$rs = $rt"; InstrItinClass Itinerary = itin; diff --git a/llvm/lib/Target/Mips/MipsInstrInfo.td b/llvm/lib/Target/Mips/MipsInstrInfo.td index 451cf80b92b..b6b6eae9aa5 100644 --- a/llvm/lib/Target/Mips/MipsInstrInfo.td +++ b/llvm/lib/Target/Mips/MipsInstrInfo.td @@ -421,6 +421,15 @@ class ConstantUImmRangeAsmOperandClass<int Bottom, int Top, let DiagnosticType = "UImmRange" # Bottom # "_" # Top; } +class SImmAsmOperandClass<int Bits, list<AsmOperandClass> Supers = []> + : AsmOperandClass { + let Name = "SImm" # Bits; + let RenderMethod = "addSImmOperands<" # Bits # ">"; + let PredicateMethod = "isSImm<" # Bits # ">"; + let SuperClasses = Supers; + let DiagnosticType = "SImm" # Bits; +} + class UImmAsmOperandClass<int Bits, list<AsmOperandClass> Supers = []> : AsmOperandClass { let Name = "UImm" # Bits; @@ -465,11 +474,19 @@ def UImm16RelaxedAsmOperandClass } def UImm16AsmOperandClass : UImmAsmOperandClass<16, [UImm16RelaxedAsmOperandClass]>; +def SImm16RelaxedAsmOperandClass + : SImmAsmOperandClass<16, [UImm16RelaxedAsmOperandClass]> { + let Name = "SImm16_Relaxed"; + let PredicateMethod = "isAnyImm<16>"; + let DiagnosticType = "SImm16_Relaxed"; +} +def SImm16AsmOperandClass + : SImmAsmOperandClass<16, [SImm16RelaxedAsmOperandClass]>; def ConstantSImm10Lsl3AsmOperandClass : AsmOperandClass { let Name = "SImm10Lsl3"; let RenderMethod = "addImmOperands"; let PredicateMethod = "isScaledSImm<10, 3>"; - let SuperClasses = [UImm16AsmOperandClass]; + let SuperClasses = [SImm16AsmOperandClass]; let DiagnosticType = "SImm10_Lsl3"; } def ConstantSImm10Lsl2AsmOperandClass : AsmOperandClass { @@ -600,10 +617,6 @@ def calltarget : Operand<iPTR> { def imm64: Operand<i64>; -def simm16 : Operand<i32> { - let DecoderMethod= "DecodeSimm16"; -} - def simm19_lsl2 : Operand<i32> { let EncoderMethod = "getSimm19Lsl2Encoding"; let DecoderMethod = "DecodeSimm19Lsl2"; @@ -618,10 +631,6 @@ def simm18_lsl3 : Operand<i32> { def simm32 : Operand<i32>; -def simm16_64 : Operand<i64> { - let DecoderMethod = "DecodeSimm16"; -} - // Zero def uimmz : Operand<i32> { let PrintMethod = "printUImm<0>"; @@ -796,6 +805,22 @@ def simm7_lsl2 : Operand<OtherVT> { let ParserMatchClass = ConstantSImm7Lsl2AsmOperandClass; } +def simm16 : Operand<i32> { + let DecoderMethod = "DecodeSImmWithOffsetAndScale<16>"; + let ParserMatchClass = !cast<AsmOperandClass>("SImm16AsmOperandClass"); +} + +// Like simm16 but coerces uimm16 to simm16. +def simm16_relaxed : Operand<i32> { + let DecoderMethod = "DecodeSImmWithOffsetAndScale<16>"; + let ParserMatchClass = !cast<AsmOperandClass>("SImm16RelaxedAsmOperandClass"); +} + +def simm16_64 : Operand<i64> { + let DecoderMethod = "DecodeSImmWithOffsetAndScale<16>"; + let ParserMatchClass = !cast<AsmOperandClass>("SImm16AsmOperandClass"); +} + // This is almost the same as a uimm7 but 0x7f is interpreted as -1. def li16_imm : Operand<i32> { let DecoderMethod = "DecodeLi16Imm"; @@ -863,6 +888,7 @@ def MipsMemSimm16AsmOperand : AsmOperandClass { let RenderMethod = "addMemOperands"; let ParserMethod = "parseMemOperand"; let PredicateMethod = "isMemWithSimmOffset<16>"; + let DiagnosticType = "MemSImm16"; } def MipsInvertedImmoperand : AsmOperandClass { @@ -1603,11 +1629,11 @@ def LONG_BRANCH_ADDiu : PseudoSE<(outs GPR32Opnd:$dst), /// Arithmetic Instructions (ALU Immediate) let AdditionalPredicates = [NotInMicroMips] in { -def ADDiu : MMRel, StdMMR6Rel, ArithLogicI<"addiu", simm16, GPR32Opnd, +def ADDiu : MMRel, StdMMR6Rel, ArithLogicI<"addiu", simm16_relaxed, GPR32Opnd, II_ADDIU, immSExt16, add>, ADDI_FM<0x9>, IsAsCheapAsAMove; } -def ADDi : MMRel, ArithLogicI<"addi", simm16, GPR32Opnd>, ADDI_FM<0x8>, +def ADDi : MMRel, ArithLogicI<"addi", simm16_relaxed, GPR32Opnd>, ADDI_FM<0x8>, ISA_MIPS1_NOT_32R6_64R6; def SLTi : MMRel, SetCC_I<"slti", setlt, simm16, immSExt16, GPR32Opnd>, SLTI_FM<0xa>; @@ -2115,19 +2141,19 @@ def : MipsInstAlias<"move $dst, $src", def : MipsInstAlias<"bal $offset", (BGEZAL ZERO, brtarget:$offset), 0>, ISA_MIPS1_NOT_32R6_64R6; def : MipsInstAlias<"addu $rs, $rt, $imm", - (ADDiu GPR32Opnd:$rs, GPR32Opnd:$rt, simm16:$imm), 0>; + (ADDiu GPR32Opnd:$rs, GPR32Opnd:$rt, simm32:$imm), 0>; def : MipsInstAlias<"addu $rs, $imm", - (ADDiu GPR32Opnd:$rs, GPR32Opnd:$rs, simm16:$imm), 0>; + (ADDiu GPR32Opnd:$rs, GPR32Opnd:$rs, simm32:$imm), 0>; def : MipsInstAlias<"add $rs, $rt, $imm", - (ADDi GPR32Opnd:$rs, GPR32Opnd:$rt, simm16:$imm), 0>, + (ADDi GPR32Opnd:$rs, GPR32Opnd:$rt, simm32:$imm), 0>, ISA_MIPS1_NOT_32R6_64R6; def : MipsInstAlias<"add $rs, $imm", - (ADDi GPR32Opnd:$rs, GPR32Opnd:$rs, simm16:$imm), 0>, + (ADDi GPR32Opnd:$rs, GPR32Opnd:$rs, simm32:$imm), 0>, ISA_MIPS1_NOT_32R6_64R6; def : MipsInstAlias<"and $rs, $rt, $imm", - (ANDi GPR32Opnd:$rs, GPR32Opnd:$rt, simm16:$imm), 0>; + (ANDi GPR32Opnd:$rs, GPR32Opnd:$rt, simm32:$imm), 0>; def : MipsInstAlias<"and $rs, $imm", - (ANDi GPR32Opnd:$rs, GPR32Opnd:$rs, simm16:$imm), 0>; + (ANDi GPR32Opnd:$rs, GPR32Opnd:$rs, simm32:$imm), 0>; def : MipsInstAlias<"j $rs", (JR GPR32Opnd:$rs), 0>; let Predicates = [NotInMicroMips] in { def : MipsInstAlias<"jalr $rs", (JALR RA, GPR32Opnd:$rs), 0>; @@ -2142,9 +2168,9 @@ def : MipsInstAlias<"negu $rt", def : MipsInstAlias<"negu $rt, $rs", (SUBu GPR32Opnd:$rt, ZERO, GPR32Opnd:$rs), 1>; def : MipsInstAlias<"slt $rs, $rt, $imm", - (SLTi GPR32Opnd:$rs, GPR32Opnd:$rt, simm16:$imm), 0>; + (SLTi GPR32Opnd:$rs, GPR32Opnd:$rt, simm32:$imm), 0>; def : MipsInstAlias<"sltu $rt, $rs, $imm", - (SLTiu GPR32Opnd:$rt, GPR32Opnd:$rs, simm16:$imm), 0>; + (SLTiu GPR32Opnd:$rt, GPR32Opnd:$rs, simm32:$imm), 0>; def : MipsInstAlias<"xor $rs, $rt, $imm", (XORi GPR32Opnd:$rs, GPR32Opnd:$rt, simm32:$imm), 0>; def : MipsInstAlias<"xor $rs, $imm", @@ -2238,8 +2264,9 @@ def JalTwoReg : MipsAsmPseudoInst<(outs GPR32Opnd:$rd), (ins GPR32Opnd:$rs), def JalOneReg : MipsAsmPseudoInst<(outs), (ins GPR32Opnd:$rs), "jal\t$rs"> ; -def NORImm : MipsAsmPseudoInst<(outs), (ins GPR32Opnd:$rs, GPR32Opnd:$rt, simm16:$imm), - "nor\t$rs, $rt, $imm"> ; +def NORImm : MipsAsmPseudoInst< + (outs), (ins GPR32Opnd:$rs, GPR32Opnd:$rt, simm32:$imm), + "nor\t$rs, $rt, $imm"> ; let hasDelaySlot = 1, isCTI = 1 in { def BneImm : MipsAsmPseudoInst<(outs GPR32Opnd:$rt), |

