mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2024-11-28 16:11:29 +00:00
[ARC] Add instruction subset for the ARC backend.
Reviewers: petecoup, kparzysz Reviewed By: petecoup Subscribers: llvm-commits Differential Revision: https://reviews.llvm.org/D37983 llvm-svn: 319609
This commit is contained in:
parent
3ea964090a
commit
f665f6a279
@ -17,18 +17,23 @@ class Encoding64 {
|
||||
}
|
||||
|
||||
// Address operands
|
||||
def immU6 : Operand<i32>, PatLeaf<(imm), [{
|
||||
return isUInt<6>(N->getSExtValue()); }]> {
|
||||
|
||||
class immU<int BSz> : Operand<i32>, PatLeaf<(imm),
|
||||
"\n return isUInt<"#BSz#">(N->getSExtValue());"> {
|
||||
}
|
||||
|
||||
def immS12 : Operand<i32>, PatLeaf<(imm), [{
|
||||
return isInt<12>(N->getSExtValue()); }]> {
|
||||
let DecoderMethod = "DecodeS12Operand";
|
||||
def immU6 : immU<6>;
|
||||
|
||||
class immS<int BSz> : Operand<i32>, PatLeaf<(imm),
|
||||
"\n return isInt<"#BSz#">(N->getSExtValue());"> {
|
||||
let DecoderMethod = "DecodeSignedOperand<"#BSz#">";
|
||||
}
|
||||
|
||||
def immS9 : Operand<i32>, PatLeaf<(imm), [{
|
||||
return isInt<9>(N->getSExtValue()); }]> {
|
||||
let DecoderMethod = "DecodeS9Operand";
|
||||
// e.g. s3 field may encode the signed integers values -1 .. 6
|
||||
// using binary codes 111, 000, 001, 010, 011, 100, 101, and 110, respectively
|
||||
class immC<int BSz> : Operand<i32>, PatLeaf<(imm),
|
||||
"\n return isInt<"#BSz#">(N->getSExtValue());"> {
|
||||
let DecoderMethod = "DecodeFromCyclicRange<"#BSz#">";
|
||||
}
|
||||
|
||||
def MEMii : Operand<i32> {
|
||||
@ -36,7 +41,7 @@ def MEMii : Operand<i32> {
|
||||
}
|
||||
|
||||
def MEMrs9 : Operand<iAny> {
|
||||
let MIOperandInfo = (ops GPR32:$B, immS9:$S9);
|
||||
let MIOperandInfo = (ops GPR32:$B, immS<9>:$S9);
|
||||
let PrintMethod = "printMemOperandRI";
|
||||
let DecoderMethod = "DecodeMEMrs9";
|
||||
}
|
||||
@ -47,6 +52,10 @@ def MEMrlimm : Operand<iAny> {
|
||||
let DecoderMethod = "DecodeMEMrlimm";
|
||||
}
|
||||
|
||||
def GPR32Reduced : Operand<iAny> {
|
||||
let DecoderMethod = "DecodeGBR32ShortRegister";
|
||||
}
|
||||
|
||||
class InstARC<int sz, dag outs, dag ins, string asmstr, list<dag> pattern>
|
||||
: Instruction, Encoding64 {
|
||||
|
||||
@ -153,7 +162,6 @@ class F32_BR1_BL_COND<dag outs, dag ins, string asmstr, list<dag> pat> :
|
||||
let Inst{17} = 0;
|
||||
}
|
||||
|
||||
|
||||
// BRcc targets have limited 9-bit range. These are for compare and branch
|
||||
// in single instruction. Their targets are 2-byte aligned. They also use
|
||||
// a different (3-bit) set of condition codes.
|
||||
@ -464,6 +472,342 @@ class F32_ST_LIMM<bit di, bits<2> zz, dag outs, dag ins,
|
||||
let DecoderMethod = "DecodeStLImmInstruction";
|
||||
}
|
||||
|
||||
// Compact Move/Load.
|
||||
// |10|9|8|7|6|5|4|3|2|1|0|
|
||||
// | |h | |i|H |
|
||||
class F16_COMPACT<bits<1> i, dag outs, dag ins,
|
||||
string asmstr> :
|
||||
InstARC<2, outs, ins, asmstr, []> {
|
||||
|
||||
bits<5> h;
|
||||
|
||||
let Inst{15-11} = 0b01000;
|
||||
let Inst{7-5} = h{2-0};
|
||||
let Inst{2} = i;
|
||||
let Inst{1-0} = h{4-3};
|
||||
}
|
||||
|
||||
// Compact Load/Add/Sub.
|
||||
class F16_LD_ADD_SUB<dag outs, dag ins, string asmstr> :
|
||||
InstARC<2, outs, ins, asmstr, []> {
|
||||
|
||||
bits<3> b;
|
||||
let Inst{15-11} = 0b01001;
|
||||
let Inst{10-8} = b;
|
||||
}
|
||||
|
||||
class F16_LD_SUB<bit i, string asmstr> :
|
||||
F16_LD_ADD_SUB<(outs GPR32:$a), (ins GPR32:$b, GPR32:$c),
|
||||
asmstr> {
|
||||
|
||||
bits<3> a;
|
||||
bits<3> c;
|
||||
|
||||
let Inst{7-5} = c;
|
||||
let Inst{4} = i;
|
||||
let Inst{3} = 0;
|
||||
let Inst{2-0} = a;
|
||||
}
|
||||
|
||||
class F16_ADD :
|
||||
F16_LD_ADD_SUB<(outs GPR32:$r), (ins GPR32:$b, immU<6>:$u6),
|
||||
"add_s\t$r, $b, $u6"> {
|
||||
|
||||
bit r;
|
||||
bits<6> u6;
|
||||
|
||||
let Inst{7} = r;
|
||||
let Inst{6-4} = u6{5-3};
|
||||
let Inst{3} = 1;
|
||||
let Inst{2-0} = u6{2-0};
|
||||
}
|
||||
|
||||
// Compact Load/Store.
|
||||
class F16_LD_ST_1<dag outs, dag ins, string asmstr> :
|
||||
InstARC<2, outs, ins, asmstr, []> {
|
||||
|
||||
let Inst{15-11} = 0b01010;
|
||||
}
|
||||
|
||||
class F16_LD_ST_s11<bit i, string asmstr> :
|
||||
F16_LD_ST_1<(outs), (ins immS<11>:$s11), asmstr> {
|
||||
|
||||
bits<11> s11;
|
||||
|
||||
let Inst{10-5} = s11{10-5};
|
||||
let Inst{4} = i;
|
||||
let Inst{3} = 0;
|
||||
let Inst{2-0} = s11{4-2};
|
||||
let s11{1-0} = 0b00;
|
||||
}
|
||||
|
||||
class F16_LDI_u7 :
|
||||
F16_LD_ST_1<(outs GPR32:$b), (ins immU<7>:$u7),
|
||||
"ldi_s\t$b, [$u7]"> {
|
||||
|
||||
bits<3> b;
|
||||
bits<7> u7;
|
||||
|
||||
let Inst{10-8} = b;
|
||||
let Inst{7-4} = u7{6-3};
|
||||
let Inst{3} = 1;
|
||||
let Inst{2-0} = u7{2-0};
|
||||
}
|
||||
|
||||
// Indexed Jump or Execute.
|
||||
class F16_JLI_EI<bit i, string asmstr> :
|
||||
InstARC<2, (outs), (ins immU<10>:$u10),
|
||||
!strconcat(asmstr, "\t$u10"), []> {
|
||||
|
||||
bits<10> u10;
|
||||
|
||||
let Inst{15-11} = 0b01011;
|
||||
let Inst{10} = i;
|
||||
let Inst{9-0} = u10;
|
||||
}
|
||||
|
||||
// Load/Add Register-Register.
|
||||
class F16_LD_ADD_RR<bits<2> i, string asmstr> :
|
||||
InstARC<2, (outs GPR32:$a), (ins GPR32:$b, GPR32:$c),
|
||||
asmstr, []> {
|
||||
|
||||
bits<3> a;
|
||||
bits<3> b;
|
||||
bits<3> c;
|
||||
|
||||
let Inst{15-11} = 0b01100;
|
||||
let Inst{10-8} = b;
|
||||
let Inst{7-5} = c;
|
||||
let Inst{4-3} = i;
|
||||
let Inst{2-0} = a;
|
||||
}
|
||||
|
||||
// Load/Add GP-Relative.
|
||||
class F16_GP_LD_ADD<bits<2> i, dag ins, string asmstr> :
|
||||
InstARC<2, (outs), ins, asmstr, []> {
|
||||
|
||||
let Inst{15-11} = 0b11001;
|
||||
let Inst{10-9} = i;
|
||||
}
|
||||
|
||||
// Add/Sub/Shift Register-Immediate.
|
||||
// |10|9|8|7|6|5|4|3|2|1|0|
|
||||
// |b |c |i |u |
|
||||
class F16_ADD_IMM<bits<2> i, string asmstr> :
|
||||
InstARC<2, (outs GPR32:$c), (ins GPR32:$b, immU<3>:$u3),
|
||||
!strconcat(asmstr, "\t$c, $b, $u3"), []> {
|
||||
|
||||
bits<3> b;
|
||||
bits<3> c;
|
||||
bits<3> u3;
|
||||
|
||||
let Inst{15-11} = 0b01101;
|
||||
let Inst{10-8} = b;
|
||||
let Inst{7-5} = c;
|
||||
let Inst{4-3} = i;
|
||||
let Inst{2-0} = u3;
|
||||
}
|
||||
|
||||
// Dual Register Operations.
|
||||
// |10|9|8|7|6|5|4|3|2|1|0|
|
||||
// |b/s |h |i |H |
|
||||
class F16_OP_HREG<bits<3> i, dag outs, dag ins, string asmstr> :
|
||||
InstARC<2, outs, ins, asmstr, []> {
|
||||
|
||||
bits<3> b_s3;
|
||||
bits<5> h;
|
||||
|
||||
let Inst{15-11} = 0b01110;
|
||||
let Inst{10-8} = b_s3;
|
||||
let Inst{7-5} = h{2-0};
|
||||
let Inst{4-2} = i;
|
||||
let Inst{1-0} = h{4-3};
|
||||
}
|
||||
|
||||
class F16_OP_HREG30<bits<3> i, dag outs, dag ins, string asmstr> :
|
||||
F16_OP_HREG<i, outs, ins, asmstr> {
|
||||
|
||||
bits<5> LImmReg = 0b11110;
|
||||
let Inst{7-5} = LImmReg{2-0};
|
||||
let Inst{1-0} = LImmReg{4-3};
|
||||
}
|
||||
|
||||
class F16_OP_HREG_LIMM<bits<3> i, dag outs, dag ins, string asmstr> :
|
||||
F16_OP_HREG30<i, outs, ins, asmstr> {
|
||||
|
||||
bits<32> LImm;
|
||||
let Inst{47-16} = LImm;
|
||||
let Size = 6;
|
||||
}
|
||||
|
||||
// General compact DOP format.
|
||||
class F16_GEN_DOP_BASE<bits<5> i, dag outs, dag ins, string asmstr> :
|
||||
InstARC<2, outs, ins, asmstr, []> {
|
||||
|
||||
bits<3> b;
|
||||
bits<3> c;
|
||||
let Inst{15-11} = 0b01111;
|
||||
let Inst{10-8} = b;
|
||||
let Inst{7-5} = c;
|
||||
let Inst{4-0} = i;
|
||||
}
|
||||
|
||||
class F16_GEN_DOP<bits<5> i, string asmstr> :
|
||||
F16_GEN_DOP_BASE<i, (outs GPR32:$b), (ins GPR32:$c),
|
||||
!strconcat(asmstr, "\t$b, $b, $c")>;
|
||||
|
||||
class F16_GEN_DOP_NODST<bits<5> i, string asmstr> :
|
||||
F16_GEN_DOP_BASE<i, (outs), (ins GPR32:$b, GPR32:$c),
|
||||
!strconcat(asmstr, "\t$b, $c")>;
|
||||
|
||||
class F16_GEN_DOP_SINGLESRC<bits<5> i, string asmstr> :
|
||||
F16_GEN_DOP_BASE<i, (outs GPR32:$b), (ins GPR32:$c),
|
||||
!strconcat(asmstr, "\t$b, $c")>;
|
||||
|
||||
class F16_GEN_SOP_BASE<bits<3> i, dag outs, dag ins, string asmstr> :
|
||||
F16_GEN_DOP_BASE<0b00000, outs, ins, asmstr> {
|
||||
|
||||
let c = i;
|
||||
}
|
||||
|
||||
class F16_GEN_SOP<bits<3> i, string asmstr> :
|
||||
F16_GEN_SOP_BASE<i, (outs), (ins GPR32:$b), asmstr>;
|
||||
|
||||
class F16_GEN_ZOP<bits<3> i, string asmstr> :
|
||||
F16_GEN_SOP_BASE<0b111, (outs), (ins), asmstr> {
|
||||
|
||||
let b = i;
|
||||
}
|
||||
|
||||
// Compact Load/Store with Offset Format.
|
||||
class F16_LD_ST_OFF<bits<5> opc, dag outs, dag ins, string asmstr> :
|
||||
InstARC<2, outs, ins, !strconcat(asmstr, "\t$c, [$b, $off]"), []> {
|
||||
|
||||
bits<3> b;
|
||||
bits<3> c;
|
||||
let Inst{15-11} = opc;
|
||||
let Inst{10-8} = b;
|
||||
let Inst{7-5} = c;
|
||||
}
|
||||
|
||||
class F16_LD_ST_WORD_OFF<bits<5> opc, dag outs, dag ins, string asmstr> :
|
||||
F16_LD_ST_OFF<opc, outs, ins, asmstr> {
|
||||
|
||||
bits<7> off;
|
||||
let Inst{4-0} = off{6-2};
|
||||
let off{1-0} = 0b00;
|
||||
}
|
||||
|
||||
class F16_LD_ST_HALF_OFF<bits<5> opc, dag outs, dag ins, string asmstr> :
|
||||
F16_LD_ST_OFF<opc, outs, ins, asmstr> {
|
||||
|
||||
bits<6> off;
|
||||
let Inst{4-0} = off{5-1};
|
||||
let off{0} = 0b0;
|
||||
}
|
||||
|
||||
class F16_LD_ST_BYTE_OFF<bits<5> opc, dag outs, dag ins, string asmstr> :
|
||||
F16_LD_ST_OFF<opc, outs, ins, asmstr> {
|
||||
|
||||
bits<5> off;
|
||||
let Inst{4-0} = off;
|
||||
}
|
||||
|
||||
// Shift/Subtract/Bit Immediate.
|
||||
// |10|9|8|7|6|5|4|3|2|1|0|
|
||||
// |b |i |u |
|
||||
class F16_SH_SUB_BIT<bits<3> i, string asmstr> :
|
||||
InstARC<2, (outs), (ins GPR32:$b, immU<5>:$u5), asmstr, []> {
|
||||
|
||||
bits<3> b;
|
||||
bits<5> u5;
|
||||
|
||||
let Inst{15-11} = 0b10111;
|
||||
let Inst{10-8} = b;
|
||||
let Inst{7-5} = i;
|
||||
let Inst{4-0} = u5;
|
||||
}
|
||||
|
||||
class F16_SH_SUB_BIT_DST<bits<3> i, string asmstr> :
|
||||
F16_SH_SUB_BIT<i, !strconcat(asmstr, "\t$b, $b, $u5")>;
|
||||
|
||||
// 16-bit stack-based operations.
|
||||
// |10|9|8|7|6|5|4|3|2|1|0|
|
||||
// |b |i |u |
|
||||
class F16_SP_OPS<bits<3> i,
|
||||
dag outs, dag ins, string asmstr> :
|
||||
InstARC<2, outs, ins, asmstr, []> {
|
||||
|
||||
bits<3> fieldB;
|
||||
bits<5> fieldU;
|
||||
|
||||
let Inst{15-11} = 0b11000;
|
||||
let Inst{10-8} = fieldB;
|
||||
let Inst{7-5} = i;
|
||||
let Inst{4-0} = fieldU;
|
||||
}
|
||||
|
||||
class F16_SP_OPS_u7_aligned<bits<3> i,
|
||||
dag outs, dag ins, string asmstr> :
|
||||
F16_SP_OPS<i, outs, ins, asmstr> {
|
||||
|
||||
bits<3> b3;
|
||||
bits<7> u7;
|
||||
|
||||
let fieldB = b3;
|
||||
let fieldU = u7{6-2};
|
||||
let u7{1-0} = 0b00;
|
||||
}
|
||||
|
||||
class F16_SP_OPS_bconst<bits<3> b, string asmop> :
|
||||
F16_SP_OPS_u7_aligned<0b101,
|
||||
(outs), (ins immU<7>:$u7),
|
||||
!strconcat(asmop, "\t%sp, %sp, $u7")> {
|
||||
|
||||
let fieldB = b;
|
||||
}
|
||||
|
||||
class F16_SP_OPS_uconst<bits<3> i,
|
||||
dag outs, dag ins, string asmop> :
|
||||
F16_SP_OPS_u7_aligned<i, outs, ins,
|
||||
!strconcat(asmop, "\t$b3")> {
|
||||
|
||||
let fieldU = 0b00001;
|
||||
}
|
||||
|
||||
class F16_SP_OPS_buconst<bits<3> i, string asmop> :
|
||||
F16_SP_OPS_u7_aligned<i, (outs), (ins),
|
||||
!strconcat(asmop, "\t%blink")> {
|
||||
|
||||
let fieldB = 0x000;
|
||||
let fieldU = 0b10001;
|
||||
}
|
||||
|
||||
class F16_SP_LD<bits<3> i, string asmop> : F16_SP_OPS_u7_aligned<i,
|
||||
(outs GPR32Reduced:$b3), (ins immU<7>:$u7),
|
||||
!strconcat(asmop, "\t$b3, [%sp, $u7]")>;
|
||||
|
||||
class F16_SP_ST<bits<3> i, string asmop> : F16_SP_OPS_u7_aligned<i,
|
||||
(outs), (ins GPR32Reduced:$b3, immU<7>:$u7),
|
||||
!strconcat(asmop, "\t$b3, [%sp, $u7]")>;
|
||||
|
||||
// Compact MOV/ADD/CMP Immediate Format.
|
||||
class F16_OP_IMM<bits<5> opc, dag outs, dag ins, string asmstr> :
|
||||
InstARC<2, outs, ins, asmstr, []> {
|
||||
|
||||
bits<3> b;
|
||||
let Inst{15-11} = opc;
|
||||
let Inst{10-8} = b;
|
||||
}
|
||||
|
||||
class F16_OP_U7<bit i, string asmstr> :
|
||||
F16_OP_IMM<0b11100, (outs GPR32:$b), (ins immU<7>:$u7), asmstr> {
|
||||
|
||||
bits<7> u7;
|
||||
let Inst{7} = i;
|
||||
let Inst{6-0} = u7;
|
||||
}
|
||||
|
||||
// Special types for different instruction operands.
|
||||
def cmovpred : Operand<i32>, PredicateOp,
|
||||
ComplexPattern<i32, 2, "SelectCMOVPred"> {
|
||||
@ -481,28 +825,67 @@ def brccond : Operand<i32> {
|
||||
let PrintMethod = "printBRCCPredicateOperand";
|
||||
}
|
||||
|
||||
// Branch targets of different offset sizes.
|
||||
def btarget : Operand<OtherVT> {
|
||||
// Branch/call targets of different offset sizes.
|
||||
class BCTarget<ValueType vt> : Operand<vt> {
|
||||
let OperandType = "OPERAND_PCREL";
|
||||
}
|
||||
|
||||
def btargetS9 : Operand<OtherVT> {
|
||||
let OperandType = "OPERAND_PCREL";
|
||||
let DecoderMethod = "DecodeBranchTargetS9";
|
||||
def btarget : BCTarget<OtherVT>;
|
||||
|
||||
class BCTargetSigned<ValueType vt, int BSz> : BCTarget<vt> {
|
||||
let DecoderMethod = "DecodeBranchTargetS<"#BSz#">";
|
||||
}
|
||||
|
||||
def btargetS21 : Operand<OtherVT> {
|
||||
let OperandType = "OPERAND_PCREL";
|
||||
let DecoderMethod = "DecodeBranchTargetS21";
|
||||
class BranchTargetS<int BSz> : BCTargetSigned<OtherVT, BSz>;
|
||||
def btargetS7 : BranchTargetS<7>;
|
||||
def btargetS8 : BranchTargetS<8>;
|
||||
def btargetS9 : BranchTargetS<9>;
|
||||
def btargetS10 : BranchTargetS<10>;
|
||||
def btargetS13 : BranchTargetS<13>;
|
||||
def btargetS21 : BranchTargetS<21>;
|
||||
def btargetS25 : BranchTargetS<25>;
|
||||
|
||||
class CallTargetS<int BSz> : BCTargetSigned<i32, BSz>;
|
||||
def calltargetS25: CallTargetS<25>;
|
||||
|
||||
// Compact Branch on Compare Register with Zero.
|
||||
class F16_BCC_REG<bit i, string asmstr> :
|
||||
InstARC<2, (outs), (ins GPR32:$b, btargetS8:$s8),
|
||||
!strconcat(asmstr, "\t$b, 0, $s8"), []> {
|
||||
|
||||
bits<3> b;
|
||||
bits<8> s8;
|
||||
|
||||
let Inst{15-11} = 0b11101;
|
||||
let Inst{10-8} = b;
|
||||
let Inst{7} = i;
|
||||
let Inst{6-0} = s8{7-1};
|
||||
let s8{0} = 0b0;
|
||||
}
|
||||
|
||||
def btargetS25 : Operand<OtherVT> {
|
||||
let OperandType = "OPERAND_PCREL";
|
||||
let DecoderMethod = "DecodeBranchTargetS25";
|
||||
// Compact Branch Conditionally Format.
|
||||
class F16_BCC<bits<2> i, dag ins, string asmstr> :
|
||||
InstARC<2, (outs), ins, asmstr, []> {
|
||||
|
||||
let Inst{15-11} = 0b11110;
|
||||
let Inst{10-9} = i;
|
||||
}
|
||||
|
||||
def calltargetS25: Operand<i32> {
|
||||
let OperandType = "OPERAND_PCREL";
|
||||
let DecoderMethod = "DecodeBranchTargetS25";
|
||||
class F16_BCC_s10<bits<2> i, string asmstr> :
|
||||
F16_BCC<i, (ins btargetS10:$s),
|
||||
!strconcat(asmstr, "\t$s")> {
|
||||
|
||||
bits<10> s;
|
||||
let Inst{8-0} = s{9-1};
|
||||
let s{0} = 0b0;
|
||||
}
|
||||
|
||||
class F16_BCC_s7<bits<3> i, string asmstr> :
|
||||
F16_BCC<0b11, (ins btargetS7:$s),
|
||||
!strconcat(asmstr, "\t$s")> {
|
||||
|
||||
bits<7> s;
|
||||
let Inst{8-6} = i;
|
||||
let Inst{5-0} = s{6-1};
|
||||
let s{0} = 0b0;
|
||||
}
|
||||
|
@ -117,7 +117,7 @@ def STB_FAR : PseudoInstARC<(outs), (ins GPR32:$dst, MEMrlimm:$addr),
|
||||
// multiclass. These classes do not contain Selection DAG patterns.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// Generic 3 operand binary instructions (i.e., add, r0, r1, r2).
|
||||
// Generic 3 operand binary instructions (i.e., add r0, r1, r2).
|
||||
multiclass ArcBinaryInst<bits<5> major, bits<6> mincode,
|
||||
string opasm> {
|
||||
// 3 register variant.
|
||||
@ -140,7 +140,7 @@ multiclass ArcBinaryInst<bits<5> major, bits<6> mincode,
|
||||
// 2 matched-register with signed 12-bit immediate variant (add r0, r0, -1).
|
||||
def _rrs12 : F32_DOP_RS12<major, mincode, 0,
|
||||
(outs GPR32:$B),
|
||||
(ins GPR32:$in, immS12:$S12),
|
||||
(ins GPR32:$in, immS<12>:$S12),
|
||||
!strconcat(opasm, "\t$B, $in, $S12"),
|
||||
[]>
|
||||
{ let Constraints = "$B = $in"; }
|
||||
@ -194,6 +194,9 @@ multiclass MultiPat<SDPatternOperator InFrag,
|
||||
// Definitions for 3 operand binary instructions.
|
||||
defm ADD : ArcBinaryGEN4Inst<0b000000, "add">;
|
||||
defm SUB : ArcBinaryGEN4Inst<0b000010, "sub">;
|
||||
defm SUB1 : ArcBinaryGEN4Inst<0b010111, "sub1">;
|
||||
defm SUB2 : ArcBinaryGEN4Inst<0b011000, "sub2">;
|
||||
defm SUB3 : ArcBinaryGEN4Inst<0b011001, "sub3">;
|
||||
defm OR : ArcBinaryGEN4Inst<0b000101, "or">;
|
||||
defm AND : ArcBinaryGEN4Inst<0b000100, "and">;
|
||||
defm XOR : ArcBinaryGEN4Inst<0b000111, "xor">;
|
||||
@ -206,6 +209,7 @@ defm ROR : ArcBinaryEXT5Inst<0b000011, "ror">;
|
||||
defm MPY : ArcBinaryGEN4Inst<0b011010, "mpy">;
|
||||
defm MPYM : ArcBinaryGEN4Inst<0b011011, "mpym">;
|
||||
defm MPYMU : ArcBinaryGEN4Inst<0b011100, "mpymu">;
|
||||
defm SETEQ : ArcBinaryGEN4Inst<0b111000, "seteq">;
|
||||
|
||||
// Patterns for 3 operand binary instructions.
|
||||
defm : MultiPat<add, ADD_rrr, ADD_rru6, ADD_rrlimm>;
|
||||
@ -223,7 +227,6 @@ defm : MultiPat<mul, MPY_rrr, MPY_rru6, MPY_rrlimm>;
|
||||
defm : MultiPat<mulhs, MPYM_rrr, MPYM_rru6, MPYM_rrlimm>;
|
||||
defm : MultiPat<mulhu, MPYMU_rrr, MPYMU_rru6, MPYMU_rrlimm>;
|
||||
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Unary Instruction definitions.
|
||||
// ---------------------------------------------------------------------------
|
||||
@ -248,9 +251,9 @@ defm : MultiPat<cmp, CMP_rr, CMP_ru6, CMP_rlimm>;
|
||||
// ---------------------------------------------------------------------------
|
||||
let isReMaterializable = 1, isAsCheapAsAMove = 1, isMoveImm = 1 in {
|
||||
def MOV_rs12 : F32_DOP_RS12<0b00100, 0b001010, 0,
|
||||
(outs GPR32:$B), (ins immS12:$S12),
|
||||
(outs GPR32:$B), (ins immS<12>:$S12),
|
||||
"mov\t$B, $S12",
|
||||
[(set GPR32:$B, immS12:$S12)]>;
|
||||
[(set GPR32:$B, immS<12>:$S12)]>;
|
||||
}
|
||||
|
||||
def MOV_rr : F32_DOP_RR<0b00100, 0b001010, 0,
|
||||
@ -288,96 +291,463 @@ def : Pat<(ARCGAWrapper tjumptable:$addr),
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
// Branch instructions
|
||||
let isBranch = 1, isTerminator = 1, isBarrier = 1 in {
|
||||
// Unconditional branch.
|
||||
def BR : F32_BR0_UCOND_FAR<(outs), (ins btargetS25:$S25),
|
||||
"b\t$S25", [(br bb:$S25)]>;
|
||||
let isBranch = 1, isTerminator = 1 in {
|
||||
|
||||
let Uses=[STATUS32] in {
|
||||
// Conditional branch.
|
||||
def Bcc : F32_BR0_COND<(outs), (ins btargetS21:$S21, ccond:$cc),
|
||||
"b$cc\t$S21", []>;
|
||||
}
|
||||
// Unconditional branch.
|
||||
let isBarrier = 1 in
|
||||
def BR : F32_BR0_UCOND_FAR<(outs), (ins btargetS25:$S25),
|
||||
"b\t$S25", [(br bb:$S25)]>;
|
||||
|
||||
// Compare and branch (limited range).
|
||||
def BRcc_rr : F32_BR1_BCC<(outs),
|
||||
(ins btargetS9:$S9, GPR32:$B, GPR32:$C, brccond:$cc),
|
||||
"br$cc\t$B, $C, $S9", 0, []>;
|
||||
def BRcc_ru6 : F32_BR1_BCC<(outs),
|
||||
(ins btargetS9:$S9, GPR32:$B, immU6:$C, brccond:$cc),
|
||||
"br$cc\t$B, $C, $S9", 1, []>;
|
||||
let Uses=[STATUS32] in
|
||||
// Conditional branch.
|
||||
def Bcc : F32_BR0_COND<(outs), (ins btargetS21:$S21, ccond:$cc),
|
||||
"b$cc\t$S21", []>;
|
||||
|
||||
// Pseudo compare and branch.
|
||||
// After register allocation, this can expand into either a limited range
|
||||
// Compare and branch (BRcc), or into CMP + Bcc.
|
||||
// At worst, this expands into 2 4-byte instructions.
|
||||
def BRcc_rr_p : PseudoInstARC<(outs),
|
||||
(ins btarget:$T, GPR32:$B, GPR32:$C, ccond:$cc),
|
||||
"pbr$cc\t$B, $C, $T",
|
||||
[(ARCbrcc bb:$T, i32:$B, i32:$C, imm32:$cc)]>
|
||||
{ let Size = 8; }
|
||||
// Compare and branch (limited range).
|
||||
def BRcc_rr : F32_BR1_BCC<(outs),
|
||||
(ins btargetS9:$S9, GPR32:$B, GPR32:$C, brccond:$cc),
|
||||
"br$cc\t$B, $C, $S9", 0, []>;
|
||||
def BRcc_ru6 : F32_BR1_BCC<(outs),
|
||||
(ins btargetS9:$S9, GPR32:$B, immU6:$C, brccond:$cc),
|
||||
"br$cc\t$B, $C, $S9", 1, []>;
|
||||
|
||||
def BRcc_ru6_p : PseudoInstARC<(outs),
|
||||
(ins btarget:$T, GPR32:$B, i32imm:$C, ccond:$cc),
|
||||
"pbr$cc\t$B, $C, $T",
|
||||
[(ARCbrcc bb:$T, i32:$B, immU6:$C, imm32:$cc)]>
|
||||
{ let Size = 8; }
|
||||
}
|
||||
// Pseudo compare and branch.
|
||||
// After register allocation, this can expand into either a limited range
|
||||
// Compare and branch (BRcc), or into CMP + Bcc.
|
||||
// At worst, this expands into 2 4-byte instructions.
|
||||
def BRcc_rr_p : PseudoInstARC<(outs),
|
||||
(ins btarget:$T, GPR32:$B, GPR32:$C, ccond:$cc),
|
||||
"pbr$cc\t$B, $C, $T",
|
||||
[(ARCbrcc bb:$T, i32:$B, i32:$C, imm32:$cc)]>
|
||||
{ let Size = 8; }
|
||||
|
||||
def BRcc_ru6_p : PseudoInstARC<(outs),
|
||||
(ins btarget:$T, GPR32:$B, i32imm:$C, ccond:$cc),
|
||||
"pbr$cc\t$B, $C, $T",
|
||||
[(ARCbrcc bb:$T, i32:$B, immU6:$C, imm32:$cc)]>
|
||||
{ let Size = 8; }
|
||||
} // let isBranch, isTerminator
|
||||
|
||||
// Indirect, unconditional Jump.
|
||||
let isBranch = 1, isTerminator = 1, isBarrier = 1, isIndirectBranch = 1 in {
|
||||
let isBranch = 1, isTerminator = 1, isBarrier = 1, isIndirectBranch = 1 in
|
||||
def J : F32_DOP_RR<0b00100, 0b100000, 0,
|
||||
(outs), (ins GPR32:$C),
|
||||
"j\t[$C]", [(brind i32:$C)]>;
|
||||
}
|
||||
|
||||
// Call instructions.
|
||||
let isCall = 1, Defs = [BLINK], Uses = [SP] in {
|
||||
// Direct unconditional call.
|
||||
def BL : F32_BR1_BL_UCOND_FAR<(outs), (ins calltargetS25:$S25),
|
||||
"bl\t$S25", [(ARCBranchLink tglobaladdr:$S25)]>;
|
||||
let isCall = 1, isBarrier = 1, Defs = [BLINK], Uses = [SP] in {
|
||||
// Direct unconditional call.
|
||||
def BL : F32_BR1_BL_UCOND_FAR<(outs), (ins calltargetS25:$S25),
|
||||
"bl\t$S25", [(ARCBranchLink tglobaladdr:$S25)]>;
|
||||
|
||||
// Indirect unconditional call.
|
||||
let isIndirectBranch = 1, Defs = [BLINK], Uses = [SP] in {
|
||||
def JL : F32_DOP_RR<0b00100, 0b100010, 0, (outs), (ins GPR32:$C),
|
||||
"jl\t[$C]", [(ARCJumpLink i32:$C)]>;
|
||||
}
|
||||
}
|
||||
// Indirect unconditional call.
|
||||
let isIndirectBranch = 1 in
|
||||
def JL : F32_DOP_RR<0b00100, 0b100010, 0, (outs), (ins GPR32:$C),
|
||||
"jl\t[$C]", [(ARCJumpLink i32:$C)]>;
|
||||
} // let isCall, isBarrier, Defs, Uses
|
||||
|
||||
// Pattern to generate BL instruction.
|
||||
def : Pat<(ARCBranchLink texternalsym:$dst), (BL texternalsym:$dst)>;
|
||||
|
||||
// Return from call.
|
||||
let isReturn = 1, isTerminator = 1, isBarrier = 1 in {
|
||||
let isReturn = 1, isTerminator = 1, isBarrier = 1 in
|
||||
// This is a specialized 2-byte instruction that doesn't generalize
|
||||
// to any larger 2-byte class, so go ahead and define it here.
|
||||
def J_S_BLINK : InstARC<2, (outs), (ins), "j_s\t[%blink]", [(ret)]> {
|
||||
let Inst{15-0} = 0b0111111011100000;
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Load/Store instructions.
|
||||
// Compact stack-based operations.
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
// 2-byte push/pop blink instructions commonly used for prolog/epilog
|
||||
// generation. These 2 instructions are actually specialized 2-byte
|
||||
// format instructions that aren't generalized to a larger 2-byte
|
||||
// class, so we might as well have them here.
|
||||
let Uses = [BLINK], Defs = [SP] in {
|
||||
def PUSH_S_BLINK : InstARC<2, (outs), (ins),
|
||||
"push_s\t%blink", []> {
|
||||
let Inst{15-0} = 0b1100000011110001;
|
||||
}
|
||||
let Uses = [BLINK], Defs = [SP] in
|
||||
def PUSH_S_BLINK : F16_SP_OPS_buconst<0b111, "push_s">;
|
||||
|
||||
let Defs = [BLINK, SP] in
|
||||
def POP_S_BLINK : F16_SP_OPS_buconst<0b110, "pop_s">;
|
||||
|
||||
def PUSH_S_r : F16_SP_OPS_uconst<0b110,
|
||||
(outs), (ins GPR32Reduced:$b3), "push_s">;
|
||||
def POP_S_r : F16_SP_OPS_uconst<0b111,
|
||||
(outs GPR32Reduced:$b3), (ins), "pop_s">;
|
||||
|
||||
def SP_SUB_SP_S : F16_SP_OPS_bconst<0b001, "sub_s">;
|
||||
def SP_ADD_SP_S : F16_SP_OPS_bconst<0b000, "add_s">;
|
||||
def SP_ADD_S : F16_SP_OPS_u7_aligned<0b100,
|
||||
(outs GPR32Reduced:$b3), (ins immU<7>:$u7),
|
||||
"add_s\t$b3, %sp, $u7">;
|
||||
|
||||
def SP_LD_S : F16_SP_LD<0b000, "ld_s">;
|
||||
def SP_LDB_S : F16_SP_LD<0b001, "ldb_s">;
|
||||
def SP_ST_S : F16_SP_ST<0b010, "st_s">;
|
||||
def SP_STB_S : F16_SP_ST<0b011, "stb_s">;
|
||||
|
||||
def LEAVE_S : F16_SP_OPS<0b110,
|
||||
(outs), (ins immU<7>:$u7), "leave_s\t$u7"> {
|
||||
|
||||
bits<7> u7;
|
||||
|
||||
let fieldB = u7{6-4};
|
||||
let fieldU{4-1} = u7{3-0};
|
||||
let fieldU{0} = 0b0;
|
||||
}
|
||||
|
||||
let Defs = [BLINK, SP] in {
|
||||
def POP_S_BLINK : InstARC<2, (outs), (ins),
|
||||
"pop_s\t%blink", []> {
|
||||
let Inst{15-0} = 0b1100000011010001;
|
||||
def ENTER_S : F16_SP_OPS<0b111,
|
||||
(outs), (ins immU<6>:$u6), "enter_s\t$u6"> {
|
||||
|
||||
bits<6> u6;
|
||||
|
||||
let fieldB{2} = 0;
|
||||
let fieldB{1-0} = u6{5-4};
|
||||
let fieldU{4-1} = u6{3-0};
|
||||
let fieldU{0} = 0b0;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Compact Move/Load instructions.
|
||||
//----------------------------------------------------------------------------
|
||||
class COMPACT_MOV_S :
|
||||
F16_COMPACT<0b0, (outs GPR32:$g), (ins GPR32:$h),
|
||||
"mov_s\t$g, $h"> {
|
||||
let DecoderMethod = "DecodeMoveHRegInstruction";
|
||||
}
|
||||
|
||||
def COMPACT_MOV_S_limm : COMPACT_MOV_S {
|
||||
bits<32> LImm;
|
||||
let Inst{47-16} = LImm;
|
||||
|
||||
bits<5> LImmReg = 0b11110;
|
||||
let Inst{7-5} = LImmReg{2-0};
|
||||
let Inst{1-0} = LImmReg{4-3};
|
||||
|
||||
let Size = 6;
|
||||
}
|
||||
|
||||
def COMPACT_MOV_S_hreg : COMPACT_MOV_S;
|
||||
|
||||
def COMPACT_LD_S :
|
||||
F16_COMPACT<0b1, (outs GPR32:$r), (ins GPR32:$h, immU<5>:$u5),
|
||||
"ld_s\t$r, [$h, $u5]"> {
|
||||
bits<5> u5;
|
||||
bits<2> r;
|
||||
|
||||
let Inst{10} = u5{4};
|
||||
let Inst{9-8} = r;
|
||||
let Inst{4-3} = u5{3-2};
|
||||
let u5{1-0} = 0b00;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Compact Load/Add/Sub.
|
||||
//----------------------------------------------------------------------------
|
||||
def LD_S_AS_rrr : F16_LD_SUB<0b0, "ld_s.as\t$a, [$b, $c]">;
|
||||
def SUB_S_rrr : F16_LD_SUB<0b1, "sub_s\t$a, $b, $c">;
|
||||
def ADD_S_rru6 : F16_ADD;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Compact Load/Store.
|
||||
//----------------------------------------------------------------------------
|
||||
def LD_S_s11 : F16_LD_ST_s11<0b0, "ld_s\t%r1, [%gp, $s11]">;
|
||||
def ST_S_s11 : F16_LD_ST_s11<0b1, "st_s\t%r0, [%gp, $s11]">;
|
||||
def LDI_S_u7 : F16_LDI_u7;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Indexed Jump or Execute.
|
||||
//----------------------------------------------------------------------------
|
||||
def JLI_S : F16_JLI_EI<0, "jli_s">;
|
||||
def EI_S : F16_JLI_EI<1, "ei_s">;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Load/Add Register-Register.
|
||||
//----------------------------------------------------------------------------
|
||||
def LD_S_rrr : F16_LD_ADD_RR<0b00, "ld_s\t$a, [$b, $c]">;
|
||||
def LDB_S_rrr : F16_LD_ADD_RR<0b01, "ldb_s\t$a, [$b, $c]">;
|
||||
def LDH_S_rrr : F16_LD_ADD_RR<0b10, "ldh_s\t$a, [$b, $c]">;
|
||||
def ADD_S_rrr : F16_LD_ADD_RR<0b11, "add_s\t$a, $b, $c">;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Load/Add GP-Relative.
|
||||
//----------------------------------------------------------------------------
|
||||
def GP_LD_S : F16_GP_LD_ADD<0b00, (ins immS<11>:$s),
|
||||
"ld_s\t%r0, [%gp, $s]"> {
|
||||
|
||||
bits<11> s;
|
||||
let Inst{8-0} = s{10-2};
|
||||
let s{1-0} = 0b00;
|
||||
}
|
||||
|
||||
def GP_LDB_S : F16_GP_LD_ADD<0b01, (ins immS<9>:$s),
|
||||
"ldb_s\t%r0, [%gp, $s]"> {
|
||||
|
||||
bits<9> s;
|
||||
let Inst{8-0} = s{8-0};
|
||||
}
|
||||
|
||||
def GP_LDH_S : F16_GP_LD_ADD<0b10, (ins immS<10>:$s),
|
||||
"ldh_s\t%r0, [%gp, $s]"> {
|
||||
|
||||
bits<10> s;
|
||||
let Inst{8-0} = s{9-1};
|
||||
let s{0} = 0b0;
|
||||
}
|
||||
|
||||
def GP_ADD_S : F16_GP_LD_ADD<0b11, (ins immS<11>:$s),
|
||||
"add_s\t%r0, %gp, $s"> {
|
||||
|
||||
bits<11> s;
|
||||
let Inst{8-0} = s{10-2};
|
||||
let s{1-0} = 0b00;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Load PCL-Relative.
|
||||
//----------------------------------------------------------------------------
|
||||
def PCL_LD : InstARC<2, (outs GPR32:$b), (ins immU<10>:$u10),
|
||||
"ld_s\t$b, [%pcl, $u10]", []> {
|
||||
|
||||
bits<3> b;
|
||||
bits<10> u10;
|
||||
|
||||
let Inst{15-11} = 0b11010;
|
||||
let Inst{10-8} = b;
|
||||
let Inst{7-0} = u10{9-2};
|
||||
let u10{1-0} = 0b00;
|
||||
}
|
||||
|
||||
let isBranch = 1 in {
|
||||
//----------------------------------------------------------------------------
|
||||
// Branch on Compare Register with Zero.
|
||||
//----------------------------------------------------------------------------
|
||||
def BREQ_S : F16_BCC_REG<0b0, "breq_s">;
|
||||
def BRNE_S : F16_BCC_REG<0b1, "brne_s">;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Branch Conditionally.
|
||||
//----------------------------------------------------------------------------
|
||||
let isBarrier = 1 in
|
||||
def B_S : F16_BCC_s10<0b00, "b_s">;
|
||||
|
||||
def BEQ_S : F16_BCC_s10<0b01, "beq_s">;
|
||||
def BNE_S : F16_BCC_s10<0b10, "bne_s">;
|
||||
def BGT_S : F16_BCC_s7<0b000, "bgt_s">;
|
||||
def BGE_S : F16_BCC_s7<0b001, "bge_s">;
|
||||
def BLT_S : F16_BCC_s7<0b010, "blt_s">;
|
||||
def BLE_S : F16_BCC_s7<0b011, "ble_s">;
|
||||
def BHI_S : F16_BCC_s7<0b100, "bhi_s">;
|
||||
def BHS_S : F16_BCC_s7<0b101, "bhs_s">;
|
||||
def BLO_S : F16_BCC_s7<0b110, "blo_s">;
|
||||
def BLS_S : F16_BCC_s7<0b111, "bls_s">;
|
||||
} // let isBranch
|
||||
|
||||
def BL_S :
|
||||
InstARC<2, (outs), (ins btargetS13:$s13), "bl_s\t$s13", []> {
|
||||
|
||||
let Inst{15-11} = 0b11111;
|
||||
|
||||
bits<13> s13;
|
||||
let Inst{10-0} = s13{12-2};
|
||||
let s13{1-0} = 0b00;
|
||||
|
||||
let isCall = 1;
|
||||
let isBarrier = 1;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Add/Sub/Shift Register-Immediate.
|
||||
//----------------------------------------------------------------------------
|
||||
def ADD_S_ru3 : F16_ADD_IMM<0b00,"add_s">;
|
||||
def SUB_S_ru3 : F16_ADD_IMM<0b01,"sub_s">;
|
||||
def ASL_S_ru3 : F16_ADD_IMM<0b10,"asl_s">;
|
||||
def ASR_S_ru3 : F16_ADD_IMM<0b11,"asr_s">;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Shift/Subtract/Bit Immediate.
|
||||
//----------------------------------------------------------------------------
|
||||
def ASL_S_ru5 : F16_SH_SUB_BIT_DST<0b000,"asl_s">;
|
||||
def LSR_S_ru5 : F16_SH_SUB_BIT_DST<0b001,"lsr_s">;
|
||||
def ASR_S_ru5 : F16_SH_SUB_BIT_DST<0b010,"asr_s">;
|
||||
def SUB_S_ru5 : F16_SH_SUB_BIT_DST<0b011,"sub_s">;
|
||||
def BSET_S_ru5 : F16_SH_SUB_BIT_DST<0b100,"bset_s">;
|
||||
def BCLR_S_ru5 : F16_SH_SUB_BIT_DST<0b101,"bclr_s">;
|
||||
def BMSK_S_ru5 : F16_SH_SUB_BIT_DST<0b110,"bmsk_s">;
|
||||
def BTST_S_ru5 : F16_SH_SUB_BIT<0b111, "btst_s\t$b, $u5">;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Dual Register Operations.
|
||||
//----------------------------------------------------------------------------
|
||||
def ADD_S_rlimm :
|
||||
F16_OP_HREG_LIMM<0b000, (outs GPR32:$b_s3), (ins i32imm:$LImm),
|
||||
!strconcat("add_s", "\t$b_s3, $b_s3, $LImm")>;
|
||||
|
||||
def ADD_S_rr :
|
||||
F16_OP_HREG<0b000, (outs GPR32:$b_s3), (ins GPR32:$h),
|
||||
!strconcat("add_s", "\t$b_s3, $b_s3, $h")>;
|
||||
|
||||
def ADD_S_rs3 :
|
||||
F16_OP_HREG<0b001, (outs GPR32:$h), (ins immC<3>:$b_s3),
|
||||
!strconcat("add_s", "\t$h, $h, $b_s3")>;
|
||||
|
||||
def ADD_S_limms3 :
|
||||
F16_OP_HREG_LIMM<0b001, (outs), (ins immC<3>:$b_s3, i32imm:$LImm),
|
||||
!strconcat("add_s", "\t0, $LImm, $b_s3")>;
|
||||
|
||||
def MOV_S_NE_rlimm :
|
||||
F16_OP_HREG_LIMM<0b111, (outs GPR32:$b_s3), (ins i32imm:$LImm),
|
||||
!strconcat("mov_s.ne", "\t$b_s3, $LImm")>;
|
||||
|
||||
def MOV_S_NE_rr :
|
||||
F16_OP_HREG<0b111,(outs GPR32:$b_s3), (ins GPR32:$h),
|
||||
!strconcat("mov_s.ne", "\t$b_s3, $h")>;
|
||||
|
||||
def MOV_S_rs3 :
|
||||
F16_OP_HREG<0b011, (outs GPR32:$h), (ins immC<3>:$b_s3),
|
||||
!strconcat("mov_s", "\t$h, $b_s3")>;
|
||||
|
||||
def MOV_S_s3 :
|
||||
F16_OP_HREG30<0b011, (outs), (ins immC<3>:$b_s3),
|
||||
!strconcat("mov_s", "\t0, $b_s3")>;
|
||||
|
||||
def CMP_S_rlimm :
|
||||
F16_OP_HREG_LIMM<0b100, (outs GPR32:$b_s3), (ins i32imm:$LImm),
|
||||
!strconcat("cmp_s", "\t$b_s3, $LImm")>;
|
||||
|
||||
def CMP_S_rr :
|
||||
F16_OP_HREG<0b100, (outs GPR32:$b_s3), (ins GPR32:$h),
|
||||
!strconcat("cmp_s", "\t$b_s3, $h")>;
|
||||
|
||||
def CMP_S_rs3 :
|
||||
F16_OP_HREG<0b101, (outs GPR32:$h), (ins immC<3>:$b_s3),
|
||||
!strconcat("cmp_s", "\t$h, $b_s3")>;
|
||||
|
||||
def CMP_S_limms3 :
|
||||
F16_OP_HREG_LIMM<0b101, (outs), (ins immC<3>:$b_s3, i32imm:$LImm),
|
||||
!strconcat("cmp_s", "\t$LImm, $b_s3")>;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Compact MOV/ADD/CMP Immediate instructions.
|
||||
//----------------------------------------------------------------------------
|
||||
def MOV_S_u8 :
|
||||
F16_OP_IMM<0b11011, (outs GPR32:$b), (ins immU<8>:$u8),
|
||||
!strconcat("mov_s", "\t$b, $u8")> {
|
||||
bits<8> u8;
|
||||
let Inst{7-0} = u8;
|
||||
}
|
||||
|
||||
def ADD_S_u7 :
|
||||
F16_OP_U7<0b0, !strconcat("add_s", "\t$b, $b, $u7")>;
|
||||
|
||||
def CMP_S_u7 :
|
||||
F16_OP_U7<0b1, !strconcat("cmp_s", "\t$b, $u7")>;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Compact Load/Store instructions with offset.
|
||||
//----------------------------------------------------------------------------
|
||||
def LD_S_OFF :
|
||||
F16_LD_ST_WORD_OFF<0x10, (outs GPR32:$c), (ins GPR32:$b, immU<7>:$off),
|
||||
"ld_s">;
|
||||
|
||||
def LDB_S_OFF :
|
||||
F16_LD_ST_BYTE_OFF<0x11, (outs GPR32:$c), (ins GPR32:$b, immU<5>:$off),
|
||||
"ldb_s">;
|
||||
|
||||
class F16_LDH_OFF<bits<5> opc, string asmstr> :
|
||||
F16_LD_ST_HALF_OFF<opc, (outs GPR32:$c), (ins GPR32:$b, immU<6>:$off),
|
||||
asmstr>;
|
||||
|
||||
def LDH_S_OFF : F16_LDH_OFF<0x12, "ldh_s">;
|
||||
def LDH_S_X_OFF : F16_LDH_OFF<0x13, "ldh_s.x">;
|
||||
|
||||
def ST_S_OFF :
|
||||
F16_LD_ST_WORD_OFF<0x14, (outs), (ins GPR32:$c, GPR32:$b, immU<7>:$off),
|
||||
"st_s">;
|
||||
|
||||
def STB_S_OFF :
|
||||
F16_LD_ST_BYTE_OFF<0x15, (outs), (ins GPR32:$c, GPR32:$b, immU<5>:$off),
|
||||
"stb_s">;
|
||||
|
||||
def STH_S_OFF :
|
||||
F16_LD_ST_HALF_OFF<0x16, (outs), (ins GPR32:$c, GPR32:$b, immU<6>:$off),
|
||||
"sth_s">;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// General compact instructions.
|
||||
//----------------------------------------------------------------------------
|
||||
def GEN_SUB_S : F16_GEN_DOP<0x02, "sub_s">;
|
||||
def GEN_AND_S : F16_GEN_DOP<0x04, "and_s">;
|
||||
def GEN_OR_S : F16_GEN_DOP<0x05, "or_s">;
|
||||
def GEN_BIC_S : F16_GEN_DOP<0x06, "bic_s">;
|
||||
def GEN_XOR_S : F16_GEN_DOP<0x07, "xor_s">;
|
||||
def GEN_MPYW_S : F16_GEN_DOP<0x09, "mpyw_s">;
|
||||
def GEN_MPYUW_S : F16_GEN_DOP<0x0a, "mpyuw_s">;
|
||||
def GEN_TST_S : F16_GEN_DOP_NODST<0x0b, "tst_s">;
|
||||
def GEN_MPY_S : F16_GEN_DOP<0x0c, "mpy_s">;
|
||||
def GEN_SEXB_S : F16_GEN_DOP_SINGLESRC<0x0d, "sexb_s">;
|
||||
def GEN_SEXH_S : F16_GEN_DOP_SINGLESRC<0x0e, "sexh_s">;
|
||||
def GEN_EXTB_S : F16_GEN_DOP_SINGLESRC<0x0f, "extb_s">;
|
||||
def GEN_EXTH_S : F16_GEN_DOP_SINGLESRC<0x10, "exth_s">;
|
||||
def GEN_ABS_S : F16_GEN_DOP_SINGLESRC<0x11, "abs_s">;
|
||||
def GEN_NOT_S : F16_GEN_DOP_SINGLESRC<0x12, "not_s">;
|
||||
def GEN_NEG_S : F16_GEN_DOP_SINGLESRC<0x13, "neg_s">;
|
||||
def GEN_ADD1_S : F16_GEN_DOP<0x14, "add1_s">;
|
||||
def GEN_ADD2_S : F16_GEN_DOP<0x15, "add2_s">;
|
||||
def GEN_ADD3_S : F16_GEN_DOP<0x16, "add3_s">;
|
||||
def GEN_ASL_S : F16_GEN_DOP<0x18, "asl_s">;
|
||||
def GEN_LSR_S : F16_GEN_DOP<0x19, "lsr_s">;
|
||||
def GEN_ASR_S : F16_GEN_DOP<0x1a, "asr_s">;
|
||||
def GEN_AS1L_S : F16_GEN_DOP_SINGLESRC<0x1b, "asl_s">;
|
||||
def GEN_AS1R_S : F16_GEN_DOP_SINGLESRC<0x1c, "asr_s">;
|
||||
def GEN_LS1R_S : F16_GEN_DOP_SINGLESRC<0x1d, "lsr_s">;
|
||||
def GEN_TRAP_S : F16_GEN_DOP_BASE<0x1e, (outs), (ins immU6:$u6),
|
||||
"trap_s\t$u6"> {
|
||||
|
||||
bits<6> u6;
|
||||
let b = u6{5-3};
|
||||
let c = u6{2-0};
|
||||
}
|
||||
|
||||
def GEN_BRK_S : F16_GEN_DOP_BASE<0x1f, (outs), (ins),
|
||||
"brk_s"> {
|
||||
|
||||
let b = 0b111;
|
||||
let c = 0b111;
|
||||
}
|
||||
|
||||
let isBarrier = 1 in {
|
||||
let isBranch = 1 in {
|
||||
def GEN_J_S : F16_GEN_SOP<0x0, "j_s\t[$b]">;
|
||||
def GEN_J_S_D : F16_GEN_SOP<0x1, "j_s.d\t[$b]">;
|
||||
} // let isBranch
|
||||
|
||||
let isCall = 1 in {
|
||||
def GEN_JL_S : F16_GEN_SOP<0x2, "jl_s\t[$b]">;
|
||||
def GEN_JL_S_D : F16_GEN_SOP<0x3, "jl_s.d\t[$b]">;
|
||||
} // let isCall
|
||||
} // let isBarrier
|
||||
|
||||
def GEN_SUB_S_NE : F16_GEN_SOP<0x6, "sub_s.ne\t$b, $b, $b">;
|
||||
|
||||
def GEN_NOP_S : F16_GEN_ZOP<0x0, "nop_s">;
|
||||
def GEN_UNIMP_S : F16_GEN_ZOP<0x1, "unimp_s">;
|
||||
def GEN_SWI_S : F16_GEN_ZOP<0x2, "swi_s">;
|
||||
|
||||
let isReturn = 1, isTerminator = 1 in {
|
||||
def GEN_JEQ_S : F16_GEN_ZOP<0x4, "jeq_s\t[%blink]">;
|
||||
def GEN_JNE_S : F16_GEN_ZOP<0x5, "jne_s\t[%blink]">;
|
||||
let isBarrier = 1 in {
|
||||
//def GEN_J_S_BLINK : F16_GEN_ZOP<0x6, "j_s\t[%blink]">;
|
||||
def GEN_J_S_D_BLINK : F16_GEN_ZOP<0x7, "j_s.d\t[%blink]">;
|
||||
} // let isBarrier
|
||||
} // let isReturn, isTerminator
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Load/Store instructions.
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
// Load instruction variants:
|
||||
// Control bits: x, aa, di, zz
|
||||
// x - sign extend.
|
||||
@ -412,7 +782,7 @@ multiclass ArcLdInst<bits<2> zz, string asmop> {
|
||||
|
||||
def _AB_rs9 : F32_LD_RS9<0, 0b10, 0, zz,
|
||||
(outs GPR32:$addrout, GPR32:$A),
|
||||
(ins GPR32:$B, immS9:$S9),
|
||||
(ins GPR32:$B, immS<9>:$S9),
|
||||
!strconcat(asmop, ".ab\t$A, [$B,$S9]"), []>
|
||||
{ let Constraints = "$addrout = $B"; }
|
||||
}
|
||||
@ -472,7 +842,7 @@ multiclass ArcStInst<bits<2> zz, string asmop> {
|
||||
!strconcat(asmop, "\t$C, [$addr]"), []>;
|
||||
|
||||
def _AW_rs9 : F32_ST_RS9<0b01, 0, zz, (outs GPR32:$addrout),
|
||||
(ins GPR32:$C, GPR32:$B, immS9:$S9),
|
||||
(ins GPR32:$C, GPR32:$B, immS<9>:$S9),
|
||||
!strconcat(asmop, ".aw\t$C, [$B,$S9]"), []>
|
||||
{ let Constraints = "$addrout = $B"; }
|
||||
}
|
||||
|
@ -67,6 +67,15 @@ static bool readInstruction64(ArrayRef<uint8_t> Bytes, uint64_t Address,
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool readInstruction48(ArrayRef<uint8_t> Bytes, uint64_t Address,
|
||||
uint64_t &Size, uint64_t &Insn) {
|
||||
Size = 6;
|
||||
Insn = ((uint64_t)Bytes[0] << 0) | ((uint64_t)Bytes[1] << 8) |
|
||||
((uint64_t)Bytes[2] << 32) | ((uint64_t)Bytes[3] << 40) |
|
||||
((uint64_t)Bytes[4] << 16) | ((uint64_t)Bytes[5] << 24);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool readInstruction16(ArrayRef<uint8_t> Bytes, uint64_t Address,
|
||||
uint64_t &Size, uint32_t &Insn) {
|
||||
Size = 2;
|
||||
@ -74,32 +83,33 @@ static bool readInstruction16(ArrayRef<uint8_t> Bytes, uint64_t Address,
|
||||
return true;
|
||||
}
|
||||
|
||||
static MCDisassembler::DecodeStatus DecodeS12Operand(MCInst &, unsigned,
|
||||
uint64_t, const void *);
|
||||
template <unsigned B>
|
||||
static DecodeStatus DecodeSignedOperand(MCInst &Inst, unsigned InsnS,
|
||||
uint64_t Address = 0,
|
||||
const void *Decoder = nullptr);
|
||||
|
||||
static MCDisassembler::DecodeStatus DecodeS9Operand(MCInst &, unsigned,
|
||||
uint64_t, const void *);
|
||||
template <unsigned B>
|
||||
static DecodeStatus DecodeFromCyclicRange(MCInst &Inst, unsigned InsnS,
|
||||
uint64_t Address = 0,
|
||||
const void *Decoder = nullptr);
|
||||
|
||||
static MCDisassembler::DecodeStatus
|
||||
DecodeBranchTargetS9(MCInst &, unsigned, uint64_t, const void *);
|
||||
template <unsigned B>
|
||||
static DecodeStatus DecodeBranchTargetS(MCInst &Inst, unsigned InsnS,
|
||||
uint64_t Address, const void *Decoder);
|
||||
|
||||
static MCDisassembler::DecodeStatus
|
||||
DecodeBranchTargetS21(MCInst &, unsigned, uint64_t, const void *);
|
||||
static DecodeStatus DecodeMEMrs9(MCInst &, unsigned, uint64_t, const void *);
|
||||
|
||||
static MCDisassembler::DecodeStatus
|
||||
DecodeBranchTargetS25(MCInst &, unsigned, uint64_t, const void *);
|
||||
static DecodeStatus DecodeLdLImmInstruction(MCInst &, uint64_t, uint64_t,
|
||||
const void *);
|
||||
|
||||
static MCDisassembler::DecodeStatus DecodeMEMrs9(MCInst &, unsigned, uint64_t,
|
||||
const void *);
|
||||
static DecodeStatus DecodeStLImmInstruction(MCInst &, uint64_t, uint64_t,
|
||||
const void *);
|
||||
|
||||
static MCDisassembler::DecodeStatus
|
||||
DecodeLdLImmInstruction(MCInst &, uint64_t, uint64_t, const void *);
|
||||
static DecodeStatus DecodeLdRLImmInstruction(MCInst &, uint64_t, uint64_t,
|
||||
const void *);
|
||||
|
||||
static MCDisassembler::DecodeStatus
|
||||
DecodeStLImmInstruction(MCInst &, uint64_t, uint64_t, const void *);
|
||||
|
||||
static MCDisassembler::DecodeStatus
|
||||
DecodeLdRLImmInstruction(MCInst &, uint64_t, uint64_t, const void *);
|
||||
static DecodeStatus DecodeMoveHRegInstruction(MCInst &Inst, uint64_t, uint64_t,
|
||||
const void *);
|
||||
|
||||
static const uint16_t GPR32DecoderTable[] = {
|
||||
ARC::R0, ARC::R1, ARC::R2, ARC::R3, ARC::R4, ARC::R5, ARC::R6,
|
||||
@ -115,11 +125,22 @@ static DecodeStatus DecodeGPR32RegisterClass(MCInst &Inst, unsigned RegNo,
|
||||
DEBUG(dbgs() << "Not a GPR32 register.");
|
||||
return MCDisassembler::Fail;
|
||||
}
|
||||
|
||||
unsigned Reg = GPR32DecoderTable[RegNo];
|
||||
Inst.addOperand(MCOperand::createReg(Reg));
|
||||
return MCDisassembler::Success;
|
||||
}
|
||||
|
||||
static DecodeStatus DecodeGBR32ShortRegister(MCInst &Inst, unsigned RegNo,
|
||||
uint64_t Address,
|
||||
const void *Decoder) {
|
||||
// Enumerates registers from ranges [r0-r3],[r12-r15].
|
||||
if (RegNo > 3)
|
||||
RegNo += 8; // 4 for r12, etc...
|
||||
|
||||
return DecodeGPR32RegisterClass(Inst, RegNo, Address, Decoder);
|
||||
}
|
||||
|
||||
#include "ARCGenDisassemblerTables.inc"
|
||||
|
||||
static unsigned decodeCField(unsigned Insn) {
|
||||
@ -135,8 +156,8 @@ static unsigned decodeAField(unsigned Insn) {
|
||||
return fieldFromInstruction(Insn, 0, 6);
|
||||
}
|
||||
|
||||
static MCDisassembler::DecodeStatus
|
||||
DecodeMEMrs9(MCInst &Inst, unsigned Insn, uint64_t Address, const void *Dec) {
|
||||
static DecodeStatus DecodeMEMrs9(MCInst &Inst, unsigned Insn, uint64_t Address,
|
||||
const void *Dec) {
|
||||
// We have the 9-bit immediate in the low bits, 6-bit register in high bits.
|
||||
unsigned S9 = Insn & 0x1ff;
|
||||
unsigned R = (Insn & (0x7fff & ~0x1ff)) >> 9;
|
||||
@ -145,49 +166,59 @@ DecodeMEMrs9(MCInst &Inst, unsigned Insn, uint64_t Address, const void *Dec) {
|
||||
return MCDisassembler::Success;
|
||||
}
|
||||
|
||||
static MCDisassembler::DecodeStatus DecodeS9Operand(MCInst &Inst,
|
||||
unsigned InsnS9,
|
||||
uint64_t Address,
|
||||
const void *Decoder) {
|
||||
Inst.addOperand(MCOperand::createImm(SignExtend32<9>(0x1ff & InsnS9)));
|
||||
static bool DecodeSymbolicOperand(MCInst &Inst, uint64_t Address,
|
||||
uint64_t Value, const void *Decoder) {
|
||||
static const uint64_t atLeast = 2;
|
||||
// TODO: Try to force emitter to use MCDisassembler* instead of void*.
|
||||
auto Disassembler = static_cast<const MCDisassembler *>(Decoder);
|
||||
return (nullptr != Disassembler &&
|
||||
Disassembler->tryAddingSymbolicOperand(Inst, Value, Address, true, 0,
|
||||
atLeast));
|
||||
}
|
||||
|
||||
static void DecodeSymbolicOperandOff(MCInst &Inst, uint64_t Address,
|
||||
uint64_t Offset, const void *Decoder) {
|
||||
uint64_t nextAddress = Address + Offset;
|
||||
|
||||
if (!DecodeSymbolicOperand(Inst, Address, nextAddress, Decoder))
|
||||
Inst.addOperand(MCOperand::createImm(Offset));
|
||||
}
|
||||
|
||||
template <unsigned B>
|
||||
static DecodeStatus DecodeBranchTargetS(MCInst &Inst, unsigned InsnS,
|
||||
uint64_t Address, const void *Decoder) {
|
||||
|
||||
static_assert(B > 0, "field is empty");
|
||||
DecodeSymbolicOperandOff(Inst, Address, SignExtend32<B>(InsnS), Decoder);
|
||||
return MCDisassembler::Success;
|
||||
}
|
||||
|
||||
static MCDisassembler::DecodeStatus DecodeS12Operand(MCInst &Inst,
|
||||
unsigned InsnS12,
|
||||
uint64_t Address,
|
||||
const void *Decoder) {
|
||||
Inst.addOperand(MCOperand::createImm(SignExtend32<12>(0xfff & InsnS12)));
|
||||
template <unsigned B>
|
||||
static DecodeStatus DecodeSignedOperand(MCInst &Inst, unsigned InsnS,
|
||||
uint64_t /*Address*/,
|
||||
const void * /*Decoder*/) {
|
||||
|
||||
static_assert(B > 0, "field is empty");
|
||||
Inst.addOperand(MCOperand::createImm(
|
||||
SignExtend32<B>(maskTrailingOnes<decltype(InsnS)>(B) & InsnS)));
|
||||
return MCDisassembler::Success;
|
||||
}
|
||||
|
||||
static MCDisassembler::DecodeStatus DecodeBranchTargetS9(MCInst &Inst,
|
||||
unsigned S,
|
||||
uint64_t Address,
|
||||
const void *Decoder) {
|
||||
Inst.addOperand(MCOperand::createImm(SignExtend32<9>(S)));
|
||||
template <unsigned B>
|
||||
static DecodeStatus DecodeFromCyclicRange(MCInst &Inst, unsigned InsnS,
|
||||
uint64_t /*Address*/,
|
||||
const void * /*Decoder*/) {
|
||||
|
||||
static_assert(B > 0, "field is empty");
|
||||
const unsigned max = (1u << B) - 1;
|
||||
Inst.addOperand(
|
||||
MCOperand::createImm(InsnS < max ? static_cast<int>(InsnS) : -1));
|
||||
return MCDisassembler::Success;
|
||||
}
|
||||
|
||||
static MCDisassembler::DecodeStatus DecodeBranchTargetS21(MCInst &Inst,
|
||||
unsigned S,
|
||||
uint64_t Address,
|
||||
const void *Decoder) {
|
||||
Inst.addOperand(MCOperand::createImm(SignExtend32<21>(S)));
|
||||
return MCDisassembler::Success;
|
||||
}
|
||||
|
||||
static MCDisassembler::DecodeStatus DecodeBranchTargetS25(MCInst &Inst,
|
||||
unsigned S,
|
||||
uint64_t Address,
|
||||
const void *Decoder) {
|
||||
Inst.addOperand(MCOperand::createImm(SignExtend32<25>(S)));
|
||||
return MCDisassembler::Success;
|
||||
}
|
||||
|
||||
static MCDisassembler::DecodeStatus
|
||||
DecodeStLImmInstruction(MCInst &Inst, uint64_t Insn, uint64_t Address,
|
||||
const void *Decoder) {
|
||||
static DecodeStatus DecodeStLImmInstruction(MCInst &Inst, uint64_t Insn,
|
||||
uint64_t Address,
|
||||
const void *Decoder) {
|
||||
unsigned SrcC, DstB, LImm;
|
||||
DstB = decodeBField(Insn);
|
||||
if (DstB != 62) {
|
||||
@ -202,9 +233,9 @@ DecodeStLImmInstruction(MCInst &Inst, uint64_t Insn, uint64_t Address,
|
||||
return MCDisassembler::Success;
|
||||
}
|
||||
|
||||
static MCDisassembler::DecodeStatus
|
||||
DecodeLdLImmInstruction(MCInst &Inst, uint64_t Insn, uint64_t Address,
|
||||
const void *Decoder) {
|
||||
static DecodeStatus DecodeLdLImmInstruction(MCInst &Inst, uint64_t Insn,
|
||||
uint64_t Address,
|
||||
const void *Decoder) {
|
||||
unsigned DstA, SrcB, LImm;
|
||||
DEBUG(dbgs() << "Decoding LdLImm:\n");
|
||||
SrcB = decodeBField(Insn);
|
||||
@ -220,9 +251,9 @@ DecodeLdLImmInstruction(MCInst &Inst, uint64_t Insn, uint64_t Address,
|
||||
return MCDisassembler::Success;
|
||||
}
|
||||
|
||||
static MCDisassembler::DecodeStatus
|
||||
DecodeLdRLImmInstruction(MCInst &Inst, uint64_t Insn, uint64_t Address,
|
||||
const void *Decoder) {
|
||||
static DecodeStatus DecodeLdRLImmInstruction(MCInst &Inst, uint64_t Insn,
|
||||
uint64_t Address,
|
||||
const void *Decoder) {
|
||||
unsigned DstA, SrcB;
|
||||
DEBUG(dbgs() << "Decoding LdRLimm\n");
|
||||
DstA = decodeAField(Insn);
|
||||
@ -237,9 +268,37 @@ DecodeLdRLImmInstruction(MCInst &Inst, uint64_t Insn, uint64_t Address,
|
||||
return MCDisassembler::Success;
|
||||
}
|
||||
|
||||
MCDisassembler::DecodeStatus ARCDisassembler::getInstruction(
|
||||
MCInst &Instr, uint64_t &Size, ArrayRef<uint8_t> Bytes, uint64_t Address,
|
||||
raw_ostream &vStream, raw_ostream &cStream) const {
|
||||
static DecodeStatus DecodeMoveHRegInstruction(MCInst &Inst, uint64_t Insn,
|
||||
uint64_t Address,
|
||||
const void *Decoder) {
|
||||
DEBUG(dbgs() << "Decoding MOV_S h-register\n");
|
||||
using Field = decltype(Insn);
|
||||
Field h = fieldFromInstruction(Insn, 5, 3) |
|
||||
(fieldFromInstruction(Insn, 0, 2) << 3);
|
||||
Field g = fieldFromInstruction(Insn, 8, 3) |
|
||||
(fieldFromInstruction(Insn, 3, 2) << 3);
|
||||
|
||||
auto DecodeRegisterOrImm = [&Inst, Address, Decoder](Field RegNum,
|
||||
Field Value) {
|
||||
if (30 == RegNum) {
|
||||
Inst.addOperand(MCOperand::createImm(Value));
|
||||
return MCDisassembler::Success;
|
||||
}
|
||||
|
||||
return DecodeGPR32RegisterClass(Inst, RegNum, Address, Decoder);
|
||||
};
|
||||
|
||||
if (MCDisassembler::Success != DecodeRegisterOrImm(g, 0))
|
||||
return MCDisassembler::Fail;
|
||||
|
||||
return DecodeRegisterOrImm(h, Insn >> 16u);
|
||||
}
|
||||
|
||||
DecodeStatus ARCDisassembler::getInstruction(MCInst &Instr, uint64_t &Size,
|
||||
ArrayRef<uint8_t> Bytes,
|
||||
uint64_t Address,
|
||||
raw_ostream &vStream,
|
||||
raw_ostream &cStream) const {
|
||||
MCDisassembler::DecodeStatus Result;
|
||||
if (Bytes.size() < 2) {
|
||||
Size = 0;
|
||||
@ -262,9 +321,9 @@ MCDisassembler::DecodeStatus ARCDisassembler::getInstruction(
|
||||
return Fail;
|
||||
Result =
|
||||
decodeInstruction(DecoderTable64, Instr, Insn64, Address, this, STI);
|
||||
if (Result == MCDisassembler::Success) {
|
||||
if (Success == Result) {
|
||||
DEBUG(dbgs() << "Successfully decoded 64-bit instruction.");
|
||||
return MCDisassembler::Success;
|
||||
return Result;
|
||||
}
|
||||
DEBUG(dbgs() << "Not a 64-bit instruction, falling back to 32-bit.");
|
||||
}
|
||||
@ -274,15 +333,28 @@ MCDisassembler::DecodeStatus ARCDisassembler::getInstruction(
|
||||
}
|
||||
// Calling the auto-generated decoder function.
|
||||
return decodeInstruction(DecoderTable32, Instr, Insn32, Address, this, STI);
|
||||
}
|
||||
} else {
|
||||
if (Bytes.size() >= 6) {
|
||||
// Attempt to treat as instr. with limm data.
|
||||
uint64_t Insn48;
|
||||
if (!readInstruction48(Bytes, Address, Size, Insn48))
|
||||
return Fail;
|
||||
Result =
|
||||
decodeInstruction(DecoderTable48, Instr, Insn48, Address, this, STI);
|
||||
if (Success == Result) {
|
||||
DEBUG(dbgs() << "Successfully decoded 16-bit instruction with limm.");
|
||||
return Result;
|
||||
}
|
||||
DEBUG(dbgs() << "Not a 16-bit instruction with limm, try without it.");
|
||||
}
|
||||
|
||||
// 16-bit instruction.
|
||||
uint32_t Insn16;
|
||||
if (!readInstruction16(Bytes, Address, Size, Insn16)) {
|
||||
return Fail;
|
||||
uint32_t Insn16;
|
||||
if (!readInstruction16(Bytes, Address, Size, Insn16))
|
||||
return Fail;
|
||||
|
||||
// Calling the auto-generated decoder function.
|
||||
return decodeInstruction(DecoderTable16, Instr, Insn16, Address, this, STI);
|
||||
}
|
||||
// Calling the auto-generated decoder function.
|
||||
return decodeInstruction(DecoderTable16, Instr, Insn16, Address, this, STI);
|
||||
}
|
||||
|
||||
static MCDisassembler *createARCDisassembler(const Target &T,
|
||||
|
@ -101,6 +101,12 @@ static void printExpr(const MCExpr *Expr, const MCAsmInfo *MAI,
|
||||
int Offset = 0;
|
||||
const MCSymbolRefExpr *SRE;
|
||||
|
||||
if (const auto *CE = dyn_cast<MCConstantExpr>(Expr)) {
|
||||
OS << "0x";
|
||||
OS.write_hex(CE->getValue());
|
||||
return;
|
||||
}
|
||||
|
||||
if (const auto *BE = dyn_cast<MCBinaryExpr>(Expr)) {
|
||||
SRE = dyn_cast<MCSymbolRefExpr>(BE->getLHS());
|
||||
const auto *CE = dyn_cast<MCConstantExpr>(BE->getRHS());
|
||||
|
@ -72,4 +72,11 @@
|
||||
# CHECK: sub %r0, %r22, %r0
|
||||
0x02 0x26 0x00 0x20
|
||||
|
||||
# CHECK: sub1 %r3, %fp, %r1
|
||||
0x17 0x23 0x43 0x30
|
||||
|
||||
# CHECK: sub2 %r3, %fp, 17
|
||||
0x58 0x23 0x43 0x34
|
||||
|
||||
# CHECK: sub3 %fp, %fp, -1
|
||||
0x99 0x23 0xff 0x3f
|
||||
|
379
llvm/test/MC/Disassembler/ARC/compact.txt
Normal file
379
llvm/test/MC/Disassembler/ARC/compact.txt
Normal file
@ -0,0 +1,379 @@
|
||||
# RUN: llvm-mc -triple=arc -disassemble %s | FileCheck %s
|
||||
|
||||
# CHECK: abs_s %r0, %r1
|
||||
0x31 0x78
|
||||
|
||||
# CHECK: add_s %r0, %r1, %r2
|
||||
0x58 0x61
|
||||
|
||||
# CHECK: add_s %r0, %r0, %fp
|
||||
0x63 0x70
|
||||
|
||||
# CHECK: add_s %fp, %fp, -1
|
||||
0x67 0x77
|
||||
|
||||
# CHECK: add_s %fp, %fp, 6
|
||||
0x67 0x76
|
||||
|
||||
# CHECK: add_s %r0, %r0, 287454020
|
||||
0xc3 0x70 0x22 0x11 0x44 0x33
|
||||
|
||||
# CHECK: add_s 0, 287454020, 4
|
||||
0xc7 0x74 0x22 0x11 0x44 0x33
|
||||
|
||||
# CHECK: add_s %r0, %sp, 64
|
||||
0x90 0xc0
|
||||
|
||||
# CHECK: add_s %r0, %r0, 64
|
||||
0x40 0xe0
|
||||
|
||||
# CHECK: add_s %r0, %r1, 7
|
||||
0x07 0x69
|
||||
|
||||
# CHECK: add_s %sp, %sp, 64
|
||||
0xb0 0xc0
|
||||
|
||||
# CHECK: add_s %r0, %gp, -4
|
||||
0xff 0xcf
|
||||
|
||||
# CHECK: add_s %r0, %r1, 4
|
||||
0x0c 0x49
|
||||
|
||||
# CHECK: add_s %r1, %r0, 4
|
||||
0x8c 0x48
|
||||
|
||||
# CHECK: add1_s %r0, %r0, %r1
|
||||
0x34 0x78
|
||||
|
||||
# CHECK: add2_s %r0, %r0, %r1
|
||||
0x35 0x78
|
||||
|
||||
# CHECK: add3_s %r0, %r0, %r1
|
||||
0x36 0x78
|
||||
|
||||
# CHECK: and_s %r0, %r0, %r1
|
||||
0x24 0x78
|
||||
|
||||
# CHECK: asl_s %r0, %r1
|
||||
0x3b 0x78
|
||||
|
||||
# CHECK: asl_s %r1, %r0, 4
|
||||
0x34 0x68
|
||||
|
||||
# CHECK: asl_s %r0, %r0, %r1
|
||||
0x38 0x78
|
||||
|
||||
# CHECK: asl_s %r0, %r0, 16
|
||||
0x10 0xb8
|
||||
|
||||
# CHECK: asr_s %r0, %r1
|
||||
0x3c 0x78
|
||||
|
||||
# CHECK: asr_s %r1, %r0, 4
|
||||
0x3c 0x68
|
||||
|
||||
# CHECK: asr_s %r0, %r0, %r1
|
||||
0x3a 0x78
|
||||
|
||||
# CHECK: asr_s %r0, %r0, 16
|
||||
0x50 0xb8
|
||||
|
||||
# CHECK: b_s 256
|
||||
0x80 0xf0
|
||||
|
||||
# CHECK: b_s -4
|
||||
0xfe 0xf1
|
||||
|
||||
# CHECK: beq_s -4
|
||||
0xfe 0xf3
|
||||
|
||||
# CHECK: bne_s -4
|
||||
0xfe 0xf5
|
||||
|
||||
# CHECK: bgt_s -4
|
||||
0x3e 0xf6
|
||||
|
||||
# CHECK: bge_s -4
|
||||
0x7e 0xf6
|
||||
|
||||
# CHECK: blt_s -4
|
||||
0xbe 0xf6
|
||||
|
||||
# CHECK: ble_s -4
|
||||
0xfe 0xf6
|
||||
|
||||
# CHECK: bhi_s -4
|
||||
0x3e 0xf7
|
||||
|
||||
# CHECK: bhs_s -4
|
||||
0x7e 0xf7
|
||||
|
||||
# CHECK: blo_s -4
|
||||
0xbe 0xf7
|
||||
|
||||
# CHECK: bls_s -4
|
||||
0xfe 0xf7
|
||||
|
||||
# CHECK: bclr_s %r0, %r0, 24
|
||||
0xb8 0xb8
|
||||
|
||||
# CHECK: bic_s %r0, %r0, %r1
|
||||
0x26 0x78
|
||||
|
||||
# CHECK: bl_s -256
|
||||
0xc0 0xff
|
||||
|
||||
# CHECK: bmsk_s %r0, %r0, 24
|
||||
0xd8 0xb8
|
||||
|
||||
# CHECK: brne_s %r0, 0, -128
|
||||
0xc0 0xe8
|
||||
|
||||
# CHECK: breq_s %r0, 0, -128
|
||||
0x40 0xe8
|
||||
|
||||
# CHECK: brk_s
|
||||
0xff 0x7f
|
||||
|
||||
# CHECK: bset_s %r0, %r0, 24
|
||||
0x98 0xb8
|
||||
|
||||
# CHECK: btst_s %r0, 24
|
||||
0xf8 0xb8
|
||||
|
||||
# CHECK: cmp_s %r0, %sp
|
||||
0x93 0x70
|
||||
|
||||
# CHECK: cmp_s %sp, -1
|
||||
0x97 0x77
|
||||
|
||||
# CHECK: cmp_s %r2, 64
|
||||
0xc0 0xe2
|
||||
|
||||
# CHECK: ei_s 512
|
||||
0x00 0x5e
|
||||
|
||||
# CHECK: enter_s 16
|
||||
0xe0 0xc1
|
||||
|
||||
# CHECK: extb_s %r0, %r1
|
||||
0x2f 0x78
|
||||
|
||||
# CHECK: exth_s %r0, %r1
|
||||
0x30 0x78
|
||||
|
||||
# CHECK: j_s [%r0]
|
||||
0x00 0x78
|
||||
|
||||
# CHECK: j_s [%blink]
|
||||
0xe0 0x7e
|
||||
|
||||
# CHECK: j_s.d [%r0]
|
||||
0x20 0x78
|
||||
|
||||
# CHECK: j_s.d [%blink]
|
||||
0xe0 0x7f
|
||||
|
||||
# CHECK: jeq_s [%blink]
|
||||
0xe0 0x7c
|
||||
|
||||
# CHECK: jne_s [%blink]
|
||||
0xe0 0x7d
|
||||
|
||||
# CHECK: jl_s [%r0]
|
||||
0x40 0x78
|
||||
|
||||
# CHECK: jl_s.d [%r0]
|
||||
0x60 0x78
|
||||
|
||||
# CHECK: jli_s 512
|
||||
0x00 0x5a
|
||||
|
||||
# CHECK: ld_s %r0, [%r1, %r2]
|
||||
0x40 0x61
|
||||
|
||||
# CHECK: ld_s %r0, [%sp, 64]
|
||||
0x10 0xc0
|
||||
|
||||
# CHECK: ld_s %r0, [%pcl, 512]
|
||||
0x80 0xd0
|
||||
|
||||
# CHECK: ld_s %r1, [%r0, 64]
|
||||
0x30 0x80
|
||||
|
||||
# CHECK: ld_s %r0, [%gp, -1024]
|
||||
0x00 0xc9
|
||||
|
||||
# CHECK: ldb_s %r0, [%r1, %r2]
|
||||
0x48 0x61
|
||||
|
||||
# CHECK: ldb_s %r0, [%sp, 64]
|
||||
0x30 0xc0
|
||||
|
||||
# CHECK: ldb_s %r1, [%r0, 16]
|
||||
0x30 0x88
|
||||
|
||||
# CHECK: ldb_s %r0, [%gp, -256]
|
||||
0x00 0xcb
|
||||
|
||||
# CHECK: ldh_s %r0, [%r1, %r2]
|
||||
0x50 0x61
|
||||
|
||||
# CHECK: ldh_s %r1, [%r0, 32]
|
||||
0x30 0x90
|
||||
|
||||
# CHECK: ldh_s %r0, [%gp, -512]
|
||||
0x00 0xcd
|
||||
|
||||
# CHECK: ldh_s.x %r1, [%r0, 32]
|
||||
0x30 0x98
|
||||
|
||||
# CHECK: ld_s %r0, [%r17, 8]
|
||||
0x36 0x40
|
||||
|
||||
# CHECK: ld_s %r1, [%r17, 8]
|
||||
0x36 0x41
|
||||
|
||||
# CHECK: ld_s %r2, [%r17, 8]
|
||||
0x36 0x42
|
||||
|
||||
# CHECK: ld_s %r3, [%r17, 8]
|
||||
0x36 0x43
|
||||
|
||||
# CHECK: ld_s.as %r0, [%r1, %r2]
|
||||
0x40 0x49
|
||||
|
||||
# CHECK: ld_s %r1, [%gp, -1024]
|
||||
0x00 0x54
|
||||
|
||||
# CHECK: ldi_s %r0, [64]
|
||||
0x88 0x50
|
||||
|
||||
# CHECK: leave_s 16
|
||||
0xc0 0xc1
|
||||
|
||||
# CHECK: lsr_s %r0, %r1
|
||||
0x3d 0x78
|
||||
|
||||
# CHECK: lsr_s %r0, %r0, %r1
|
||||
0x39 0x78
|
||||
|
||||
# CHECK: lsr_s %r0, %r0, 16
|
||||
0x30 0xb8
|
||||
|
||||
# CHECK: mov_s %r17, -1
|
||||
0x2e 0x77
|
||||
|
||||
# CHECK: mov_s 0, 5
|
||||
0xcf 0x75
|
||||
|
||||
# CHECK: mov_s.ne %r0, %r17
|
||||
0x3e 0x70
|
||||
|
||||
# CHECK: mov_s.ne %r0, 1024
|
||||
0xdf 0x70 0x00 0x00 0x00 0x04
|
||||
|
||||
# CHECK: mov_s %r0, 128
|
||||
0x80 0xd8
|
||||
|
||||
# CHECK: mov_s %r16, %r17
|
||||
0x32 0x40
|
||||
|
||||
# CHECK: mov_s %r16, 1024
|
||||
0xd3 0x40 0x00 0x00 0x00 0x04
|
||||
|
||||
# CHECK: mov_s 0, %r17
|
||||
0x3a 0x46
|
||||
|
||||
# CHECK: mov_s 0, 1024
|
||||
0xdb 0x46 0x00 0x00 0x00 0x04
|
||||
|
||||
# CHECK: mpy_s %r0, %r0, %r1
|
||||
0x2c 0x78
|
||||
|
||||
# CHECK: mpyuw_s %r0, %r0, %r1
|
||||
0x2a 0x78
|
||||
|
||||
# CHECK: mpyw_s %r0, %r0, %r1
|
||||
0x29 0x78
|
||||
|
||||
# CHECK: neg_s %r0, %r1
|
||||
0x33 0x78
|
||||
|
||||
# CHECK: nop_s
|
||||
0xe0 0x78
|
||||
|
||||
# CHECK: not_s %r0, %r1
|
||||
0x32 0x78
|
||||
|
||||
# CHECK: or_s %r0, %r0, %r1
|
||||
0x25 0x78
|
||||
|
||||
# CHECK: pop_s %r0
|
||||
0xe1 0xc0
|
||||
|
||||
# CHECK: pop_s %blink
|
||||
0xd1 0xc0
|
||||
|
||||
# CHECK: push_s %r0
|
||||
0xc1 0xc0
|
||||
|
||||
# CHECK: push_s %blink
|
||||
0xf1 0xc0
|
||||
|
||||
# CHECK: sexb_s %r0, %r1
|
||||
0x2d 0x78
|
||||
|
||||
# CHECK: sexh_s %r0, %r1
|
||||
0x2e 0x78
|
||||
|
||||
# CHECK: st_s %r0, [%sp, 64]
|
||||
0x50 0xc0
|
||||
|
||||
# CHECK: st_s %r1, [%r0, 64]
|
||||
0x30 0xa0
|
||||
|
||||
# CHECK: st_s %r0, [%gp, -1024]
|
||||
0x10 0x54
|
||||
|
||||
# CHECK: stb_s %r0, [%sp, 64]
|
||||
0x70 0xc0
|
||||
|
||||
# CHECK: stb_s %r1, [%r0, 16]
|
||||
0x30 0xa8
|
||||
|
||||
# CHECK: sth_s %r1, [%r0, 32]
|
||||
0x30 0xb0
|
||||
|
||||
# CHECK: sub_s %r1, %r0, 4
|
||||
0x2c 0x68
|
||||
|
||||
# CHECK: sub_s.ne %r0, %r0, %r0
|
||||
0xc0 0x78
|
||||
|
||||
# CHECK: sub_s %r0, %r0, %r1
|
||||
0x22 0x78
|
||||
|
||||
# CHECK: sub_s %r0, %r0, 16
|
||||
0x70 0xb8
|
||||
|
||||
# CHECK: sub_s %sp, %sp, 64
|
||||
0xb0 0xc1
|
||||
|
||||
# CHECK: sub_s %r0, %r1, %r2
|
||||
0x50 0x49
|
||||
|
||||
# CHECK: swi_s
|
||||
0xe0 0x7a
|
||||
|
||||
# CHECK: trap_s 32
|
||||
0x1e 0x7c
|
||||
|
||||
# CHECK: tst_s %r0, %r1
|
||||
0x2b 0x78
|
||||
|
||||
# CHECK: unimp_s
|
||||
0xe0 0x79
|
||||
|
||||
# CHECK: xor_s %r0, %r0, %r1
|
||||
0x27 0x78
|
@ -40,3 +40,11 @@
|
||||
# CHECK: j [%r3]
|
||||
0x20 0x20 0xc0 0x00
|
||||
|
||||
# CHECK: seteq %r3, %fp, %r1
|
||||
0x38 0x23 0x43 0x30
|
||||
|
||||
# CHECK: seteq %r3, %fp, 17
|
||||
0x78 0x23 0x43 0x34
|
||||
|
||||
# CHECK: seteq %fp, %fp, -1
|
||||
0xb8 0x23 0xff 0x3f
|
||||
|
Loading…
Reference in New Issue
Block a user