mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-01-14 16:33:28 +00:00
ARM LDRD(register) assembly parsing and encoding.
Add support for literal encoding of #-0 along the way. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@137254 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
b549bcfe6c
commit
251bf25e7e
@ -722,7 +722,10 @@ def addrmode3 : Operand<i32>,
|
|||||||
|
|
||||||
// FIXME: split into imm vs. reg versions.
|
// FIXME: split into imm vs. reg versions.
|
||||||
// FIXME: parser method to handle +/- register.
|
// FIXME: parser method to handle +/- register.
|
||||||
def AM3OffsetAsmOperand : AsmOperandClass { let Name = "AM3Offset"; }
|
def AM3OffsetAsmOperand : AsmOperandClass {
|
||||||
|
let Name = "AM3Offset";
|
||||||
|
let ParserMethod = "parseAM3Offset";
|
||||||
|
}
|
||||||
def am3offset : Operand<i32>,
|
def am3offset : Operand<i32>,
|
||||||
ComplexPattern<i32, 2, "SelectAddrMode3Offset",
|
ComplexPattern<i32, 2, "SelectAddrMode3Offset",
|
||||||
[], [SDNPWantRoot]> {
|
[], [SDNPWantRoot]> {
|
||||||
|
@ -114,6 +114,7 @@ class ARMAsmParser : public MCTargetAsmParser {
|
|||||||
OperandMatchResultTy parseRotImm(SmallVectorImpl<MCParsedAsmOperand*>&);
|
OperandMatchResultTy parseRotImm(SmallVectorImpl<MCParsedAsmOperand*>&);
|
||||||
OperandMatchResultTy parseBitfield(SmallVectorImpl<MCParsedAsmOperand*>&);
|
OperandMatchResultTy parseBitfield(SmallVectorImpl<MCParsedAsmOperand*>&);
|
||||||
OperandMatchResultTy parsePostIdxReg(SmallVectorImpl<MCParsedAsmOperand*>&);
|
OperandMatchResultTy parsePostIdxReg(SmallVectorImpl<MCParsedAsmOperand*>&);
|
||||||
|
OperandMatchResultTy parseAM3Offset(SmallVectorImpl<MCParsedAsmOperand*>&);
|
||||||
|
|
||||||
// Asm Match Converter Methods
|
// Asm Match Converter Methods
|
||||||
bool cvtLdWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
|
bool cvtLdWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
|
||||||
@ -557,7 +558,8 @@ public:
|
|||||||
const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
|
const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
|
||||||
if (!CE) return false;
|
if (!CE) return false;
|
||||||
int64_t Val = CE->getValue();
|
int64_t Val = CE->getValue();
|
||||||
return Val > -256 && Val < 256;
|
// Special case, #-0 is INT32_MIN.
|
||||||
|
return (Val > -256 && Val < 256) || Val == INT32_MIN;
|
||||||
}
|
}
|
||||||
bool isAddrMode5() const {
|
bool isAddrMode5() const {
|
||||||
if (Kind != Memory)
|
if (Kind != Memory)
|
||||||
@ -865,6 +867,7 @@ public:
|
|||||||
ARM_AM::getAM3Opc(PostIdxReg.isAdd ? ARM_AM::add : ARM_AM::sub, 0);
|
ARM_AM::getAM3Opc(PostIdxReg.isAdd ? ARM_AM::add : ARM_AM::sub, 0);
|
||||||
Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum));
|
Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum));
|
||||||
Inst.addOperand(MCOperand::CreateImm(Val));
|
Inst.addOperand(MCOperand::CreateImm(Val));
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Constant offset.
|
// Constant offset.
|
||||||
@ -874,7 +877,7 @@ public:
|
|||||||
// Special case for #-0
|
// Special case for #-0
|
||||||
if (Val == INT32_MIN) Val = 0;
|
if (Val == INT32_MIN) Val = 0;
|
||||||
if (Val < 0) Val = -Val;
|
if (Val < 0) Val = -Val;
|
||||||
Val = ARM_AM::getAM2Opc(AddSub, Val, ARM_AM::no_shift);
|
Val = ARM_AM::getAM3Opc(AddSub, Val);
|
||||||
Inst.addOperand(MCOperand::CreateReg(0));
|
Inst.addOperand(MCOperand::CreateReg(0));
|
||||||
Inst.addOperand(MCOperand::CreateImm(Val));
|
Inst.addOperand(MCOperand::CreateImm(Val));
|
||||||
}
|
}
|
||||||
@ -2007,6 +2010,76 @@ parsePostIdxReg(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
|
|||||||
return MatchOperand_Success;
|
return MatchOperand_Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ARMAsmParser::OperandMatchResultTy ARMAsmParser::
|
||||||
|
parseAM3Offset(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
|
||||||
|
// Check for a post-index addressing register operand. Specifically:
|
||||||
|
// am3offset := '+' register
|
||||||
|
// | '-' register
|
||||||
|
// | register
|
||||||
|
// | # imm
|
||||||
|
// | # + imm
|
||||||
|
// | # - imm
|
||||||
|
|
||||||
|
// This method must return MatchOperand_NoMatch without consuming any tokens
|
||||||
|
// in the case where there is no match, as other alternatives take other
|
||||||
|
// parse methods.
|
||||||
|
AsmToken Tok = Parser.getTok();
|
||||||
|
SMLoc S = Tok.getLoc();
|
||||||
|
|
||||||
|
// Do immediates first, as we always parse those if we have a '#'.
|
||||||
|
if (Parser.getTok().is(AsmToken::Hash)) {
|
||||||
|
Parser.Lex(); // Eat the '#'.
|
||||||
|
// Explicitly look for a '-', as we need to encode negative zero
|
||||||
|
// differently.
|
||||||
|
bool isNegative = Parser.getTok().is(AsmToken::Minus);
|
||||||
|
const MCExpr *Offset;
|
||||||
|
if (getParser().ParseExpression(Offset))
|
||||||
|
return MatchOperand_ParseFail;
|
||||||
|
const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Offset);
|
||||||
|
if (!CE) {
|
||||||
|
Error(S, "constant expression expected");
|
||||||
|
return MatchOperand_ParseFail;
|
||||||
|
}
|
||||||
|
SMLoc E = Tok.getLoc();
|
||||||
|
// Negative zero is encoded as the flag value INT32_MIN.
|
||||||
|
int32_t Val = CE->getValue();
|
||||||
|
if (isNegative && Val == 0)
|
||||||
|
Val = INT32_MIN;
|
||||||
|
|
||||||
|
Operands.push_back(
|
||||||
|
ARMOperand::CreateImm(MCConstantExpr::Create(Val, getContext()), S, E));
|
||||||
|
|
||||||
|
return MatchOperand_Success;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool haveEaten = false;
|
||||||
|
bool isAdd = true;
|
||||||
|
int Reg = -1;
|
||||||
|
if (Tok.is(AsmToken::Plus)) {
|
||||||
|
Parser.Lex(); // Eat the '+' token.
|
||||||
|
haveEaten = true;
|
||||||
|
} else if (Tok.is(AsmToken::Minus)) {
|
||||||
|
Parser.Lex(); // Eat the '-' token.
|
||||||
|
isAdd = false;
|
||||||
|
haveEaten = true;
|
||||||
|
}
|
||||||
|
if (Parser.getTok().is(AsmToken::Identifier))
|
||||||
|
Reg = tryParseRegister();
|
||||||
|
if (Reg == -1) {
|
||||||
|
if (!haveEaten)
|
||||||
|
return MatchOperand_NoMatch;
|
||||||
|
Error(Parser.getTok().getLoc(), "register expected");
|
||||||
|
return MatchOperand_ParseFail;
|
||||||
|
}
|
||||||
|
SMLoc E = Parser.getTok().getLoc();
|
||||||
|
|
||||||
|
Operands.push_back(ARMOperand::CreatePostIdxReg(Reg, isAdd, ARM_AM::no_shift,
|
||||||
|
0, S, E));
|
||||||
|
|
||||||
|
return MatchOperand_Success;
|
||||||
|
}
|
||||||
|
|
||||||
/// cvtLdWriteBackRegAddrMode2 - Convert parsed operands to MCInst.
|
/// cvtLdWriteBackRegAddrMode2 - Convert parsed operands to MCInst.
|
||||||
/// Needed here because the Asm Gen Matcher can't handle properly tied operands
|
/// Needed here because the Asm Gen Matcher can't handle properly tied operands
|
||||||
/// when they refer multiple MIOperands inside a single one.
|
/// when they refer multiple MIOperands inside a single one.
|
||||||
|
@ -114,8 +114,28 @@ _func:
|
|||||||
ldrd r7, r8, [r2, #15]
|
ldrd r7, r8, [r2, #15]
|
||||||
ldrd r1, r2, [r9, #32]!
|
ldrd r1, r2, [r9, #32]!
|
||||||
ldrd r6, r7, [r1], #8
|
ldrd r6, r7, [r1], #8
|
||||||
|
ldrd r1, r2, [r8], #0
|
||||||
|
ldrd r1, r2, [r8], #+0
|
||||||
|
ldrd r1, r2, [r8], #-0
|
||||||
|
|
||||||
@ CHECK: ldrd r3, r4, [r5] @ encoding: [0xd0,0x30,0xc5,0xe1]
|
@ CHECK: ldrd r3, r4, [r5] @ encoding: [0xd0,0x30,0xc5,0xe1]
|
||||||
@ CHECK: ldrd r7, r8, [r2, #15] @ encoding: [0xdf,0x70,0xc2,0xe1]
|
@ CHECK: ldrd r7, r8, [r2, #15] @ encoding: [0xdf,0x70,0xc2,0xe1]
|
||||||
@ CHECK: ldrd r1, r2, [r9, #32]! @ encoding: [0xd0,0x12,0xe9,0xe1]
|
@ CHECK: ldrd r1, r2, [r9, #32]! @ encoding: [0xd0,0x12,0xe9,0xe1]
|
||||||
@ CHECK: ldrd r6, r7, [r1], #8 @ encoding: [0xd8,0x60,0xc1,0xe0]
|
@ CHECK: ldrd r6, r7, [r1], #8 @ encoding: [0xd8,0x60,0xc1,0xe0]
|
||||||
|
@ CHECK: ldrd r1, r2, [r8], #0 @ encoding: [0xd0,0x10,0xc8,0xe0]
|
||||||
|
@ CHECK: ldrd r1, r2, [r8], #0 @ encoding: [0xd0,0x10,0xc8,0xe0]
|
||||||
|
@ CHECK: ldrd r1, r2, [r8], #-0 @ encoding: [0xd0,0x10,0x48,0xe0]
|
||||||
|
|
||||||
|
|
||||||
|
@------------------------------------------------------------------------------
|
||||||
|
@ LDRD (register)
|
||||||
|
@------------------------------------------------------------------------------
|
||||||
|
ldrd r3, r4, [r1, r3]
|
||||||
|
ldrd r4, r5, [r7, r2]!
|
||||||
|
ldrd r1, r2, [r8], r12
|
||||||
|
ldrd r1, r2, [r8], -r12
|
||||||
|
|
||||||
|
ldrd r3, r4, [r1, r3] @ encoding: [0xd3,0x30,0x81,0xe1]
|
||||||
|
ldrd r4, r5, [r7, r2]! @ encoding: [0xd2,0x40,0xa7,0xe1]
|
||||||
|
ldrd r1, r2, [r8], r12 @ encoding: [0xdc,0x10,0x88,0xe0]
|
||||||
|
ldrd r1, r2, [r8], -r12 @ encoding: [0xdc,0x10,0x08,0xe0]
|
||||||
|
Loading…
x
Reference in New Issue
Block a user