diff --git a/llvm/lib/Target/MSP430/AsmParser/MSP430AsmParser.cpp b/llvm/lib/Target/MSP430/AsmParser/MSP430AsmParser.cpp --- a/llvm/lib/Target/MSP430/AsmParser/MSP430AsmParser.cpp +++ b/llvm/lib/Target/MSP430/AsmParser/MSP430AsmParser.cpp @@ -60,6 +60,18 @@ bool parseJccInstruction(ParseInstructionInfo &Info, StringRef Name, SMLoc NameLoc, OperandVector &Operands); + /// Parse an rpt directive and the associated 430X extended instruction. + /// + /// '{' is a separator string, so two formats are accepted: + /// rpt # { ... + /// or + /// rpt # + /// ... + /// + /// Returns true on error. + bool parseRptDirective(ParseInstructionInfo &Info, StringRef Name, + SMLoc NameLoc, OperandVector &Operands); + bool ParseOperand(OperandVector &Operands); bool ParseLiteralValues(unsigned Size, SMLoc L); @@ -186,6 +198,19 @@ return false; } + /// Return true if the immediate value can be used for a 4-bit reptition + /// count after it is encoded. + bool isRpt4Imm() const { + int64_t Val; + if (!isImm() || !Imm->evaluateAsAbsolute(Val)) + return false; + + if (Val >= 1 && Val <= 16) + return true; + + return false; + } + StringRef getToken() const { assert(Kind == k_Tok && "Invalid access!"); return Tok; @@ -396,6 +421,59 @@ return false; } +bool MSP430AsmParser::parseRptDirective(ParseInstructionInfo &Info, + StringRef Name, SMLoc NameLoc, + OperandVector &Operands) { + assert(Name.startswith_insensitive("rpt") && "\"rpt\" directive expected"); + + SMLoc ExprLoc = getLexer().getLoc(); + if (!getLexer().is(AsmToken::Hash)) + return Error(ExprLoc, "expected immediate operand"); + + getLexer().Lex(); + + const MCExpr *Val; + if (getParser().parseExpression(Val)) + return Error(ExprLoc, "expected expression operand"); + + int64_t Res; + if (Val->evaluateAsAbsolute(Res)) + if (Res < 1 || Res > 16) + return Error(ExprLoc, "invalid repetition count"); + + // The repetition count operand is the second operand to the parsed + // instruction, so save it for later. + std::unique_ptr CntOp = + MSP430Operand::CreateImm(Val, ExprLoc, getLexer().getLoc()); + + if (getLexer().isNot(AsmToken::EndOfStatement)) { + SMLoc Loc = getLexer().getLoc(); + getParser().eatToEndOfStatement(); + return Error(Loc, "expected '{' or a newline after \"rpt #\""); + } + + getParser().eatToEndOfStatement(); + + // Get the name of the actual mnemonic. + Operands.push_back(MSP430Operand::CreateToken(getLexer().getTok().getString(), + getLexer().getLoc())); + getLexer().Lex(); + + // This is the first asm operand to the mnemonic, and to the parsed + // instruction. + if (ParseOperand(Operands)) + return true; + + Operands.push_back(std::move(CntOp)); + + if (getLexer().isNot(AsmToken::EndOfStatement)) { + SMLoc Loc = getLexer().getLoc(); + getParser().eatToEndOfStatement(); + return Error(Loc, "only one operand expected"); + } + return false; +} + bool MSP430AsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name, SMLoc NameLoc, OperandVector &Operands) { @@ -406,6 +484,9 @@ if (!parseJccInstruction(Info, Name, NameLoc, Operands)) return false; + if (Name.startswith_insensitive("rpt")) + return parseRptDirective(Info, Name, NameLoc, Operands); + // First operand is instruction mnemonic Operands.push_back(MSP430Operand::CreateToken(Name, NameLoc)); diff --git a/llvm/lib/Target/MSP430/MCTargetDesc/MSP430InstPrinter.cpp b/llvm/lib/Target/MSP430/MCTargetDesc/MSP430InstPrinter.cpp --- a/llvm/lib/Target/MSP430/MCTargetDesc/MSP430InstPrinter.cpp +++ b/llvm/lib/Target/MSP430/MCTargetDesc/MSP430InstPrinter.cpp @@ -12,6 +12,7 @@ #include "MSP430InstPrinter.h" #include "MSP430.h" +#include "MSP430InstrInfo.h" #include "llvm/MC/MCAsmInfo.h" #include "llvm/MC/MCExpr.h" #include "llvm/MC/MCInst.h" @@ -26,9 +27,29 @@ #define PRINT_ALIAS_INSTR #include "MSP430GenAsmWriter.inc" +/// Print the "rpt" directive and associated repetition count for a 430X +/// extended instruction that has the repetition flag set. +static void printRptDirective(const MCInst *MI, raw_ostream &O) { + assert(MI->getNumOperands() == 3 && "expected 3 operands"); + + const MCOperand &Op = MI->getOperand(2); + assert(Op.isImm() && "expected immediate operand for shift count"); + + unsigned Cnt = Op.getImm(); + // Accept a reptition count of 0, for when the instruction was parsed from + // assembly, without an rpt directive. + if (Cnt == 0 || Cnt == 1) + return; + O << "\trpt\t#" << Cnt << "\t{"; +} + void MSP430InstPrinter::printInst(const MCInst *MI, uint64_t Address, StringRef Annot, const MCSubtargetInfo &STI, raw_ostream &O) { + const MCInstrDesc &Desc = MII.get(MI->getOpcode()); + if (Desc.TSFlags & MSP430TSFlags::RptCount) + printRptDirective(MI, O); + if (!printAliasInstr(MI, Address, O)) printInstruction(MI, Address, O); printAnnotation(O, Annot); diff --git a/llvm/lib/Target/MSP430/MCTargetDesc/MSP430MCCodeEmitter.cpp b/llvm/lib/Target/MSP430/MCTargetDesc/MSP430MCCodeEmitter.cpp --- a/llvm/lib/Target/MSP430/MCTargetDesc/MSP430MCCodeEmitter.cpp +++ b/llvm/lib/Target/MSP430/MCTargetDesc/MSP430MCCodeEmitter.cpp @@ -72,6 +72,10 @@ unsigned getRpt2ImmOpValue(const MCInst &MI, unsigned Op, SmallVectorImpl &Fixups, const MCSubtargetInfo &STI) const; + /// Encode the repetition count for a 430X extended instruction. + unsigned getRpt4ImmOpValue(const MCInst &MI, unsigned Op, + SmallVectorImpl &Fixups, + const MCSubtargetInfo &STI) const; unsigned getCCOpValue(const MCInst &MI, unsigned Op, SmallVectorImpl &Fixups, @@ -212,6 +216,22 @@ return Imm - 1; } +unsigned +MSP430MCCodeEmitter::getRpt4ImmOpValue(const MCInst &MI, unsigned Op, + SmallVectorImpl &Fixups, + const MCSubtargetInfo &STI) const { + const MCOperand &MO = MI.getOperand(Op); + assert(MO.isImm() && "expr operand expected"); + + int64_t Imm = MO.getImm(); + assert((Imm >= 0 && Imm <= 16) && "invalid repetition count"); + // Imm is zero when there is no repetition count, because the instruction has + // been used without the rpt directive. + if (Imm == 0) + return Imm; + return Imm - 1; +} + unsigned MSP430MCCodeEmitter::getCCOpValue(const MCInst &MI, unsigned Op, SmallVectorImpl &Fixups, const MCSubtargetInfo &STI) const { diff --git a/llvm/lib/Target/MSP430/MSP430InstrFormats.td b/llvm/lib/Target/MSP430/MSP430InstrFormats.td --- a/llvm/lib/Target/MSP430/MSP430InstrFormats.td +++ b/llvm/lib/Target/MSP430/MSP430InstrFormats.td @@ -49,7 +49,9 @@ let Size = size; bit ExtensionWordFlag = 0; + bit RptCountFlag = 0; let TSFlags{0} = ExtensionWordFlag; + let TSFlags{1} = RptCountFlag; } // MSP430 Double Operand (Format I) Instructions @@ -475,7 +477,7 @@ // implemented. class ExtensionWordRegForm { bits<16> ExtensionWord; - bits<4> cnt = 0; + bits<4> cnt; let ExtensionWord{15-9} = 0b0001100; let ExtensionWord{8} = zc; diff --git a/llvm/lib/Target/MSP430/MSP430InstrInfo.h b/llvm/lib/Target/MSP430/MSP430InstrInfo.h --- a/llvm/lib/Target/MSP430/MSP430InstrInfo.h +++ b/llvm/lib/Target/MSP430/MSP430InstrInfo.h @@ -29,6 +29,9 @@ /// This bit is set if the instruction is an MSP430X extended instruction with /// an extension word. ExtensionWord = 0x1, + /// This bit is set if the instruction uses the reptition count field of the + /// the extension word. + RptCount = 0x2 }; } // namespace MSP430TSFlags diff --git a/llvm/lib/Target/MSP430/MSP430InstrInfoExtended.td b/llvm/lib/Target/MSP430/MSP430InstrInfoExtended.td --- a/llvm/lib/Target/MSP430/MSP430InstrInfoExtended.td +++ b/llvm/lib/Target/MSP430/MSP430InstrInfoExtended.td @@ -23,6 +23,11 @@ let RenderMethod = "addImmOperands"; } +def Rpt4ImmAsmOperand : AsmOperandClass { + let Name = "Rpt4Imm"; + let RenderMethod = "addImmOperands"; +} + def rpt2imm : Operand, ImmLeaf= 1 && Imm <= 4;}]> { let ParserMatchClass = Rpt2ImmAsmOperand; @@ -30,6 +35,13 @@ let DecoderMethod = "decodeRptImm"; } +def rpt4imm : Operand, + ImmLeaf= 1 && Imm <= 16;}]> { + let ParserMatchClass = Rpt4ImmAsmOperand; + let EncoderMethod = "getRpt4ImmOpValue"; + let DecoderMethod = "decodeRptImm"; +} + //===----------------------------------------------------------------------===// // Shift Instructions // @@ -46,28 +58,48 @@ defm RLAM : IIExtExcRot<"rlam", 0b10>; multiclass IIExtRot OpCode, bit ZC> { - def _8 : II8rExtended; - def _16 : II16rExtended; + let RptCountFlag = 1 in { + def _8 : II8rExtended; + def _16 : II16rExtended; + } } defm RRAX : IIExtRot<"rrax", 0b010, 0>; // RRUX is encoded as RRCX with the ZC flag set. defm RRUX : IIExtRot<"rrux", 0b000, 1>; multiclass IExtRot OpCode> { - def _8 : I8rExtended; - def _16 : I16rExtended; + let RptCountFlag = 1 in { + def _8 : I8rExtended; + def _16 : I16rExtended; + } } // RLAX is encoded as ADDX. defm RLAX : IExtRot<"rlax", 0b0101>; } // Defs = [SR], Constraints = "$rs = $rd" + +// These aliases are required so the DAG node created from +// "rpt # { " can be matched. +// +// When parsing the "rpt" directive and associated instruction, the repetition +// count is set up as the 2nd operand of the instruction. The default assembly +// string for these instructions only has one operand because the count is set +// separately by the rpt directive. +// +// The instructions don't actually have this format, so don't ever print them. +def : InstAlias<"rrax\t$rd, $cnt", (RRAX_16 GR16:$rd, rpt4imm:$cnt), 0>; +def : InstAlias<"rrux\t$rd, $cnt", (RRUX_16 GR16:$rd, rpt4imm:$cnt), 0>; +def : InstAlias<"rlax\t$rd, $cnt", (RLAX_16 GR16:$rd, rpt4imm:$cnt), 0>; +def : InstAlias<"rrax.b\t$rd, $cnt", (RRAX_8 GR8:$rd, rpt4imm:$cnt), 0>; +def : InstAlias<"rrux.b\t$rd, $cnt", (RRUX_8 GR8:$rd, rpt4imm:$cnt), 0>; +def : InstAlias<"rlax.b\t$rd, $cnt", (RLAX_8 GR8:$rd, rpt4imm:$cnt), 0>; } // Predicates = [HasMSP430X] diff --git a/llvm/test/MC/MSP430/shifts-430x-invalid.s b/llvm/test/MC/MSP430/shifts-430x-invalid.s --- a/llvm/test/MC/MSP430/shifts-430x-invalid.s +++ b/llvm/test/MC/MSP430/shifts-430x-invalid.s @@ -10,6 +10,14 @@ // CHECK: :8: error: invalid operand for instruction // CHECK: :8: error: invalid operand for instruction +// Check for an error when the reptition count is too large. + rpt #17 { rrux r12 + rpt #17 { rrax r12 + rpt #17 { rlax r12 +// CHECK: :7: error: invalid repetition count +// CHECK: :7: error: invalid repetition count +// CHECK: :7: error: invalid repetition count + // Check for an error when RxxX shifts have a shift amount operand. rrux #3, r12 rrax #3, r12 @@ -17,3 +25,40 @@ // CHECK: :8: error: invalid operand for instruction // CHECK: :8: error: invalid operand for instruction // CHECK: :8: error: invalid operand for instruction + +// Check for an error when there is no separator between rpt and the extended +// instruction. + rpt #3 rrux r12 + rpt #3 rrax r12 + rpt #3 rlax r12 +// CHECK: :10: error: expected '{' or a newline after "rpt #" +// CHECK: :10: error: expected '{' or a newline after "rpt #" +// CHECK: :10: error: expected '{' or a newline after "rpt #" + +// Check that rpt cannot be used with RxxM shifts. + rpt #3 { rrum #3, r12 + rpt #3 { rram #3, r12 + rpt #3 { rlam #3, r12 +// CHECK: :19: error: only one operand expected +// CHECK: :19: error: only one operand expected +// CHECK: :19: error: only one operand expected + +// Check that rpt cannot be used with 430 instructions. + rpt #3 { rrc r12 + rpt #3 { rra r12 + rpt #3 { rla r12 +// CHECK: :7: error: invalid operand for instruction +// CHECK: :7: error: invalid operand for instruction +// CHECK: :7: error: invalid operand for instruction + +// Check that the operand to rpt must be an immediate. + rpt foo { rrux r12 + rpt r13 { rrax r12 + rpt @r13 { rrax r12 + rpt &bar { rrax r12 + rpt 2(r14) { rlax r12 +// CHECK: :7: error: expected immediate operand +// CHECK: :7: error: expected immediate operand +// CHECK: :7: error: expected immediate operand +// CHECK: :7: error: expected immediate operand +// CHECK: :7: error: expected immediate operand diff --git a/llvm/test/MC/MSP430/shifts-430x.s b/llvm/test/MC/MSP430/shifts-430x.s --- a/llvm/test/MC/MSP430/shifts-430x.s +++ b/llvm/test/MC/MSP430/shifts-430x.s @@ -35,36 +35,385 @@ rrux: rrux r12 + rpt #1 { rrux r12 + rpt #2 { rrux r12 + rpt #3 { rrux r12 + rpt #4 { rrux r12 + rpt #5 { rrux r12 + rpt #6 { rrux r12 + rpt #7 { rrux r12 + rpt #8 { rrux r12 + rpt #9 { rrux r12 + rpt #10 { rrux r12 + rpt #11 { rrux r12 + rpt #12 { rrux r12 + rpt #13 { rrux r12 + rpt #14 { rrux r12 + rpt #15 { rrux r12 + rpt #16 { rrux r12 // CHECK-LABEL: rrux: // CHECK-NEXT: rrux r12 ; encoding: [0x40,0x19,0x0c,0x10] +// CHECK: rrux r12 ; encoding: [0x40,0x19,0x0c,0x10] +// CHECK: rpt #2 { rrux r12 ; encoding: [0x41,0x19,0x0c,0x10] +// CHECK: rpt #3 { rrux r12 ; encoding: [0x42,0x19,0x0c,0x10] +// CHECK: rpt #4 { rrux r12 ; encoding: [0x43,0x19,0x0c,0x10] +// CHECK: rpt #5 { rrux r12 ; encoding: [0x44,0x19,0x0c,0x10] +// CHECK: rpt #6 { rrux r12 ; encoding: [0x45,0x19,0x0c,0x10] +// CHECK: rpt #7 { rrux r12 ; encoding: [0x46,0x19,0x0c,0x10] +// CHECK: rpt #8 { rrux r12 ; encoding: [0x47,0x19,0x0c,0x10] +// CHECK: rpt #9 { rrux r12 ; encoding: [0x48,0x19,0x0c,0x10] +// CHECK: rpt #10 { rrux r12 ; encoding: [0x49,0x19,0x0c,0x10] +// CHECK: rpt #11 { rrux r12 ; encoding: [0x4a,0x19,0x0c,0x10] +// CHECK: rpt #12 { rrux r12 ; encoding: [0x4b,0x19,0x0c,0x10] +// CHECK: rpt #13 { rrux r12 ; encoding: [0x4c,0x19,0x0c,0x10] +// CHECK: rpt #14 { rrux r12 ; encoding: [0x4d,0x19,0x0c,0x10] +// CHECK: rpt #15 { rrux r12 ; encoding: [0x4e,0x19,0x0c,0x10] +// CHECK: rpt #16 { rrux r12 ; encoding: [0x4f,0x19,0x0c,0x10] rrux_b: rrux.b r12 + rpt #1 { rrux.b r12 + rpt #2 { rrux.b r12 + rpt #3 { rrux.b r12 + rpt #4 { rrux.b r12 + rpt #5 { rrux.b r12 + rpt #6 { rrux.b r12 + rpt #7 { rrux.b r12 + rpt #8 { rrux.b r12 + rpt #9 { rrux.b r12 + rpt #10 { rrux.b r12 + rpt #11 { rrux.b r12 + rpt #12 { rrux.b r12 + rpt #13 { rrux.b r12 + rpt #14 { rrux.b r12 + rpt #15 { rrux.b r12 + rpt #16 { rrux.b r12 // CHECK-LABEL: rrux_b: // CHECK-NEXT: rrux.b r12 ; encoding: [0x40,0x19,0x4c,0x10] +// CHECK: rrux.b r12 ; encoding: [0x40,0x19,0x4c,0x10] +// CHECK: rpt #2 { rrux.b r12 ; encoding: [0x41,0x19,0x4c,0x10] +// CHECK: rpt #3 { rrux.b r12 ; encoding: [0x42,0x19,0x4c,0x10] +// CHECK: rpt #4 { rrux.b r12 ; encoding: [0x43,0x19,0x4c,0x10] +// CHECK: rpt #5 { rrux.b r12 ; encoding: [0x44,0x19,0x4c,0x10] +// CHECK: rpt #6 { rrux.b r12 ; encoding: [0x45,0x19,0x4c,0x10] +// CHECK: rpt #7 { rrux.b r12 ; encoding: [0x46,0x19,0x4c,0x10] +// CHECK: rpt #8 { rrux.b r12 ; encoding: [0x47,0x19,0x4c,0x10] +// CHECK: rpt #9 { rrux.b r12 ; encoding: [0x48,0x19,0x4c,0x10] +// CHECK: rpt #10 { rrux.b r12 ; encoding: [0x49,0x19,0x4c,0x10] +// CHECK: rpt #11 { rrux.b r12 ; encoding: [0x4a,0x19,0x4c,0x10] +// CHECK: rpt #12 { rrux.b r12 ; encoding: [0x4b,0x19,0x4c,0x10] +// CHECK: rpt #13 { rrux.b r12 ; encoding: [0x4c,0x19,0x4c,0x10] +// CHECK: rpt #14 { rrux.b r12 ; encoding: [0x4d,0x19,0x4c,0x10] +// CHECK: rpt #15 { rrux.b r12 ; encoding: [0x4e,0x19,0x4c,0x10] +// CHECK: rpt #16 { rrux.b r12 ; encoding: [0x4f,0x19,0x4c,0x10] rrax: rrax r12 + rpt #1 { rrax r12 + rpt #2 { rrax r12 + rpt #3 { rrax r12 + rpt #4 { rrax r12 + rpt #5 { rrax r12 + rpt #6 { rrax r12 + rpt #7 { rrax r12 + rpt #8 { rrax r12 + rpt #9 { rrax r12 + rpt #10 { rrax r12 + rpt #11 { rrax r12 + rpt #12 { rrax r12 + rpt #13 { rrax r12 + rpt #14 { rrax r12 + rpt #15 { rrax r12 + rpt #16 { rrax r12 // CHECK-LABEL: rrax: // CHECK-NEXT: rrax r12 ; encoding: [0x40,0x18,0x0c,0x11] +// CHECK: rrax r12 ; encoding: [0x40,0x18,0x0c,0x11] +// CHECK: rpt #2 { rrax r12 ; encoding: [0x41,0x18,0x0c,0x11] +// CHECK: rpt #3 { rrax r12 ; encoding: [0x42,0x18,0x0c,0x11] +// CHECK: rpt #4 { rrax r12 ; encoding: [0x43,0x18,0x0c,0x11] +// CHECK: rpt #5 { rrax r12 ; encoding: [0x44,0x18,0x0c,0x11] +// CHECK: rpt #6 { rrax r12 ; encoding: [0x45,0x18,0x0c,0x11] +// CHECK: rpt #7 { rrax r12 ; encoding: [0x46,0x18,0x0c,0x11] +// CHECK: rpt #8 { rrax r12 ; encoding: [0x47,0x18,0x0c,0x11] +// CHECK: rpt #9 { rrax r12 ; encoding: [0x48,0x18,0x0c,0x11] +// CHECK: rpt #10 { rrax r12 ; encoding: [0x49,0x18,0x0c,0x11] +// CHECK: rpt #11 { rrax r12 ; encoding: [0x4a,0x18,0x0c,0x11] +// CHECK: rpt #12 { rrax r12 ; encoding: [0x4b,0x18,0x0c,0x11] +// CHECK: rpt #13 { rrax r12 ; encoding: [0x4c,0x18,0x0c,0x11] +// CHECK: rpt #14 { rrax r12 ; encoding: [0x4d,0x18,0x0c,0x11] +// CHECK: rpt #15 { rrax r12 ; encoding: [0x4e,0x18,0x0c,0x11] +// CHECK: rpt #16 { rrax r12 ; encoding: [0x4f,0x18,0x0c,0x11] rrax_b: rrax.b r12 + rpt #1 { rrax.b r12 + rpt #2 { rrax.b r12 + rpt #3 { rrax.b r12 + rpt #4 { rrax.b r12 + rpt #5 { rrax.b r12 + rpt #6 { rrax.b r12 + rpt #7 { rrax.b r12 + rpt #8 { rrax.b r12 + rpt #9 { rrax.b r12 + rpt #10 { rrax.b r12 + rpt #11 { rrax.b r12 + rpt #12 { rrax.b r12 + rpt #13 { rrax.b r12 + rpt #14 { rrax.b r12 + rpt #15 { rrax.b r12 + rpt #16 { rrax.b r12 // CHECK-LABEL: rrax_b: // CHECK-NEXT: rrax.b r12 ; encoding: [0x40,0x18,0x4c,0x11] +// CHECK: rrax.b r12 ; encoding: [0x40,0x18,0x4c,0x11] +// CHECK: rpt #2 { rrax.b r12 ; encoding: [0x41,0x18,0x4c,0x11] +// CHECK: rpt #3 { rrax.b r12 ; encoding: [0x42,0x18,0x4c,0x11] +// CHECK: rpt #4 { rrax.b r12 ; encoding: [0x43,0x18,0x4c,0x11] +// CHECK: rpt #5 { rrax.b r12 ; encoding: [0x44,0x18,0x4c,0x11] +// CHECK: rpt #6 { rrax.b r12 ; encoding: [0x45,0x18,0x4c,0x11] +// CHECK: rpt #7 { rrax.b r12 ; encoding: [0x46,0x18,0x4c,0x11] +// CHECK: rpt #8 { rrax.b r12 ; encoding: [0x47,0x18,0x4c,0x11] +// CHECK: rpt #9 { rrax.b r12 ; encoding: [0x48,0x18,0x4c,0x11] +// CHECK: rpt #10 { rrax.b r12 ; encoding: [0x49,0x18,0x4c,0x11] +// CHECK: rpt #11 { rrax.b r12 ; encoding: [0x4a,0x18,0x4c,0x11] +// CHECK: rpt #12 { rrax.b r12 ; encoding: [0x4b,0x18,0x4c,0x11] +// CHECK: rpt #13 { rrax.b r12 ; encoding: [0x4c,0x18,0x4c,0x11] +// CHECK: rpt #14 { rrax.b r12 ; encoding: [0x4d,0x18,0x4c,0x11] +// CHECK: rpt #15 { rrax.b r12 ; encoding: [0x4e,0x18,0x4c,0x11] +// CHECK: rpt #16 { rrax.b r12 ; encoding: [0x4f,0x18,0x4c,0x11] rlax: rlax r12 + rpt #1 { rlax r12 + rpt #2 { rlax r12 + rpt #3 { rlax r12 + rpt #4 { rlax r12 + rpt #5 { rlax r12 + rpt #6 { rlax r12 + rpt #7 { rlax r12 + rpt #8 { rlax r12 + rpt #9 { rlax r12 + rpt #10 { rlax r12 + rpt #11 { rlax r12 + rpt #12 { rlax r12 + rpt #13 { rlax r12 + rpt #14 { rlax r12 + rpt #15 { rlax r12 + rpt #16 { rlax r12 // CHECK-LABEL: rlax: // CHECK: rlax r12 ; encoding: [0x40,0x18,0x0c,0x5c] +// CHECK: rlax r12 ; encoding: [0x40,0x18,0x0c,0x5c] +// CHECK: rpt #2 { rlax r12 ; encoding: [0x41,0x18,0x0c,0x5c] +// CHECK: rpt #3 { rlax r12 ; encoding: [0x42,0x18,0x0c,0x5c] +// CHECK: rpt #4 { rlax r12 ; encoding: [0x43,0x18,0x0c,0x5c] +// CHECK: rpt #5 { rlax r12 ; encoding: [0x44,0x18,0x0c,0x5c] +// CHECK: rpt #6 { rlax r12 ; encoding: [0x45,0x18,0x0c,0x5c] +// CHECK: rpt #7 { rlax r12 ; encoding: [0x46,0x18,0x0c,0x5c] +// CHECK: rpt #8 { rlax r12 ; encoding: [0x47,0x18,0x0c,0x5c] +// CHECK: rpt #9 { rlax r12 ; encoding: [0x48,0x18,0x0c,0x5c] +// CHECK: rpt #10 { rlax r12 ; encoding: [0x49,0x18,0x0c,0x5c] +// CHECK: rpt #11 { rlax r12 ; encoding: [0x4a,0x18,0x0c,0x5c] +// CHECK: rpt #12 { rlax r12 ; encoding: [0x4b,0x18,0x0c,0x5c] +// CHECK: rpt #13 { rlax r12 ; encoding: [0x4c,0x18,0x0c,0x5c] +// CHECK: rpt #14 { rlax r12 ; encoding: [0x4d,0x18,0x0c,0x5c] +// CHECK: rpt #15 { rlax r12 ; encoding: [0x4e,0x18,0x0c,0x5c] +// CHECK: rpt #16 { rlax r12 ; encoding: [0x4f,0x18,0x0c,0x5c] rlax_b: rlax.b r12 + rpt #1 { rlax.b r12 + rpt #2 { rlax.b r12 + rpt #3 { rlax.b r12 + rpt #4 { rlax.b r12 + rpt #5 { rlax.b r12 + rpt #6 { rlax.b r12 + rpt #7 { rlax.b r12 + rpt #8 { rlax.b r12 + rpt #9 { rlax.b r12 + rpt #10 { rlax.b r12 + rpt #11 { rlax.b r12 + rpt #12 { rlax.b r12 + rpt #13 { rlax.b r12 + rpt #14 { rlax.b r12 + rpt #15 { rlax.b r12 + rpt #16 { rlax.b r12 // CHECK-LABEL: rlax_b: // CHECK-NEXT: rlax.b r12 ; encoding: [0x40,0x18,0x4c,0x5c] +// CHECK: rlax.b r12 ; encoding: [0x40,0x18,0x4c,0x5c] +// CHECK: rpt #2 { rlax.b r12 ; encoding: [0x41,0x18,0x4c,0x5c] +// CHECK: rpt #3 { rlax.b r12 ; encoding: [0x42,0x18,0x4c,0x5c] +// CHECK: rpt #4 { rlax.b r12 ; encoding: [0x43,0x18,0x4c,0x5c] +// CHECK: rpt #5 { rlax.b r12 ; encoding: [0x44,0x18,0x4c,0x5c] +// CHECK: rpt #6 { rlax.b r12 ; encoding: [0x45,0x18,0x4c,0x5c] +// CHECK: rpt #7 { rlax.b r12 ; encoding: [0x46,0x18,0x4c,0x5c] +// CHECK: rpt #8 { rlax.b r12 ; encoding: [0x47,0x18,0x4c,0x5c] +// CHECK: rpt #9 { rlax.b r12 ; encoding: [0x48,0x18,0x4c,0x5c] +// CHECK: rpt #10 { rlax.b r12 ; encoding: [0x49,0x18,0x4c,0x5c] +// CHECK: rpt #11 { rlax.b r12 ; encoding: [0x4a,0x18,0x4c,0x5c] +// CHECK: rpt #12 { rlax.b r12 ; encoding: [0x4b,0x18,0x4c,0x5c] +// CHECK: rpt #13 { rlax.b r12 ; encoding: [0x4c,0x18,0x4c,0x5c] +// CHECK: rpt #14 { rlax.b r12 ; encoding: [0x4d,0x18,0x4c,0x5c] +// CHECK: rpt #15 { rlax.b r12 ; encoding: [0x4e,0x18,0x4c,0x5c] +// CHECK: rpt #16 { rlax.b r12 ; encoding: [0x4f,0x18,0x4c,0x5c] + +// Test parsing of "rpt" when it's on it's own line. +rrux2: + rpt #1 + rrux r12 + rpt #2 + rrux r12 + rpt #3 + rrux r12 + rpt #4 + rrux r12 + rpt #5 + rrux r12 + rpt #6 + rrux r12 + rpt #7 + rrux r12 + rpt #8 + rrux r12 + rpt #9 + rrux r12 + rpt #10 + rrux r12 + rpt #11 + rrux r12 + rpt #12 + rrux r12 + rpt #13 + rrux r12 + rpt #14 + rrux r12 + rpt #15 + rrux r12 + rpt #16 + rrux r12 + +// CHECK-LABEL: rrux2: +// CHECK-NEXT: rrux r12 ; encoding: [0x40,0x19,0x0c,0x10] +// CHECK: rpt #2 { rrux r12 ; encoding: [0x41,0x19,0x0c,0x10] +// CHECK: rpt #3 { rrux r12 ; encoding: [0x42,0x19,0x0c,0x10] +// CHECK: rpt #4 { rrux r12 ; encoding: [0x43,0x19,0x0c,0x10] +// CHECK: rpt #5 { rrux r12 ; encoding: [0x44,0x19,0x0c,0x10] +// CHECK: rpt #6 { rrux r12 ; encoding: [0x45,0x19,0x0c,0x10] +// CHECK: rpt #7 { rrux r12 ; encoding: [0x46,0x19,0x0c,0x10] +// CHECK: rpt #8 { rrux r12 ; encoding: [0x47,0x19,0x0c,0x10] +// CHECK: rpt #9 { rrux r12 ; encoding: [0x48,0x19,0x0c,0x10] +// CHECK: rpt #10 { rrux r12 ; encoding: [0x49,0x19,0x0c,0x10] +// CHECK: rpt #11 { rrux r12 ; encoding: [0x4a,0x19,0x0c,0x10] +// CHECK: rpt #12 { rrux r12 ; encoding: [0x4b,0x19,0x0c,0x10] +// CHECK: rpt #13 { rrux r12 ; encoding: [0x4c,0x19,0x0c,0x10] +// CHECK: rpt #14 { rrux r12 ; encoding: [0x4d,0x19,0x0c,0x10] +// CHECK: rpt #15 { rrux r12 ; encoding: [0x4e,0x19,0x0c,0x10] +// CHECK: rpt #16 { rrux r12 ; encoding: [0x4f,0x19,0x0c,0x10] + +rrax2: + rpt #1 + rrax r12 + rpt #2 + rrax r12 + rpt #3 + rrax r12 + rpt #4 + rrax r12 + rpt #5 + rrax r12 + rpt #6 + rrax r12 + rpt #7 + rrax r12 + rpt #8 + rrax r12 + rpt #9 + rrax r12 + rpt #10 + rrax r12 + rpt #11 + rrax r12 + rpt #12 + rrax r12 + rpt #13 + rrax r12 + rpt #14 + rrax r12 + rpt #15 + rrax r12 + rpt #16 + rrax r12 + +// CHECK-LABEL: rrax2: +// CHECK-NEXT: rrax r12 ; encoding: [0x40,0x18,0x0c,0x11] +// CHECK: rpt #2 { rrax r12 ; encoding: [0x41,0x18,0x0c,0x11] +// CHECK: rpt #3 { rrax r12 ; encoding: [0x42,0x18,0x0c,0x11] +// CHECK: rpt #4 { rrax r12 ; encoding: [0x43,0x18,0x0c,0x11] +// CHECK: rpt #5 { rrax r12 ; encoding: [0x44,0x18,0x0c,0x11] +// CHECK: rpt #6 { rrax r12 ; encoding: [0x45,0x18,0x0c,0x11] +// CHECK: rpt #7 { rrax r12 ; encoding: [0x46,0x18,0x0c,0x11] +// CHECK: rpt #8 { rrax r12 ; encoding: [0x47,0x18,0x0c,0x11] +// CHECK: rpt #9 { rrax r12 ; encoding: [0x48,0x18,0x0c,0x11] +// CHECK: rpt #10 { rrax r12 ; encoding: [0x49,0x18,0x0c,0x11] +// CHECK: rpt #11 { rrax r12 ; encoding: [0x4a,0x18,0x0c,0x11] +// CHECK: rpt #12 { rrax r12 ; encoding: [0x4b,0x18,0x0c,0x11] +// CHECK: rpt #13 { rrax r12 ; encoding: [0x4c,0x18,0x0c,0x11] +// CHECK: rpt #14 { rrax r12 ; encoding: [0x4d,0x18,0x0c,0x11] +// CHECK: rpt #15 { rrax r12 ; encoding: [0x4e,0x18,0x0c,0x11] +// CHECK: rpt #16 { rrax r12 ; encoding: [0x4f,0x18,0x0c,0x11] + +rlax2: + rpt #1 + rlax r12 + rpt #2 + rlax r12 + rpt #3 + rlax r12 + rpt #4 + rlax r12 + rpt #5 + rlax r12 + rpt #6 + rlax r12 + rpt #7 + rlax r12 + rpt #8 + rlax r12 + rpt #9 + rlax r12 + rpt #10 + rlax r12 + rpt #11 + rlax r12 + rpt #12 + rlax r12 + rpt #13 + rlax r12 + rpt #14 + rlax r12 + rpt #15 + rlax r12 + rpt #16 + rlax r12 + +// CHECK-LABEL: rlax2: +// CHECK-NEXT: rlax r12 ; encoding: [0x40,0x18,0x0c,0x5c] +// CHECK: rpt #2 { rlax r12 ; encoding: [0x41,0x18,0x0c,0x5c] +// CHECK: rpt #3 { rlax r12 ; encoding: [0x42,0x18,0x0c,0x5c] +// CHECK: rpt #4 { rlax r12 ; encoding: [0x43,0x18,0x0c,0x5c] +// CHECK: rpt #5 { rlax r12 ; encoding: [0x44,0x18,0x0c,0x5c] +// CHECK: rpt #6 { rlax r12 ; encoding: [0x45,0x18,0x0c,0x5c] +// CHECK: rpt #7 { rlax r12 ; encoding: [0x46,0x18,0x0c,0x5c] +// CHECK: rpt #8 { rlax r12 ; encoding: [0x47,0x18,0x0c,0x5c] +// CHECK: rpt #9 { rlax r12 ; encoding: [0x48,0x18,0x0c,0x5c] +// CHECK: rpt #10 { rlax r12 ; encoding: [0x49,0x18,0x0c,0x5c] +// CHECK: rpt #11 { rlax r12 ; encoding: [0x4a,0x18,0x0c,0x5c] +// CHECK: rpt #12 { rlax r12 ; encoding: [0x4b,0x18,0x0c,0x5c] +// CHECK: rpt #13 { rlax r12 ; encoding: [0x4c,0x18,0x0c,0x5c] +// CHECK: rpt #14 { rlax r12 ; encoding: [0x4d,0x18,0x0c,0x5c] +// CHECK: rpt #15 { rlax r12 ; encoding: [0x4e,0x18,0x0c,0x5c] +// CHECK: rpt #16 { rlax r12 ; encoding: [0x4f,0x18,0x0c,0x5c]