Skip to content

Commit

Permalink
clang: Swich add register to register opcode
Browse files Browse the repository at this point in the history
03f1           add esi, ecx
  • Loading branch information
bwrsandman committed Dec 20, 2024
1 parent 59242dc commit baf6893
Show file tree
Hide file tree
Showing 2 changed files with 229 additions and 2 deletions.
218 changes: 216 additions & 2 deletions llvm/lib/Target/X86/X86InstrArithmetic.td
Original file line number Diff line number Diff line change
Expand Up @@ -832,6 +832,220 @@ multiclass ArithBinOp_RF<bits<8> BaseOpc, bits<8> BaseOpc2, bits<8> BaseOpc4,
def 64i32 : BinOpAI_AF<BaseOpc4, mnemonic, Xi64, RAX, "{$src, %rax|rax, $src}">;
}

multiclass BW1_ArithBinOp_RF<bits<8> BaseOpc, bits<8> BaseOpc2, bits<8> BaseOpc4,
string mnemonic, Format RegMRM, Format MemMRM,
SDNode opnodeflag, SDNode opnode,
bit CommutableRR, bit ConvertibleToThreeAddress,
bit ConvertibleToThreeAddressRR> {
let isCommutable = CommutableRR,
isConvertibleToThreeAddress = ConvertibleToThreeAddressRR in {
let Predicates = [NoNDD] in {
def 8rr : BW1_BinOpRR_RF<BaseOpc, mnemonic, Xi8 , opnodeflag>;
def 16rr : BW1_BinOpRR_RF<BaseOpc, mnemonic, Xi16, opnodeflag>, OpSize16;
def 32rr : BW1_BinOpRR_RF<BaseOpc, mnemonic, Xi32, opnodeflag>, OpSize32;
def 64rr : BW1_BinOpRR_RF<BaseOpc, mnemonic, Xi64, opnodeflag>;
}
let Predicates = [HasNDD, In64BitMode] in {
def 8rr_ND : BW1_BinOpRR_RF<BaseOpc, mnemonic, Xi8 , opnodeflag, 1>;
def 16rr_ND : BW1_BinOpRR_RF<BaseOpc, mnemonic, Xi16, opnodeflag, 1>, PD;
def 32rr_ND : BW1_BinOpRR_RF<BaseOpc, mnemonic, Xi32, opnodeflag, 1>;
def 64rr_ND : BW1_BinOpRR_RF<BaseOpc, mnemonic, Xi64, opnodeflag, 1>;
def 8rr_NF_ND : BinOpRR_R<BaseOpc, mnemonic, Xi8, 1>, EVEX_NF;
def 16rr_NF_ND : BinOpRR_R<BaseOpc, mnemonic, Xi16, 1>, EVEX_NF, PD;
def 32rr_NF_ND : BinOpRR_R<BaseOpc, mnemonic, Xi32, 1>, EVEX_NF;
def 64rr_NF_ND : BinOpRR_R<BaseOpc, mnemonic, Xi64, 1>, EVEX_NF;
}
let Predicates = [In64BitMode] in {
def 8rr_NF : BinOpRR_R<BaseOpc, mnemonic, Xi8>, NF;
def 16rr_NF : BinOpRR_R<BaseOpc, mnemonic, Xi16>, NF, PD;
def 32rr_NF : BinOpRR_R<BaseOpc, mnemonic, Xi32>, NF;
def 64rr_NF : BinOpRR_R<BaseOpc, mnemonic, Xi64>, NF;
def 8rr_EVEX : BW1_BinOpRR_RF<BaseOpc, mnemonic, Xi8 , null_frag>, PL;
def 16rr_EVEX : BW1_BinOpRR_RF<BaseOpc, mnemonic, Xi16, null_frag>, PL, PD;
def 32rr_EVEX : BW1_BinOpRR_RF<BaseOpc, mnemonic, Xi32, null_frag>, PL;
def 64rr_EVEX : BW1_BinOpRR_RF<BaseOpc, mnemonic, Xi64, null_frag>, PL;
}
}

def 8rr_REV : BW1_BinOpRR_RF_Rev<BaseOpc2, mnemonic, Xi8>;
def 16rr_REV : BW1_BinOpRR_RF_Rev<BaseOpc2, mnemonic, Xi16>, OpSize16;
def 32rr_REV : BW1_BinOpRR_RF_Rev<BaseOpc2, mnemonic, Xi32>, OpSize32;
def 64rr_REV : BW1_BinOpRR_RF_Rev<BaseOpc2, mnemonic, Xi64>;
let Predicates = [In64BitMode] in {
def 8rr_EVEX_REV : BW1_BinOpRR_RF_Rev<BaseOpc2, mnemonic, Xi8>, PL;
def 16rr_EVEX_REV : BW1_BinOpRR_RF_Rev<BaseOpc2, mnemonic, Xi16>, PL, PD;
def 32rr_EVEX_REV : BW1_BinOpRR_RF_Rev<BaseOpc2, mnemonic, Xi32>, PL;
def 64rr_EVEX_REV : BW1_BinOpRR_RF_Rev<BaseOpc2, mnemonic, Xi64>, PL;
def 8rr_ND_REV : BW1_BinOpRR_RF_Rev<BaseOpc2, mnemonic, Xi8, 1>;
def 16rr_ND_REV : BW1_BinOpRR_RF_Rev<BaseOpc2, mnemonic, Xi16, 1>, PD;
def 32rr_ND_REV : BW1_BinOpRR_RF_Rev<BaseOpc2, mnemonic, Xi32, 1>;
def 64rr_ND_REV : BW1_BinOpRR_RF_Rev<BaseOpc2, mnemonic, Xi64, 1>;
def 8rr_NF_REV : BinOpRR_R_Rev<BaseOpc2, mnemonic, Xi8>, NF;
def 16rr_NF_REV : BinOpRR_R_Rev<BaseOpc2, mnemonic, Xi16>, NF, PD;
def 32rr_NF_REV : BinOpRR_R_Rev<BaseOpc2, mnemonic, Xi32>, NF;
def 64rr_NF_REV : BinOpRR_R_Rev<BaseOpc2, mnemonic, Xi64>, NF;
def 8rr_NF_ND_REV : BinOpRR_R_Rev<BaseOpc2, mnemonic, Xi8, 1>, EVEX_NF;
def 16rr_NF_ND_REV : BinOpRR_R_Rev<BaseOpc2, mnemonic, Xi16, 1>, EVEX_NF, PD;
def 32rr_NF_ND_REV : BinOpRR_R_Rev<BaseOpc2, mnemonic, Xi32, 1>, EVEX_NF;
def 64rr_NF_ND_REV : BinOpRR_R_Rev<BaseOpc2, mnemonic, Xi64, 1>, EVEX_NF;
}

let Predicates = [NoNDD] in {
def 8rm : BinOpRM_RF<BaseOpc2, mnemonic, Xi8 , opnodeflag>;
def 16rm : BinOpRM_RF<BaseOpc2, mnemonic, Xi16, opnodeflag>, OpSize16;
def 32rm : BinOpRM_RF<BaseOpc2, mnemonic, Xi32, opnodeflag>, OpSize32;
def 64rm : BinOpRM_RF<BaseOpc2, mnemonic, Xi64, opnodeflag>;
}
let Predicates = [HasNDD, In64BitMode] in {
def 8rm_ND : BinOpRM_RF<BaseOpc2, mnemonic, Xi8 , opnodeflag, 1>;
def 16rm_ND : BinOpRM_RF<BaseOpc2, mnemonic, Xi16, opnodeflag, 1>, PD;
def 32rm_ND : BinOpRM_RF<BaseOpc2, mnemonic, Xi32, opnodeflag, 1>;
def 64rm_ND : BinOpRM_RF<BaseOpc2, mnemonic, Xi64, opnodeflag, 1>;
def 8rm_NF_ND : BinOpRM_R<BaseOpc2, mnemonic, Xi8, 1>, EVEX_NF;
def 16rm_NF_ND : BinOpRM_R<BaseOpc2, mnemonic, Xi16, 1>, EVEX_NF, PD;
def 32rm_NF_ND : BinOpRM_R<BaseOpc2, mnemonic, Xi32, 1>, EVEX_NF;
def 64rm_NF_ND : BinOpRM_R<BaseOpc2, mnemonic, Xi64, 1>, EVEX_NF;
}
let Predicates = [In64BitMode] in {
def 8rm_NF : BinOpRM_R<BaseOpc2, mnemonic, Xi8>, NF;
def 16rm_NF : BinOpRM_R<BaseOpc2, mnemonic, Xi16>, NF, PD;
def 32rm_NF : BinOpRM_R<BaseOpc2, mnemonic, Xi32>, NF;
def 64rm_NF : BinOpRM_R<BaseOpc2, mnemonic, Xi64>, NF;
def 8rm_EVEX : BinOpRM_RF<BaseOpc2, mnemonic, Xi8 , null_frag>, PL;
def 16rm_EVEX : BinOpRM_RF<BaseOpc2, mnemonic, Xi16, null_frag>, PL, PD;
def 32rm_EVEX : BinOpRM_RF<BaseOpc2, mnemonic, Xi32, null_frag>, PL;
def 64rm_EVEX : BinOpRM_RF<BaseOpc2, mnemonic, Xi64, null_frag>, PL;
}

let isConvertibleToThreeAddress = ConvertibleToThreeAddress in {
let Predicates = [NoNDD] in {
// NOTE: These are order specific, we want the ri8 forms to be listed
// first so that they are slightly preferred to the ri forms.
def 16ri8 : BinOpRI8_RF<0x83, mnemonic, Xi16, RegMRM>, OpSize16;
def 32ri8 : BinOpRI8_RF<0x83, mnemonic, Xi32, RegMRM>, OpSize32;
def 64ri8 : BinOpRI8_RF<0x83, mnemonic, Xi64, RegMRM>;
def 8ri : BinOpRI_RF<0x80, mnemonic, Xi8 , opnodeflag, RegMRM>;
def 16ri : BinOpRI_RF<0x81, mnemonic, Xi16, opnodeflag, RegMRM>, OpSize16;
def 32ri : BinOpRI_RF<0x81, mnemonic, Xi32, opnodeflag, RegMRM>, OpSize32;
def 64ri32: BinOpRI_RF<0x81, mnemonic, Xi64, opnodeflag, RegMRM>;
}
let Predicates = [HasNDD, In64BitMode] in {
def 16ri8_ND : BinOpRI8_RF<0x83, mnemonic, Xi16, RegMRM, 1>, PD;
def 32ri8_ND : BinOpRI8_RF<0x83, mnemonic, Xi32, RegMRM, 1>;
def 64ri8_ND : BinOpRI8_RF<0x83, mnemonic, Xi64, RegMRM, 1>;
def 8ri_ND : BinOpRI_RF<0x80, mnemonic, Xi8 , opnodeflag, RegMRM, 1>;
def 16ri_ND : BinOpRI_RF<0x81, mnemonic, Xi16, opnodeflag, RegMRM, 1>, PD;
def 32ri_ND : BinOpRI_RF<0x81, mnemonic, Xi32, opnodeflag, RegMRM, 1>;
def 64ri32_ND: BinOpRI_RF<0x81, mnemonic, Xi64, opnodeflag, RegMRM, 1>;
def 16ri8_NF_ND : BinOpRI8_R<0x83, mnemonic, Xi16, RegMRM, 1>, EVEX_NF, PD;
def 32ri8_NF_ND : BinOpRI8_R<0x83, mnemonic, Xi32, RegMRM, 1>, EVEX_NF;
def 64ri8_NF_ND : BinOpRI8_R<0x83, mnemonic, Xi64, RegMRM, 1>, EVEX_NF;
def 8ri_NF_ND : BinOpRI_R<0x80, mnemonic, Xi8, RegMRM, 1>, EVEX_NF;
def 16ri_NF_ND : BinOpRI_R<0x81, mnemonic, Xi16, RegMRM, 1>, EVEX_NF, PD;
def 32ri_NF_ND : BinOpRI_R<0x81, mnemonic, Xi32, RegMRM, 1>, EVEX_NF;
def 64ri32_NF_ND : BinOpRI_R<0x81, mnemonic, Xi64, RegMRM, 1>, EVEX_NF;
}
let Predicates = [In64BitMode] in {
def 16ri8_NF : BinOpRI8_R<0x83, mnemonic, Xi16, RegMRM>, NF, PD;
def 32ri8_NF : BinOpRI8_R<0x83, mnemonic, Xi32, RegMRM>, NF;
def 64ri8_NF : BinOpRI8_R<0x83, mnemonic, Xi64, RegMRM>, NF;
def 8ri_NF : BinOpRI_R<0x80, mnemonic, Xi8, RegMRM>, NF;
def 16ri_NF : BinOpRI_R<0x81, mnemonic, Xi16, RegMRM>, NF, PD;
def 32ri_NF : BinOpRI_R<0x81, mnemonic, Xi32, RegMRM>, NF;
def 64ri32_NF : BinOpRI_R<0x81, mnemonic, Xi64, RegMRM>, NF;
def 16ri8_EVEX : BinOpRI8_RF<0x83, mnemonic, Xi16, RegMRM>, PL, PD;
def 32ri8_EVEX : BinOpRI8_RF<0x83, mnemonic, Xi32, RegMRM>, PL;
def 64ri8_EVEX : BinOpRI8_RF<0x83, mnemonic, Xi64, RegMRM>, PL;
def 8ri_EVEX : BinOpRI_RF<0x80, mnemonic, Xi8 , null_frag, RegMRM>, PL;
def 16ri_EVEX : BinOpRI_RF<0x81, mnemonic, Xi16, null_frag, RegMRM>, PL, PD;
def 32ri_EVEX : BinOpRI_RF<0x81, mnemonic, Xi32, null_frag, RegMRM>, PL;
def 64ri32_EVEX: BinOpRI_RF<0x81, mnemonic, Xi64, null_frag, RegMRM>, PL;
}
}

def 8mr : BinOpMR_MF<BaseOpc, mnemonic, Xi8 , opnode>;
def 16mr : BinOpMR_MF<BaseOpc, mnemonic, Xi16, opnode>, OpSize16;
def 32mr : BinOpMR_MF<BaseOpc, mnemonic, Xi32, opnode>, OpSize32;
def 64mr : BinOpMR_MF<BaseOpc, mnemonic, Xi64, opnode>;
let Predicates = [HasNDD, In64BitMode] in {
defvar node = !if(!eq(CommutableRR, 0), opnode, null_frag);
def 8mr_ND : BinOpMR_RF<BaseOpc, mnemonic, Xi8 , node>;
def 16mr_ND : BinOpMR_RF<BaseOpc, mnemonic, Xi16, node>, PD;
def 32mr_ND : BinOpMR_RF<BaseOpc, mnemonic, Xi32, node>;
def 64mr_ND : BinOpMR_RF<BaseOpc, mnemonic, Xi64, node>;
def 8mr_NF_ND : BinOpMR_R<BaseOpc, mnemonic, Xi8>, EVEX_NF;
def 16mr_NF_ND : BinOpMR_R<BaseOpc, mnemonic, Xi16>, EVEX_NF, PD;
def 32mr_NF_ND : BinOpMR_R<BaseOpc, mnemonic, Xi32>, EVEX_NF;
def 64mr_NF_ND : BinOpMR_R<BaseOpc, mnemonic, Xi64>, EVEX_NF;
}
let Predicates = [In64BitMode] in {
def 8mr_NF : BinOpMR_M<BaseOpc, mnemonic, Xi8>, NF;
def 16mr_NF : BinOpMR_M<BaseOpc, mnemonic, Xi16>, NF, PD;
def 32mr_NF : BinOpMR_M<BaseOpc, mnemonic, Xi32>, NF;
def 64mr_NF : BinOpMR_M<BaseOpc, mnemonic, Xi64>, NF;
def 8mr_EVEX : BinOpMR_MF<BaseOpc, mnemonic, Xi8 , null_frag>, PL;
def 16mr_EVEX : BinOpMR_MF<BaseOpc, mnemonic, Xi16, null_frag>, PL, PD;
def 32mr_EVEX : BinOpMR_MF<BaseOpc, mnemonic, Xi32, null_frag>, PL;
def 64mr_EVEX : BinOpMR_MF<BaseOpc, mnemonic, Xi64, null_frag>, PL;
}

// NOTE: These are order specific, we want the mi8 forms to be listed
// first so that they are slightly preferred to the mi forms.
def 16mi8 : BinOpMI8_MF<mnemonic, Xi16, MemMRM>, OpSize16;
def 32mi8 : BinOpMI8_MF<mnemonic, Xi32, MemMRM>, OpSize32;
let Predicates = [In64BitMode] in
def 64mi8 : BinOpMI8_MF<mnemonic, Xi64, MemMRM>;
def 8mi : BinOpMI_MF<0x80, mnemonic, Xi8 , opnode, MemMRM>;
def 16mi : BinOpMI_MF<0x81, mnemonic, Xi16, opnode, MemMRM>, OpSize16;
def 32mi : BinOpMI_MF<0x81, mnemonic, Xi32, opnode, MemMRM>, OpSize32;
let Predicates = [In64BitMode] in
def 64mi32 : BinOpMI_MF<0x81, mnemonic, Xi64, opnode, MemMRM>;
let Predicates = [HasNDD, In64BitMode] in {
def 16mi8_ND : BinOpMI8_RF<mnemonic, Xi16, MemMRM>, PD;
def 32mi8_ND : BinOpMI8_RF<mnemonic, Xi32, MemMRM>;
def 64mi8_ND : BinOpMI8_RF<mnemonic, Xi64, MemMRM>;
def 8mi_ND : BinOpMI_RF<0x80, mnemonic, Xi8 , opnode, MemMRM>;
def 16mi_ND : BinOpMI_RF<0x81, mnemonic, Xi16, opnode, MemMRM>, PD;
def 32mi_ND : BinOpMI_RF<0x81, mnemonic, Xi32, opnode, MemMRM>;
def 64mi32_ND : BinOpMI_RF<0x81, mnemonic, Xi64, opnode, MemMRM>;
def 16mi8_NF_ND : BinOpMI8_R<mnemonic, Xi16, MemMRM>, NF, PD;
def 32mi8_NF_ND : BinOpMI8_R<mnemonic, Xi32, MemMRM>, NF;
def 64mi8_NF_ND : BinOpMI8_R<mnemonic, Xi64, MemMRM>, NF;
def 8mi_NF_ND : BinOpMI_R<0x80, mnemonic, Xi8, MemMRM>, NF;
def 16mi_NF_ND : BinOpMI_R<0x81, mnemonic, Xi16, MemMRM>, NF, PD;
def 32mi_NF_ND : BinOpMI_R<0x81, mnemonic, Xi32, MemMRM>, NF;
def 64mi32_NF_ND : BinOpMI_R<0x81, mnemonic, Xi64, MemMRM>, NF;
}
let Predicates = [In64BitMode] in {
def 16mi8_NF : BinOpMI8_M<mnemonic, Xi16, MemMRM>, NF, PD;
def 32mi8_NF : BinOpMI8_M<mnemonic, Xi32, MemMRM>, NF;
def 64mi8_NF : BinOpMI8_M<mnemonic, Xi64, MemMRM>, NF;
def 8mi_NF : BinOpMI_M<0x80, mnemonic, Xi8, MemMRM>, NF;
def 16mi_NF : BinOpMI_M<0x81, mnemonic, Xi16, MemMRM>, NF, PD;
def 32mi_NF : BinOpMI_M<0x81, mnemonic, Xi32, MemMRM>, NF;
def 64mi32_NF : BinOpMI_M<0x81, mnemonic, Xi64, MemMRM>, NF;
def 16mi8_EVEX : BinOpMI8_MF<mnemonic, Xi16, MemMRM>, PL, PD;
def 32mi8_EVEX : BinOpMI8_MF<mnemonic, Xi32, MemMRM>, PL;
def 64mi8_EVEX : BinOpMI8_MF<mnemonic, Xi64, MemMRM>, PL;
def 8mi_EVEX : BinOpMI_MF<0x80, mnemonic, Xi8 , null_frag, MemMRM>, PL;
def 16mi_EVEX : BinOpMI_MF<0x81, mnemonic, Xi16, null_frag, MemMRM>, PL, PD;
def 32mi_EVEX : BinOpMI_MF<0x81, mnemonic, Xi32, null_frag, MemMRM>, PL;
def 64mi32_EVEX : BinOpMI_MF<0x81, mnemonic, Xi64, null_frag, MemMRM>, PL;
}

// These are for the disassembler since 0x82 opcode behaves like 0x80, but
// not in 64-bit mode.
let Predicates = [Not64BitMode] in {
def 8ri8 : BinOpRI8_RF<0x82, mnemonic, Xi8, RegMRM>, DisassembleOnly;
def 8mi8 : BinOpMI8_MF<mnemonic, Xi8, MemMRM>, DisassembleOnly;
}

def 8i8 : BinOpAI_AF<BaseOpc4, mnemonic, Xi8 , AL, "{$src, %al|al, $src}">;
def 16i16 : BinOpAI_AF<BaseOpc4, mnemonic, Xi16, AX, "{$src, %ax|ax, $src}">, OpSize16;
def 32i32 : BinOpAI_AF<BaseOpc4, mnemonic, Xi32, EAX, "{$src, %eax|eax, $src}">, OpSize32;
def 64i32 : BinOpAI_AF<BaseOpc4, mnemonic, Xi64, RAX, "{$src, %rax|rax, $src}">;
}

/// ArithBinOp_RFF - This is an arithmetic binary operator where the pattern is
/// defined with "(set GPR:$dst, EFLAGS, (node LHS, RHS, EFLAGS))" like ADC and
/// SBB.
Expand Down Expand Up @@ -1080,8 +1294,8 @@ defm OR : ArithBinOp_RF<0x09, 0x0B, 0x0D, "or", MRM1r, MRM1m,
X86or_flag, or, 1, 0, 0>;
defm XOR : ArithBinOp_RF<0x31, 0x33, 0x35, "xor", MRM6r, MRM6m,
X86xor_flag, xor, 1, 0, 0>;
defm ADD : ArithBinOp_RF<0x01, 0x03, 0x05, "add", MRM0r, MRM0m,
X86add_flag, add, 1, 1, 1>;
defm ADD : BW1_ArithBinOp_RF<0x03, 0x01, 0x05, "add", MRM0r, MRM0m,
X86add_flag, add, 1, 1, 1>;
let isCompare = 1 in {
defm SUB : ArithBinOp_RF<0x29, 0x2B, 0x2D, "sub", MRM5r, MRM5m,
X86sub_flag, sub, 0, 1, 0>;
Expand Down
13 changes: 13 additions & 0 deletions llvm/lib/Target/X86/X86InstrUtils.td
Original file line number Diff line number Diff line change
Expand Up @@ -1004,6 +1004,19 @@ class BinOpRR_RF_Rev<bits<8> o, string m, X86TypeInfo t, bit ndd = 0>
: BinOpRR_RF<o, m, t, null_frag, ndd>, DisassembleOnly {
let Form = MRMSrcReg;
}

class BW1_BinOpRR_RF<bits<8> o, string m, X86TypeInfo t, SDPatternOperator node, bit ndd = 0>
: BinOpRR<o, m, !if(!eq(ndd, 0), binop_args, binop_ndd_args), t,
(outs t.RegClass:$dst),
[(set t.RegClass:$dst, EFLAGS,
(node t.RegClass:$src1, t.RegClass:$src2))]>, DefEFLAGS, NDD<ndd> {
let Form = MRMSrcReg;
}
class BW1_BinOpRR_RF_Rev<bits<8> o, string m, X86TypeInfo t, bit ndd = 0>
: BinOpRR_RF<o, m, t, null_frag, ndd>, DisassembleOnly {
let Form = MRMDestReg;
}

// BinOpRRF_RF - Instructions that read "reg, reg", write "reg" and read/write
// EFLAGS.
class BinOpRRF_RF<bits<8> o, string m, X86TypeInfo t, SDPatternOperator node = null_frag, bit ndd = 0>
Expand Down

0 comments on commit baf6893

Please sign in to comment.