1
0
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:
Owen Anderson 2010-11-30 00:14:31 +00:00
parent 184d1ba738
commit 6af50f7dd1
5 changed files with 111 additions and 48 deletions

@ -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]!