diff options
Diffstat (limited to 'llvm')
-rw-r--r-- | llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp | 56 | ||||
-rw-r--r-- | llvm/test/MC/Mips/memory-offsets.s | 33 |
2 files changed, 87 insertions, 2 deletions
diff --git a/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp b/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp index ec8873289d6..70a5e50748b 100644 --- a/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp +++ b/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp @@ -4553,8 +4553,60 @@ MipsAsmParser::parseMemOperand(OperandVector &Operands) { MipsOperand::CreateMem(std::move(Base), IdVal, S, E, *this)); return MatchOperand_Success; } - Error(Parser.getTok().getLoc(), "'(' expected"); - return MatchOperand_ParseFail; + MCBinaryExpr::Opcode Opcode; + // GAS and LLVM treat comparison operators different. GAS will generate -1 + // or 0, while LLVM will generate 0 or 1. Since a comparsion operator is + // highly unlikely to be found in a memory offset expression, we don't + // handle them. + switch (Tok.getKind()) { + case AsmToken::Plus: + Opcode = MCBinaryExpr::Add; + Parser.Lex(); + break; + case AsmToken::Minus: + Opcode = MCBinaryExpr::Sub; + Parser.Lex(); + break; + case AsmToken::Star: + Opcode = MCBinaryExpr::Mul; + Parser.Lex(); + break; + case AsmToken::Pipe: + Opcode = MCBinaryExpr::Or; + Parser.Lex(); + break; + case AsmToken::Amp: + Opcode = MCBinaryExpr::And; + Parser.Lex(); + break; + case AsmToken::LessLess: + Opcode = MCBinaryExpr::Shl; + Parser.Lex(); + break; + case AsmToken::GreaterGreater: + Opcode = MCBinaryExpr::LShr; + Parser.Lex(); + break; + case AsmToken::Caret: + Opcode = MCBinaryExpr::Xor; + Parser.Lex(); + break; + case AsmToken::Slash: + Opcode = MCBinaryExpr::Div; + Parser.Lex(); + break; + case AsmToken::Percent: + Opcode = MCBinaryExpr::Mod; + Parser.Lex(); + break; + default: + Error(Parser.getTok().getLoc(), "'(' or expression expected"); + return MatchOperand_ParseFail; + } + const MCExpr * NextExpr; + if (getParser().parseExpression(NextExpr)) + return MatchOperand_ParseFail; + IdVal = MCBinaryExpr::create(Opcode, IdVal, NextExpr, getContext()); } Parser.Lex(); // Eat the '(' token. diff --git a/llvm/test/MC/Mips/memory-offsets.s b/llvm/test/MC/Mips/memory-offsets.s new file mode 100644 index 00000000000..7fd1e7e503c --- /dev/null +++ b/llvm/test/MC/Mips/memory-offsets.s @@ -0,0 +1,33 @@ +# RUN: llvm-mc -arch=mips -mcpu=mips32 -show-encoding %s | FileCheck %s + +# Check that parseMemOperand handles expressions such as <int>, (<int>), +# <expr>, <expr> op <expr>, (<expr>) op (<expr>). + + .global __start + .ent __start +__start: + lw $31, ($29) # CHECK: lw $ra, 0($sp) # encoding: [0x8f,0xbf,0x00,0x00] + lw $31, 0($29) # CHECK: lw $ra, 0($sp) # encoding: [0x8f,0xbf,0x00,0x00] + lw $31, (8)($29) # CHECK: lw $ra, 8($sp) # encoding: [0x8f,0xbf,0x00,0x08] + lw $31, 3 + (4 * 8)($29) # CHECK: lw $ra, 35($sp) # encoding: [0x8f,0xbf,0x00,0x23] + lw $31, (8 + 8)($29) # CHECK: lw $ra, 16($sp) # encoding: [0x8f,0xbf,0x00,0x10] + lw $31, (8 << 4)($29) # CHECK: lw $ra, 128($sp) # encoding: [0x8f,0xbf,0x00,0x80] + lw $31, (32768 >> 2)($29) # CHECK: lw $ra, 8192($sp) # encoding: [0x8f,0xbf,0x20,0x00] + lw $31, 32768 >> 2($29) # CHECK: lw $ra, 8192($sp) # encoding: [0x8f,0xbf,0x20,0x00] + lw $31, 2 << 3($29) # CHECK: lw $ra, 16($sp) # encoding: [0x8f,0xbf,0x00,0x10] + lw $31, (2 << 3)($29) # CHECK: lw $ra, 16($sp) # encoding: [0x8f,0xbf,0x00,0x10] + lw $31, 4 - (4 * 8)($29) # CHECK: lw $ra, -28($sp) # encoding: [0x8f,0xbf,0xff,0xe4] + lw $31, 4 | 8 ($29) # CHECK: lw $ra, 12($sp) # encoding: [0x8f,0xbf,0x00,0x0c] + lw $31, 4 || 8 ($29) # CHECK: lw $ra, 1($sp) # encoding: [0x8f,0xbf,0x00,0x01] + lw $31, 8 & 8 ($29) # CHECK: lw $ra, 8($sp) # encoding: [0x8f,0xbf,0x00,0x08] + lw $31, (8 * 4) ^ (8 * 31)($29) # CHECK: lw $ra, 216($sp) # encoding: [0x8f,0xbf,0x00,0xd8] + lw $31, (8 * 4) / (8 * 31)($29) # CHECK: lw $ra, 0($sp) # encoding: [0x8f,0xbf,0x00,0x00] + lw $31, (8 * 4) % (8 * 31)($29) # CHECK: lw $ra, 32($sp) # encoding: [0x8f,0xbf,0x00,0x20] + lw $31, (8 * 4) % (8)($29) # CHECK: lw $ra, 0($sp) # encoding: [0x8f,0xbf,0x00,0x00] + lw $31, (8 * 4) + (8 * 31) ($29) # CHECK: lw $ra, 280($sp) # encoding: [0x8f,0xbf,0x01,0x18] + lw $31, (8*4) + (8*31) + (8*32 + __start) ($29) # CHECK: lui $ra, %hi((248+((8*32)+__start))+32) # encoding: [0x3c,0x1f,A,A] + # CHECK: # fixup A - offset: 0, value: %hi((248+((8*32)+__start))+32), kind: fixup_Mips_HI16 + # CHECK: addu $ra, $ra, $sp # encoding: [0x03,0xfd,0xf8,0x21] + # CHECK: lw $ra, %lo((248+((8*32)+__start))+32)($ra) # encoding: [0x8f,0xff,A,A] + # CHECK: # fixup A - offset: 0, value: %lo((248+((8*32)+__start))+32), kind: fixup_Mips_LO16 + .end __start |