mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-01-01 00:33:09 +00:00
Thumb2 parsing and encoding for LDR(immediate).
The immediate offset of the non-writeback i8 form (encoding T4) allows negative offsets only. The positive offset form of the encoding is the LDRT instruction. Immediate offsets in the range [0,255] use encoding T3 instead. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@139254 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
94f914e3fd
commit
a8307dd1c9
@ -101,11 +101,13 @@ def lo5AllOne : PatLeaf<(i32 imm), [{
|
||||
// Define Thumb2 specific addressing modes.
|
||||
|
||||
// t2addrmode_imm12 := reg + imm12
|
||||
def t2addrmode_imm12_asmoperand : AsmOperandClass {let Name="MemUImm12Offset";}
|
||||
def t2addrmode_imm12 : Operand<i32>,
|
||||
ComplexPattern<i32, 2, "SelectT2AddrModeImm12", []> {
|
||||
let PrintMethod = "printAddrModeImm12Operand";
|
||||
let EncoderMethod = "getAddrModeImm12OpValue";
|
||||
let DecoderMethod = "DecodeT2AddrModeImm12";
|
||||
let ParserMatchClass = t2addrmode_imm12_asmoperand;
|
||||
let MIOperandInfo = (ops GPR:$base, i32imm:$offsimm);
|
||||
}
|
||||
|
||||
@ -121,6 +123,17 @@ def t2adrlabel : Operand<i32> {
|
||||
}
|
||||
|
||||
|
||||
// t2addrmode_negimm8 := reg - imm8
|
||||
def MemNegImm8OffsetAsmOperand : AsmOperandClass {let Name="MemNegImm8Offset";}
|
||||
def t2addrmode_negimm8 : Operand<i32>,
|
||||
ComplexPattern<i32, 2, "SelectT2AddrModeImm8", []> {
|
||||
let PrintMethod = "printT2AddrModeImm8Operand";
|
||||
let EncoderMethod = "getT2AddrModeImm8OpValue";
|
||||
let DecoderMethod = "DecodeT2AddrModeImm8";
|
||||
let ParserMatchClass = MemNegImm8OffsetAsmOperand;
|
||||
let MIOperandInfo = (ops GPR:$base, i32imm:$offsimm);
|
||||
}
|
||||
|
||||
// t2addrmode_imm8 := reg +/- imm8
|
||||
def MemImm8OffsetAsmOperand : AsmOperandClass { let Name = "MemImm8Offset"; }
|
||||
def t2addrmode_imm8 : Operand<i32>,
|
||||
@ -880,42 +893,35 @@ multiclass T2I_ld<bit signed, bits<2> opcod, string opc,
|
||||
def i12 : T2Ii12<(outs target:$Rt), (ins t2addrmode_imm12:$addr), iii,
|
||||
opc, ".w\t$Rt, $addr",
|
||||
[(set target:$Rt, (opnode t2addrmode_imm12:$addr))]> {
|
||||
let Inst{31-27} = 0b11111;
|
||||
let Inst{26-25} = 0b00;
|
||||
bits<4> Rt;
|
||||
bits<17> addr;
|
||||
let Inst{31-25} = 0b1111100;
|
||||
let Inst{24} = signed;
|
||||
let Inst{23} = 1;
|
||||
let Inst{22-21} = opcod;
|
||||
let Inst{20} = 1; // load
|
||||
|
||||
bits<4> Rt;
|
||||
let Inst{15-12} = Rt;
|
||||
|
||||
bits<17> addr;
|
||||
let addr{12} = 1; // add = TRUE
|
||||
let Inst{19-16} = addr{16-13}; // Rn
|
||||
let Inst{23} = addr{12}; // U
|
||||
let Inst{15-12} = Rt;
|
||||
let Inst{11-0} = addr{11-0}; // imm
|
||||
}
|
||||
def i8 : T2Ii8 <(outs target:$Rt), (ins t2addrmode_imm8:$addr), iii,
|
||||
def i8 : T2Ii8 <(outs target:$Rt), (ins t2addrmode_negimm8:$addr), iii,
|
||||
opc, "\t$Rt, $addr",
|
||||
[(set target:$Rt, (opnode t2addrmode_imm8:$addr))]> {
|
||||
[(set target:$Rt, (opnode t2addrmode_negimm8:$addr))]> {
|
||||
bits<4> Rt;
|
||||
bits<13> addr;
|
||||
let Inst{31-27} = 0b11111;
|
||||
let Inst{26-25} = 0b00;
|
||||
let Inst{24} = signed;
|
||||
let Inst{23} = 0;
|
||||
let Inst{22-21} = opcod;
|
||||
let Inst{20} = 1; // load
|
||||
let Inst{19-16} = addr{12-9}; // Rn
|
||||
let Inst{15-12} = Rt;
|
||||
let Inst{11} = 1;
|
||||
// Offset: index==TRUE, wback==FALSE
|
||||
let Inst{10} = 1; // The P bit.
|
||||
let Inst{8} = 0; // The W bit.
|
||||
|
||||
bits<4> Rt;
|
||||
let Inst{15-12} = Rt;
|
||||
|
||||
bits<13> addr;
|
||||
let Inst{19-16} = addr{12-9}; // Rn
|
||||
let Inst{9} = addr{8}; // U
|
||||
let Inst{8} = 0; // The W bit.
|
||||
let Inst{7-0} = addr{7-0}; // imm
|
||||
}
|
||||
def s : T2Iso <(outs target:$Rt), (ins t2addrmode_so_reg:$addr), iis,
|
||||
@ -980,9 +986,9 @@ multiclass T2I_st<bits<2> opcod, string opc,
|
||||
let Inst{23} = addr{12}; // U
|
||||
let Inst{11-0} = addr{11-0}; // imm
|
||||
}
|
||||
def i8 : T2Ii8 <(outs), (ins target:$Rt, t2addrmode_imm8:$addr), iii,
|
||||
def i8 : T2Ii8 <(outs), (ins target:$Rt, t2addrmode_negimm8:$addr), iii,
|
||||
opc, "\t$Rt, $addr",
|
||||
[(opnode target:$Rt, t2addrmode_imm8:$addr)]> {
|
||||
[(opnode target:$Rt, t2addrmode_negimm8:$addr)]> {
|
||||
let Inst{31-27} = 0b11111;
|
||||
let Inst{26-23} = 0b0000;
|
||||
let Inst{22-21} = opcod;
|
||||
@ -1181,8 +1187,8 @@ def t2LDRDi8 : T2Ii8s4<1, 0, 1, (outs rGPR:$Rt, rGPR:$Rt2),
|
||||
// zextload i1 -> zextload i8
|
||||
def : T2Pat<(zextloadi1 t2addrmode_imm12:$addr),
|
||||
(t2LDRBi12 t2addrmode_imm12:$addr)>;
|
||||
def : T2Pat<(zextloadi1 t2addrmode_imm8:$addr),
|
||||
(t2LDRBi8 t2addrmode_imm8:$addr)>;
|
||||
def : T2Pat<(zextloadi1 t2addrmode_negimm8:$addr),
|
||||
(t2LDRBi8 t2addrmode_negimm8:$addr)>;
|
||||
def : T2Pat<(zextloadi1 t2addrmode_so_reg:$addr),
|
||||
(t2LDRBs t2addrmode_so_reg:$addr)>;
|
||||
def : T2Pat<(zextloadi1 (ARMWrapper tconstpool:$addr)),
|
||||
@ -1193,8 +1199,8 @@ def : T2Pat<(zextloadi1 (ARMWrapper tconstpool:$addr)),
|
||||
// earlier?
|
||||
def : T2Pat<(extloadi1 t2addrmode_imm12:$addr),
|
||||
(t2LDRBi12 t2addrmode_imm12:$addr)>;
|
||||
def : T2Pat<(extloadi1 t2addrmode_imm8:$addr),
|
||||
(t2LDRBi8 t2addrmode_imm8:$addr)>;
|
||||
def : T2Pat<(extloadi1 t2addrmode_negimm8:$addr),
|
||||
(t2LDRBi8 t2addrmode_negimm8:$addr)>;
|
||||
def : T2Pat<(extloadi1 t2addrmode_so_reg:$addr),
|
||||
(t2LDRBs t2addrmode_so_reg:$addr)>;
|
||||
def : T2Pat<(extloadi1 (ARMWrapper tconstpool:$addr)),
|
||||
@ -1202,8 +1208,8 @@ def : T2Pat<(extloadi1 (ARMWrapper tconstpool:$addr)),
|
||||
|
||||
def : T2Pat<(extloadi8 t2addrmode_imm12:$addr),
|
||||
(t2LDRBi12 t2addrmode_imm12:$addr)>;
|
||||
def : T2Pat<(extloadi8 t2addrmode_imm8:$addr),
|
||||
(t2LDRBi8 t2addrmode_imm8:$addr)>;
|
||||
def : T2Pat<(extloadi8 t2addrmode_negimm8:$addr),
|
||||
(t2LDRBi8 t2addrmode_negimm8:$addr)>;
|
||||
def : T2Pat<(extloadi8 t2addrmode_so_reg:$addr),
|
||||
(t2LDRBs t2addrmode_so_reg:$addr)>;
|
||||
def : T2Pat<(extloadi8 (ARMWrapper tconstpool:$addr)),
|
||||
@ -1211,8 +1217,8 @@ def : T2Pat<(extloadi8 (ARMWrapper tconstpool:$addr)),
|
||||
|
||||
def : T2Pat<(extloadi16 t2addrmode_imm12:$addr),
|
||||
(t2LDRHi12 t2addrmode_imm12:$addr)>;
|
||||
def : T2Pat<(extloadi16 t2addrmode_imm8:$addr),
|
||||
(t2LDRHi8 t2addrmode_imm8:$addr)>;
|
||||
def : T2Pat<(extloadi16 t2addrmode_negimm8:$addr),
|
||||
(t2LDRHi8 t2addrmode_negimm8:$addr)>;
|
||||
def : T2Pat<(extloadi16 t2addrmode_so_reg:$addr),
|
||||
(t2LDRHs t2addrmode_so_reg:$addr)>;
|
||||
def : T2Pat<(extloadi16 (ARMWrapper tconstpool:$addr)),
|
||||
@ -1444,9 +1450,9 @@ multiclass T2Ipl<bits<1> write, bits<1> instr, string opc> {
|
||||
let Inst{11-0} = addr{11-0}; // imm12
|
||||
}
|
||||
|
||||
def i8 : T2Ii8<(outs), (ins t2addrmode_imm8:$addr), IIC_Preload, opc,
|
||||
def i8 : T2Ii8<(outs), (ins t2addrmode_negimm8:$addr), IIC_Preload, opc,
|
||||
"\t$addr",
|
||||
[(ARMPreload t2addrmode_imm8:$addr, (i32 write), (i32 instr))]> {
|
||||
[(ARMPreload t2addrmode_negimm8:$addr, (i32 write), (i32 instr))]> {
|
||||
let Inst{31-25} = 0b1111100;
|
||||
let Inst{24} = instr;
|
||||
let Inst{23} = 0; // U = 0
|
||||
@ -3514,38 +3520,38 @@ def : T2Pat<(add rGPR:$Rn, (sext_inreg rGPR:$Rm, i16)),
|
||||
// Atomic load/store patterns
|
||||
def : T2Pat<(atomic_load_8 t2addrmode_imm12:$addr),
|
||||
(t2LDRBi12 t2addrmode_imm12:$addr)>;
|
||||
def : T2Pat<(atomic_load_8 t2addrmode_imm8:$addr),
|
||||
(t2LDRBi8 t2addrmode_imm8:$addr)>;
|
||||
def : T2Pat<(atomic_load_8 t2addrmode_negimm8:$addr),
|
||||
(t2LDRBi8 t2addrmode_negimm8:$addr)>;
|
||||
def : T2Pat<(atomic_load_8 t2addrmode_so_reg:$addr),
|
||||
(t2LDRBs t2addrmode_so_reg:$addr)>;
|
||||
def : T2Pat<(atomic_load_16 t2addrmode_imm12:$addr),
|
||||
(t2LDRHi12 t2addrmode_imm12:$addr)>;
|
||||
def : T2Pat<(atomic_load_16 t2addrmode_imm8:$addr),
|
||||
(t2LDRHi8 t2addrmode_imm8:$addr)>;
|
||||
def : T2Pat<(atomic_load_16 t2addrmode_negimm8:$addr),
|
||||
(t2LDRHi8 t2addrmode_negimm8:$addr)>;
|
||||
def : T2Pat<(atomic_load_16 t2addrmode_so_reg:$addr),
|
||||
(t2LDRHs t2addrmode_so_reg:$addr)>;
|
||||
def : T2Pat<(atomic_load_32 t2addrmode_imm12:$addr),
|
||||
(t2LDRi12 t2addrmode_imm12:$addr)>;
|
||||
def : T2Pat<(atomic_load_32 t2addrmode_imm8:$addr),
|
||||
(t2LDRi8 t2addrmode_imm8:$addr)>;
|
||||
def : T2Pat<(atomic_load_32 t2addrmode_negimm8:$addr),
|
||||
(t2LDRi8 t2addrmode_negimm8:$addr)>;
|
||||
def : T2Pat<(atomic_load_32 t2addrmode_so_reg:$addr),
|
||||
(t2LDRs t2addrmode_so_reg:$addr)>;
|
||||
def : T2Pat<(atomic_store_8 t2addrmode_imm12:$addr, GPR:$val),
|
||||
(t2STRBi12 GPR:$val, t2addrmode_imm12:$addr)>;
|
||||
def : T2Pat<(atomic_store_8 t2addrmode_imm8:$addr, GPR:$val),
|
||||
(t2STRBi8 GPR:$val, t2addrmode_imm8:$addr)>;
|
||||
def : T2Pat<(atomic_store_8 t2addrmode_negimm8:$addr, GPR:$val),
|
||||
(t2STRBi8 GPR:$val, t2addrmode_negimm8:$addr)>;
|
||||
def : T2Pat<(atomic_store_8 t2addrmode_so_reg:$addr, GPR:$val),
|
||||
(t2STRBs GPR:$val, t2addrmode_so_reg:$addr)>;
|
||||
def : T2Pat<(atomic_store_16 t2addrmode_imm12:$addr, GPR:$val),
|
||||
(t2STRHi12 GPR:$val, t2addrmode_imm12:$addr)>;
|
||||
def : T2Pat<(atomic_store_16 t2addrmode_imm8:$addr, GPR:$val),
|
||||
(t2STRHi8 GPR:$val, t2addrmode_imm8:$addr)>;
|
||||
def : T2Pat<(atomic_store_16 t2addrmode_negimm8:$addr, GPR:$val),
|
||||
(t2STRHi8 GPR:$val, t2addrmode_negimm8:$addr)>;
|
||||
def : T2Pat<(atomic_store_16 t2addrmode_so_reg:$addr, GPR:$val),
|
||||
(t2STRHs GPR:$val, t2addrmode_so_reg:$addr)>;
|
||||
def : T2Pat<(atomic_store_32 t2addrmode_imm12:$addr, GPR:$val),
|
||||
(t2STRi12 GPR:$val, t2addrmode_imm12:$addr)>;
|
||||
def : T2Pat<(atomic_store_32 t2addrmode_imm8:$addr, GPR:$val),
|
||||
(t2STRi8 GPR:$val, t2addrmode_imm8:$addr)>;
|
||||
def : T2Pat<(atomic_store_32 t2addrmode_negimm8:$addr, GPR:$val),
|
||||
(t2STRi8 GPR:$val, t2addrmode_negimm8:$addr)>;
|
||||
def : T2Pat<(atomic_store_32 t2addrmode_so_reg:$addr, GPR:$val),
|
||||
(t2STRs GPR:$val, t2addrmode_so_reg:$addr)>;
|
||||
|
||||
@ -3591,3 +3597,7 @@ def : t2InstAlias<"tst${p} $Rn, $Rm",
|
||||
def : InstAlias<"dmb", (t2DMB 0xf)>, Requires<[IsThumb2, HasDB]>;
|
||||
def : InstAlias<"dsb", (t2DSB 0xf)>, Requires<[IsThumb2, HasDB]>;
|
||||
def : InstAlias<"isb", (t2ISB 0xf)>, Requires<[IsThumb2, HasDB]>;
|
||||
|
||||
// Alias for LDRi12 without the ".w" optional width specifier.
|
||||
def : t2InstAlias<"ldr${p} $Rd, $addr",
|
||||
(t2LDRi12 GPR:$Rd, t2addrmode_imm12:$addr, pred:$p)>;
|
||||
|
@ -732,6 +732,28 @@ public:
|
||||
int64_t Val = Mem.OffsetImm->getValue();
|
||||
return Val > -256 && Val < 256;
|
||||
}
|
||||
bool isMemNegImm8Offset() const {
|
||||
if (Kind != Memory || Mem.OffsetRegNum != 0)
|
||||
return false;
|
||||
// Immediate offset in range [-255, -1].
|
||||
if (!Mem.OffsetImm) return true;
|
||||
int64_t Val = Mem.OffsetImm->getValue();
|
||||
return Val > -256 && Val < 0;
|
||||
}
|
||||
bool isMemUImm12Offset() const {
|
||||
// If we have an immediate that's not a constant, treat it as a label
|
||||
// reference needing a fixup. If it is a constant, it's something else
|
||||
// and we reject it.
|
||||
if (Kind == Immediate && !isa<MCConstantExpr>(getImm()))
|
||||
return true;
|
||||
|
||||
if (Kind != Memory || Mem.OffsetRegNum != 0)
|
||||
return false;
|
||||
// Immediate offset in range [0, 4095].
|
||||
if (!Mem.OffsetImm) return true;
|
||||
int64_t Val = Mem.OffsetImm->getValue();
|
||||
return (Val >= 0 && Val < 4096);
|
||||
}
|
||||
bool isMemImm12Offset() const {
|
||||
// If we have an immediate that's not a constant, treat it as a label
|
||||
// reference needing a fixup. If it is a constant, it's something else
|
||||
@ -1077,6 +1099,28 @@ public:
|
||||
Inst.addOperand(MCOperand::CreateImm(Val));
|
||||
}
|
||||
|
||||
void addMemNegImm8OffsetOperands(MCInst &Inst, unsigned N) const {
|
||||
assert(N == 2 && "Invalid number of operands!");
|
||||
int64_t Val = Mem.OffsetImm ? Mem.OffsetImm->getValue() : 0;
|
||||
Inst.addOperand(MCOperand::CreateReg(Mem.BaseRegNum));
|
||||
Inst.addOperand(MCOperand::CreateImm(Val));
|
||||
}
|
||||
|
||||
void addMemUImm12OffsetOperands(MCInst &Inst, unsigned N) const {
|
||||
assert(N == 2 && "Invalid number of operands!");
|
||||
// If this is an immediate, it's a label reference.
|
||||
if (Kind == Immediate) {
|
||||
addExpr(Inst, getImm());
|
||||
Inst.addOperand(MCOperand::CreateImm(0));
|
||||
return;
|
||||
}
|
||||
|
||||
// Otherwise, it's a normal memory reg+offset.
|
||||
int64_t Val = Mem.OffsetImm ? Mem.OffsetImm->getValue() : 0;
|
||||
Inst.addOperand(MCOperand::CreateReg(Mem.BaseRegNum));
|
||||
Inst.addOperand(MCOperand::CreateImm(Val));
|
||||
}
|
||||
|
||||
void addMemImm12OffsetOperands(MCInst &Inst, unsigned N) const {
|
||||
assert(N == 2 && "Invalid number of operands!");
|
||||
// If this is an immediate, it's a label reference.
|
||||
|
@ -666,6 +666,7 @@ static int ARMFlagFromOpName(LiteralConstantEmitter *type,
|
||||
MISC("spr_reglist", "kOperandTypeARMSPRRegisterList"); // I, R, ...
|
||||
MISC("it_mask", "kOperandTypeThumbITMask"); // I
|
||||
MISC("t2addrmode_reg", "kOperandTypeThumb2AddrModeReg"); // R
|
||||
MISC("t2addrmode_negimm8", "kOperandTypeThumb2AddrModeImm8"); // R, I
|
||||
MISC("t2addrmode_imm8", "kOperandTypeThumb2AddrModeImm8"); // R, I
|
||||
MISC("t2am_imm8_offset", "kOperandTypeThumb2AddrModeImm8Offset");//I
|
||||
MISC("t2addrmode_imm12", "kOperandTypeThumb2AddrModeImm12"); // R, I
|
||||
|
Loading…
Reference in New Issue
Block a user