mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-08-22 10:29:35 +00:00
ARM assembly parsing and encoding for LDC{2}{L}/STC{2}{L} instructions.
Fill out the rest of the encoding information, update to properly mark the LDC/STC instructions as predicable while the LDC2/STC2 instructions are not, and adjust the parser accordingly. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@141721 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
d8212b2916
commit
2bd0118472
@ -651,8 +651,10 @@ def postidx_imm8 : Operand<i32> {
|
||||
// 9 bit value:
|
||||
// {8} 1 is imm8 is non-negative. 0 otherwise.
|
||||
// {7-0} [0,255] imm8 value, scaled by 4.
|
||||
def PostIdxImm8s4AsmOperand : AsmOperandClass { let Name = "PostIdxImm8s4"; }
|
||||
def postidx_imm8s4 : Operand<i32> {
|
||||
let PrintMethod = "printPostIdxImm8s4Operand";
|
||||
let ParserMatchClass = PostIdxImm8s4AsmOperand;
|
||||
let MIOperandInfo = (ops i32imm);
|
||||
}
|
||||
|
||||
@ -4246,117 +4248,168 @@ def CDP2 : ABXI<0b1110, (outs), (ins p_imm:$cop, imm0_15:$opc1,
|
||||
|
||||
class ACI<dag oops, dag iops, string opc, string asm,
|
||||
IndexMode im = IndexModeNone>
|
||||
: InoP<oops, iops, AddrModeNone, 4, im, BrFrm, NoItinerary,
|
||||
: I<oops, iops, AddrModeNone, 4, im, BrFrm, NoItinerary,
|
||||
opc, asm, "", []> {
|
||||
let Inst{27-25} = 0b110;
|
||||
}
|
||||
|
||||
multiclass LdStCop<bits<4> op31_28, bit load, dag ops, string opc, string cond>{
|
||||
def _OFFSET : ACI<(outs),
|
||||
!con((ins p_imm:$cop, c_imm:$CRd, addrmode5:$addr), ops),
|
||||
!strconcat(opc, cond), "\t$cop, $CRd, $addr"> {
|
||||
let Inst{31-28} = op31_28;
|
||||
class ACInoP<dag oops, dag iops, string opc, string asm,
|
||||
IndexMode im = IndexModeNone>
|
||||
: InoP<oops, iops, AddrModeNone, 4, im, BrFrm, NoItinerary,
|
||||
opc, asm, "", []> {
|
||||
let Inst{31-28} = 0b1111;
|
||||
let Inst{27-25} = 0b110;
|
||||
}
|
||||
multiclass LdStCop<bit load, bit Dbit, string asm> {
|
||||
def _OFFSET : ACI<(outs), (ins p_imm:$cop, c_imm:$CRd, addrmode5:$addr),
|
||||
asm, "\t$cop, $CRd, $addr"> {
|
||||
bits<13> addr;
|
||||
bits<4> cop;
|
||||
bits<4> CRd;
|
||||
let Inst{24} = 1; // P = 1
|
||||
let Inst{23} = addr{8};
|
||||
let Inst{22} = Dbit;
|
||||
let Inst{21} = 0; // W = 0
|
||||
let Inst{22} = 0; // D = 0
|
||||
let Inst{20} = load;
|
||||
let Inst{19-16} = addr{12-9};
|
||||
let Inst{15-12} = CRd;
|
||||
let Inst{11-8} = cop;
|
||||
let Inst{7-0} = addr{7-0};
|
||||
let DecoderMethod = "DecodeCopMemInstruction";
|
||||
}
|
||||
|
||||
def _PRE : ACI<(outs),
|
||||
!con((ins p_imm:$cop, c_imm:$CRd, addrmode5:$addr), ops),
|
||||
!strconcat(opc, cond), "\t$cop, $CRd, $addr!", IndexModePre> {
|
||||
let Inst{31-28} = op31_28;
|
||||
def _PRE : ACI<(outs), (ins p_imm:$cop, c_imm:$CRd, addrmode5:$addr),
|
||||
asm, "\t$cop, $CRd, $addr!", IndexModePre> {
|
||||
bits<13> addr;
|
||||
bits<4> cop;
|
||||
bits<4> CRd;
|
||||
let Inst{24} = 1; // P = 1
|
||||
let Inst{23} = addr{8};
|
||||
let Inst{22} = Dbit;
|
||||
let Inst{21} = 1; // W = 1
|
||||
let Inst{22} = 0; // D = 0
|
||||
let Inst{20} = load;
|
||||
let Inst{19-16} = addr{12-9};
|
||||
let Inst{15-12} = CRd;
|
||||
let Inst{11-8} = cop;
|
||||
let Inst{7-0} = addr{7-0};
|
||||
let DecoderMethod = "DecodeCopMemInstruction";
|
||||
}
|
||||
|
||||
def _POST : ACI<(outs),
|
||||
!con((ins p_imm:$cop, c_imm:$CRd, addr_offset_none:$addr,
|
||||
postidx_imm8s4:$offset), ops),
|
||||
!strconcat(opc, cond), "\t$cop, $CRd, $addr, $offset",
|
||||
IndexModePost> {
|
||||
let Inst{31-28} = op31_28;
|
||||
def _POST: ACI<(outs), (ins p_imm:$cop, c_imm:$CRd, addr_offset_none:$addr,
|
||||
postidx_imm8s4:$offset),
|
||||
asm, "\t$cop, $CRd, $addr, $offset", IndexModePost> {
|
||||
bits<9> offset;
|
||||
bits<4> addr;
|
||||
bits<4> cop;
|
||||
bits<4> CRd;
|
||||
let Inst{24} = 0; // P = 0
|
||||
let Inst{23} = offset{8};
|
||||
let Inst{22} = Dbit;
|
||||
let Inst{21} = 1; // W = 1
|
||||
let Inst{22} = 0; // D = 0
|
||||
let Inst{20} = load;
|
||||
let Inst{19-16} = addr;
|
||||
let Inst{15-12} = CRd;
|
||||
let Inst{11-8} = cop;
|
||||
let Inst{7-0} = offset{7-0};
|
||||
let DecoderMethod = "DecodeCopMemInstruction";
|
||||
}
|
||||
|
||||
def _OPTION : ACI<(outs),
|
||||
!con((ins p_imm:$cop, c_imm:$CRd, addr_offset_none:$base,
|
||||
(ins p_imm:$cop, c_imm:$CRd, addr_offset_none:$addr,
|
||||
nohash_imm:$option),
|
||||
ops),
|
||||
!strconcat(opc, cond), "\t$cop, $CRd, $base, \\{$option\\}"> {
|
||||
let Inst{31-28} = op31_28;
|
||||
asm, "\t$cop, $CRd, $addr, \\{$option\\}"> {
|
||||
bits<8> option;
|
||||
bits<4> addr;
|
||||
bits<4> cop;
|
||||
bits<4> CRd;
|
||||
let Inst{24} = 0; // P = 0
|
||||
let Inst{23} = 1; // U = 1
|
||||
let Inst{22} = Dbit;
|
||||
let Inst{21} = 0; // W = 0
|
||||
let Inst{22} = 0; // D = 0
|
||||
let Inst{20} = load;
|
||||
let Inst{19-16} = addr;
|
||||
let Inst{15-12} = CRd;
|
||||
let Inst{11-8} = cop;
|
||||
let Inst{7-0} = option;
|
||||
let DecoderMethod = "DecodeCopMemInstruction";
|
||||
}
|
||||
|
||||
def L_OFFSET : ACI<(outs),
|
||||
!con((ins p_imm:$cop, c_imm:$CRd, addrmode5:$addr), ops),
|
||||
!strconcat(!strconcat(opc, "l"), cond), "\t$cop, $CRd, $addr"> {
|
||||
let Inst{31-28} = op31_28;
|
||||
}
|
||||
multiclass LdSt2Cop<bit load, bit Dbit, string asm> {
|
||||
def _OFFSET : ACInoP<(outs), (ins p_imm:$cop, c_imm:$CRd, addrmode5:$addr),
|
||||
asm, "\t$cop, $CRd, $addr"> {
|
||||
bits<13> addr;
|
||||
bits<4> cop;
|
||||
bits<4> CRd;
|
||||
let Inst{24} = 1; // P = 1
|
||||
let Inst{23} = addr{8};
|
||||
let Inst{22} = Dbit;
|
||||
let Inst{21} = 0; // W = 0
|
||||
let Inst{22} = 1; // D = 1
|
||||
let Inst{20} = load;
|
||||
let Inst{19-16} = addr{12-9};
|
||||
let Inst{15-12} = CRd;
|
||||
let Inst{11-8} = cop;
|
||||
let Inst{7-0} = addr{7-0};
|
||||
let DecoderMethod = "DecodeCopMemInstruction";
|
||||
}
|
||||
|
||||
def L_PRE : ACI<(outs),
|
||||
!con((ins p_imm:$cop, c_imm:$CRd, addrmode5:$addr), ops),
|
||||
!strconcat(!strconcat(opc, "l"), cond), "\t$cop, $CRd, $addr!",
|
||||
IndexModePre> {
|
||||
let Inst{31-28} = op31_28;
|
||||
def _PRE : ACInoP<(outs), (ins p_imm:$cop, c_imm:$CRd, addrmode5:$addr),
|
||||
asm, "\t$cop, $CRd, $addr!", IndexModePre> {
|
||||
bits<13> addr;
|
||||
bits<4> cop;
|
||||
bits<4> CRd;
|
||||
let Inst{24} = 1; // P = 1
|
||||
let Inst{23} = addr{8};
|
||||
let Inst{22} = Dbit;
|
||||
let Inst{21} = 1; // W = 1
|
||||
let Inst{22} = 1; // D = 1
|
||||
let Inst{20} = load;
|
||||
let Inst{19-16} = addr{12-9};
|
||||
let Inst{15-12} = CRd;
|
||||
let Inst{11-8} = cop;
|
||||
let Inst{7-0} = addr{7-0};
|
||||
let DecoderMethod = "DecodeCopMemInstruction";
|
||||
}
|
||||
|
||||
def L_POST : ACI<(outs),
|
||||
!con((ins p_imm:$cop, c_imm:$CRd, addr_offset_none:$addr,
|
||||
postidx_imm8s4:$offset), ops),
|
||||
!strconcat(!strconcat(opc, "l"), cond), "\t$cop, $CRd, $addr, $offset",
|
||||
IndexModePost> {
|
||||
let Inst{31-28} = op31_28;
|
||||
def _POST: ACInoP<(outs), (ins p_imm:$cop, c_imm:$CRd, addr_offset_none:$addr,
|
||||
postidx_imm8s4:$offset),
|
||||
asm, "\t$cop, $CRd, $addr, $offset", IndexModePost> {
|
||||
bits<9> offset;
|
||||
bits<4> addr;
|
||||
bits<4> cop;
|
||||
bits<4> CRd;
|
||||
let Inst{24} = 0; // P = 0
|
||||
let Inst{23} = offset{8};
|
||||
let Inst{22} = Dbit;
|
||||
let Inst{21} = 1; // W = 1
|
||||
let Inst{22} = 1; // D = 1
|
||||
let Inst{20} = load;
|
||||
let Inst{19-16} = addr;
|
||||
let Inst{15-12} = CRd;
|
||||
let Inst{11-8} = cop;
|
||||
let Inst{7-0} = offset{7-0};
|
||||
let DecoderMethod = "DecodeCopMemInstruction";
|
||||
}
|
||||
|
||||
def L_OPTION : ACI<(outs),
|
||||
!con((ins p_imm:$cop, c_imm:$CRd, addr_offset_none:$base,
|
||||
def _OPTION : ACInoP<(outs),
|
||||
(ins p_imm:$cop, c_imm:$CRd, addr_offset_none:$addr,
|
||||
nohash_imm:$option),
|
||||
ops),
|
||||
!strconcat(!strconcat(opc, "l"), cond),
|
||||
"\t$cop, $CRd, $base, \\{$option\\}"> {
|
||||
let Inst{31-28} = op31_28;
|
||||
asm, "\t$cop, $CRd, $addr, \\{$option\\}"> {
|
||||
bits<8> option;
|
||||
bits<4> addr;
|
||||
bits<4> cop;
|
||||
bits<4> CRd;
|
||||
let Inst{24} = 0; // P = 0
|
||||
let Inst{23} = 1; // U = 1
|
||||
let Inst{22} = Dbit;
|
||||
let Inst{21} = 0; // W = 0
|
||||
let Inst{22} = 1; // D = 1
|
||||
let Inst{20} = load;
|
||||
let Inst{19-16} = addr;
|
||||
let Inst{15-12} = CRd;
|
||||
let Inst{11-8} = cop;
|
||||
let Inst{7-0} = option;
|
||||
let DecoderMethod = "DecodeCopMemInstruction";
|
||||
}
|
||||
}
|
||||
|
||||
defm LDC : LdStCop<{?,?,?,?}, 1, (ins pred:$p), "ldc", "${p}">;
|
||||
defm LDC2 : LdStCop<0b1111, 1, (ins), "ldc2", "">;
|
||||
defm STC : LdStCop<{?,?,?,?}, 0, (ins pred:$p), "stc", "${p}">;
|
||||
defm STC2 : LdStCop<0b1111, 0, (ins), "stc2", "">;
|
||||
defm LDC : LdStCop <1, 0, "ldc">;
|
||||
defm LDCL : LdStCop <1, 1, "ldcl">;
|
||||
defm STC : LdStCop <0, 0, "stc">;
|
||||
defm STCL : LdStCop <0, 1, "stcl">;
|
||||
defm LDC2 : LdSt2Cop<1, 0, "ldc2">;
|
||||
defm LDC2L : LdSt2Cop<1, 1, "ldc2l">;
|
||||
defm STC2 : LdSt2Cop<0, 0, "stc2">;
|
||||
defm STC2L : LdSt2Cop<0, 1, "stc2l">;
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Move between coprocessor and ARM core register.
|
||||
|
@ -874,6 +874,15 @@ public:
|
||||
int64_t Val = CE->getValue();
|
||||
return (Val > -256 && Val < 256) || (Val == INT32_MIN);
|
||||
}
|
||||
bool isPostIdxImm8s4() const {
|
||||
if (Kind != k_Immediate)
|
||||
return false;
|
||||
const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
|
||||
if (!CE) return false;
|
||||
int64_t Val = CE->getValue();
|
||||
return ((Val & 3) == 0 && Val >= -1020 && Val <= 1020) ||
|
||||
(Val == INT32_MIN);
|
||||
}
|
||||
|
||||
bool isMSRMask() const { return Kind == k_MSRMask; }
|
||||
bool isProcIFlags() const { return Kind == k_ProcIFlags; }
|
||||
@ -1356,6 +1365,18 @@ public:
|
||||
Inst.addOperand(MCOperand::CreateImm(Imm));
|
||||
}
|
||||
|
||||
void addPostIdxImm8s4Operands(MCInst &Inst, unsigned N) const {
|
||||
assert(N == 1 && "Invalid number of operands!");
|
||||
const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
|
||||
assert(CE && "non-constant post-idx-imm8s4 operand!");
|
||||
int Imm = CE->getValue();
|
||||
bool isAdd = Imm >= 0;
|
||||
if (Imm == INT32_MIN) Imm = 0;
|
||||
// Immediate is scaled by 4.
|
||||
Imm = ((Imm < 0 ? -Imm : Imm) / 4) | (int)isAdd << 8;
|
||||
Inst.addOperand(MCOperand::CreateImm(Imm));
|
||||
}
|
||||
|
||||
void addPostIdxRegOperands(MCInst &Inst, unsigned N) const {
|
||||
assert(N == 2 && "Invalid number of operands!");
|
||||
Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum));
|
||||
@ -3539,8 +3560,9 @@ getMnemonicAcceptInfo(StringRef Mnemonic, bool &CanAcceptCarrySet,
|
||||
Mnemonic == "dsb" || Mnemonic == "isb" || Mnemonic == "setend" ||
|
||||
(Mnemonic == "clrex" && !isThumb()) ||
|
||||
(Mnemonic == "nop" && isThumbOne()) ||
|
||||
((Mnemonic == "pld" || Mnemonic == "pli" || Mnemonic == "pldw") &&
|
||||
!isThumb()) ||
|
||||
((Mnemonic == "pld" || Mnemonic == "pli" || Mnemonic == "pldw" ||
|
||||
Mnemonic == "ldc2" || Mnemonic == "ldc2l" ||
|
||||
Mnemonic == "stc2" || Mnemonic == "stc2l") && !isThumb()) ||
|
||||
((Mnemonic.startswith("rfe") || Mnemonic.startswith("srs")) &&
|
||||
!isThumb()) ||
|
||||
Mnemonic.startswith("cps") || (Mnemonic == "movs" && isThumbOne())) {
|
||||
|
@ -642,6 +642,87 @@ Lforward:
|
||||
@ CHECK: isb sy @ encoding: [0x6f,0xf0,0x7f,0xf5]
|
||||
|
||||
|
||||
@------------------------------------------------------------------------------
|
||||
@ LDC{L}/LDC2{L}
|
||||
@------------------------------------------------------------------------------
|
||||
ldc2 p0, c8, [r1, #4]
|
||||
ldc2 p1, c7, [r2]
|
||||
ldc2 p2, c6, [r3, #-224]
|
||||
ldc2 p3, c5, [r4, #-120]!
|
||||
ldc2 p4, c4, [r5], #16
|
||||
ldc2 p5, c3, [r6], #-72
|
||||
ldc2l p6, c2, [r7, #4]
|
||||
ldc2l p7, c1, [r8]
|
||||
ldc2l p8, c0, [r9, #-224]
|
||||
ldc2l p9, c1, [r10, #-120]!
|
||||
ldc2l p10, c2, [r11], #16
|
||||
ldc2l p11, c3, [r12], #-72
|
||||
|
||||
ldc p12, c4, [r0, #4]
|
||||
ldc p13, c5, [r1]
|
||||
ldc p14, c6, [r2, #-224]
|
||||
ldc p15, c7, [r3, #-120]!
|
||||
ldc p5, c8, [r4], #16
|
||||
ldc p4, c9, [r5], #-72
|
||||
ldcl p3, c10, [r6, #4]
|
||||
ldcl p2, c11, [r7]
|
||||
ldcl p1, c12, [r8, #-224]
|
||||
ldcl p0, c13, [r9, #-120]!
|
||||
ldcl p6, c14, [r10], #16
|
||||
ldcl p7, c15, [r11], #-72
|
||||
|
||||
ldclo p12, c4, [r0, #4]
|
||||
ldchi p13, c5, [r1]
|
||||
ldccs p14, c6, [r2, #-224]
|
||||
ldccc p15, c7, [r3, #-120]!
|
||||
ldceq p5, c8, [r4], #16
|
||||
ldcgt p4, c9, [r5], #-72
|
||||
ldcllt p3, c10, [r6, #4]
|
||||
ldclge p2, c11, [r7]
|
||||
ldclle p1, c12, [r8, #-224]
|
||||
ldclne p0, c13, [r9, #-120]!
|
||||
ldcleq p6, c14, [r10], #16
|
||||
ldclhi p7, c15, [r11], #-72
|
||||
|
||||
@ CHECK: ldc2 p0, c8, [r1, #4] @ encoding: [0x01,0x80,0x91,0xfd]
|
||||
@ CHECK: ldc2 p1, c7, [r2] @ encoding: [0x00,0x71,0x92,0xfd]
|
||||
@ CHECK: ldc2 p2, c6, [r3, #-224] @ encoding: [0x38,0x62,0x13,0xfd]
|
||||
@ CHECK: ldc2 p3, c5, [r4, #-120]! @ encoding: [0x1e,0x53,0x34,0xfd]
|
||||
@ CHECK: ldc2 p4, c4, [r5], #16 @ encoding: [0x04,0x44,0xb5,0xfc]
|
||||
@ CHECK: ldc2 p5, c3, [r6], #-72 @ encoding: [0x12,0x35,0x36,0xfc]
|
||||
@ CHECK: ldc2l p6, c2, [r7, #4] @ encoding: [0x01,0x26,0xd7,0xfd]
|
||||
@ CHECK: ldc2l p7, c1, [r8] @ encoding: [0x00,0x17,0xd8,0xfd]
|
||||
@ CHECK: ldc2l p8, c0, [r9, #-224] @ encoding: [0x38,0x08,0x59,0xfd]
|
||||
@ CHECK: ldc2l p9, c1, [r10, #-120]! @ encoding: [0x1e,0x19,0x7a,0xfd]
|
||||
@ CHECK: ldc2l p10, c2, [r11], #16 @ encoding: [0x04,0x2a,0xfb,0xfc]
|
||||
@ CHECK: ldc2l p11, c3, [r12], #-72 @ encoding: [0x12,0x3b,0x7c,0xfc]
|
||||
|
||||
@ CHECK: ldc p12, c4, [r0, #4] @ encoding: [0x01,0x4c,0x90,0xed]
|
||||
@ CHECK: ldc p13, c5, [r1] @ encoding: [0x00,0x5d,0x91,0xed]
|
||||
@ CHECK: ldc p14, c6, [r2, #-224] @ encoding: [0x38,0x6e,0x12,0xed]
|
||||
@ CHECK: ldc p15, c7, [r3, #-120]! @ encoding: [0x1e,0x7f,0x33,0xed]
|
||||
@ CHECK: ldc p5, c8, [r4], #16 @ encoding: [0x04,0x85,0xb4,0xec]
|
||||
@ CHECK: ldc p4, c9, [r5], #-72 @ encoding: [0x12,0x94,0x35,0xec]
|
||||
@ CHECK: ldcl p3, c10, [r6, #4] @ encoding: [0x01,0xa3,0xd6,0xed]
|
||||
@ CHECK: ldcl p2, c11, [r7] @ encoding: [0x00,0xb2,0xd7,0xed]
|
||||
@ CHECK: ldcl p1, c12, [r8, #-224] @ encoding: [0x38,0xc1,0x58,0xed]
|
||||
@ CHECK: ldcl p0, c13, [r9, #-120]! @ encoding: [0x1e,0xd0,0x79,0xed]
|
||||
@ CHECK: ldcl p6, c14, [r10], #16 @ encoding: [0x04,0xe6,0xfa,0xec]
|
||||
@ CHECK: ldcl p7, c15, [r11], #-72 @ encoding: [0x12,0xf7,0x7b,0xec]
|
||||
|
||||
@ CHECK: ldclo p12, c4, [r0, #4] @ encoding: [0x01,0x4c,0x90,0x3d]
|
||||
@ CHECK: ldchi p13, c5, [r1] @ encoding: [0x00,0x5d,0x91,0x8d]
|
||||
@ CHECK: ldchs p14, c6, [r2, #-224] @ encoding: [0x38,0x6e,0x12,0x2d]
|
||||
@ CHECK: ldclo p15, c7, [r3, #-120]! @ encoding: [0x1e,0x7f,0x33,0x3d]
|
||||
@ CHECK: ldceq p5, c8, [r4], #16 @ encoding: [0x04,0x85,0xb4,0x0c]
|
||||
@ CHECK: ldcgt p4, c9, [r5], #-72 @ encoding: [0x12,0x94,0x35,0xcc]
|
||||
@ CHECK: ldcllt p3, c10, [r6, #4] @ encoding: [0x01,0xa3,0xd6,0xbd]
|
||||
@ CHECK: ldclge p2, c11, [r7] @ encoding: [0x00,0xb2,0xd7,0xad]
|
||||
@ CHECK: ldclle p1, c12, [r8, #-224] @ encoding: [0x38,0xc1,0x58,0xdd]
|
||||
@ CHECK: ldclne p0, c13, [r9, #-120]! @ encoding: [0x1e,0xd0,0x79,0x1d]
|
||||
@ CHECK: ldcleq p6, c14, [r10], #16 @ encoding: [0x04,0xe6,0xfa,0x0c]
|
||||
@ CHECK: ldclhi p7, c15, [r11], #-72 @ encoding: [0x12,0xf7,0x7b,0x8c]
|
||||
|
||||
|
||||
@------------------------------------------------------------------------------
|
||||
@ LDM*
|
||||
|
Loading…
Reference in New Issue
Block a user