Index: lib/Target/Mips/AsmParser/MipsAsmParser.cpp =================================================================== --- lib/Target/Mips/AsmParser/MipsAsmParser.cpp +++ lib/Target/Mips/AsmParser/MipsAsmParser.cpp @@ -72,6 +72,8 @@ #define GET_ASSEMBLER_HEADER #include "MipsGenAsmMatcher.inc" + unsigned checkTargetMatchPredicate(MCInst &Inst) override; + bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, OperandVector &Operands, MCStreamer &Out, unsigned &ErrorInfo, @@ -219,6 +221,14 @@ } public: + enum MipsMatchResultTy { + Match_RequiresDifferentSrcAndDst = FIRST_TARGET_MATCH_RESULT_TY +#define GET_OPERAND_DIAGNOSTIC_TYPES +#include "MipsGenAsmMatcher.inc" +#undef GET_OPERAND_DIAGNOSTIC_TYPES + + }; + MipsAsmParser(MCSubtargetInfo &sti, MCAsmParser &parser, const MCInstrInfo &MII, const MCTargetOptions &Options) @@ -1157,11 +1167,24 @@ TempInst.clear(); } +unsigned MipsAsmParser::checkTargetMatchPredicate(MCInst &Inst) { + // As described by the Mips32r2 spec, the registers Rd and Rs for + // jalr.hb must be different. + unsigned Opcode = Inst.getOpcode(); + + if (Opcode == Mips::JALR_HB && + (Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg())) + return Match_RequiresDifferentSrcAndDst; + + return Match_Success; +} + bool MipsAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, OperandVector &Operands, MCStreamer &Out, unsigned &ErrorInfo, bool MatchingInlineAsm) { + MCInst Inst; SmallVector Instructions; unsigned MatchResult = @@ -1195,6 +1218,8 @@ } case Match_MnemonicFail: return Error(IDLoc, "invalid instruction"); + case Match_RequiresDifferentSrcAndDst: + return Error(IDLoc, "source and destination must be different"); } return true; } Index: lib/Target/Mips/Mips32r6InstrFormats.td =================================================================== --- lib/Target/Mips/Mips32r6InstrFormats.td +++ lib/Target/Mips/Mips32r6InstrFormats.td @@ -72,6 +72,7 @@ def OPCODE6_DALIGN : OPCODE6<0b100100>; def OPCODE6_BITSWAP : OPCODE6<0b100000>; def OPCODE6_DBITSWAP : OPCODE6<0b100100>; +def OPCODE6_JALR : OPCODE6<0b001001>; class FIELD_FMT Val> { bits<5> Value = Val; @@ -401,3 +402,16 @@ let Inst{4-0} = Cond.Value; } +class JR_HB_R6_FM : MipsR6Inst { + bits<5> rs; + + bits<32> Inst; + + let Inst{31-26} = OPGROUP_SPECIAL.Value; + let Inst{25-21} = rs; + let Inst{20-16} = 0; + let Inst{15-11} = 0; + let Inst{10} = 1; + let Inst{9-6} = 0; + let Inst{5-0} = Operation.Value; +} Index: lib/Target/Mips/Mips32r6InstrInfo.td =================================================================== --- lib/Target/Mips/Mips32r6InstrInfo.td +++ lib/Target/Mips/Mips32r6InstrInfo.td @@ -120,7 +120,7 @@ class JIALC_ENC : JMP_IDX_COMPACT_FM<0b111110>; class JIC_ENC : JMP_IDX_COMPACT_FM<0b110110>; - +class JR_HB_R6_ENC : JR_HB_R6_FM; class BITSWAP_ENC : SPECIAL3_2R_FM; class BLEZALC_ENC : CMP_BRANCH_1R_RT_OFF16_FM; class BNVC_ENC : CMP_BRANCH_2R_OFF16_FM, @@ -381,6 +381,14 @@ list Defs = [AT]; } +class JR_HB_R6_DESC : JR_HB_DESC_BASE<"jr.hb", GPR32Opnd> { + bit isBranch = 1; + bit isIndirectBranch = 1; + bit hasDelaySlot = 1; + bit isTerminator=1; + bit isBarrier=1; +} + class BITSWAP_DESC_BASE { dag OutOperandList = (outs GPROpnd:$rd); dag InOperandList = (ins GPROpnd:$rt); @@ -550,6 +558,7 @@ def DIVU : DIVU_ENC, DIVU_DESC, ISA_MIPS32R6; def JIALC : JIALC_ENC, JIALC_DESC, ISA_MIPS32R6; def JIC : JIC_ENC, JIC_DESC, ISA_MIPS32R6; +def JR_HB_R6 : JR_HB_R6_ENC, JR_HB_R6_DESC, ISA_MIPS32R6; // def LSA; // See MSA def LWPC : LWPC_ENC, LWPC_DESC, ISA_MIPS32R6; def LWUPC : LWUPC_ENC, LWUPC_DESC, ISA_MIPS32R6; Index: lib/Target/Mips/MipsInstrFormats.td =================================================================== --- lib/Target/Mips/MipsInstrFormats.td +++ lib/Target/Mips/MipsInstrFormats.td @@ -844,6 +844,34 @@ let Inst{5-0} = 0; // SLL } +class JR_HB_FM op> : StdArch{ + bits<5> rs; + + bits<32> Inst; + + let Inst{31-26} = 0; // SPECIAL + let Inst{25-21} = rs; + let Inst{20-11} = 0; + let Inst{10} = 1; + let Inst{9-6} = 0; + let Inst{5-0} = op; +} + +class JALR_HB_FM op> : StdArch { + bits<5> rd; + bits<5> rs; + + bits<32> Inst; + + let Inst{31-26} = 0; // SPECIAL + let Inst{25-21} = rs; + let Inst{20-16} = 0; + let Inst{15-11} = rd; + let Inst{10} = 1; + let Inst{9-6} = 0; + let Inst{5-0} = op; +} + class COP0_TLB_FM op> : StdArch { bits<32> Inst; Index: lib/Target/Mips/MipsInstrInfo.td =================================================================== --- lib/Target/Mips/MipsInstrInfo.td +++ lib/Target/Mips/MipsInstrInfo.td @@ -232,6 +232,9 @@ list InsnPredicates = [HasMips3, NotMips32r6, NotMips64r6]; } class ISA_MIPS32 { list InsnPredicates = [HasMips32]; } +class ISA_MIPS32_NOT_32R6_64R6 { + list InsnPredicates = [HasMips32, NotMips32r6, NotMips64r6]; +} class ISA_MIPS32R2 { list InsnPredicates = [HasMips32r2]; } class ISA_MIPS64 { list InsnPredicates = [HasMips64]; } class ISA_MIPS64R2 { list InsnPredicates = [HasMips64r2]; } @@ -1279,6 +1282,46 @@ def EHB : Barrier<"ehb">, BARRIER_FM<3>; def PAUSE : Barrier<"pause">, BARRIER_FM<5>, ISA_MIPS32R2; +// JR_HB and JALR_HB are defined here using the new style naming +// scheme because some of this code is shared with Mips32r6InstrInfo.td +// and because of that it doesn't follow the naming convention of the +// rest of the file. To avoid a mixture of old vs new style, the new +// style was chosen. +class JR_HB_DESC_BASE { + dag OutOperandList = (outs); + dag InOperandList = (ins GPROpnd:$rs); + string AsmString = !strconcat(instr_asm, "\t$rs"); + list Pattern = []; +} + +class JALR_HB_DESC_BASE { + dag OutOperandList = (outs GPROpnd:$rd); + dag InOperandList = (ins GPROpnd:$rs); + string AsmString = !strconcat(instr_asm, "\t$rd, $rs"); + list Pattern = []; +} + +class JR_HB_DESC : InstSE<(outs), (ins), "", [], NoItinerary, FrmJ>, + JR_HB_DESC_BASE<"jr.hb", GPR32Opnd> { + let isBranch=1; + let isIndirectBranch=1; + let hasDelaySlot=1; + let isTerminator=1; + let isBarrier=1; +} + +class JALR_HB_DESC : InstSE<(outs), (ins), "", [], NoItinerary, FrmJ>, + JALR_HB_DESC_BASE<"jalr.hb", GPR32Opnd> { + let isIndirectBranch=1; + let hasDelaySlot=1; +} + +class JR_HB_ENC : JR_HB_FM<8>; +class JALR_HB_ENC : JALR_HB_FM<9>; + +def JR_HB : JR_HB_DESC, JR_HB_ENC, ISA_MIPS32_NOT_32R6_64R6; +def JALR_HB : JALR_HB_DESC, JALR_HB_ENC, ISA_MIPS32; + class TLB : InstSE<(outs), (ins), asmstr, [], NoItinerary, FrmOther>; def TLBP : TLB<"tlbp">, COP0_TLB_FM<0x08>; @@ -1307,6 +1350,7 @@ } def : MipsInstAlias<"jal $rs", (JALR RA, GPR32Opnd:$rs), 0>; def : MipsInstAlias<"jal $rd,$rs", (JALR GPR32Opnd:$rd, GPR32Opnd:$rs), 0>; +def : MipsInstAlias<"jalr.hb $rs", (JALR_HB RA, GPR32Opnd:$rs), 1>, ISA_MIPS32; def : MipsInstAlias<"not $rt, $rs", (NOR GPR32Opnd:$rt, GPR32Opnd:$rs, ZERO), 0>; def : MipsInstAlias<"neg $rt, $rs", Index: test/MC/Disassembler/Mips/mips32r6.txt =================================================================== --- test/MC/Disassembler/Mips/mips32r6.txt +++ test/MC/Disassembler/Mips/mips32r6.txt @@ -114,3 +114,6 @@ 0x46 0x20 0x20 0x9a # CHECK: rint.d $f2, $f4 0x46 0x00 0x20 0x9b # CHECK: class.s $f2, $f4 0x46 0x20 0x20 0x9b # CHECK: class.d $f2, $f4 +0x00 0x80 0x04 0x09 # CHECK: jr.hb $4 +0x00 0x80 0xfc 0x09 # CHECK: jalr.hb $4 +0x00 0xa0 0x24 0x09 # CHECK: jalr.hb $4, $5 Index: test/MC/Disassembler/Mips/mips64r6.txt =================================================================== --- test/MC/Disassembler/Mips/mips64r6.txt +++ test/MC/Disassembler/Mips/mips64r6.txt @@ -128,3 +128,6 @@ 0x46 0x00 0x20 0x9b # CHECK: class.s $f2, $f4 0x46 0x20 0x20 0x9b # CHECK: class.d $f2, $f4 0xec 0x58 0x3c 0x48 # CHECK: ldpc $2, 123456 +0x00 0x80 0x04 0x09 # CHECK: jr.hb $4 +0x00 0x80 0xfc 0x09 # CHECK: jalr.hb $4 +0x00 0xa0 0x24 0x09 # CHECK: jalr.hb $4, $5 Index: test/MC/Mips/mips2/invalid-mips32.s =================================================================== --- test/MC/Mips/mips2/invalid-mips32.s +++ test/MC/Mips/mips2/invalid-mips32.s @@ -9,6 +9,9 @@ clz $sp,$gp # CHECK: :[[@LINE]]:{{[0-9]+}}: error: instruction requires a CPU feature not currently enabled deret # CHECK: :[[@LINE]]:{{[0-9]+}}: error: instruction requires a CPU feature not currently enabled eret # CHECK: :[[@LINE]]:{{[0-9]+}}: error: instruction requires a CPU feature not currently enabled + jr.hb $4 # CHECK: :[[@LINE]]:{{[0-9]+}}: error: instruction requires a CPU feature not currently enabled + jalr.hb $4 # CHECK: :[[@LINE]]:{{[0-9]+}}: error: instruction requires a CPU feature not currently enabled + jalr.hb $4, $5 # CHECK: :[[@LINE]]:{{[0-9]+}}: error: instruction requires a CPU feature not currently enabled madd $s6,$13 # CHECK: :[[@LINE]]:{{[0-9]+}}: error: instruction requires a CPU feature not currently enabled madd $zero,$9 # CHECK: :[[@LINE]]:{{[0-9]+}}: error: instruction requires a CPU feature not currently enabled maddu $s3,$gp # CHECK: :[[@LINE]]:{{[0-9]+}}: error: instruction requires a CPU feature not currently enabled Index: test/MC/Mips/mips32r2/invalid.s =================================================================== --- /dev/null +++ test/MC/Mips/mips32r2/invalid.s @@ -0,0 +1,10 @@ +# Instructions that are valid for the current ISA but should be rejected by the assembler (e.g. +# invalid set of operands or operand's restrictions not met). + +# RUN: not llvm-mc %s -triple=mips-unknown-linux -mcpu=mips32r2 2>%t1 +# RUN: FileCheck %s < %t1 -check-prefix=ASM + + .text + .set noreorder + jalr.hb $31 # ASM: :[[@LINE]]:9: error: source and destination must be different + jalr.hb $31, $31 # ASM: :[[@LINE]]:9: error: source and destination must be different Index: test/MC/Mips/mips32r2/valid.s =================================================================== --- test/MC/Mips/mips32r2/valid.s +++ test/MC/Mips/mips32r2/valid.s @@ -40,6 +40,9 @@ eret floor.w.d $f14,$f11 floor.w.s $f8,$f9 + jr.hb $4 # CHECK: jr.hb $4 # encoding: [0x00,0x80,0x04,0x08] + jalr.hb $4 # CHECK: jalr.hb $4 # encoding: [0x00,0x80,0xfc,0x09] + jalr.hb $4, $5 # CHECK: jalr.hb $4, $5 # encoding: [0x00,0xa0,0x24,0x09] lb $24,-14515($10) lbu $8,30195($v1) ldc1 $f11,16391($s0) Index: test/MC/Mips/mips32r6/invalid.s =================================================================== --- /dev/null +++ test/MC/Mips/mips32r6/invalid.s @@ -0,0 +1,12 @@ +# Instructions that are valid for the current ISA but should be rejected by the assembler (e.g. +# invalid set of operands or operand's restrictions not met). + +# RUN: not llvm-mc %s -triple=mips-unknown-linux -mcpu=mips32r6 2>%t1 +# RUN: FileCheck %s < %t1 -check-prefix=ASM + + .text + .set noreorder + jalr.hb $31 +# ASM: :[[@LINE-1]]:9: error: source and destination must be different + jalr.hb $31, $31 +# ASM: :[[@LINE-1]]:9: error: source and destination must be different Index: test/MC/Mips/mips32r6/valid.s =================================================================== --- test/MC/Mips/mips32r6/valid.s +++ test/MC/Mips/mips32r6/valid.s @@ -124,3 +124,6 @@ rint.d $f2, $f4 # CHECK: rint.d $f2, $f4 # encoding: [0x46,0x20,0x20,0x9a] class.s $f2, $f4 # CHECK: class.s $f2, $f4 # encoding: [0x46,0x00,0x20,0x9b] class.d $f2, $f4 # CHECK: class.d $f2, $f4 # encoding: [0x46,0x20,0x20,0x9b] + jr.hb $4 # CHECK: jr.hb $4 # encoding: [0x00,0x80,0x04,0x09] + jalr.hb $4 # CHECK: jalr.hb $4 # encoding: [0x00,0x80,0xfc,0x09] + jalr.hb $4, $5 # CHECK: jalr.hb $4, $5 # encoding: [0x00,0xa0,0x24,0x09] Index: test/MC/Mips/mips5/invalid-mips64.s =================================================================== --- test/MC/Mips/mips5/invalid-mips64.s +++ test/MC/Mips/mips5/invalid-mips64.s @@ -10,6 +10,9 @@ dclo $s2,$a2 # CHECK: :[[@LINE]]:{{[0-9]+}}: error: instruction requires a CPU feature not currently enabled dclz $s0,$25 # CHECK: :[[@LINE]]:{{[0-9]+}}: error: instruction requires a CPU feature not currently enabled deret # CHECK: :[[@LINE]]:{{[0-9]+}}: error: instruction requires a CPU feature not currently enabled + jr.hb $4 # CHECK: :[[@LINE]]:{{[0-9]+}}: error: instruction requires a CPU feature not currently enabled + jalr.hb $4 # CHECK: :[[@LINE]]:{{[0-9]+}}: error: instruction requires a CPU feature not currently enabled + jalr.hb $4, $5 # CHECK: :[[@LINE]]:{{[0-9]+}}: error: instruction requires a CPU feature not currently enabled madd $s6,$13 # CHECK: :[[@LINE]]:{{[0-9]+}}: error: instruction requires a CPU feature not currently enabled madd $zero,$9 # CHECK: :[[@LINE]]:{{[0-9]+}}: error: instruction requires a CPU feature not currently enabled maddu $s3,$gp # CHECK: :[[@LINE]]:{{[0-9]+}}: error: instruction requires a CPU feature not currently enabled Index: test/MC/Mips/mips64r2/invalid.s =================================================================== --- /dev/null +++ test/MC/Mips/mips64r2/invalid.s @@ -0,0 +1,12 @@ +# Instructions that are valid for the current ISA but should be rejected by the assembler (e.g. +# invalid set of operands or operand's restrictions not met). + +# RUN: not llvm-mc %s -triple=mips64-unknown-linux -mcpu=mips64r2 2>%t1 +# RUN: FileCheck %s < %t1 -check-prefix=ASM + + .text + .set noreorder + jalr.hb $31 +# ASM: :[[@LINE-1]]:9: error: source and destination must be different + jalr.hb $31, $31 +# ASM: :[[@LINE-1]]:9: error: source and destination must be different Index: test/MC/Mips/mips64r2/valid.s =================================================================== --- test/MC/Mips/mips64r2/valid.s +++ test/MC/Mips/mips64r2/valid.s @@ -87,6 +87,9 @@ floor.l.s $f12,$f5 floor.w.d $f14,$f11 floor.w.s $f8,$f9 + jr.hb $4 # CHECK: jr.hb $4 # encoding: [0x00,0x80,0x04,0x08] + jalr.hb $4 # CHECK: jalr.hb $4 # encoding: [0x00,0x80,0xfc,0x09] + jalr.hb $4, $5 # CHECK: jalr.hb $4, $5 # encoding: [0x00,0xa0,0x24,0x09] lb $24,-14515($10) lbu $8,30195($v1) ld $sp,-28645($s1) Index: test/MC/Mips/mips64r6/invalid.s =================================================================== --- /dev/null +++ test/MC/Mips/mips64r6/invalid.s @@ -0,0 +1,10 @@ +# Instructions that are valid for the current ISA but should be rejected by the assembler (e.g. +# invalid set of operands or operand's restrictions not met). + +# RUN: not llvm-mc %s -triple=mips64-unknown-linux -mcpu=mips64r6 2>%t1 +# RUN: FileCheck %s < %t1 -check-prefix=ASM + + .text + .set noreorder + jalr.hb $31 # ASM: :[[@LINE]]:9: error: source and destination must be different + jalr.hb $31, $31 # ASM: :[[@LINE]]:9: error: source and destination must be different Index: test/MC/Mips/mips64r6/valid.s =================================================================== --- test/MC/Mips/mips64r6/valid.s +++ test/MC/Mips/mips64r6/valid.s @@ -138,3 +138,6 @@ rint.d $f2, $f4 # CHECK: rint.d $f2, $f4 # encoding: [0x46,0x20,0x20,0x9a] class.s $f2, $f4 # CHECK: class.s $f2, $f4 # encoding: [0x46,0x00,0x20,0x9b] class.d $f2, $f4 # CHECK: class.d $f2, $f4 # encoding: [0x46,0x20,0x20,0x9b] + jr.hb $4 # CHECK: jr.hb $4 # encoding: [0x00,0x80,0x04,0x09] + jalr.hb $4 # CHECK: jalr.hb $4 # encoding: [0x00,0x80,0xfc,0x09] + jalr.hb $4, $5 # CHECK: jalr.hb $4, $5 # encoding: [0x00,0xa0,0x24,0x09]