mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-04-05 17:39:16 +00:00
X86: Fix Defs/Uses for insts that imp-def/imp-use both an A-register and EFLAGS.
This corrects a problem where x86 instructions that implicitly define/use both an A-register (RAX, EAX, ..) and EFLAGS were declared as only defining/using EFLAGS, because the outer "let Defs/Uses = [EFLAGS]" in the various multiclasses overrides the "let Defs/Uses = [areg]" in BinOpAI. The instructions deriving from BinOpAI were moved out of the "let Defs", and a BinOpAI_FF class was created, for instructions that implicitly define and use EFLAGS and the A-register (SBC, ADC). git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@182883 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
8ed5506e85
commit
8df6f4bc8b
@ -960,7 +960,7 @@ class BinOpMI8_F<string mnemonic, X86TypeInfo typeinfo,
|
||||
[(set EFLAGS, (opnode (load addr:$dst),
|
||||
typeinfo.Imm8Operator:$src))]>;
|
||||
|
||||
// BinOpAI - Instructions like "add %eax, %eax, imm".
|
||||
// BinOpAI - Instructions like "add %eax, %eax, imm", that imp-def EFLAGS.
|
||||
class BinOpAI<bits<8> opcode, string mnemonic, X86TypeInfo typeinfo,
|
||||
Register areg, string operands>
|
||||
: ITy<opcode, RawFrm, typeinfo,
|
||||
@ -968,10 +968,18 @@ class BinOpAI<bits<8> opcode, string mnemonic, X86TypeInfo typeinfo,
|
||||
mnemonic, operands, []>, Sched<[WriteALU]> {
|
||||
let ImmT = typeinfo.ImmEncoding;
|
||||
let Uses = [areg];
|
||||
let Defs = [areg];
|
||||
let Defs = [areg, EFLAGS];
|
||||
let hasSideEffects = 0;
|
||||
}
|
||||
|
||||
// BinOpAI_FF - Instructions like "adc %eax, %eax, imm", that implicitly define
|
||||
// and use EFLAGS.
|
||||
class BinOpAI_FF<bits<8> opcode, string mnemonic, X86TypeInfo typeinfo,
|
||||
Register areg, string operands>
|
||||
: BinOpAI<opcode, mnemonic, typeinfo, areg, operands> {
|
||||
let Uses = [areg, EFLAGS];
|
||||
}
|
||||
|
||||
/// ArithBinOp_RF - This is an arithmetic binary operator where the pattern is
|
||||
/// defined with "(set GPR:$dst, EFLAGS, (...".
|
||||
///
|
||||
@ -1030,16 +1038,16 @@ multiclass ArithBinOp_RF<bits<8> BaseOpc, bits<8> BaseOpc2, bits<8> BaseOpc4,
|
||||
def NAME#16mi : BinOpMI_RMW<mnemonic, Xi16, opnode, MemMRM>;
|
||||
def NAME#32mi : BinOpMI_RMW<mnemonic, Xi32, opnode, MemMRM>;
|
||||
def NAME#64mi32 : BinOpMI_RMW<mnemonic, Xi64, opnode, MemMRM>;
|
||||
} // Defs = [EFLAGS]
|
||||
|
||||
def NAME#8i8 : BinOpAI<BaseOpc4, mnemonic, Xi8 , AL,
|
||||
"{$src, %al|AL, $src}">;
|
||||
def NAME#16i16 : BinOpAI<BaseOpc4, mnemonic, Xi16, AX,
|
||||
"{$src, %ax|AX, $src}">;
|
||||
def NAME#32i32 : BinOpAI<BaseOpc4, mnemonic, Xi32, EAX,
|
||||
"{$src, %eax|EAX, $src}">;
|
||||
def NAME#64i32 : BinOpAI<BaseOpc4, mnemonic, Xi64, RAX,
|
||||
"{$src, %rax|RAX, $src}">;
|
||||
}
|
||||
def NAME#8i8 : BinOpAI<BaseOpc4, mnemonic, Xi8 , AL,
|
||||
"{$src, %al|AL, $src}">;
|
||||
def NAME#16i16 : BinOpAI<BaseOpc4, mnemonic, Xi16, AX,
|
||||
"{$src, %ax|AX, $src}">;
|
||||
def NAME#32i32 : BinOpAI<BaseOpc4, mnemonic, Xi32, EAX,
|
||||
"{$src, %eax|EAX, $src}">;
|
||||
def NAME#64i32 : BinOpAI<BaseOpc4, mnemonic, Xi64, RAX,
|
||||
"{$src, %rax|RAX, $src}">;
|
||||
}
|
||||
|
||||
/// ArithBinOp_RFF - This is an arithmetic binary operator where the pattern is
|
||||
@ -1052,7 +1060,7 @@ multiclass ArithBinOp_RFF<bits<8> BaseOpc, bits<8> BaseOpc2, bits<8> BaseOpc4,
|
||||
string mnemonic, Format RegMRM, Format MemMRM,
|
||||
SDNode opnode, bit CommutableRR,
|
||||
bit ConvertibleToThreeAddress> {
|
||||
let Defs = [EFLAGS] in {
|
||||
let Uses = [EFLAGS], Defs = [EFLAGS] in {
|
||||
let Constraints = "$src1 = $dst" in {
|
||||
let isCommutable = CommutableRR,
|
||||
isConvertibleToThreeAddress = ConvertibleToThreeAddress in {
|
||||
@ -1101,16 +1109,16 @@ multiclass ArithBinOp_RFF<bits<8> BaseOpc, bits<8> BaseOpc2, bits<8> BaseOpc4,
|
||||
def NAME#16mi : BinOpMI_RMW_FF<mnemonic, Xi16, opnode, MemMRM>;
|
||||
def NAME#32mi : BinOpMI_RMW_FF<mnemonic, Xi32, opnode, MemMRM>;
|
||||
def NAME#64mi32 : BinOpMI_RMW_FF<mnemonic, Xi64, opnode, MemMRM>;
|
||||
} // Uses = [EFLAGS], Defs = [EFLAGS]
|
||||
|
||||
def NAME#8i8 : BinOpAI<BaseOpc4, mnemonic, Xi8 , AL,
|
||||
"{$src, %al|AL, $src}">;
|
||||
def NAME#16i16 : BinOpAI<BaseOpc4, mnemonic, Xi16, AX,
|
||||
"{$src, %ax|AX, $src}">;
|
||||
def NAME#32i32 : BinOpAI<BaseOpc4, mnemonic, Xi32, EAX,
|
||||
"{$src, %eax|EAX, $src}">;
|
||||
def NAME#64i32 : BinOpAI<BaseOpc4, mnemonic, Xi64, RAX,
|
||||
"{$src, %rax|RAX, $src}">;
|
||||
}
|
||||
def NAME#8i8 : BinOpAI_FF<BaseOpc4, mnemonic, Xi8 , AL,
|
||||
"{$src, %al|AL, $src}">;
|
||||
def NAME#16i16 : BinOpAI_FF<BaseOpc4, mnemonic, Xi16, AX,
|
||||
"{$src, %ax|AX, $src}">;
|
||||
def NAME#32i32 : BinOpAI_FF<BaseOpc4, mnemonic, Xi32, EAX,
|
||||
"{$src, %eax|EAX, $src}">;
|
||||
def NAME#64i32 : BinOpAI_FF<BaseOpc4, mnemonic, Xi64, RAX,
|
||||
"{$src, %rax|RAX, $src}">;
|
||||
}
|
||||
|
||||
/// ArithBinOp_F - This is an arithmetic binary operator where the pattern is
|
||||
@ -1168,16 +1176,16 @@ multiclass ArithBinOp_F<bits<8> BaseOpc, bits<8> BaseOpc2, bits<8> BaseOpc4,
|
||||
def NAME#16mi : BinOpMI_F<mnemonic, Xi16, opnode, MemMRM>;
|
||||
def NAME#32mi : BinOpMI_F<mnemonic, Xi32, opnode, MemMRM>;
|
||||
def NAME#64mi32 : BinOpMI_F<mnemonic, Xi64, opnode, MemMRM>;
|
||||
} // Defs = [EFLAGS]
|
||||
|
||||
def NAME#8i8 : BinOpAI<BaseOpc4, mnemonic, Xi8 , AL,
|
||||
"{$src, %al|AL, $src}">;
|
||||
def NAME#16i16 : BinOpAI<BaseOpc4, mnemonic, Xi16, AX,
|
||||
"{$src, %ax|AX, $src}">;
|
||||
def NAME#32i32 : BinOpAI<BaseOpc4, mnemonic, Xi32, EAX,
|
||||
"{$src, %eax|EAX, $src}">;
|
||||
def NAME#64i32 : BinOpAI<BaseOpc4, mnemonic, Xi64, RAX,
|
||||
"{$src, %rax|RAX, $src}">;
|
||||
}
|
||||
def NAME#8i8 : BinOpAI<BaseOpc4, mnemonic, Xi8 , AL,
|
||||
"{$src, %al|AL, $src}">;
|
||||
def NAME#16i16 : BinOpAI<BaseOpc4, mnemonic, Xi16, AX,
|
||||
"{$src, %ax|AX, $src}">;
|
||||
def NAME#32i32 : BinOpAI<BaseOpc4, mnemonic, Xi32, EAX,
|
||||
"{$src, %eax|EAX, $src}">;
|
||||
def NAME#64i32 : BinOpAI<BaseOpc4, mnemonic, Xi64, RAX,
|
||||
"{$src, %rax|RAX, $src}">;
|
||||
}
|
||||
|
||||
|
||||
@ -1195,12 +1203,10 @@ defm SUB : ArithBinOp_RF<0x28, 0x2A, 0x2C, "sub", MRM5r, MRM5m,
|
||||
}
|
||||
|
||||
// Arithmetic.
|
||||
let Uses = [EFLAGS] in {
|
||||
defm ADC : ArithBinOp_RFF<0x10, 0x12, 0x14, "adc", MRM2r, MRM2m, X86adc_flag,
|
||||
1, 0>;
|
||||
defm SBB : ArithBinOp_RFF<0x18, 0x1A, 0x1C, "sbb", MRM3r, MRM3m, X86sbb_flag,
|
||||
0, 0>;
|
||||
}
|
||||
defm ADC : ArithBinOp_RFF<0x10, 0x12, 0x14, "adc", MRM2r, MRM2m, X86adc_flag,
|
||||
1, 0>;
|
||||
defm SBB : ArithBinOp_RFF<0x18, 0x1A, 0x1C, "sbb", MRM3r, MRM3m, X86sbb_flag,
|
||||
0, 0>;
|
||||
|
||||
let isCompare = 1 in {
|
||||
defm CMP : ArithBinOp_F<0x38, 0x3A, 0x3C, "cmp", MRM7r, MRM7m, X86cmp, 0, 0>;
|
||||
@ -1215,28 +1221,36 @@ defm CMP : ArithBinOp_F<0x38, 0x3A, 0x3C, "cmp", MRM7r, MRM7m, X86cmp, 0, 0>;
|
||||
def X86testpat : PatFrag<(ops node:$lhs, node:$rhs),
|
||||
(X86cmp (and_su node:$lhs, node:$rhs), 0)>;
|
||||
|
||||
let isCompare = 1, Defs = [EFLAGS] in {
|
||||
let isCommutable = 1 in {
|
||||
def TEST8rr : BinOpRR_F<0x84, "test", Xi8 , X86testpat, MRMSrcReg>;
|
||||
def TEST16rr : BinOpRR_F<0x84, "test", Xi16, X86testpat, MRMSrcReg>;
|
||||
def TEST32rr : BinOpRR_F<0x84, "test", Xi32, X86testpat, MRMSrcReg>;
|
||||
def TEST64rr : BinOpRR_F<0x84, "test", Xi64, X86testpat, MRMSrcReg>;
|
||||
} // isCommutable
|
||||
let isCompare = 1 in {
|
||||
let Defs = [EFLAGS] in {
|
||||
let isCommutable = 1 in {
|
||||
def TEST8rr : BinOpRR_F<0x84, "test", Xi8 , X86testpat, MRMSrcReg>;
|
||||
def TEST16rr : BinOpRR_F<0x84, "test", Xi16, X86testpat, MRMSrcReg>;
|
||||
def TEST32rr : BinOpRR_F<0x84, "test", Xi32, X86testpat, MRMSrcReg>;
|
||||
def TEST64rr : BinOpRR_F<0x84, "test", Xi64, X86testpat, MRMSrcReg>;
|
||||
} // isCommutable
|
||||
|
||||
def TEST8rm : BinOpRM_F<0x84, "test", Xi8 , X86testpat>;
|
||||
def TEST16rm : BinOpRM_F<0x84, "test", Xi16, X86testpat>;
|
||||
def TEST32rm : BinOpRM_F<0x84, "test", Xi32, X86testpat>;
|
||||
def TEST64rm : BinOpRM_F<0x84, "test", Xi64, X86testpat>;
|
||||
def TEST8rm : BinOpRM_F<0x84, "test", Xi8 , X86testpat>;
|
||||
def TEST16rm : BinOpRM_F<0x84, "test", Xi16, X86testpat>;
|
||||
def TEST32rm : BinOpRM_F<0x84, "test", Xi32, X86testpat>;
|
||||
def TEST64rm : BinOpRM_F<0x84, "test", Xi64, X86testpat>;
|
||||
|
||||
def TEST8ri : BinOpRI_F<0xF6, "test", Xi8 , X86testpat, MRM0r>;
|
||||
def TEST16ri : BinOpRI_F<0xF6, "test", Xi16, X86testpat, MRM0r>;
|
||||
def TEST32ri : BinOpRI_F<0xF6, "test", Xi32, X86testpat, MRM0r>;
|
||||
def TEST64ri32 : BinOpRI_F<0xF6, "test", Xi64, X86testpat, MRM0r>;
|
||||
def TEST8ri : BinOpRI_F<0xF6, "test", Xi8 , X86testpat, MRM0r>;
|
||||
def TEST16ri : BinOpRI_F<0xF6, "test", Xi16, X86testpat, MRM0r>;
|
||||
def TEST32ri : BinOpRI_F<0xF6, "test", Xi32, X86testpat, MRM0r>;
|
||||
def TEST64ri32 : BinOpRI_F<0xF6, "test", Xi64, X86testpat, MRM0r>;
|
||||
|
||||
def TEST8mi : BinOpMI_F<"test", Xi8 , X86testpat, MRM0m, 0xF6>;
|
||||
def TEST16mi : BinOpMI_F<"test", Xi16, X86testpat, MRM0m, 0xF6>;
|
||||
def TEST32mi : BinOpMI_F<"test", Xi32, X86testpat, MRM0m, 0xF6>;
|
||||
def TEST64mi32 : BinOpMI_F<"test", Xi64, X86testpat, MRM0m, 0xF6>;
|
||||
def TEST8mi : BinOpMI_F<"test", Xi8 , X86testpat, MRM0m, 0xF6>;
|
||||
def TEST16mi : BinOpMI_F<"test", Xi16, X86testpat, MRM0m, 0xF6>;
|
||||
def TEST32mi : BinOpMI_F<"test", Xi32, X86testpat, MRM0m, 0xF6>;
|
||||
def TEST64mi32 : BinOpMI_F<"test", Xi64, X86testpat, MRM0m, 0xF6>;
|
||||
|
||||
// When testing the result of EXTRACT_SUBREG sub_8bit_hi, make sure the
|
||||
// register class is constrained to GR8_NOREX.
|
||||
let isPseudo = 1 in
|
||||
def TEST8ri_NOREX : I<0, Pseudo, (outs), (ins GR8_NOREX:$src, i8imm:$mask),
|
||||
"", [], IIC_BIN_NONMEM>, Sched<[WriteALU]>;
|
||||
} // Defs = [EFLAGS]
|
||||
|
||||
def TEST8i8 : BinOpAI<0xA8, "test", Xi8 , AL,
|
||||
"{$src, %al|AL, $src}">;
|
||||
@ -1246,13 +1260,7 @@ let isCompare = 1, Defs = [EFLAGS] in {
|
||||
"{$src, %eax|EAX, $src}">;
|
||||
def TEST64i32 : BinOpAI<0xA8, "test", Xi64, RAX,
|
||||
"{$src, %rax|RAX, $src}">;
|
||||
|
||||
// When testing the result of EXTRACT_SUBREG sub_8bit_hi, make sure the
|
||||
// register class is constrained to GR8_NOREX.
|
||||
let isPseudo = 1 in
|
||||
def TEST8ri_NOREX : I<0, Pseudo, (outs), (ins GR8_NOREX:$src, i8imm:$mask),
|
||||
"", [], IIC_BIN_NONMEM>, Sched<[WriteALU]>;
|
||||
}
|
||||
} // isCompare
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// ANDN Instruction
|
||||
|
Loading…
x
Reference in New Issue
Block a user