mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-07-16 11:24:39 +00:00
Add parsing for the Thumb t_addrmode_s4 addressing mode. This can almost
certainly be made more generic. But it does allow us to parse something like: ldr r3, [r2, r4] correctly in Thumb mode. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@120408 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
@@ -235,8 +235,10 @@ namespace {
|
|||||||
const { return 0;}
|
const { return 0;}
|
||||||
uint32_t getAddrMode3OffsetOpValue(const MachineInstr &MI, unsigned OpIdx)
|
uint32_t getAddrMode3OffsetOpValue(const MachineInstr &MI, unsigned OpIdx)
|
||||||
const { return 0;}
|
const { return 0;}
|
||||||
uint32_t getAddrMode3OpValue(const MachineInstr &MI, unsigned Op) const
|
uint32_t getAddrMode3OpValue(const MachineInstr &MI, unsigned Op)
|
||||||
{ return 0; }
|
const { return 0; }
|
||||||
|
uint32_t getAddrModeS4OpValue(const MachineInstr &MI, unsigned Op)
|
||||||
|
const { return 0; }
|
||||||
uint32_t getAddrMode5OpValue(const MachineInstr &MI, unsigned Op) const {
|
uint32_t getAddrMode5OpValue(const MachineInstr &MI, unsigned Op) const {
|
||||||
// {17-13} = reg
|
// {17-13} = reg
|
||||||
// {12} = (U)nsigned (add == '1', sub == '0')
|
// {12} = (U)nsigned (add == '1', sub == '0')
|
||||||
|
@@ -74,6 +74,11 @@ def t_imm_s4 : Operand<i32> {
|
|||||||
|
|
||||||
// Define Thumb specific addressing modes.
|
// Define Thumb specific addressing modes.
|
||||||
|
|
||||||
|
def MemModeThumbAsmOperand : AsmOperandClass {
|
||||||
|
let Name = "MemModeThumb";
|
||||||
|
let SuperClasses = [];
|
||||||
|
}
|
||||||
|
|
||||||
// t_addrmode_rr := reg + reg
|
// t_addrmode_rr := reg + reg
|
||||||
//
|
//
|
||||||
def t_addrmode_rr : Operand<i32>,
|
def t_addrmode_rr : Operand<i32>,
|
||||||
@@ -87,8 +92,10 @@ def t_addrmode_rr : Operand<i32>,
|
|||||||
//
|
//
|
||||||
def t_addrmode_s4 : Operand<i32>,
|
def t_addrmode_s4 : Operand<i32>,
|
||||||
ComplexPattern<i32, 3, "SelectThumbAddrModeS4", []> {
|
ComplexPattern<i32, 3, "SelectThumbAddrModeS4", []> {
|
||||||
|
string EncoderMethod = "getAddrModeS4OpValue";
|
||||||
let PrintMethod = "printThumbAddrModeS4Operand";
|
let PrintMethod = "printThumbAddrModeS4Operand";
|
||||||
let MIOperandInfo = (ops tGPR:$base, i32imm:$offsimm, tGPR:$offsreg);
|
let MIOperandInfo = (ops tGPR:$base, i32imm:$offsimm, tGPR:$offsreg);
|
||||||
|
let ParserMatchClass = MemModeThumbAsmOperand;
|
||||||
}
|
}
|
||||||
|
|
||||||
// t_addrmode_s2 := reg + reg
|
// t_addrmode_s2 := reg + reg
|
||||||
@@ -489,8 +496,7 @@ def tSVC : T1pI<(outs), (ins i32imm:$imm), IIC_Br,
|
|||||||
let Inst{7-0} = imm;
|
let Inst{7-0} = imm;
|
||||||
}
|
}
|
||||||
|
|
||||||
// A8.6.16 B: Encoding T1
|
// The assembler uses 0xDEFE for a trap instruction.
|
||||||
// If Inst{11-8} == 0b1110 then UNDEFINED
|
|
||||||
let isBarrier = 1, isTerminator = 1 in
|
let isBarrier = 1, isTerminator = 1 in
|
||||||
def tTRAP : TI<(outs), (ins), IIC_Br,
|
def tTRAP : TI<(outs), (ins), IIC_Br,
|
||||||
"trap", [(trap)]>, Encoding16 {
|
"trap", [(trap)]>, Encoding16 {
|
||||||
@@ -505,12 +511,26 @@ let canFoldAsLoad = 1, isReMaterializable = 1 in
|
|||||||
def tLDR : T1pI4<(outs tGPR:$Rt), (ins t_addrmode_s4:$addr), IIC_iLoad_r,
|
def tLDR : T1pI4<(outs tGPR:$Rt), (ins t_addrmode_s4:$addr), IIC_iLoad_r,
|
||||||
"ldr", "\t$Rt, $addr",
|
"ldr", "\t$Rt, $addr",
|
||||||
[(set tGPR:$Rt, (load t_addrmode_s4:$addr))]>,
|
[(set tGPR:$Rt, (load t_addrmode_s4:$addr))]>,
|
||||||
T1LdSt<0b100>;
|
T1LdSt<0b100> {
|
||||||
|
// A8.6.60
|
||||||
|
bits<3> Rt;
|
||||||
|
bits<8> addr;
|
||||||
|
let Inst{8-6} = addr{5-3}; // Rm
|
||||||
|
let Inst{5-3} = addr{2-0}; // Rn
|
||||||
|
let Inst{2-0} = Rt;
|
||||||
|
}
|
||||||
|
|
||||||
def tLDRi: T1pI4<(outs tGPR:$dst), (ins t_addrmode_s4:$addr), IIC_iLoad_r,
|
def tLDRi: T1pI4<(outs tGPR:$Rt), (ins t_addrmode_s4:$addr), IIC_iLoad_r,
|
||||||
"ldr", "\t$dst, $addr",
|
"ldr", "\t$Rt, $addr",
|
||||||
[]>,
|
[]>,
|
||||||
T1LdSt4Imm<{1,?,?}>;
|
T1LdSt4Imm<{1,?,?}> {
|
||||||
|
// A8.6.57
|
||||||
|
bits<3> Rt;
|
||||||
|
bits<8> addr;
|
||||||
|
let Inst{10-6} = addr{7-3}; // imm5
|
||||||
|
let Inst{5-3} = addr{2-0}; // Rn
|
||||||
|
let Inst{2-0} = Rt;
|
||||||
|
}
|
||||||
|
|
||||||
def tLDRB : T1pI1<(outs tGPR:$dst), (ins t_addrmode_s1:$addr), IIC_iLoad_bh_r,
|
def tLDRB : T1pI1<(outs tGPR:$dst), (ins t_addrmode_s1:$addr), IIC_iLoad_bh_r,
|
||||||
"ldrb", "\t$dst, $addr",
|
"ldrb", "\t$dst, $addr",
|
||||||
|
@@ -136,6 +136,10 @@ public:
|
|||||||
uint32_t getAddrMode3OpValue(const MCInst &MI, unsigned OpIdx,
|
uint32_t getAddrMode3OpValue(const MCInst &MI, unsigned OpIdx,
|
||||||
SmallVectorImpl<MCFixup> &Fixups) const;
|
SmallVectorImpl<MCFixup> &Fixups) const;
|
||||||
|
|
||||||
|
/// getAddrModeS4OpValue - Return encoding for t_addrmode_s4 operands.
|
||||||
|
uint32_t getAddrModeS4OpValue(const MCInst &MI, unsigned OpIdx,
|
||||||
|
SmallVectorImpl<MCFixup> &Fixups) const;
|
||||||
|
|
||||||
/// getAddrMode5OpValue - Return encoding info for 'reg +/- imm8' operand.
|
/// getAddrMode5OpValue - Return encoding info for 'reg +/- imm8' operand.
|
||||||
uint32_t getAddrMode5OpValue(const MCInst &MI, unsigned OpIdx,
|
uint32_t getAddrMode5OpValue(const MCInst &MI, unsigned OpIdx,
|
||||||
SmallVectorImpl<MCFixup> &Fixups) const;
|
SmallVectorImpl<MCFixup> &Fixups) const;
|
||||||
@@ -540,6 +544,26 @@ getAddrMode3OpValue(const MCInst &MI, unsigned OpIdx,
|
|||||||
return (Rn << 9) | Imm8 | (isAdd << 8) | (isImm << 13);
|
return (Rn << 9) | Imm8 | (isAdd << 8) | (isImm << 13);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// getAddrModeS4OpValue - Return encoding for t_addrmode_s4 operands.
|
||||||
|
uint32_t ARMMCCodeEmitter::
|
||||||
|
getAddrModeS4OpValue(const MCInst &MI, unsigned OpIdx,
|
||||||
|
SmallVectorImpl<MCFixup> &Fixups) const {
|
||||||
|
// [Rn, Rm]
|
||||||
|
// {5-3} = Rm
|
||||||
|
// {2-0} = Rn
|
||||||
|
//
|
||||||
|
// [Rn, #imm]
|
||||||
|
// {7-3} = imm5
|
||||||
|
// {2-0} = Rn
|
||||||
|
const MCOperand &MO = MI.getOperand(OpIdx);
|
||||||
|
const MCOperand &MO1 = MI.getOperand(OpIdx + 1);
|
||||||
|
const MCOperand &MO2 = MI.getOperand(OpIdx + 2);
|
||||||
|
unsigned Rn = getARMRegisterNumbering(MO.getReg());
|
||||||
|
unsigned Imm5 = MO1.getImm();
|
||||||
|
unsigned Rm = getARMRegisterNumbering(MO2.getReg());
|
||||||
|
return (Rm << 3) | (Imm5 << 3) | Rn;
|
||||||
|
}
|
||||||
|
|
||||||
/// getAddrMode5OpValue - Return encoding info for 'reg +/- imm12' operand.
|
/// getAddrMode5OpValue - Return encoding info for 'reg +/- imm12' operand.
|
||||||
uint32_t ARMMCCodeEmitter::
|
uint32_t ARMMCCodeEmitter::
|
||||||
getAddrMode5OpValue(const MCInst &MI, unsigned OpIdx,
|
getAddrMode5OpValue(const MCInst &MI, unsigned OpIdx,
|
||||||
|
@@ -222,16 +222,30 @@ public:
|
|||||||
if (!isMemory() || Mem.OffsetIsReg || Mem.OffsetRegShifted ||
|
if (!isMemory() || Mem.OffsetIsReg || Mem.OffsetRegShifted ||
|
||||||
Mem.Writeback || Mem.Negative)
|
Mem.Writeback || Mem.Negative)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// If there is an offset expression, make sure it's valid.
|
// If there is an offset expression, make sure it's valid.
|
||||||
if (!Mem.Offset)
|
if (!Mem.Offset) return true;
|
||||||
return true;
|
|
||||||
const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Mem.Offset);
|
const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Mem.Offset);
|
||||||
if (!CE)
|
if (!CE) return false;
|
||||||
return false;
|
|
||||||
// The offset must be a multiple of 4 in the range 0-1020.
|
// The offset must be a multiple of 4 in the range 0-1020.
|
||||||
int64_t Value = CE->getValue();
|
int64_t Value = CE->getValue();
|
||||||
return ((Value & 0x3) == 0 && Value <= 1020 && Value >= -1020);
|
return ((Value & 0x3) == 0 && Value <= 1020 && Value >= -1020);
|
||||||
}
|
}
|
||||||
|
bool isMemModeThumb() const {
|
||||||
|
if (!isMemory() || (!Mem.OffsetIsReg && !Mem.Offset) || Mem.Writeback)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!Mem.Offset) return true;
|
||||||
|
|
||||||
|
const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Mem.Offset);
|
||||||
|
if (!CE) return false;
|
||||||
|
|
||||||
|
// The offset must be a multiple of 4 in the range 0-124.
|
||||||
|
uint64_t Value = CE->getValue();
|
||||||
|
return ((Value & 0x3) == 0 && Value <= 124);
|
||||||
|
}
|
||||||
|
|
||||||
void addExpr(MCInst &Inst, const MCExpr *Expr) const {
|
void addExpr(MCInst &Inst, const MCExpr *Expr) const {
|
||||||
// Add as immediates when possible. Null MCExpr = 0.
|
// Add as immediates when possible. Null MCExpr = 0.
|
||||||
@@ -302,6 +316,21 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void addMemModeThumbOperands(MCInst &Inst, unsigned N) const {
|
||||||
|
assert(N == 3 && isMemModeThumb() && "Invalid number of operands!");
|
||||||
|
Inst.addOperand(MCOperand::CreateReg(Mem.BaseRegNum));
|
||||||
|
|
||||||
|
if (Mem.Offset) {
|
||||||
|
const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Mem.Offset);
|
||||||
|
assert(CE && "Non-constant mode offset operand!");
|
||||||
|
Inst.addOperand(MCOperand::CreateImm(CE->getValue() / 4));
|
||||||
|
Inst.addOperand(MCOperand::CreateReg(0));
|
||||||
|
} else {
|
||||||
|
Inst.addOperand(MCOperand::CreateImm(0));
|
||||||
|
Inst.addOperand(MCOperand::CreateReg(Mem.OffsetRegNum));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
virtual void dump(raw_ostream &OS) const;
|
virtual void dump(raw_ostream &OS) const;
|
||||||
|
|
||||||
static ARMOperand *CreateCondCode(ARMCC::CondCodes CC, SMLoc S) {
|
static ARMOperand *CreateCondCode(ARMCC::CondCodes CC, SMLoc S) {
|
||||||
@@ -592,8 +621,8 @@ ParseMemory(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
|
|||||||
int OffsetRegNum;
|
int OffsetRegNum;
|
||||||
bool OffsetRegShifted;
|
bool OffsetRegShifted;
|
||||||
enum ShiftType ShiftType;
|
enum ShiftType ShiftType;
|
||||||
const MCExpr *ShiftAmount;
|
const MCExpr *ShiftAmount = 0;
|
||||||
const MCExpr *Offset;
|
const MCExpr *Offset = 0;
|
||||||
if (ParseMemoryOffsetReg(Negative, OffsetRegShifted, ShiftType, ShiftAmount,
|
if (ParseMemoryOffsetReg(Negative, OffsetRegShifted, ShiftType, ShiftAmount,
|
||||||
Offset, OffsetIsReg, OffsetRegNum, E))
|
Offset, OffsetIsReg, OffsetRegNum, E))
|
||||||
return true;
|
return true;
|
||||||
|
@@ -32,3 +32,6 @@
|
|||||||
@ CHECK: uxth r3, r6 @ encoding: [0xb3,0xb2]
|
@ CHECK: uxth r3, r6 @ encoding: [0xb3,0xb2]
|
||||||
uxtb r3, r6
|
uxtb r3, r6
|
||||||
uxth r3, r6
|
uxth r3, r6
|
||||||
|
|
||||||
|
@ CHECK: ldr r3, [r1, r2] @ encoding: [0x8b,0x58]
|
||||||
|
ldr r3, [r1, r2]
|
||||||
|
Reference in New Issue
Block a user