Index: lib/Target/ARC/ARCInstrFormats.td =================================================================== --- lib/Target/ARC/ARCInstrFormats.td +++ lib/Target/ARC/ARCInstrFormats.td @@ -17,18 +17,23 @@ } // Address operands -def immU6 : Operand, PatLeaf<(imm), [{ - return isUInt<6>(N->getSExtValue()); }]> { + +class immU : Operand, PatLeaf<(imm), + "\n return isUInt<"#BSz#">(N->getSExtValue());"> { } -def immS12 : Operand, PatLeaf<(imm), [{ - return isInt<12>(N->getSExtValue()); }]> { - let DecoderMethod = "DecodeS12Operand"; +def immU6 : immU<6> {} + +class immS : Operand, PatLeaf<(imm), + "\n return isInt<"#BSz#">(N->getSExtValue());"> { + let DecoderMethod = "DecodeSignedOperand<"#BSz#">"; } -def immS9 : Operand, 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 : Operand, PatLeaf<(imm), + "\n return isInt<"#BSz#">(N->getSExtValue());"> { + let DecoderMethod = "DecodeFromCyclicRange<"#BSz#">"; } def MEMii : Operand { @@ -36,7 +41,7 @@ } def MEMrs9 : Operand { - 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 @@ let DecoderMethod = "DecodeMEMrlimm"; } +def GPR32Reduced : Operand { + let DecoderMethod = "DecodeGBR32ShortRegister"; +} + class InstARC pattern> : Instruction, Encoding64 { @@ -153,7 +162,6 @@ 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 @@ let DecoderMethod = "DecodeStLImmInstruction"; } +// Compact Move/Load. +// |10|9|8|7|6|5|4|3|2|1|0| +// | |h | |i|H | +class F16_COMPACT 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 : + InstARC<2, outs, ins, asmstr, []> { + + bits<3> b; + let Inst{15-11} = 0b01001; + let Inst{10-8} = b; +} + +class F16_LD_SUB : + 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 : + InstARC<2, outs, ins, asmstr, []> { + + let Inst{15-11} = 0b01010; +} + +class F16_LD_ST_s11 : + 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 : + 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 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 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 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 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 i, dag outs, dag ins, string asmstr> : + F16_OP_HREG { + + bits<5> LImmReg = 0b11110; + let Inst{7-5} = LImmReg{2-0}; + let Inst{1-0} = LImmReg{4-3}; +} + +class F16_OP_HREG_LIMM i, dag outs, dag ins, string asmstr> : + F16_OP_HREG30 { + + bits<32> LImm; + let Inst{47-16} = LImm; + let Size = 6; +} + +// General compact DOP format. +class F16_GEN_DOP_BASE 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 i, string asmstr> : + F16_GEN_DOP_BASE {} + +class F16_GEN_DOP_NODST i, string asmstr> : + F16_GEN_DOP_BASE {} + +class F16_GEN_DOP_SINGLESRC i, string asmstr> : + F16_GEN_DOP_BASE {} + +class F16_GEN_SOP_BASE i, dag outs, dag ins, string asmstr> : + F16_GEN_DOP_BASE<0b00000, outs, ins, asmstr> { + + let c = i; +} + +class F16_GEN_SOP i, string asmstr> : + F16_GEN_SOP_BASE {} + +class F16_GEN_ZOP 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 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 opc, dag outs, dag ins, string asmstr> : + F16_LD_ST_OFF { + + bits<7> off; + let Inst{4-0} = off{6-2}; + let off{1-0} = 0b00; +} + +class F16_LD_ST_HALF_OFF opc, dag outs, dag ins, string asmstr> : + F16_LD_ST_OFF { + + bits<6> off; + let Inst{4-0} = off{5-1}; + let off{0} = 0b0; +} + +class F16_LD_ST_BYTE_OFF opc, dag outs, dag ins, string asmstr> : + F16_LD_ST_OFF { + + 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 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 i, string asmstr> : + F16_SH_SUB_BIT {} + +// 16-bit stack-based operations. +// |10|9|8|7|6|5|4|3|2|1|0| +// |b |i |u | +class F16_SP_OPS 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 i, + dag outs, dag ins, string asmstr> : + F16_SP_OPS { + + bits<3> b3; + bits<7> u7; + + let fieldB = b3; + let fieldU = u7{6-2}; + let u7{1-0} = 0b00; +} + +class F16_SP_OPS_bconst 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 i, + dag outs, dag ins, string asmop> : + F16_SP_OPS_u7_aligned { + + let fieldU = 0b00001; +} + +class F16_SP_OPS_buconst i, string asmop> : + F16_SP_OPS_u7_aligned { + + let fieldB = 0x000; + let fieldU = 0b10001; +} + +class F16_SP_LD i, string asmop> : F16_SP_OPS_u7_aligned:$u7), + !strconcat(asmop, "\t$b3, [%sp, $u7]")> {} + +class F16_SP_ST i, string asmop> : F16_SP_OPS_u7_aligned:$u7), + !strconcat(asmop, "\t$b3, [%sp, $u7]")> {} + +// Compact MOV/ADD/CMP Immediate Format. +class F16_OP_IMM 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 : + 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, PredicateOp, ComplexPattern { @@ -481,28 +825,67 @@ let PrintMethod = "printBRCCPredicateOperand"; } -// Branch targets of different offset sizes. -def btarget : Operand { +// Branch/call targets of different offset sizes. +class BCTarget : Operand { let OperandType = "OPERAND_PCREL"; } -def btargetS9 : Operand { - let OperandType = "OPERAND_PCREL"; - let DecoderMethod = "DecodeBranchTargetS9"; +def btarget : BCTarget {} + +class BCTargetSigned : BCTarget { + let DecoderMethod = "DecodeBranchTargetS<"#BSz#">"; } -def btargetS21 : Operand { - let OperandType = "OPERAND_PCREL"; - let DecoderMethod = "DecodeBranchTargetS21"; +class BranchTargetS : BCTargetSigned {} +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 : BCTargetSigned {} +def calltargetS25: CallTargetS<25> {} + +// Compact Branch on Compare Register with Zero. +class F16_BCC_REG : + 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 { - let OperandType = "OPERAND_PCREL"; - let DecoderMethod = "DecodeBranchTargetS25"; +// Compact Branch Conditionally Format. +class F16_BCC i, dag ins, string asmstr> : + InstARC<2, (outs), ins, asmstr, []> { + + let Inst{15-11} = 0b11110; + let Inst{10-9} = i; } -def calltargetS25: Operand { - let OperandType = "OPERAND_PCREL"; - let DecoderMethod = "DecodeBranchTargetS25"; +class F16_BCC_s10 i, string asmstr> : + F16_BCC { + + bits<10> s; + let Inst{8-0} = s{9-1}; + let s{0} = 0b0; } +class F16_BCC_s7 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; +} Index: lib/Target/ARC/ARCInstrInfo.td =================================================================== --- lib/Target/ARC/ARCInstrInfo.td +++ lib/Target/ARC/ARCInstrInfo.td @@ -117,7 +117,7 @@ // 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 major, bits<6> mincode, string opasm> { // 3 register variant. @@ -140,7 +140,7 @@ // 2 matched-register with signed 12-bit immediate variant (add r0, r0, -1). def _rrs12 : F32_DOP_RS12:$S12), !strconcat(opasm, "\t$B, $in, $S12"), []> { let Constraints = "$B = $in"; } @@ -194,6 +194,9 @@ // 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 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; @@ -223,7 +227,6 @@ defm : MultiPat; defm : MultiPat; - // --------------------------------------------------------------------------- // Unary Instruction definitions. // --------------------------------------------------------------------------- @@ -248,9 +251,9 @@ // --------------------------------------------------------------------------- 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, @@ -357,7 +360,7 @@ } //---------------------------------------------------------------------------- -// Load/Store instructions. +// Compact stack-based operations. //---------------------------------------------------------------------------- // 2-byte push/pop blink instructions commonly used for prolog/epilog @@ -365,19 +368,370 @@ // 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; + def PUSH_S_BLINK : F16_SP_OPS_buconst<0b111, "push_s"> {} } -} let Defs = [BLINK, SP] in { -def POP_S_BLINK : InstARC<2, (outs), (ins), - "pop_s\t%blink", []> { - let Inst{15-0} = 0b1100000011010001; + 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; } +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; +} + +//---------------------------------------------------------------------------- +// 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. +//---------------------------------------------------------------------------- +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"> {} + +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; +} + +//---------------------------------------------------------------------------- +// 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 opc, string asmstr> : + F16_LD_ST_HALF_OFF:$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; +} + +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]"> {} +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]"> {} +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"> {} +def GEN_JEQ_S : F16_GEN_ZOP<0x4, "jeq_s\t[%blink]"> {} +def GEN_JNE_S : F16_GEN_ZOP<0x5, "jne_s\t[%blink]"> {} +//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]"> {} + +//---------------------------------------------------------------------------- +// Load/Store instructions. +//---------------------------------------------------------------------------- + // Load instruction variants: // Control bits: x, aa, di, zz // x - sign extend. @@ -412,7 +766,7 @@ 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 +826,7 @@ !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"; } } Index: lib/Target/ARC/Disassembler/ARCDisassembler.cpp =================================================================== --- lib/Target/ARC/Disassembler/ARCDisassembler.cpp +++ lib/Target/ARC/Disassembler/ARCDisassembler.cpp @@ -67,6 +67,15 @@ return true; } +static bool readInstruction48(ArrayRef 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 Bytes, uint64_t Address, uint64_t &Size, uint32_t &Insn) { Size = 2; @@ -74,33 +83,34 @@ return true; } -static MCDisassembler::DecodeStatus DecodeS12Operand(MCInst &, unsigned, - uint64_t, const void *); +template +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 +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 +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 DecodeStatus DecodeMoveHRegInstruction(MCInst &Inst, uint64_t, uint64_t, + const void *); -static MCDisassembler::DecodeStatus -DecodeLdRLImmInstruction(MCInst &, 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, ARC::R7, ARC::R8, ARC::R9, ARC::R10, ARC::R11, ARC::R12, ARC::R13, @@ -115,11 +125,22 @@ 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 @@ 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 @@ 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))); - return MCDisassembler::Success; +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(Decoder); + return (nullptr != Disassembler && + Disassembler->tryAddingSymbolicOperand(Inst, Value, Address, true, 0, + atLeast)); } -static MCDisassembler::DecodeStatus DecodeS12Operand(MCInst &Inst, - unsigned InsnS12, - uint64_t Address, - const void *Decoder) { - Inst.addOperand(MCOperand::createImm(SignExtend32<12>(0xfff & InsnS12))); - return MCDisassembler::Success; +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)); } -static MCDisassembler::DecodeStatus DecodeBranchTargetS9(MCInst &Inst, - unsigned S, - uint64_t Address, - const void *Decoder) { - Inst.addOperand(MCOperand::createImm(SignExtend32<9>(S))); +template +static DecodeStatus DecodeBranchTargetS(MCInst &Inst, unsigned InsnS, + uint64_t Address, const void *Decoder) { + + static_assert(B > 0, "field is empty"); + DecodeSymbolicOperandOff(Inst, Address, SignExtend32(InsnS), Decoder); return MCDisassembler::Success; } -static MCDisassembler::DecodeStatus DecodeBranchTargetS21(MCInst &Inst, - unsigned S, - uint64_t Address, - const void *Decoder) { - Inst.addOperand(MCOperand::createImm(SignExtend32<21>(S))); +template +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(maskTrailingOnes(B) & InsnS))); return MCDisassembler::Success; } -static MCDisassembler::DecodeStatus DecodeBranchTargetS25(MCInst &Inst, - unsigned S, - uint64_t Address, - const void *Decoder) { - Inst.addOperand(MCOperand::createImm(SignExtend32<25>(S))); +template +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(InsnS) : -1)); 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 @@ 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 @@ 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,36 @@ return MCDisassembler::Success; } -MCDisassembler::DecodeStatus ARCDisassembler::getInstruction( - MCInst &Instr, uint64_t &Size, ArrayRef 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"); + auto h = fieldFromInstruction(Insn, 5, 3) | + (fieldFromInstruction(Insn, 0, 2) << 3); + auto g = fieldFromInstruction(Insn, 8, 3) | + (fieldFromInstruction(Insn, 3, 2) << 3); + + auto DecodeRegisterOrImm = [&Inst, Address, Decoder](decltype(h) field, + decltype(Insn) value) { + if (30 == field) { + Inst.addOperand(MCOperand::createImm(value)); + return MCDisassembler::Success; + } + + return DecodeGPR32RegisterClass(Inst, field, 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 Bytes, + uint64_t Address, + raw_ostream &vStream, + raw_ostream &cStream) const { MCDisassembler::DecodeStatus Result; if (Bytes.size() < 2) { Size = 0; @@ -262,9 +320,9 @@ 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 +332,28 @@ } // 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, Index: lib/Target/ARC/InstPrinter/ARCInstPrinter.cpp =================================================================== --- lib/Target/ARC/InstPrinter/ARCInstPrinter.cpp +++ lib/Target/ARC/InstPrinter/ARCInstPrinter.cpp @@ -101,6 +101,12 @@ int Offset = 0; const MCSymbolRefExpr *SRE; + if (const auto *CE = dyn_cast(Expr)) { + OS << "0x"; + OS.write_hex(CE->getValue()); + return; + } + if (const auto *BE = dyn_cast(Expr)) { SRE = dyn_cast(BE->getLHS()); const auto *CE = dyn_cast(BE->getRHS()); Index: test/MC/Disassembler/ARC/alu.txt =================================================================== --- test/MC/Disassembler/ARC/alu.txt +++ test/MC/Disassembler/ARC/alu.txt @@ -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 Index: test/MC/Disassembler/ARC/compact.txt =================================================================== --- test/MC/Disassembler/ARC/compact.txt +++ test/MC/Disassembler/ARC/compact.txt @@ -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 Index: test/MC/Disassembler/ARC/misc.txt =================================================================== --- test/MC/Disassembler/ARC/misc.txt +++ test/MC/Disassembler/ARC/misc.txt @@ -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