mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-01-02 07:32:52 +00:00
Thumb2 assembly parsing and encoding for LDR pre-indexed w/ writeback.
Adjust encoding of writeback load/store instructions to better reflect the way the operand types are represented. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@139270 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
170580e8f4
commit
eeec025cf5
@ -1161,8 +1161,8 @@ class T2XIt<dag oops, dag iops, InstrItinClass itin,
|
||||
string asm, string cstr, list<dag> pattern>
|
||||
: Thumb2XI<oops, iops, AddrModeNone, 4, itin, asm, cstr, pattern>;
|
||||
|
||||
// T2Iidxldst - Thumb2 indexed load / store instructions.
|
||||
class T2Iidxldst<bit signed, bits<2> opcod, bit load, bit pre,
|
||||
// T2Ipreldst - Thumb2 pre-indexed load / store instructions.
|
||||
class T2Ipreldst<bit signed, bits<2> opcod, bit load, bit pre,
|
||||
dag oops, dag iops,
|
||||
AddrMode am, IndexMode im, InstrItinClass itin,
|
||||
string opc, string asm, string cstr, list<dag> pattern>
|
||||
@ -1173,25 +1173,55 @@ class T2Iidxldst<bit signed, bits<2> opcod, bit load, bit pre,
|
||||
let Pattern = pattern;
|
||||
list<Predicate> Predicates = [IsThumb2];
|
||||
let DecoderNamespace = "Thumb2";
|
||||
|
||||
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} = load;
|
||||
let Inst{19-16} = addr{12-9};
|
||||
let Inst{15-12} = Rt{3-0};
|
||||
let Inst{11} = 1;
|
||||
// (P, W) = (1, 1) Pre-indexed or (0, 1) Post-indexed
|
||||
let Inst{10} = pre; // The P bit.
|
||||
let Inst{9} = addr{8}; // Sign bit
|
||||
let Inst{8} = 1; // The W bit.
|
||||
let Inst{7-0} = addr{7-0};
|
||||
}
|
||||
|
||||
bits<9> addr;
|
||||
let Inst{7-0} = addr{7-0};
|
||||
let Inst{9} = addr{8}; // Sign bit
|
||||
// T2Ipostldst - Thumb2 post-indexed load / store instructions.
|
||||
class T2Ipostldst<bit signed, bits<2> opcod, bit load, bit pre,
|
||||
dag oops, dag iops,
|
||||
AddrMode am, IndexMode im, InstrItinClass itin,
|
||||
string opc, string asm, string cstr, list<dag> pattern>
|
||||
: InstARM<am, 4, im, ThumbFrm, GenericDomain, cstr, itin> {
|
||||
let OutOperandList = oops;
|
||||
let InOperandList = !con(iops, (ins pred:$p));
|
||||
let AsmString = !strconcat(opc, "${p}", asm);
|
||||
let Pattern = pattern;
|
||||
list<Predicate> Predicates = [IsThumb2];
|
||||
let DecoderNamespace = "Thumb2";
|
||||
|
||||
bits<4> Rt;
|
||||
bits<4> Rn;
|
||||
bits<9> 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} = load;
|
||||
let Inst{19-16} = Rn;
|
||||
let Inst{15-12} = Rt{3-0};
|
||||
let Inst{19-16} = Rn{3-0};
|
||||
let Inst{11} = 1;
|
||||
// (P, W) = (1, 1) Pre-indexed or (0, 1) Post-indexed
|
||||
let Inst{10} = pre; // The P bit.
|
||||
let Inst{9} = addr{8}; // Sign bit
|
||||
let Inst{8} = 1; // The W bit.
|
||||
let Inst{7-0} = addr{7-0};
|
||||
}
|
||||
|
||||
// Tv5Pat - Same as Pat<>, but requires V5T Thumb mode.
|
||||
|
@ -1244,61 +1244,66 @@ def : T2Pat<(extloadi16 (ARMWrapper tconstpool:$addr)),
|
||||
// Indexed loads
|
||||
|
||||
let mayLoad = 1, neverHasSideEffects = 1 in {
|
||||
def t2LDR_PRE : T2Iidxldst<0, 0b10, 1, 1, (outs GPR:$Rt, GPR:$Rn),
|
||||
def t2LDR_PRE : T2Ipreldst<0, 0b10, 1, 1, (outs GPR:$Rt, GPR:$Rn_wb),
|
||||
(ins t2addrmode_imm8:$addr),
|
||||
AddrModeT2_i8, IndexModePre, IIC_iLoad_iu,
|
||||
"ldr", "\t$Rt, $addr!", "$addr.base = $Rn",
|
||||
[]>;
|
||||
"ldr", "\t$Rt, $addr!", "$addr.base = $Rn_wb",
|
||||
[]> {
|
||||
let AsmMatchConverter = "cvtLdWriteBackRegT2AddrModeImm8";
|
||||
}
|
||||
|
||||
def t2LDR_POST : T2Iidxldst<0, 0b10, 1, 0, (outs GPR:$Rt, GPR:$Rn),
|
||||
(ins GPR:$base, t2am_imm8_offset:$addr),
|
||||
def t2LDR_POST : T2Ipostldst<0, 0b10, 1, 0, (outs GPR:$Rt, GPR:$Rn_wb),
|
||||
(ins GPR:$Rn, t2am_imm8_offset:$addr),
|
||||
AddrModeT2_i8, IndexModePost, IIC_iLoad_iu,
|
||||
"ldr", "\t$Rt, [$Rn], $addr", "$base = $Rn",
|
||||
[]>;
|
||||
"ldr", "\t$Rt, [$Rn], $addr", "$Rn = $Rn_wb", []>;
|
||||
|
||||
def t2LDRB_PRE : T2Iidxldst<0, 0b00, 1, 1, (outs GPR:$Rt, GPR:$Rn),
|
||||
def t2LDRB_PRE : T2Ipreldst<0, 0b00, 1, 1, (outs GPR:$Rt, GPR:$Rn_wb),
|
||||
(ins t2addrmode_imm8:$addr),
|
||||
AddrModeT2_i8, IndexModePre, IIC_iLoad_bh_iu,
|
||||
"ldrb", "\t$Rt, $addr!", "$addr.base = $Rn",
|
||||
[]>;
|
||||
def t2LDRB_POST : T2Iidxldst<0, 0b00, 1, 0, (outs GPR:$Rt, GPR:$Rn),
|
||||
(ins GPR:$base, t2am_imm8_offset:$addr),
|
||||
"ldrb", "\t$Rt, $addr!", "$addr.base = $Rn_wb",
|
||||
[]> {
|
||||
let AsmMatchConverter = "cvtLdWriteBackRegT2AddrModeImm8";
|
||||
}
|
||||
def t2LDRB_POST : T2Ipostldst<0, 0b00, 1, 0, (outs GPR:$Rt, GPR:$Rn_wb),
|
||||
(ins GPR:$Rn, t2am_imm8_offset:$addr),
|
||||
AddrModeT2_i8, IndexModePost, IIC_iLoad_bh_iu,
|
||||
"ldrb", "\t$Rt, [$Rn], $addr", "$base = $Rn",
|
||||
[]>;
|
||||
"ldrb", "\t$Rt, [$Rn], $addr", "$Rn = $Rn_wb", []>;
|
||||
|
||||
def t2LDRH_PRE : T2Iidxldst<0, 0b01, 1, 1, (outs GPR:$Rt, GPR:$Rn),
|
||||
def t2LDRH_PRE : T2Ipreldst<0, 0b01, 1, 1, (outs GPR:$Rt, GPR:$Rn_wb),
|
||||
(ins t2addrmode_imm8:$addr),
|
||||
AddrModeT2_i8, IndexModePre, IIC_iLoad_bh_iu,
|
||||
"ldrh", "\t$Rt, $addr!", "$addr.base = $Rn",
|
||||
[]>;
|
||||
def t2LDRH_POST : T2Iidxldst<0, 0b01, 1, 0, (outs GPR:$Rt, GPR:$Rn),
|
||||
(ins GPR:$base, t2am_imm8_offset:$addr),
|
||||
"ldrh", "\t$Rt, $addr!", "$addr.base = $Rn_wb",
|
||||
[]> {
|
||||
let AsmMatchConverter = "cvtLdWriteBackRegT2AddrModeImm8";
|
||||
}
|
||||
def t2LDRH_POST : T2Ipostldst<0, 0b01, 1, 0, (outs GPR:$Rt, GPR:$Rn_wb),
|
||||
(ins GPR:$Rn, t2am_imm8_offset:$addr),
|
||||
AddrModeT2_i8, IndexModePost, IIC_iLoad_bh_iu,
|
||||
"ldrh", "\t$Rt, [$Rn], $addr", "$base = $Rn",
|
||||
[]>;
|
||||
"ldrh", "\t$Rt, [$Rn], $addr", "$Rn = $Rn_wb", []>;
|
||||
|
||||
def t2LDRSB_PRE : T2Iidxldst<1, 0b00, 1, 1, (outs GPR:$Rt, GPR:$Rn),
|
||||
def t2LDRSB_PRE : T2Ipreldst<1, 0b00, 1, 1, (outs GPR:$Rt, GPR:$Rn_wb),
|
||||
(ins t2addrmode_imm8:$addr),
|
||||
AddrModeT2_i8, IndexModePre, IIC_iLoad_bh_iu,
|
||||
"ldrsb", "\t$Rt, $addr!", "$addr.base = $Rn",
|
||||
[]>;
|
||||
def t2LDRSB_POST : T2Iidxldst<1, 0b00, 1, 0, (outs GPR:$Rt, GPR:$Rn),
|
||||
(ins GPR:$base, t2am_imm8_offset:$addr),
|
||||
"ldrsb", "\t$Rt, $addr!", "$addr.base = $Rn_wb",
|
||||
[]> {
|
||||
let AsmMatchConverter = "cvtLdWriteBackRegT2AddrModeImm8";
|
||||
}
|
||||
def t2LDRSB_POST : T2Ipostldst<1, 0b00, 1, 0, (outs GPR:$Rt, GPR:$Rn_wb),
|
||||
(ins GPR:$Rn, t2am_imm8_offset:$addr),
|
||||
AddrModeT2_i8, IndexModePost, IIC_iLoad_bh_iu,
|
||||
"ldrsb", "\t$Rt, [$Rn], $addr", "$base = $Rn",
|
||||
[]>;
|
||||
"ldrsb", "\t$Rt, [$Rn], $addr", "$Rn = $Rn_wb", []>;
|
||||
|
||||
def t2LDRSH_PRE : T2Iidxldst<1, 0b01, 1, 1, (outs GPR:$Rt, GPR:$Rn),
|
||||
def t2LDRSH_PRE : T2Ipreldst<1, 0b01, 1, 1, (outs GPR:$Rt, GPR:$Rn_wb),
|
||||
(ins t2addrmode_imm8:$addr),
|
||||
AddrModeT2_i8, IndexModePre, IIC_iLoad_bh_iu,
|
||||
"ldrsh", "\t$Rt, $addr!", "$addr.base = $Rn",
|
||||
[]>;
|
||||
def t2LDRSH_POST : T2Iidxldst<1, 0b01, 1, 0, (outs GPR:$Rt, GPR:$Rn),
|
||||
(ins GPR:$base, t2am_imm8_offset:$addr),
|
||||
"ldrsh", "\t$Rt, $addr!", "$addr.base = $Rn_wb",
|
||||
[]> {
|
||||
let AsmMatchConverter = "cvtLdWriteBackRegT2AddrModeImm8";
|
||||
}
|
||||
def t2LDRSH_POST : T2Ipostldst<1, 0b01, 1, 0, (outs GPR:$Rt, GPR:$Rn_wb),
|
||||
(ins GPR:$Rn, t2am_imm8_offset:$addr),
|
||||
AddrModeT2_i8, IndexModePost, IIC_iLoad_bh_iu,
|
||||
"ldrsh", "\t$Rt, [$Rn], $addr", "$base = $Rn",
|
||||
[]>;
|
||||
"ldrsh", "\t$Rt, [$Rn], $addr", "$Rn = $Rn_wb", []>;
|
||||
} // mayLoad = 1, neverHasSideEffects = 1
|
||||
|
||||
// LDRT, LDRBT, LDRHT, LDRSBT, LDRSHT all have offset mode (PUW=0b110).
|
||||
@ -1342,52 +1347,52 @@ def t2STRDi8 : T2Ii8s4<1, 0, 0, (outs),
|
||||
IIC_iStore_d_r, "strd", "\t$Rt, $Rt2, $addr", []>;
|
||||
|
||||
// Indexed stores
|
||||
def t2STR_PRE : T2Iidxldst<0, 0b10, 0, 1, (outs GPRnopc:$base_wb),
|
||||
def t2STR_PRE : T2Ipreldst<0, 0b10, 0, 1, (outs GPRnopc:$Rn_wb),
|
||||
(ins rGPR:$Rt, GPRnopc:$Rn, t2am_imm8_offset:$addr),
|
||||
AddrModeT2_i8, IndexModePre, IIC_iStore_iu,
|
||||
"str", "\t$Rt, [$Rn, $addr]!",
|
||||
"$Rn = $base_wb,@earlyclobber $base_wb",
|
||||
[(set GPRnopc:$base_wb,
|
||||
"$Rn = $Rn_wb,@earlyclobber $Rn_wb",
|
||||
[(set GPRnopc:$Rn_wb,
|
||||
(pre_store rGPR:$Rt, GPRnopc:$Rn, t2am_imm8_offset:$addr))]>;
|
||||
|
||||
def t2STR_POST : T2Iidxldst<0, 0b10, 0, 0, (outs GPRnopc:$base_wb),
|
||||
def t2STR_POST : T2Ipostldst<0, 0b10, 0, 0, (outs GPRnopc:$Rn_wb),
|
||||
(ins rGPR:$Rt, GPRnopc:$Rn, t2am_imm8_offset:$addr),
|
||||
AddrModeT2_i8, IndexModePost, IIC_iStore_iu,
|
||||
"str", "\t$Rt, [$Rn], $addr",
|
||||
"$Rn = $base_wb,@earlyclobber $base_wb",
|
||||
[(set GPRnopc:$base_wb,
|
||||
"$Rn = $Rn_wb,@earlyclobber $Rn_wb",
|
||||
[(set GPRnopc:$Rn_wb,
|
||||
(post_store rGPR:$Rt, GPRnopc:$Rn, t2am_imm8_offset:$addr))]>;
|
||||
|
||||
def t2STRH_PRE : T2Iidxldst<0, 0b01, 0, 1, (outs GPRnopc:$base_wb),
|
||||
def t2STRH_PRE : T2Ipreldst<0, 0b01, 0, 1, (outs GPRnopc:$Rn_wb),
|
||||
(ins rGPR:$Rt, GPRnopc:$Rn, t2am_imm8_offset:$addr),
|
||||
AddrModeT2_i8, IndexModePre, IIC_iStore_iu,
|
||||
"strh", "\t$Rt, [$Rn, $addr]!",
|
||||
"$Rn = $base_wb,@earlyclobber $base_wb",
|
||||
[(set GPRnopc:$base_wb,
|
||||
"$Rn = $Rn_wb,@earlyclobber $Rn_wb",
|
||||
[(set GPRnopc:$Rn_wb,
|
||||
(pre_truncsti16 rGPR:$Rt, GPRnopc:$Rn, t2am_imm8_offset:$addr))]>;
|
||||
|
||||
def t2STRH_POST : T2Iidxldst<0, 0b01, 0, 0, (outs GPRnopc:$base_wb),
|
||||
def t2STRH_POST : T2Ipostldst<0, 0b01, 0, 0, (outs GPRnopc:$Rn_wb),
|
||||
(ins rGPR:$Rt, GPRnopc:$Rn, t2am_imm8_offset:$addr),
|
||||
AddrModeT2_i8, IndexModePost, IIC_iStore_bh_iu,
|
||||
"strh", "\t$Rt, [$Rn], $addr",
|
||||
"$Rn = $base_wb,@earlyclobber $base_wb",
|
||||
[(set GPRnopc:$base_wb,
|
||||
"$Rn = $Rn_wb,@earlyclobber $Rn_wb",
|
||||
[(set GPRnopc:$Rn_wb,
|
||||
(post_truncsti16 rGPR:$Rt, GPRnopc:$Rn, t2am_imm8_offset:$addr))]>;
|
||||
|
||||
def t2STRB_PRE : T2Iidxldst<0, 0b00, 0, 1, (outs GPRnopc:$base_wb),
|
||||
def t2STRB_PRE : T2Ipreldst<0, 0b00, 0, 1, (outs GPRnopc:$Rn_wb),
|
||||
(ins rGPR:$Rt, GPRnopc:$Rn, t2am_imm8_offset:$addr),
|
||||
AddrModeT2_i8, IndexModePre, IIC_iStore_bh_iu,
|
||||
"strb", "\t$Rt, [$Rn, $addr]!",
|
||||
"$Rn = $base_wb,@earlyclobber $base_wb",
|
||||
[(set GPRnopc:$base_wb,
|
||||
"$Rn = $Rn_wb,@earlyclobber $Rn_wb",
|
||||
[(set GPRnopc:$Rn_wb,
|
||||
(pre_truncsti8 rGPR:$Rt, GPRnopc:$Rn, t2am_imm8_offset:$addr))]>;
|
||||
|
||||
def t2STRB_POST : T2Iidxldst<0, 0b00, 0, 0, (outs GPRnopc:$base_wb),
|
||||
def t2STRB_POST : T2Ipostldst<0, 0b00, 0, 0, (outs GPRnopc:$Rn_wb),
|
||||
(ins rGPR:$Rt, GPRnopc:$Rn, t2am_imm8_offset:$addr),
|
||||
AddrModeT2_i8, IndexModePost, IIC_iStore_bh_iu,
|
||||
"strb", "\t$Rt, [$Rn], $addr",
|
||||
"$Rn = $base_wb,@earlyclobber $base_wb",
|
||||
[(set GPRnopc:$base_wb,
|
||||
"$Rn = $Rn_wb,@earlyclobber $Rn_wb",
|
||||
[(set GPRnopc:$Rn_wb,
|
||||
(post_truncsti8 rGPR:$Rt, GPRnopc:$Rn, t2am_imm8_offset:$addr))]>;
|
||||
|
||||
// STRT, STRBT, STRHT all have offset mode (PUW=0b110) and are for disassembly
|
||||
|
@ -158,6 +158,8 @@ class ARMAsmParser : public MCTargetAsmParser {
|
||||
OperandMatchResultTy parseAM3Offset(SmallVectorImpl<MCParsedAsmOperand*>&);
|
||||
|
||||
// Asm Match Converter Methods
|
||||
bool cvtLdWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
|
||||
const SmallVectorImpl<MCParsedAsmOperand*> &);
|
||||
bool cvtLdWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
|
||||
const SmallVectorImpl<MCParsedAsmOperand*> &);
|
||||
bool cvtLdWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
|
||||
@ -2398,6 +2400,22 @@ parseAM3Offset(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
|
||||
return MatchOperand_Success;
|
||||
}
|
||||
|
||||
/// cvtLdWriteBackRegT2AddrModeImm8 - Convert parsed operands to MCInst.
|
||||
/// Needed here because the Asm Gen Matcher can't handle properly tied operands
|
||||
/// when they refer multiple MIOperands inside a single one.
|
||||
bool ARMAsmParser::
|
||||
cvtLdWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
|
||||
const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
|
||||
((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
|
||||
|
||||
// Create a writeback register dummy placeholder.
|
||||
Inst.addOperand(MCOperand::CreateImm(0));
|
||||
|
||||
((ARMOperand*)Operands[3])->addMemImm8OffsetOperands(Inst, 2);
|
||||
((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
|
||||
return true;
|
||||
}
|
||||
|
||||
/// cvtLdWriteBackRegAddrMode2 - Convert parsed operands to MCInst.
|
||||
/// Needed here because the Asm Gen Matcher can't handle properly tied operands
|
||||
/// when they refer multiple MIOperands inside a single one.
|
||||
|
@ -548,6 +548,9 @@ _func:
|
||||
ldr r8, [r8, r2, lsl #2]
|
||||
ldr r7, [sp, r2, lsl #1]
|
||||
ldr r7, [sp, r2, lsl #0]
|
||||
ldr r2, [r4, #255]!
|
||||
ldr r8, [sp, #4]!
|
||||
ldr lr, [sp, #-4]!
|
||||
|
||||
@ CHECK: ldr.w r1, [r8, r1] @ encoding: [0x58,0xf8,0x01,0x10]
|
||||
@ CHECK: ldr.w r4, [r5, r2] @ encoding: [0x55,0xf8,0x02,0x40]
|
||||
@ -555,6 +558,9 @@ _func:
|
||||
@ CHECK: ldr.w r8, [r8, r2, lsl #2] @ encoding: [0x58,0xf8,0x22,0x80]
|
||||
@ CHECK: ldr.w r7, [sp, r2, lsl #1] @ encoding: [0x5d,0xf8,0x12,0x70]
|
||||
@ CHECK: ldr.w r7, [sp, r2] @ encoding: [0x5d,0xf8,0x02,0x70]
|
||||
@ CHECK: ldr r2, [r4, #255]! @ encoding: [0x54,0xf8,0xff,0x2f]
|
||||
@ CHECK: ldr r8, [sp, #4]! @ encoding: [0x5d,0xf8,0x04,0x8f]
|
||||
@ CHECK: ldr lr, [sp, #-4]! @ encoding: [0x5d,0xf8,0x04,0xed]
|
||||
|
||||
|
||||
@------------------------------------------------------------------------------
|
||||
|
Loading…
Reference in New Issue
Block a user