Thumb2 alternate syntax for LDR(literal) and friends.

Explicit pc-relative syntax. For example, "ldrb r2, [pc, #-22]".

rdar://10250964

llvm-svn: 148432
This commit is contained in:
Jim Grosbach 2012-01-18 22:46:46 +00:00
parent ee49d825b1
commit b7ab9edb4e
4 changed files with 96 additions and 0 deletions

View File

@ -136,6 +136,12 @@ def t2ldrlabel : Operand<i32> {
let PrintMethod = "printT2LdrLabelOperand";
}
def t2ldr_pcrel_imm12_asmoperand : AsmOperandClass {let Name = "MemPCRelImm12";}
def t2ldr_pcrel_imm12 : Operand<i32> {
let ParserMatchClass = t2ldr_pcrel_imm12_asmoperand;
// used for assembler pseudo instruction and maps to t2ldrlabel, so
// doesn't need encoder or print methods of its own.
}
// ADR instruction labels.
def t2adrlabel : Operand<i32> {
@ -4151,3 +4157,26 @@ def t2MOVSsr: t2AsmPseudo<"movs${p} $Rd, $shift",
// ADR w/o the .w suffix
def : t2InstAlias<"adr${p} $Rd, $addr",
(t2ADR rGPR:$Rd, t2adrlabel:$addr, pred:$p)>;
// LDR(literal) w/ alternate [pc, #imm] syntax.
def t2LDRpcrel : t2AsmPseudo<"ldr${p} $Rt, $addr",
(ins GPRnopc:$Rt, t2ldr_pcrel_imm12:$addr, pred:$p)>;
def t2LDRBpcrel : t2AsmPseudo<"ldrb${p} $Rt, $addr",
(ins GPRnopc:$Rt, t2ldr_pcrel_imm12:$addr, pred:$p)>;
def t2LDRHpcrel : t2AsmPseudo<"ldrh${p} $Rt, $addr",
(ins GPRnopc:$Rt, t2ldr_pcrel_imm12:$addr, pred:$p)>;
def t2LDRSBpcrel : t2AsmPseudo<"ldrsb${p} $Rt, $addr",
(ins GPRnopc:$Rt, t2ldr_pcrel_imm12:$addr, pred:$p)>;
def t2LDRSHpcrel : t2AsmPseudo<"ldrsh${p} $Rt, $addr",
(ins GPRnopc:$Rt, t2ldr_pcrel_imm12:$addr, pred:$p)>;
// Version w/ the .w suffix.
def : t2InstAlias<"ldr${p}.w $Rt, $addr",
(t2LDRpcrel GPRnopc:$Rt, t2ldr_pcrel_imm12:$addr, pred:$p)>;
def : t2InstAlias<"ldrb${p}.w $Rt, $addr",
(t2LDRBpcrel GPRnopc:$Rt, t2ldr_pcrel_imm12:$addr, pred:$p)>;
def : t2InstAlias<"ldrh${p}.w $Rt, $addr",
(t2LDRHpcrel GPRnopc:$Rt, t2ldr_pcrel_imm12:$addr, pred:$p)>;
def : t2InstAlias<"ldrsb${p}.w $Rt, $addr",
(t2LDRSBpcrel GPRnopc:$Rt, t2ldr_pcrel_imm12:$addr, pred:$p)>;
def : t2InstAlias<"ldrsh${p}.w $Rt, $addr",
(t2LDRSHpcrel GPRnopc:$Rt, t2ldr_pcrel_imm12:$addr, pred:$p)>;

View File

@ -838,6 +838,17 @@ public:
return Memory.OffsetRegNum == 0 && Memory.OffsetImm == 0 &&
(alignOK || Memory.Alignment == 0);
}
bool isMemPCRelImm12() const {
if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
return false;
// Base register must be PC.
if (Memory.BaseRegNum != ARM::PC)
return false;
// Immediate offset in range [-4095, 4095].
if (!Memory.OffsetImm) return true;
int64_t Val = Memory.OffsetImm->getValue();
return (Val > -4096 && Val < 4096) || (Val == INT32_MIN);
}
bool isAlignedMemory() const {
return isMemNoOffset(true);
}
@ -999,6 +1010,8 @@ public:
bool isMemImm8Offset() const {
if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
return false;
// Base reg of PC isn't allowed for these encodings.
if (Memory.BaseRegNum == ARM::PC) return false;
// Immediate offset in range [-255, 255].
if (!Memory.OffsetImm) return true;
int64_t Val = Memory.OffsetImm->getValue();
@ -1015,6 +1028,8 @@ public:
bool isMemNegImm8Offset() const {
if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
return false;
// Base reg of PC isn't allowed for these encodings.
if (Memory.BaseRegNum == ARM::PC) return false;
// Immediate offset in range [-255, -1].
if (!Memory.OffsetImm) return false;
int64_t Val = Memory.OffsetImm->getValue();
@ -1482,6 +1497,14 @@ public:
Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
}
void addMemPCRelImm12Operands(MCInst &Inst, unsigned N) const {
assert(N == 1 && "Invalid number of operands!");
int32_t Imm = Memory.OffsetImm->getValue();
// FIXME: Handle #-0
if (Imm == INT32_MIN) Imm = 0;
Inst.addOperand(MCOperand::CreateImm(Imm));
}
void addAlignedMemoryOperands(MCInst &Inst, unsigned N) const {
assert(N == 2 && "Invalid number of operands!");
Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
@ -5389,6 +5412,22 @@ bool ARMAsmParser::
processInstruction(MCInst &Inst,
const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
switch (Inst.getOpcode()) {
// Aliases for alternate PC+imm syntax of LDR instructions.
case ARM::t2LDRpcrel:
Inst.setOpcode(ARM::t2LDRpci);
return true;
case ARM::t2LDRBpcrel:
Inst.setOpcode(ARM::t2LDRBpci);
return true;
case ARM::t2LDRHpcrel:
Inst.setOpcode(ARM::t2LDRHpci);
return true;
case ARM::t2LDRSBpcrel:
Inst.setOpcode(ARM::t2LDRSBpci);
return true;
case ARM::t2LDRSHpcrel:
Inst.setOpcode(ARM::t2LDRSHpci);
return true;
// Handle NEON VST complex aliases.
case ARM::VST1LNdWB_register_Asm_8: case ARM::VST1LNdWB_register_Asm_P8:
case ARM::VST1LNdWB_register_Asm_I8: case ARM::VST1LNdWB_register_Asm_S8:

View File

@ -723,6 +723,7 @@ getAddrModeImm12OpValue(const MCInst &MI, unsigned OpIdx,
} else {
Reg = ARM::PC;
int32_t Offset = MO.getImm();
// FIXME: Handle #-0.
if (Offset < 0) {
Offset *= -1;
isAdd = false;

View File

@ -3323,3 +3323,30 @@ _func:
@ CHECK: wfelt @ encoding: [0x20,0xbf]
@ CHECK: wfige @ encoding: [0x30,0xbf]
@ CHECK: yieldlt @ encoding: [0x10,0xbf]
@------------------------------------------------------------------------------
@ Alternate syntax for LDR*(literal) encodings
@------------------------------------------------------------------------------
ldr r11, [pc, #-22]
ldrb r11, [pc, #-22]
ldrh r11, [pc, #-22]
ldrsb r11, [pc, #-22]
ldrsh r11, [pc, #-22]
ldr.w r11, [pc, #-22]
ldrb.w r11, [pc, #-22]
ldrh.w r11, [pc, #-22]
ldrsb.w r11, [pc, #-22]
ldrsh.w r11, [pc, #-22]
@ CHECK: ldr.w r11, [pc, #-22] @ encoding: [0x5f,0xf8,0x16,0xb0]
@ CHECK: ldrb.w r11, [pc, #-22] @ encoding: [0x1f,0xf8,0x16,0xb0]
@ CHECK: ldrh.w r11, [pc, #-22] @ encoding: [0x3f,0xf8,0x16,0xb0]
@ CHECK: ldrsb.w r11, [pc, #-22] @ encoding: [0x1f,0xf9,0x16,0xb0]
@ CHECK: ldrsh.w r11, [pc, #-22] @ encoding: [0x3f,0xf9,0x16,0xb0]
@ CHECK: ldr.w r11, [pc, #-22] @ encoding: [0x5f,0xf8,0x16,0xb0]
@ CHECK: ldrb.w r11, [pc, #-22] @ encoding: [0x1f,0xf8,0x16,0xb0]
@ CHECK: ldrh.w r11, [pc, #-22] @ encoding: [0x3f,0xf8,0x16,0xb0]
@ CHECK: ldrsb.w r11, [pc, #-22] @ encoding: [0x1f,0xf9,0x16,0xb0]
@ CHECK: ldrsh.w r11, [pc, #-22] @ encoding: [0x3f,0xf9,0x16,0xb0]