diff options
author | Daniel Sanders <daniel.sanders@imgtec.com> | 2015-11-26 16:35:41 +0000 |
---|---|---|
committer | Daniel Sanders <daniel.sanders@imgtec.com> | 2015-11-26 16:35:41 +0000 |
commit | daa4b6fbd933fe81bac1cb22b12f78bf1e3628ef (patch) | |
tree | 91a51285dd42a2c3f911a4c61be567ee165b2b10 /llvm/lib/Target | |
parent | e4fbec4a37ce2079fa53ddb1d79c8fbd070877ed (diff) | |
download | bcm5719-llvm-daa4b6fbd933fe81bac1cb22b12f78bf1e3628ef.tar.gz bcm5719-llvm-daa4b6fbd933fe81bac1cb22b12f78bf1e3628ef.zip |
[mips][ias] Range check uimm5 operands and fix several bugs this revealed.
Summary:
The bugs were:
* append, prepend, and balign were not tested
* balign takes a uimm2 not a uimm5.
* drotr32 was correctly implemented with a uimm5 but the tests expected
'52' to be valid.
* li/la were implemented with a uimm5 instead of simm32. simm32 isn't
completely correct either but I'll fix that when I get to simm32.
A notable omission are some of the shift instructions. Several of these
have been implemented using a single uimm6 instruction (rather than two
uimm5 instructions and a CodeGen-only uimm6 pseudo). These will be updated
in the uimm6 patch.
Reviewers: vkalintiris
Subscribers: llvm-commits, dsanders
Differential Revision: http://reviews.llvm.org/D14712
llvm-svn: 254164
Diffstat (limited to 'llvm/lib/Target')
-rw-r--r-- | llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp | 59 | ||||
-rw-r--r-- | llvm/lib/Target/Mips/MicroMipsInstrInfo.td | 13 | ||||
-rw-r--r-- | llvm/lib/Target/Mips/Mips64InstrInfo.td | 53 | ||||
-rw-r--r-- | llvm/lib/Target/Mips/MipsDSPInstrInfo.td | 14 | ||||
-rw-r--r-- | llvm/lib/Target/Mips/MipsInstrInfo.td | 65 |
5 files changed, 127 insertions, 77 deletions
diff --git a/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp b/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp index 32856550b70..44f665a86c6 100644 --- a/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp +++ b/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp @@ -928,12 +928,13 @@ public: Inst.addOperand(MCOperand::createReg(getHWRegsReg())); } - template <unsigned Bits, int Offset = 0> + template <unsigned Bits, int Offset = 0, int AdjustOffset = 0> void addConstantUImmOperands(MCInst &Inst, unsigned N) const { assert(N == 1 && "Invalid number of operands!"); uint64_t Imm = getConstantImm() - Offset; Imm &= (1 << Bits) - 1; Imm += Offset; + Imm += AdjustOffset; Inst.addOperand(MCOperand::createImm(Imm)); } @@ -1034,8 +1035,10 @@ public: && (getConstantMemOff() % 4 == 0) && getMemBase()->isRegIdx() && (getMemBase()->getGPR32Reg() == Mips::SP); } - bool isUImm5Lsl2() const { - return (isImm() && isConstantImm() && isShiftedUInt<5, 2>(getConstantImm())); + template <unsigned Bits, unsigned ShiftLeftAmount> + bool isScaledUImm() const { + return isConstantImm() && + isShiftedUInt<Bits, ShiftLeftAmount>(getConstantImm()); } bool isRegList16() const { if (!isRegList()) @@ -1620,32 +1623,6 @@ bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc, } break; - case Mips::CINS: - case Mips::CINS32: - case Mips::EXTS: - case Mips::EXTS32: - assert(MCID.getNumOperands() == 4 && "unexpected number of operands"); - // Check length - Opnd = Inst.getOperand(3); - if (!Opnd.isImm()) - return Error(IDLoc, "expected immediate operand kind"); - Imm = Opnd.getImm(); - if (Imm < 0 || Imm > 31) - return Error(IDLoc, "immediate operand value out of range"); - // Check position - Opnd = Inst.getOperand(2); - if (!Opnd.isImm()) - return Error(IDLoc, "expected immediate operand kind"); - Imm = Opnd.getImm(); - if (Imm < 0 || Imm > (Opcode == Mips::CINS || - Opcode == Mips::EXTS ? 63 : 31)) - return Error(IDLoc, "immediate operand value out of range"); - if (Imm > 31) { - Inst.setOpcode(Opcode == Mips::CINS ? Mips::CINS32 : Mips::EXTS32); - Inst.getOperand(2).setImm(Imm - 32); - } - break; - case Mips::SEQi: case Mips::SNEi: assert(MCID.getNumOperands() == 3 && "unexpected number of operands"); @@ -1909,16 +1886,6 @@ bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc, if (Imm < 0 || Imm > 60 || (Imm % 4 != 0)) return Error(IDLoc, "immediate operand value out of range"); break; - case Mips::PREFX_MM: - case Mips::CACHE: - case Mips::PREF: - Opnd = Inst.getOperand(2); - if (!Opnd.isImm()) - return Error(IDLoc, "expected immediate operand kind"); - Imm = Opnd.getImm(); - if (!isUInt<5>(Imm)) - return Error(IDLoc, "immediate operand value out of range"); - break; case Mips::ADDIUPC_MM: MCOperand Opnd = Inst.getOperand(1); if (!Opnd.isImm()) @@ -3666,6 +3633,20 @@ bool MipsAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, case Match_UImm4_0: return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), "expected 4-bit unsigned immediate"); + case Match_UImm5_0: + return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), + "expected 5-bit unsigned immediate"); + case Match_UImm5_32: + return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), + "expected immediate in range 32 .. 63"); + case Match_UImm5_0_Report_UImm6: + // This is used on UImm5 operands that have a corresponding UImm5_32 + // operand to avoid confusing the user. + return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), + "expected 6-bit unsigned immediate"); + case Match_UImm5_Lsl2: + return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), + "expected both 7-bit unsigned immediate and multiple of 4"); } llvm_unreachable("Implement any new match types added!"); diff --git a/llvm/lib/Target/Mips/MicroMipsInstrInfo.td b/llvm/lib/Target/Mips/MicroMipsInstrInfo.td index 5eb5a4d233b..175a9559e00 100644 --- a/llvm/lib/Target/Mips/MicroMipsInstrInfo.td +++ b/llvm/lib/Target/Mips/MicroMipsInstrInfo.td @@ -13,19 +13,6 @@ def simm12 : Operand<i32> { let DecoderMethod = "DecodeSimm12"; } -def MipsUimm5Lsl2AsmOperand : AsmOperandClass { - let Name = "Uimm5Lsl2"; - let RenderMethod = "addImmOperands"; - let ParserMethod = "parseImm"; - let PredicateMethod = "isUImm5Lsl2"; -} - -def uimm5_lsl2 : Operand<OtherVT> { - let EncoderMethod = "getUImm5Lsl2Encoding"; - let DecoderMethod = "DecodeUImm5lsl2"; - let ParserMatchClass = MipsUimm5Lsl2AsmOperand; -} - def uimm6_lsl2 : Operand<i32> { let EncoderMethod = "getUImm6Lsl2Encoding"; let DecoderMethod = "DecodeUImm6Lsl2"; diff --git a/llvm/lib/Target/Mips/Mips64InstrInfo.td b/llvm/lib/Target/Mips/Mips64InstrInfo.td index ec0953cae03..0992186a087 100644 --- a/llvm/lib/Target/Mips/Mips64InstrInfo.td +++ b/llvm/lib/Target/Mips/Mips64InstrInfo.td @@ -16,10 +16,6 @@ //===----------------------------------------------------------------------===// // Unsigned Operand -def uimm5_64 : Operand<i64> { - let PrintMethod = "printUnsignedImm"; -} - def uimm16_64 : Operand<i64> { let PrintMethod = "printUnsignedImm"; } @@ -343,8 +339,8 @@ class SetCC64_I<string opstr, PatFrag cond_op>: } class CBranchBitNum<string opstr, DAGOperand opnd, PatFrag cond_op, - RegisterOperand RO, bits<64> shift = 1> : - InstSE<(outs), (ins RO:$rs, uimm5_64:$p, opnd:$offset), + RegisterOperand RO, Operand ImmOp, bits<64> shift = 1> : + InstSE<(outs), (ins RO:$rs, ImmOp:$p, opnd:$offset), !strconcat(opstr, "\t$rs, $p, $offset"), [(brcond (i32 (cond_op (and RO:$rs, (shl shift, immZExt5_64:$p)), 0)), bb:$offset)], II_BBIT, FrmI, opstr> { @@ -365,14 +361,17 @@ def BADDu : ArithLogicR<"baddu", GPR64Opnd, 1, II_BADDU>, ADD_FM<0x1c, 0x28>; // Branch on Bit Clear /+32 -def BBIT0 : CBranchBitNum<"bbit0", brtarget, seteq, GPR64Opnd>, BBIT_FM<0x32>; -def BBIT032: CBranchBitNum<"bbit032", brtarget, seteq, GPR64Opnd, 0x100000000>, +def BBIT0 : CBranchBitNum<"bbit0", brtarget, seteq, GPR64Opnd, + uimm5_64_report_uimm6>, BBIT_FM<0x32>; +def BBIT032: CBranchBitNum<"bbit032", brtarget, seteq, GPR64Opnd, uimm5_64, + 0x100000000>, BBIT_FM<0x36>; // Branch on Bit Set /+32 -def BBIT1 : CBranchBitNum<"bbit1", brtarget, setne, GPR64Opnd>, BBIT_FM<0x3a>; -def BBIT132: CBranchBitNum<"bbit132", brtarget, setne, GPR64Opnd, 0x100000000>, - BBIT_FM<0x3e>; +def BBIT1 : CBranchBitNum<"bbit1", brtarget, setne, GPR64Opnd, + uimm5_64_report_uimm6>, BBIT_FM<0x3a>; +def BBIT132: CBranchBitNum<"bbit132", brtarget, setne, GPR64Opnd, uimm5_64, + 0x100000000>, BBIT_FM<0x3e>; // Multiply Doubleword to GPR let Defs = [HI0, LO0, P0, P1, P2] in @@ -634,6 +633,38 @@ def : MipsInstAlias<"syncw", (SYNC 0x4), 0>; def : MipsInstAlias<"syncws", (SYNC 0x5), 0>; } +// cnMIPS Aliases. + +// bbit* with $p 32-63 converted to bbit*32 with $p 0-31 +def : MipsInstAlias<"bbit0 $rs, $p, $offset", + (BBIT032 GPR64Opnd:$rs, uimm5_plus32_normalize_64:$p, + brtarget:$offset), 0>, + ASE_CNMIPS; +def : MipsInstAlias<"bbit1 $rs, $p, $offset", + (BBIT132 GPR64Opnd:$rs, uimm5_plus32_normalize_64:$p, + brtarget:$offset), 0>, + ASE_CNMIPS; + +// exts with $pos 32-63 in converted to exts32 with $pos 0-31 +def : MipsInstAlias<"exts $rt, $rs, $pos, $lenm1", + (EXTS32 GPR64Opnd:$rt, GPR64Opnd:$rs, + uimm5_plus32_normalize:$pos, uimm5:$lenm1), 0>, + ASE_CNMIPS; +def : MipsInstAlias<"exts $rt, $pos, $lenm1", + (EXTS32 GPR64Opnd:$rt, GPR64Opnd:$rt, + uimm5_plus32_normalize:$pos, uimm5:$lenm1), 0>, + ASE_CNMIPS; + +// cins with $pos 32-63 in converted to cins32 with $pos 0-31 +def : MipsInstAlias<"cins $rt, $rs, $pos, $lenm1", + (CINS32 GPR64Opnd:$rt, GPR64Opnd:$rs, + uimm5_plus32_normalize:$pos, uimm5:$lenm1), 0>, + ASE_CNMIPS; +def : MipsInstAlias<"cins $rt, $pos, $lenm1", + (CINS32 GPR64Opnd:$rt, GPR64Opnd:$rt, + uimm5_plus32_normalize:$pos, uimm5:$lenm1), 0>, + ASE_CNMIPS; + //===----------------------------------------------------------------------===// // Assembler Pseudo Instructions //===----------------------------------------------------------------------===// diff --git a/llvm/lib/Target/Mips/MipsDSPInstrInfo.td b/llvm/lib/Target/Mips/MipsDSPInstrInfo.td index 0ad0d344efb..9b4b9d17818 100644 --- a/llvm/lib/Target/Mips/MipsDSPInstrInfo.td +++ b/llvm/lib/Target/Mips/MipsDSPInstrInfo.td @@ -372,12 +372,12 @@ class ADDUH_QB_DESC_BASE<string instr_asm, SDPatternOperator OpNode, } class APPEND_DESC_BASE<string instr_asm, SDPatternOperator OpNode, - SDPatternOperator ImmOp, InstrItinClass itin> { + Operand ImmOp, SDPatternOperator Imm, InstrItinClass itin> { dag OutOperandList = (outs GPR32Opnd:$rt); - dag InOperandList = (ins GPR32Opnd:$rs, uimm5:$sa, GPR32Opnd:$src); + dag InOperandList = (ins GPR32Opnd:$rs, ImmOp:$sa, GPR32Opnd:$src); string AsmString = !strconcat(instr_asm, "\t$rt, $rs, $sa"); list<dag> Pattern = [(set GPR32Opnd:$rt, - (OpNode GPR32Opnd:$src, GPR32Opnd:$rs, ImmOp:$sa))]; + (OpNode GPR32Opnd:$src, GPR32Opnd:$rs, Imm:$sa))]; InstrItinClass Itinerary = itin; string Constraints = "$src = $rt"; } @@ -1074,14 +1074,14 @@ class SHRLV_PH_DESC : SHLL_QB_R3_DESC_BASE<"shrlv.ph", int_mips_shrl_ph, NoItinerary, DSPROpnd>; // Misc -class APPEND_DESC : APPEND_DESC_BASE<"append", int_mips_append, immZExt5, +class APPEND_DESC : APPEND_DESC_BASE<"append", int_mips_append, uimm5, immZExt5, NoItinerary>; -class BALIGN_DESC : APPEND_DESC_BASE<"balign", int_mips_balign, immZExt2, +class BALIGN_DESC : APPEND_DESC_BASE<"balign", int_mips_balign, uimm2, immZExt2, NoItinerary>; -class PREPEND_DESC : APPEND_DESC_BASE<"prepend", int_mips_prepend, immZExt5, - NoItinerary>; +class PREPEND_DESC : APPEND_DESC_BASE<"prepend", int_mips_prepend, uimm5, + immZExt5, NoItinerary>; // Pseudos. def BPOSGE32_PSEUDO : BPOSGE32_PSEUDO_DESC_BASE<int_mips_bposge32, diff --git a/llvm/lib/Target/Mips/MipsInstrInfo.td b/llvm/lib/Target/Mips/MipsInstrInfo.td index 0fe181001a6..e0b317e9bf2 100644 --- a/llvm/lib/Target/Mips/MipsInstrInfo.td +++ b/llvm/lib/Target/Mips/MipsInstrInfo.td @@ -311,6 +311,10 @@ class INSN_MIPS5_32R2_NOT_32R6_64R6 { list<Predicate> InsnPredicates = [HasMips5_32r2, NotMips32r6, NotMips64r6]; } +class ASE_CNMIPS { + list<Predicate> InsnPredicates = [HasCnMips]; +} + class ASE_MSA { list<Predicate> InsnPredicates = [HasMSA]; } @@ -390,8 +394,29 @@ class ConstantUImmAsmOperandClass<int Bits, list<AsmOperandClass> Supers = [], let DiagnosticType = "UImm" # Bits # "_" # Offset; } +def ConstantUImm5Plus32NormalizeAsmOperandClass + : ConstantUImmAsmOperandClass<5, [], 32> { + // We must also subtract 32 when we render the operand. + let RenderMethod = "addConstantUImmOperands<5, 32, -32>"; +} +def ConstantUImm5Lsl2AsmOperandClass : AsmOperandClass { + let Name = "UImm5Lsl2"; + let RenderMethod = "addImmOperands"; + let PredicateMethod = "isScaledUImm<5, 2>"; + let SuperClasses = []; + let DiagnosticType = "UImm5_Lsl2"; +} +def ConstantUImm5ReportUImm6AsmOperandClass + : ConstantUImmAsmOperandClass<5, []> { + let Name = "ConstantUImm5_0_Report_UImm6"; + let DiagnosticType = "UImm5_0_Report_UImm6"; +} +def ConstantUImm5AsmOperandClass + : ConstantUImmAsmOperandClass<5, []>; def ConstantUImm4AsmOperandClass - : ConstantUImmAsmOperandClass<4, []>; + : ConstantUImmAsmOperandClass< + 4, [ConstantUImm5AsmOperandClass, + ConstantUImm5Plus32NormalizeAsmOperandClass]>; def ConstantUImm3AsmOperandClass : ConstantUImmAsmOperandClass<3, [ConstantUImm4AsmOperandClass]>; def ConstantUImm2Plus1AsmOperandClass @@ -453,8 +478,8 @@ def simm18_lsl3 : Operand<i32> { let ParserMatchClass = MipsJumpTargetAsmOperand; } -def simm20 : Operand<i32> { -} +def simm20 : Operand<i32>; +def simm32 : Operand<i32>; def uimm20 : Operand<i32> { } @@ -481,7 +506,7 @@ def uimmz : Operand<i32> { } // Unsigned Operands -foreach I = {1, 2, 3, 4} in +foreach I = {1, 2, 3, 4, 5} in def uimm # I : Operand<i32> { let PrintMethod = "printUnsignedImm"; let ParserMatchClass = @@ -495,8 +520,34 @@ def uimm2_plus1 : Operand<i32> { let ParserMatchClass = ConstantUImm2Plus1AsmOperandClass; } -def uimm5 : Operand<i32> { +def uimm5_plus32_normalize : Operand<i32> { + let PrintMethod = "printUnsignedImm"; + let ParserMatchClass = ConstantUImm5Plus32NormalizeAsmOperandClass; +} + +def uimm5_lsl2 : Operand<OtherVT> { + let EncoderMethod = "getUImm5Lsl2Encoding"; + let DecoderMethod = "DecodeUImm5lsl2"; + let ParserMatchClass = ConstantUImm5Lsl2AsmOperandClass; +} + +def uimm5_plus32_normalize_64 : Operand<i64> { + let PrintMethod = "printUnsignedImm"; + let ParserMatchClass = ConstantUImm5Plus32NormalizeAsmOperandClass; +} + +foreach I = {5} in + def uimm # I # _64 : Operand<i64> { + let PrintMethod = "printUnsignedImm"; + let ParserMatchClass = + !cast<AsmOperandClass>("ConstantUImm" # I # "AsmOperandClass"); + } + +// Like uimm5_64 but reports a less confusing error for 32-63 when +// an instruction alias permits that. +def uimm5_64_report_uimm6 : Operand<i64> { let PrintMethod = "printUnsignedImm"; + let ParserMatchClass = ConstantUImm5ReportUImm6AsmOperandClass; } def uimm6 : Operand<i32> { @@ -1847,7 +1898,7 @@ def : MipsInstAlias<"sync", class LoadImmediate32<string instr_asm, Operand Od, RegisterOperand RO> : MipsAsmPseudoInst<(outs RO:$rt), (ins Od:$imm32), !strconcat(instr_asm, "\t$rt, $imm32")> ; -def LoadImm32 : LoadImmediate32<"li", uimm5, GPR32Opnd>; +def LoadImm32 : LoadImmediate32<"li", simm32, GPR32Opnd>; class LoadAddressFromReg32<string instr_asm, Operand MemOpnd, RegisterOperand RO> : @@ -1858,7 +1909,7 @@ def LoadAddrReg32 : LoadAddressFromReg32<"la", mem, GPR32Opnd>; class LoadAddressFromImm32<string instr_asm, Operand Od, RegisterOperand RO> : MipsAsmPseudoInst<(outs RO:$rt), (ins Od:$imm32), !strconcat(instr_asm, "\t$rt, $imm32")> ; -def LoadAddrImm32 : LoadAddressFromImm32<"la", uimm5, GPR32Opnd>; +def LoadAddrImm32 : LoadAddressFromImm32<"la", simm32, GPR32Opnd>; def JalTwoReg : MipsAsmPseudoInst<(outs GPR32Opnd:$rd), (ins GPR32Opnd:$rs), "jal\t$rd, $rs"> ; |