#include "llvm/Support/Debug.h"
#include "llvm/Support/MathExtras.h"
+#include <array>
#include <sstream>
#define DEBUG_TYPE "avr-asm-parser"
OperandMatchResultTy parseMemriOperand(OperandVector &Operands);
- bool parseOperand(OperandVector &Operands);
+ bool parseOperand(OperandVector &Operands, bool maybeReg);
int parseRegisterName(unsigned (*matchFn)(StringRef));
int parseRegisterName();
int parseRegister(bool RestoreOnFailure = false);
// Check for sign.
AsmToken tokens[2];
if (Parser.getLexer().peekTokens(tokens) == 2)
- if (tokens[0].getKind() == AsmToken::LParen &&
- tokens[1].getKind() == AsmToken::Minus)
- isNegated = true;
+ if (tokens[0].getKind() == AsmToken::LParen &&
+ tokens[1].getKind() == AsmToken::Minus)
+ isNegated = true;
// Check if we have a target specific modifier (lo8, hi8, &c)
if (CurTok != AsmToken::Identifier ||
return false;
}
-bool AVRAsmParser::parseOperand(OperandVector &Operands) {
+bool AVRAsmParser::parseOperand(OperandVector &Operands, bool maybeReg) {
LLVM_DEBUG(dbgs() << "parseOperand\n");
switch (getLexer().getKind()) {
return Error(Parser.getTok().getLoc(), "unexpected token in operand");
case AsmToken::Identifier:
- // Try to parse a register, if it fails,
- // fall through to the next case.
- if (!tryParseRegisterOperand(Operands)) {
+ // Try to parse a register, fall through to the next case if it fails.
+ if (maybeReg && !tryParseRegisterOperand(Operands)) {
return false;
}
[[fallthrough]];
OperandVector &Operands) {
Operands.push_back(AVROperand::CreateToken(Mnemonic, NameLoc));
- bool first = true;
+ int OperandNum = -1;
while (getLexer().isNot(AsmToken::EndOfStatement)) {
- if (!first)
+ OperandNum++;
+ if (OperandNum > 0)
eatComma();
- first = false;
-
auto MatchResult = MatchOperandParserImpl(Operands, Mnemonic);
if (MatchResult == MatchOperand_Success) {
return Error(Loc, "failed to parse register and immediate pair");
}
- if (parseOperand(Operands)) {
+ // These specific operands should be treated as addresses/symbols/labels,
+ // other than registers.
+ bool maybeReg = true;
+ if (OperandNum == 1) {
+ std::array<StringRef, 8> Insts = {"lds", "adiw", "sbiw", "ldi"};
+ for (auto Inst : Insts) {
+ if (Inst == Mnemonic) {
+ maybeReg = false;
+ break;
+ }
+ }
+ } else if (OperandNum == 0) {
+ std::array<StringRef, 8> Insts = {"sts", "call", "rcall", "rjmp", "jmp"};
+ for (auto Inst : Insts) {
+ if (Inst == Mnemonic) {
+ maybeReg = false;
+ break;
+ }
+ }
+ }
+
+ if (parseOperand(Operands, maybeReg)) {
SMLoc Loc = getLexer().getLoc();
Parser.eatToEndOfStatement();
return Error(Loc, "unexpected token in argument list");
adiw r30, 0
adiw r24, SYMBOL
+ adiw r24, r25
; CHECK: adiw r26, 12 ; encoding: [0x1c,0x96]
; CHECK: adiw r26, 63 ; encoding: [0xdf,0x96]
; CHECK: adiw r24, SYMBOL ; encoding: [0b00AAAAAA,0x96]
; fixup A - offset: 0, value: SYMBOL, kind: fixup_6_adiw
+; CHECK: adiw r24, r25 ; encoding: [0b00AAAAAA,0x96]
+ ; fixup A - offset: 0, value: r25, kind: fixup_6_adiw
; CHECK-INST: adiw r26, 12
; CHECK-INST: adiw r26, 63
; CHECK-INST: adiw r24, 0
; CHECK-INST: R_AVR_6_ADIW SYMBOL
+; CHECK-INST: adiw r24, 0
+; CHECK-INST: R_AVR_6_ADIW r25
call -12
call 0
+r25:
+ call r25
+
; CHECK: call 4096 ; encoding: [0x0e,0x94,0x00,0x08]
; CHECK: call -124 ; encoding: [0xff,0x95,0xc2,0xff]
; CHECK: call -12 ; encoding: [0xff,0x95,0xfa,0xff]
; CHECK: call 0 ; encoding: [0x0e,0x94,0x00,0x00]
-
+; CHECK: call r25 ; encoding: [0x0e'A',0x94'A',0b00AAAAAA,0x00]
+; CHECK: ; fixup A - offset: 0, value: r25, kind: fixup_call
; CHECK-INST: call 4096
; CHECK-INST: call 8388484
; CHECK-INST: call 8388596
; CHECK-INST: call 0
+; CHECK-INST: call 0
+; CHECK-INST: R_AVR_CALL
lds r22, 44
lds r27, 92
lds r20, SYMBOL+12
+ lds r20, r21
+ lds r20, z+6
; CHECK: lds r16, 113 ; encoding: [0x01,0xa7]
; CHECK: lds r29, 62 ; encoding: [0xde,0xa3]
; CHECK: lds r27, 92 ; encoding: [0xbc,0xa5]
; CHECK: lds r20, SYMBOL+12 ; encoding: [0x40'A',0xa0'A']
; CHECK: ; fixup A - offset: 0, value: SYMBOL+12, kind: fixup_lds_sts_16
+; CHECK: lds r20, r21 ; encoding: [0x40'A',0xa0'A']
+; CHECK: ; fixup A - offset: 0, value: r21, kind: fixup_lds_sts_16
+; CHECK: lds r20, z+6 ; encoding: [0x40'A',0xa0'A']
+; CHECK: ; fixup A - offset: 0, value: z+6, kind: fixup_lds_sts_16
; CHECK-INST: lds r16, 113
; CHECK-INST: lds r29, 62
; CHECK-INST: lds r22, 44
; CHECK-INST: lds r27, 92
-; CHECK-INST: lds r20, 0
-; CHECK-INST: R_AVR_LDS_STS_16 SYMBOL+0xc
+; CHECK-INST: lds r20, 0
+; CHECK-INST: R_AVR_LDS_STS_16 SYMBOL+0xc
+; CHECK-INST: lds r20, 0
+; CHECK-INST: R_AVR_LDS_STS_16 r21
+; CHECK-INST: lds r20, 0
+; CHECK-INST: R_AVR_LDS_STS_16 z+0x6
lds r29, 190
lds r22, 172
lds r27, 92
- lds r4, SYMBOL+12
+ lds r4, SYMBOL+12
+ lds r4, r25
+ lds r4, x+2
; CHECK: lds r16, 241 ; encoding: [0x00,0x91,0xf1,0x00]
; CHECK: lds r29, 190 ; encoding: [0xd0,0x91,0xbe,0x00]
; CHECK: lds r22, 172 ; encoding: [0x60,0x91,0xac,0x00]
; CHECK: lds r27, 92 ; encoding: [0xb0,0x91,0x5c,0x00]
-; CHECK: lds r4, SYMBOL+12 ; encoding: [0x40,0x90,A,A]
+; CHECK: lds r4, SYMBOL+12 ; encoding: [0x40,0x90,A,A]
; CHECK: ; fixup A - offset: 2, value: SYMBOL+12, kind: fixup_16
-
+; CHECK: lds r4, r25 ; encoding: [0x40,0x90,A,A]
+; CHECK: ; fixup A - offset: 2, value: r25, kind: fixup_16
+; CHECK: lds r4, x+2 ; encoding: [0x40,0x90,A,A]
+; CHECK: ; fixup A - offset: 2, value: x+2, kind: fixup_16
; CHECK-INST: lds r16, 241
; CHECK-INST: lds r29, 190
; CHECK-INST: lds r22, 172
; CHECK-INST: lds r27, 92
; CHECK-INST: lds r4, 0
-; CHECK-INST: R_AVR_16 SYMBOL+0xc
+; CHECK-INST: R_AVR_16 SYMBOL+0xc
+; CHECK-INST: lds r4, 0
+; CHECK-INST: R_AVR_16 r25
+; CHECK-INST: lds r4, 0
+; CHECK-INST: R_AVR_16 x+0x2
end:
rjmp .-4
rjmp .-6
+x:
+ rjmp x
; CHECK: rjmp .Ltmp0+2 ; encoding: [A,0b1100AAAA]
; CHECK: ; fixup A - offset: 0, value: .Ltmp0+2, kind: fixup_13_pcrel
; CHECK: ; fixup A - offset: 0, value: .Ltmp4-4, kind: fixup_13_pcrel
; CHECK: rjmp .Ltmp5-6 ; encoding: [A,0b1100AAAA]
; CHECK: ; fixup A - offset: 0, value: .Ltmp5-6, kind: fixup_13_pcrel
+; CHECK: rjmp x ; encoding: [A,0b1100AAAA]
+; CHECK: ; fixup A - offset: 0, value: x, kind: fixup_13_pcrel
; INST: rjmp .+0
; INST: rjmp .+0
; INST: rjmp .+0
; INST: rjmp .+0
; INST: rjmp .+0
+; INST: rjmp .+0
sbiw r24, 2
sbiw r24, SYMBOL-1
+ sbiw r24, z+15
; CHECK: sbiw r26, 54 ; encoding: [0xd6,0x97]
; CHECK: sbiw r26, 63 ; encoding: [0xdf,0x97]
; CHECK: sbiw r24, SYMBOL-1 ; encoding: [0b00AAAAAA,0x97]
; fixup A - offset: 0, value: SYMBOL-1, kind: fixup_6_adiw
+; CHECK: sbiw r24, z+15 ; encoding: [0b00AAAAAA,0x97]
+ ; fixup A - offset: 0, value: z+15, kind: fixup_6_adiw
; CHECK-INST: sbiw r26, 54
; CHECK-INST: sbiw r26, 63
; CHECK-INST: sbiw r24, 0
; CHECK-INST: R_AVR_6_ADIW SYMBOL-0x1
+; CHECK-INST: sbiw r24, 0
+; CHECK-INST: R_AVR_6_ADIW z+0xf
sts 3, r16
sts 127, r17
sts SYMBOL+1, r25
+ sts x, r25
+ sts r25+1, r25
; CHECK: sts 3, r16 ; encoding: [0x03,0xa8]
; CHECK: sts 127, r17 ; encoding: [0x1f,0xaf]
; CHECK: sts SYMBOL+1, r25 ; encoding: [0x90'A',0xa8'A']
; CHECK: ; fixup A - offset: 0, value: SYMBOL+1, kind: fixup_lds_sts_16
+; CHECK: sts x, r25 ; encoding: [0x90'A',0xa8'A']
+; CHECK: ; fixup A - offset: 0, value: x, kind: fixup_lds_sts_16
+; CHECK: sts r25+1, r25 ; encoding: [0x90'A',0xa8'A']
+; CHECK: ; fixup A - offset: 0, value: r25+1, kind: fixup_lds_sts_16
; CHECK-INST: sts 3, r16
; CHECK-INST: sts 127, r17
; CHECK-INST: sts 0, r25
-; CHECK-INST: R_AVR_LDS_STS_16 SYMBOL+0x1
+; CHECK-INST: R_AVR_LDS_STS_16 SYMBOL+0x1
+; CHECK-INST: sts 0, r25
+; CHECK-INST: R_AVR_LDS_STS_16 x
+; CHECK-INST: sts 0, r25
+; CHECK-INST: R_AVR_LDS_STS_16 r25+0x1
foo:
- sts 3, r5
- sts 255, r7
+ sts 3, r5
+ sts 255, r7
sts SYMBOL+1, r25
+ sts r25, r25
+ sts y+3, r25
-; CHECK: sts 3, r5 ; encoding: [0x50,0x92,0x03,0x00]
-; CHECK: sts 255, r7 ; encoding: [0x70,0x92,0xff,0x00]
+; CHECK: sts 3, r5 ; encoding: [0x50,0x92,0x03,0x00]
+; CHECK: sts 255, r7 ; encoding: [0x70,0x92,0xff,0x00]
; CHECK: sts SYMBOL+1, r25 ; encoding: [0x90,0x93,A,A]
; CHECK: ; fixup A - offset: 2, value: SYMBOL+1, kind: fixup_16
+; CHECK: sts r25, r25 ; encoding: [0x90,0x93,A,A]
+; CHECK: ; fixup A - offset: 2, value: r25, kind: fixup_16
+; CHECK: sts y+3, r25 ; encoding: [0x90,0x93,A,A]
+; CHECK: ; fixup A - offset: 2, value: y+3, kind: fixup_16
-; CHECK-INST: sts 3, r5
+; CHECK-INST: sts 3, r5
; CHECK-INST: sts 255, r7
-; CHECK-INST: sts 0, r25
+; CHECK-INST: sts 0, r25
; CHECK-INST: R_AVR_16 SYMBOL+0x1
+; CHECK-INST: sts 0, r25
+; CHECK-INST: R_AVR_16 r25
+; CHECK-INST: sts 0, r25
+; CHECK-INST: R_AVR_16 y+0x3