mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-12-29 06:53:53 +00:00
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:
parent
ee49d825b1
commit
b7ab9edb4e
@ -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)>;
|
||||
|
@ -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:
|
||||
|
@ -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;
|
||||
|
@ -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]
|
||||
|
Loading…
Reference in New Issue
Block a user