mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-03-23 01:31:05 +00:00
Correct Thumb2 encodings for a much wider range of loads and stores.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@120364 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
184d1ba738
commit
6af50f7dd1
lib/Target/ARM
test/MC/ARM
@ -181,6 +181,8 @@ namespace {
|
||||
const { return 0; }
|
||||
unsigned getT2AddrModeImm8OpValue(const MachineInstr &MI, unsigned Op)
|
||||
const { return 0; }
|
||||
unsigned getT2AddrModeImm8OffsetOpValue(const MachineInstr &MI, unsigned Op)
|
||||
const { return 0; }
|
||||
unsigned getT2AddrModeSORegOpValue(const MachineInstr &MI, unsigned Op)
|
||||
const { return 0; }
|
||||
unsigned getT2SORegOpValue(const MachineInstr &MI, unsigned Op)
|
||||
|
@ -1050,6 +1050,15 @@ class T2Iidxldst<bit signed, bits<2> opcod, bit load, bit pre,
|
||||
// (P, W) = (1, 1) Pre-indexed or (0, 1) Post-indexed
|
||||
let Inst{10} = pre; // The P bit.
|
||||
let Inst{8} = 1; // The W bit.
|
||||
|
||||
bits<9> addr;
|
||||
let Inst{7-0} = addr{7-0};
|
||||
let Inst{9} = addr{8}; // Sign bit
|
||||
|
||||
bits<4> Rt;
|
||||
bits<4> Rn;
|
||||
let Inst{15-12} = Rt{3-0};
|
||||
let Inst{19-16} = Rn{3-0};
|
||||
}
|
||||
|
||||
// Tv5Pat - Same as Pat<>, but requires V5T Thumb mode.
|
||||
|
@ -143,6 +143,7 @@ def t2am_imm8_offset : Operand<i32>,
|
||||
ComplexPattern<i32, 1, "SelectT2AddrModeImm8Offset",
|
||||
[], [SDNPWantRoot]> {
|
||||
let PrintMethod = "printT2AddrModeImm8OffsetOperand";
|
||||
string EncoderMethod = "getT2AddrModeImm8OffsetOpValue";
|
||||
}
|
||||
|
||||
// t2addrmode_imm8s4 := reg +/- (imm8 << 2)
|
||||
@ -917,7 +918,7 @@ multiclass T2I_st<bits<2> opcod, string opc,
|
||||
let Inst{20} = 0; // !load
|
||||
|
||||
bits<4> Rt;
|
||||
let Inst{19-16} = Rt{3-0};
|
||||
let Inst{15-12} = Rt{3-0};
|
||||
|
||||
bits<16> addr;
|
||||
let Inst{19-16} = addr{15-12}; // Rn
|
||||
@ -936,7 +937,7 @@ multiclass T2I_st<bits<2> opcod, string opc,
|
||||
let Inst{8} = 0; // The W bit.
|
||||
|
||||
bits<4> Rt;
|
||||
let Inst{19-16} = Rt{3-0};
|
||||
let Inst{15-12} = Rt{3-0};
|
||||
|
||||
bits<13> addr;
|
||||
let Inst{19-16} = addr{12-9}; // Rn
|
||||
@ -1319,61 +1320,75 @@ def : T2Pat<(extloadi16 (ARMWrapper tconstpool:$addr)),
|
||||
// not via pattern.
|
||||
|
||||
// Indexed loads
|
||||
|
||||
class T2Iidxld<bit signed, bits<2> opcod, bit pre,
|
||||
dag oops, dag iops,
|
||||
AddrMode am, IndexMode im, InstrItinClass itin,
|
||||
string opc, string asm, string cstr, list<dag> pattern>
|
||||
: T2Iidxldst<signed, opcod, 1, pre, oops,
|
||||
iops, am,im,itin, opc, asm, cstr, pattern>;
|
||||
class T2Iidxst<bit signed, bits<2> opcod, bit pre,
|
||||
dag oops, dag iops,
|
||||
AddrMode am, IndexMode im, InstrItinClass itin,
|
||||
string opc, string asm, string cstr, list<dag> pattern>
|
||||
: T2Iidxldst<signed, opcod, 0, pre, oops,
|
||||
iops, am,im,itin, opc, asm, cstr, pattern>;
|
||||
|
||||
let mayLoad = 1, neverHasSideEffects = 1 in {
|
||||
def t2LDR_PRE : T2Iidxldst<0, 0b10, 1, 1, (outs GPR:$dst, GPR:$base_wb),
|
||||
def t2LDR_PRE : T2Iidxld<0, 0b10, 1, (outs GPR:$Rt, GPR:$Rn),
|
||||
(ins t2addrmode_imm8:$addr),
|
||||
AddrModeT2_i8, IndexModePre, IIC_iLoad_iu,
|
||||
"ldr", "\t$dst, $addr!", "$addr.base = $base_wb",
|
||||
"ldr", "\t$Rt, $addr!", "$addr.base = $Rn",
|
||||
[]>;
|
||||
|
||||
def t2LDR_POST : T2Iidxldst<0, 0b10, 1, 0, (outs GPR:$dst, GPR:$base_wb),
|
||||
def t2LDR_POST : T2Iidxld<0, 0b10, 0, (outs GPR:$Rt, GPR:$Rn),
|
||||
(ins GPR:$base, t2am_imm8_offset:$offset),
|
||||
AddrModeT2_i8, IndexModePost, IIC_iLoad_iu,
|
||||
"ldr", "\t$dst, [$base], $offset", "$base = $base_wb",
|
||||
"ldr", "\t$Rt, [$Rn], $offset", "$base = $Rn",
|
||||
[]>;
|
||||
|
||||
def t2LDRB_PRE : T2Iidxldst<0, 0b00, 1, 1, (outs GPR:$dst, GPR:$base_wb),
|
||||
def t2LDRB_PRE : T2Iidxld<0, 0b00, 1, (outs GPR:$Rt, GPR:$Rn),
|
||||
(ins t2addrmode_imm8:$addr),
|
||||
AddrModeT2_i8, IndexModePre, IIC_iLoad_bh_iu,
|
||||
"ldrb", "\t$dst, $addr!", "$addr.base = $base_wb",
|
||||
"ldrb", "\t$Rt, $addr!", "$addr.base = $Rn",
|
||||
[]>;
|
||||
def t2LDRB_POST : T2Iidxldst<0, 0b00, 1, 0, (outs GPR:$dst, GPR:$base_wb),
|
||||
def t2LDRB_POST : T2Iidxld<0, 0b00, 0, (outs GPR:$Rt, GPR:$Rn),
|
||||
(ins GPR:$base, t2am_imm8_offset:$offset),
|
||||
AddrModeT2_i8, IndexModePost, IIC_iLoad_bh_iu,
|
||||
"ldrb", "\t$dst, [$base], $offset", "$base = $base_wb",
|
||||
"ldrb", "\t$Rt, [$Rn], $offset", "$base = $Rn",
|
||||
[]>;
|
||||
|
||||
def t2LDRH_PRE : T2Iidxldst<0, 0b01, 1, 1, (outs GPR:$dst, GPR:$base_wb),
|
||||
def t2LDRH_PRE : T2Iidxld<0, 0b01, 1, (outs GPR:$Rt, GPR:$Rn),
|
||||
(ins t2addrmode_imm8:$addr),
|
||||
AddrModeT2_i8, IndexModePre, IIC_iLoad_bh_iu,
|
||||
"ldrh", "\t$dst, $addr!", "$addr.base = $base_wb",
|
||||
"ldrh", "\t$Rt, $addr!", "$addr.base = $Rn",
|
||||
[]>;
|
||||
def t2LDRH_POST : T2Iidxldst<0, 0b01, 1, 0, (outs GPR:$dst, GPR:$base_wb),
|
||||
def t2LDRH_POST : T2Iidxld<0, 0b01, 0, (outs GPR:$Rt, GPR:$Rn),
|
||||
(ins GPR:$base, t2am_imm8_offset:$offset),
|
||||
AddrModeT2_i8, IndexModePost, IIC_iLoad_bh_iu,
|
||||
"ldrh", "\t$dst, [$base], $offset", "$base = $base_wb",
|
||||
"ldrh", "\t$Rt, [$Rn], $offset", "$base = $Rn",
|
||||
[]>;
|
||||
|
||||
def t2LDRSB_PRE : T2Iidxldst<1, 0b00, 1, 1, (outs GPR:$dst, GPR:$base_wb),
|
||||
def t2LDRSB_PRE : T2Iidxld<1, 0b00, 1, (outs GPR:$Rt, GPR:$Rn),
|
||||
(ins t2addrmode_imm8:$addr),
|
||||
AddrModeT2_i8, IndexModePre, IIC_iLoad_bh_iu,
|
||||
"ldrsb", "\t$dst, $addr!", "$addr.base = $base_wb",
|
||||
"ldrsb", "\t$Rt, $addr!", "$addr.base = $Rn",
|
||||
[]>;
|
||||
def t2LDRSB_POST : T2Iidxldst<1, 0b00, 1, 0, (outs GPR:$dst, GPR:$base_wb),
|
||||
def t2LDRSB_POST : T2Iidxld<1, 0b00, 0, (outs GPR:$Rt, GPR:$Rn),
|
||||
(ins GPR:$base, t2am_imm8_offset:$offset),
|
||||
AddrModeT2_i8, IndexModePost, IIC_iLoad_bh_iu,
|
||||
"ldrsb", "\t$dst, [$base], $offset", "$base = $base_wb",
|
||||
"ldrsb", "\t$Rt, [$Rn], $offset", "$base = $Rn",
|
||||
[]>;
|
||||
|
||||
def t2LDRSH_PRE : T2Iidxldst<1, 0b01, 1, 1, (outs GPR:$dst, GPR:$base_wb),
|
||||
def t2LDRSH_PRE : T2Iidxld<1, 0b01, 1, (outs GPR:$Rt, GPR:$Rn),
|
||||
(ins t2addrmode_imm8:$addr),
|
||||
AddrModeT2_i8, IndexModePre, IIC_iLoad_bh_iu,
|
||||
"ldrsh", "\t$dst, $addr!", "$addr.base = $base_wb",
|
||||
"ldrsh", "\t$Rt, $addr!", "$addr.base = $Rn",
|
||||
[]>;
|
||||
def t2LDRSH_POST : T2Iidxldst<1, 0b01, 1, 0, (outs GPR:$dst, GPR:$base_wb),
|
||||
def t2LDRSH_POST : T2Iidxld<1, 0b01, 0, (outs GPR:$dst, GPR:$Rn),
|
||||
(ins GPR:$base, t2am_imm8_offset:$offset),
|
||||
AddrModeT2_i8, IndexModePost, IIC_iLoad_bh_iu,
|
||||
"ldrsh", "\t$dst, [$base], $offset", "$base = $base_wb",
|
||||
"ldrsh", "\t$dst, [$Rn], $offset", "$base = $Rn",
|
||||
[]>;
|
||||
} // mayLoad = 1, neverHasSideEffects = 1
|
||||
|
||||
@ -1415,47 +1430,47 @@ def t2STRDi8 : T2Ii8s4<1, 0, 0, (outs),
|
||||
IIC_iStore_d_r, "strd", "\t$src1, $addr", []>;
|
||||
|
||||
// Indexed stores
|
||||
def t2STR_PRE : T2Iidxldst<0, 0b10, 0, 1, (outs GPR:$base_wb),
|
||||
(ins GPR:$src, GPR:$base, t2am_imm8_offset:$offset),
|
||||
def t2STR_PRE : T2Iidxst<0, 0b10, 1, (outs GPR:$base_wb),
|
||||
(ins GPR:$Rt, GPR:$Rn, t2am_imm8_offset:$addr),
|
||||
AddrModeT2_i8, IndexModePre, IIC_iStore_iu,
|
||||
"str", "\t$src, [$base, $offset]!", "$base = $base_wb",
|
||||
"str", "\t$Rt, [$Rn, $addr]!", "$Rn = $base_wb",
|
||||
[(set GPR:$base_wb,
|
||||
(pre_store GPR:$src, GPR:$base, t2am_imm8_offset:$offset))]>;
|
||||
(pre_store GPR:$Rt, GPR:$Rn, t2am_imm8_offset:$addr))]>;
|
||||
|
||||
def t2STR_POST : T2Iidxldst<0, 0b10, 0, 0, (outs GPR:$base_wb),
|
||||
(ins GPR:$src, GPR:$base, t2am_imm8_offset:$offset),
|
||||
def t2STR_POST : T2Iidxst<0, 0b10, 0, (outs GPR:$base_wb),
|
||||
(ins GPR:$Rt, GPR:$Rn, t2am_imm8_offset:$addr),
|
||||
AddrModeT2_i8, IndexModePost, IIC_iStore_iu,
|
||||
"str", "\t$src, [$base], $offset", "$base = $base_wb",
|
||||
"str", "\t$Rt, [$Rn], $addr", "$Rn = $base_wb",
|
||||
[(set GPR:$base_wb,
|
||||
(post_store GPR:$src, GPR:$base, t2am_imm8_offset:$offset))]>;
|
||||
(post_store GPR:$Rt, GPR:$Rn, t2am_imm8_offset:$addr))]>;
|
||||
|
||||
def t2STRH_PRE : T2Iidxldst<0, 0b01, 0, 1, (outs GPR:$base_wb),
|
||||
(ins GPR:$src, GPR:$base, t2am_imm8_offset:$offset),
|
||||
def t2STRH_PRE : T2Iidxst<0, 0b01, 1, (outs GPR:$base_wb),
|
||||
(ins GPR:$Rt, GPR:$Rn, t2am_imm8_offset:$addr),
|
||||
AddrModeT2_i8, IndexModePre, IIC_iStore_iu,
|
||||
"strh", "\t$src, [$base, $offset]!", "$base = $base_wb",
|
||||
"strh", "\t$Rt, [$Rn, $addr]!", "$Rn = $base_wb",
|
||||
[(set GPR:$base_wb,
|
||||
(pre_truncsti16 GPR:$src, GPR:$base, t2am_imm8_offset:$offset))]>;
|
||||
(pre_truncsti16 GPR:$Rt, GPR:$Rn, t2am_imm8_offset:$addr))]>;
|
||||
|
||||
def t2STRH_POST : T2Iidxldst<0, 0b01, 0, 0, (outs GPR:$base_wb),
|
||||
(ins GPR:$src, GPR:$base, t2am_imm8_offset:$offset),
|
||||
def t2STRH_POST : T2Iidxst<0, 0b01, 0, (outs GPR:$base_wb),
|
||||
(ins GPR:$Rt, GPR:$Rn, t2am_imm8_offset:$addr),
|
||||
AddrModeT2_i8, IndexModePost, IIC_iStore_bh_iu,
|
||||
"strh", "\t$src, [$base], $offset", "$base = $base_wb",
|
||||
"strh", "\t$Rt, [$Rn], $addr", "$Rn = $base_wb",
|
||||
[(set GPR:$base_wb,
|
||||
(post_truncsti16 GPR:$src, GPR:$base, t2am_imm8_offset:$offset))]>;
|
||||
(post_truncsti16 GPR:$Rt, GPR:$Rn, t2am_imm8_offset:$addr))]>;
|
||||
|
||||
def t2STRB_PRE : T2Iidxldst<0, 0b00, 0, 1, (outs GPR:$base_wb),
|
||||
(ins GPR:$src, GPR:$base, t2am_imm8_offset:$offset),
|
||||
def t2STRB_PRE : T2Iidxst<0, 0b00, 1, (outs GPR:$base_wb),
|
||||
(ins GPR:$Rt, GPR:$Rn, t2am_imm8_offset:$addr),
|
||||
AddrModeT2_i8, IndexModePre, IIC_iStore_bh_iu,
|
||||
"strb", "\t$src, [$base, $offset]!", "$base = $base_wb",
|
||||
"strb", "\t$Rt, [$Rn, $addr]!", "$Rn = $base_wb",
|
||||
[(set GPR:$base_wb,
|
||||
(pre_truncsti8 GPR:$src, GPR:$base, t2am_imm8_offset:$offset))]>;
|
||||
(pre_truncsti8 GPR:$Rt, GPR:$Rn, t2am_imm8_offset:$addr))]>;
|
||||
|
||||
def t2STRB_POST : T2Iidxldst<0, 0b00, 0, 0, (outs GPR:$base_wb),
|
||||
(ins GPR:$src, GPR:$base, t2am_imm8_offset:$offset),
|
||||
def t2STRB_POST : T2Iidxst<0, 0b00, 0, (outs GPR:$base_wb),
|
||||
(ins GPR:$Rt, GPR:$Rn, t2am_imm8_offset:$addr),
|
||||
AddrModeT2_i8, IndexModePost, IIC_iStore_bh_iu,
|
||||
"strb", "\t$src, [$base], $offset", "$base = $base_wb",
|
||||
"strb", "\t$Rt, [$Rn], $addr", "$Rn = $base_wb",
|
||||
[(set GPR:$base_wb,
|
||||
(post_truncsti8 GPR:$src, GPR:$base, t2am_imm8_offset:$offset))]>;
|
||||
(post_truncsti8 GPR:$Rt, GPR:$Rn, t2am_imm8_offset:$addr))]>;
|
||||
|
||||
// STRT, STRBT, STRHT all have offset mode (PUW=0b110) and are for disassembly
|
||||
// only.
|
||||
|
@ -177,6 +177,8 @@ public:
|
||||
SmallVectorImpl<MCFixup> &Fixups) const;
|
||||
unsigned getT2AddrModeImm8OpValue(const MCInst &MI, unsigned OpNum,
|
||||
SmallVectorImpl<MCFixup> &Fixups) const;
|
||||
unsigned getT2AddrModeImm8OffsetOpValue(const MCInst &MI, unsigned OpNum,
|
||||
SmallVectorImpl<MCFixup> &Fixups) const;
|
||||
unsigned getT2AddrModeImm12OpValue(const MCInst &MI, unsigned OpNum,
|
||||
SmallVectorImpl<MCFixup> &Fixups) const;
|
||||
|
||||
@ -671,8 +673,28 @@ getT2AddrModeImm8OpValue(const MCInst &MI, unsigned OpNum,
|
||||
// Even though the immediate is 8 bits long, we need 9 bits in order
|
||||
// to represent the (inverse of the) sign bit.
|
||||
Value <<= 9;
|
||||
Value |= ((int32_t)MO2.getImm()) & 511;
|
||||
Value ^= 256; // Invert the sign bit.
|
||||
int32_t tmp = (int32_t)MO2.getImm();
|
||||
if (tmp < 0)
|
||||
tmp = abs(tmp);
|
||||
else
|
||||
Value |= 256; // Set the ADD bit
|
||||
Value |= tmp & 255;
|
||||
return Value;
|
||||
}
|
||||
|
||||
unsigned ARMMCCodeEmitter::
|
||||
getT2AddrModeImm8OffsetOpValue(const MCInst &MI, unsigned OpNum,
|
||||
SmallVectorImpl<MCFixup> &Fixups) const {
|
||||
const MCOperand &MO1 = MI.getOperand(OpNum);
|
||||
|
||||
// FIXME: Needs fixup support.
|
||||
unsigned Value = 0;
|
||||
int32_t tmp = (int32_t)MO1.getImm();
|
||||
if (tmp < 0)
|
||||
tmp = abs(tmp);
|
||||
else
|
||||
Value |= 256; // Set the ADD bit
|
||||
Value |= tmp & 255;
|
||||
return Value;
|
||||
}
|
||||
|
||||
|
@ -115,3 +115,18 @@
|
||||
@ CHECK: ldr.w r0, [r0, r1, lsl #2] @ encoding: [0x21,0x00,0x50,0xf8]
|
||||
ldr.w r0, [r0, r1, lsl #2]
|
||||
|
||||
@ CHECK: str r1, [r0, #16]! @ encoding: [0x10,0x1f,0x40,0xf8]
|
||||
str r1, [r0, #16]!
|
||||
@ CHECK: strh r1, [r0, #8]! @ encoding: [0x08,0x1f,0x20,0xf8]
|
||||
strh r1, [r0, #8]!
|
||||
@ CHECK: strh r2, [r0], #-4 @ encoding: [0x04,0x29,0x20,0xf8]
|
||||
strh r2, [r0], #-4
|
||||
@ CHECK: str r2, [r0], #-4 @ encoding: [0x04,0x29,0x40,0xf8]
|
||||
str r2, [r0], #-4
|
||||
|
||||
@ CHECK: ldr r2, [r0, #16]! @ encoding: [0x10,0x2f,0x50,0xf8]
|
||||
ldr r2, [r0, #16]!
|
||||
@ CHECK: ldr r2, [r0, #-64]! @ encoding: [0x40,0x2d,0x50,0xf8]
|
||||
ldr r2, [r0, #-64]!
|
||||
@ CHECK: ldrsb r2, [r0, #4]! @ encoding: [0x04,0x2f,0x10,0xf9]
|
||||
ldrsb r2, [r0, #4]!
|
||||
|
Loading…
x
Reference in New Issue
Block a user