[X86] Allow any 8-bit immediate to be used with BT/BTC/BTR/BTS not just sign extended 8-bit immediates.

We need to allow [128,255] in addition to [-128, 127] to match gas.

llvm-svn: 356413
This commit is contained in:
Craig Topper 2019-03-18 21:33:59 +00:00
parent b4a3b29d16
commit e732bc6bea
4 changed files with 116 additions and 30 deletions

View File

@ -695,6 +695,14 @@ def u8imm : Operand<i8> {
let OperandType = "OPERAND_IMMEDIATE";
}
// 16-bit immediate but only 8-bits are significant and they are unsigned.
// Used by BT instructions.
def i16u8imm : Operand<i16> {
let PrintMethod = "printU8Imm";
let ParserMatchClass = ImmUnsignedi8AsmOperand;
let OperandType = "OPERAND_IMMEDIATE";
}
// 32-bit immediate but only 8-bits are significant and they are unsigned.
// Used by some SSE/AVX instructions that use intrinsics.
def i32u8imm : Operand<i32> {
@ -703,6 +711,14 @@ def i32u8imm : Operand<i32> {
let OperandType = "OPERAND_IMMEDIATE";
}
// 64-bit immediate but only 8-bits are significant and they are unsigned.
// Used by BT instructions.
def i64u8imm : Operand<i64> {
let PrintMethod = "printU8Imm";
let ParserMatchClass = ImmUnsignedi8AsmOperand;
let OperandType = "OPERAND_IMMEDIATE";
}
// 64-bits but only 32 bits are significant, and those bits are treated as being
// pc relative.
def i64i32imm_pcrel : Operand<i64> {
@ -1747,36 +1763,36 @@ let mayLoad = 1, hasSideEffects = 0, SchedRW = [WriteBitTestRegLd] in {
}
let SchedRW = [WriteBitTest] in {
def BT16ri8 : Ii8<0xBA, MRM4r, (outs), (ins GR16:$src1, i16i8imm:$src2),
def BT16ri8 : Ii8<0xBA, MRM4r, (outs), (ins GR16:$src1, i16u8imm:$src2),
"bt{w}\t{$src2, $src1|$src1, $src2}",
[(set EFLAGS, (X86bt GR16:$src1, i16immSExt8:$src2))]>,
[(set EFLAGS, (X86bt GR16:$src1, imm:$src2))]>,
OpSize16, TB;
def BT32ri8 : Ii8<0xBA, MRM4r, (outs), (ins GR32:$src1, i32i8imm:$src2),
def BT32ri8 : Ii8<0xBA, MRM4r, (outs), (ins GR32:$src1, i32u8imm:$src2),
"bt{l}\t{$src2, $src1|$src1, $src2}",
[(set EFLAGS, (X86bt GR32:$src1, i32immSExt8:$src2))]>,
[(set EFLAGS, (X86bt GR32:$src1, imm:$src2))]>,
OpSize32, TB;
def BT64ri8 : RIi8<0xBA, MRM4r, (outs), (ins GR64:$src1, i64i8imm:$src2),
def BT64ri8 : RIi8<0xBA, MRM4r, (outs), (ins GR64:$src1, i64u8imm:$src2),
"bt{q}\t{$src2, $src1|$src1, $src2}",
[(set EFLAGS, (X86bt GR64:$src1, i64immSExt8:$src2))]>, TB;
[(set EFLAGS, (X86bt GR64:$src1, imm:$src2))]>, TB;
} // SchedRW
// Note that these instructions aren't slow because that only applies when the
// other operand is in a register. When it's an immediate, bt is still fast.
let SchedRW = [WriteBitTestImmLd] in {
def BT16mi8 : Ii8<0xBA, MRM4m, (outs), (ins i16mem:$src1, i16i8imm:$src2),
def BT16mi8 : Ii8<0xBA, MRM4m, (outs), (ins i16mem:$src1, i16u8imm:$src2),
"bt{w}\t{$src2, $src1|$src1, $src2}",
[(set EFLAGS, (X86bt (loadi16 addr:$src1),
i16immSExt8:$src2))]>,
imm:$src2))]>,
OpSize16, TB;
def BT32mi8 : Ii8<0xBA, MRM4m, (outs), (ins i32mem:$src1, i32i8imm:$src2),
def BT32mi8 : Ii8<0xBA, MRM4m, (outs), (ins i32mem:$src1, i32u8imm:$src2),
"bt{l}\t{$src2, $src1|$src1, $src2}",
[(set EFLAGS, (X86bt (loadi32 addr:$src1),
i32immSExt8:$src2))]>,
imm:$src2))]>,
OpSize32, TB;
def BT64mi8 : RIi8<0xBA, MRM4m, (outs), (ins i64mem:$src1, i64i8imm:$src2),
def BT64mi8 : RIi8<0xBA, MRM4m, (outs), (ins i64mem:$src1, i64u8imm:$src2),
"bt{q}\t{$src2, $src1|$src1, $src2}",
[(set EFLAGS, (X86bt (loadi64 addr:$src1),
i64immSExt8:$src2))]>, TB,
imm:$src2))]>, TB,
Requires<[In64BitMode]>;
} // SchedRW
@ -1806,20 +1822,20 @@ def BTC64mr : RI<0xBB, MRMDestMem, (outs), (ins i64mem:$src1, GR64:$src2),
}
let SchedRW = [WriteBitTestSet], Constraints = "$src1 = $dst" in {
def BTC16ri8 : Ii8<0xBA, MRM7r, (outs GR16:$dst), (ins GR16:$src1, i16i8imm:$src2),
def BTC16ri8 : Ii8<0xBA, MRM7r, (outs GR16:$dst), (ins GR16:$src1, i16u8imm:$src2),
"btc{w}\t{$src2, $src1|$src1, $src2}", []>, OpSize16, TB;
def BTC32ri8 : Ii8<0xBA, MRM7r, (outs GR32:$dst), (ins GR32:$src1, i32i8imm:$src2),
def BTC32ri8 : Ii8<0xBA, MRM7r, (outs GR32:$dst), (ins GR32:$src1, i32u8imm:$src2),
"btc{l}\t{$src2, $src1|$src1, $src2}", []>, OpSize32, TB;
def BTC64ri8 : RIi8<0xBA, MRM7r, (outs GR64:$dst), (ins GR64:$src1, i64i8imm:$src2),
def BTC64ri8 : RIi8<0xBA, MRM7r, (outs GR64:$dst), (ins GR64:$src1, i64u8imm:$src2),
"btc{q}\t{$src2, $src1|$src1, $src2}", []>, TB;
} // SchedRW
let mayLoad = 1, mayStore = 1, SchedRW = [WriteBitTestSetImmRMW] in {
def BTC16mi8 : Ii8<0xBA, MRM7m, (outs), (ins i16mem:$src1, i16i8imm:$src2),
def BTC16mi8 : Ii8<0xBA, MRM7m, (outs), (ins i16mem:$src1, i16u8imm:$src2),
"btc{w}\t{$src2, $src1|$src1, $src2}", []>, OpSize16, TB;
def BTC32mi8 : Ii8<0xBA, MRM7m, (outs), (ins i32mem:$src1, i32i8imm:$src2),
def BTC32mi8 : Ii8<0xBA, MRM7m, (outs), (ins i32mem:$src1, i32u8imm:$src2),
"btc{l}\t{$src2, $src1|$src1, $src2}", []>, OpSize32, TB;
def BTC64mi8 : RIi8<0xBA, MRM7m, (outs), (ins i64mem:$src1, i64i8imm:$src2),
def BTC64mi8 : RIi8<0xBA, MRM7m, (outs), (ins i64mem:$src1, i64u8imm:$src2),
"btc{q}\t{$src2, $src1|$src1, $src2}", []>, TB,
Requires<[In64BitMode]>;
}
@ -1849,24 +1865,24 @@ def BTR64mr : RI<0xB3, MRMDestMem, (outs), (ins i64mem:$src1, GR64:$src2),
}
let SchedRW = [WriteBitTestSet], Constraints = "$src1 = $dst" in {
def BTR16ri8 : Ii8<0xBA, MRM6r, (outs GR16:$dst), (ins GR16:$src1, i16i8imm:$src2),
def BTR16ri8 : Ii8<0xBA, MRM6r, (outs GR16:$dst), (ins GR16:$src1, i16u8imm:$src2),
"btr{w}\t{$src2, $src1|$src1, $src2}", []>,
OpSize16, TB;
def BTR32ri8 : Ii8<0xBA, MRM6r, (outs GR32:$dst), (ins GR32:$src1, i32i8imm:$src2),
def BTR32ri8 : Ii8<0xBA, MRM6r, (outs GR32:$dst), (ins GR32:$src1, i32u8imm:$src2),
"btr{l}\t{$src2, $src1|$src1, $src2}", []>,
OpSize32, TB;
def BTR64ri8 : RIi8<0xBA, MRM6r, (outs GR64:$dst), (ins GR64:$src1, i64i8imm:$src2),
def BTR64ri8 : RIi8<0xBA, MRM6r, (outs GR64:$dst), (ins GR64:$src1, i64u8imm:$src2),
"btr{q}\t{$src2, $src1|$src1, $src2}", []>, TB;
} // SchedRW
let mayLoad = 1, mayStore = 1, SchedRW = [WriteBitTestSetImmRMW] in {
def BTR16mi8 : Ii8<0xBA, MRM6m, (outs), (ins i16mem:$src1, i16i8imm:$src2),
def BTR16mi8 : Ii8<0xBA, MRM6m, (outs), (ins i16mem:$src1, i16u8imm:$src2),
"btr{w}\t{$src2, $src1|$src1, $src2}", []>,
OpSize16, TB;
def BTR32mi8 : Ii8<0xBA, MRM6m, (outs), (ins i32mem:$src1, i32i8imm:$src2),
def BTR32mi8 : Ii8<0xBA, MRM6m, (outs), (ins i32mem:$src1, i32u8imm:$src2),
"btr{l}\t{$src2, $src1|$src1, $src2}", []>,
OpSize32, TB;
def BTR64mi8 : RIi8<0xBA, MRM6m, (outs), (ins i64mem:$src1, i64i8imm:$src2),
def BTR64mi8 : RIi8<0xBA, MRM6m, (outs), (ins i64mem:$src1, i64u8imm:$src2),
"btr{q}\t{$src2, $src1|$src1, $src2}", []>, TB,
Requires<[In64BitMode]>;
}
@ -1896,20 +1912,20 @@ def BTS64mr : RI<0xAB, MRMDestMem, (outs), (ins i64mem:$src1, GR64:$src2),
}
let SchedRW = [WriteBitTestSet], Constraints = "$src1 = $dst" in {
def BTS16ri8 : Ii8<0xBA, MRM5r, (outs GR16:$dst), (ins GR16:$src1, i16i8imm:$src2),
def BTS16ri8 : Ii8<0xBA, MRM5r, (outs GR16:$dst), (ins GR16:$src1, i16u8imm:$src2),
"bts{w}\t{$src2, $src1|$src1, $src2}", []>, OpSize16, TB;
def BTS32ri8 : Ii8<0xBA, MRM5r, (outs GR32:$dst), (ins GR32:$src1, i32i8imm:$src2),
def BTS32ri8 : Ii8<0xBA, MRM5r, (outs GR32:$dst), (ins GR32:$src1, i32u8imm:$src2),
"bts{l}\t{$src2, $src1|$src1, $src2}", []>, OpSize32, TB;
def BTS64ri8 : RIi8<0xBA, MRM5r, (outs GR64:$dst), (ins GR64:$src1, i64i8imm:$src2),
def BTS64ri8 : RIi8<0xBA, MRM5r, (outs GR64:$dst), (ins GR64:$src1, i64u8imm:$src2),
"bts{q}\t{$src2, $src1|$src1, $src2}", []>, TB;
} // SchedRW
let mayLoad = 1, mayStore = 1, SchedRW = [WriteBitTestSetImmRMW] in {
def BTS16mi8 : Ii8<0xBA, MRM5m, (outs), (ins i16mem:$src1, i16i8imm:$src2),
def BTS16mi8 : Ii8<0xBA, MRM5m, (outs), (ins i16mem:$src1, i16u8imm:$src2),
"bts{w}\t{$src2, $src1|$src1, $src2}", []>, OpSize16, TB;
def BTS32mi8 : Ii8<0xBA, MRM5m, (outs), (ins i32mem:$src1, i32i8imm:$src2),
def BTS32mi8 : Ii8<0xBA, MRM5m, (outs), (ins i32mem:$src1, i32u8imm:$src2),
"bts{l}\t{$src2, $src1|$src1, $src2}", []>, OpSize32, TB;
def BTS64mi8 : RIi8<0xBA, MRM5m, (outs), (ins i64mem:$src1, i64i8imm:$src2),
def BTS64mi8 : RIi8<0xBA, MRM5m, (outs), (ins i64mem:$src1, i64u8imm:$src2),
"bts{q}\t{$src2, $src1|$src1, $src2}", []>, TB,
Requires<[In64BitMode]>;
}

View File

@ -12,6 +12,14 @@ bsrl %eax, %eax
// CHECK: encoding: [0x0f,0xba,0xf8,0x00]
btcl $0, %eax
// CHECK: btcl $255, %eax
// CHECK: encoding: [0x0f,0xba,0xf8,0xff]
btcl $-1, %eax
// CHECK: btcl $255, %eax
// CHECK: encoding: [0x0f,0xba,0xf8,0xff]
btcl $255, %eax
// CHECK: btcl %eax, %eax
// CHECK: encoding: [0x0f,0xbb,0xc0]
btcl %eax, %eax
@ -20,6 +28,14 @@ btcl %eax, %eax
// CHECK: encoding: [0x0f,0xba,0xe0,0x00]
btl $0, %eax
// CHECK: btl $255, %eax
// CHECK: encoding: [0x0f,0xba,0xe0,0xff]
btl $-1, %eax
// CHECK: btl $255, %eax
// CHECK: encoding: [0x0f,0xba,0xe0,0xff]
btl $255, %eax
// CHECK: btl %eax, %eax
// CHECK: encoding: [0x0f,0xa3,0xc0]
btl %eax, %eax
@ -28,6 +44,14 @@ btl %eax, %eax
// CHECK: encoding: [0x0f,0xba,0xf0,0x00]
btrl $0, %eax
// CHECK: btrl $255, %eax
// CHECK: encoding: [0x0f,0xba,0xf0,0xff]
btrl $-1, %eax
// CHECK: btrl $255, %eax
// CHECK: encoding: [0x0f,0xba,0xf0,0xff]
btrl $255, %eax
// CHECK: btrl %eax, %eax
// CHECK: encoding: [0x0f,0xb3,0xc0]
btrl %eax, %eax
@ -36,6 +60,14 @@ btrl %eax, %eax
// CHECK: encoding: [0x0f,0xba,0xe8,0x00]
btsl $0, %eax
// CHECK: btsl $255, %eax
// CHECK: encoding: [0x0f,0xba,0xe8,0xff]
btsl $-1, %eax
// CHECK: btsl $255, %eax
// CHECK: encoding: [0x0f,0xba,0xe8,0xff]
btsl $255, %eax
// CHECK: btsl %eax, %eax
// CHECK: encoding: [0x0f,0xab,0xc0]
btsl %eax, %eax

View File

@ -12,6 +12,14 @@ bsrl %r13d, %r13d
// CHECK: encoding: [0x41,0x0f,0xba,0xfd,0x00]
btcl $0, %r13d
// CHECK: btcl $255, %r13d
// CHECK: encoding: [0x41,0x0f,0xba,0xfd,0xff]
btcl $-1, %r13d
// CHECK: btcl $255, %r13d
// CHECK: encoding: [0x41,0x0f,0xba,0xfd,0xff]
btcl $255, %r13d
// CHECK: btcl %r13d, %r13d
// CHECK: encoding: [0x45,0x0f,0xbb,0xed]
btcl %r13d, %r13d
@ -20,6 +28,14 @@ btcl %r13d, %r13d
// CHECK: encoding: [0x41,0x0f,0xba,0xe5,0x00]
btl $0, %r13d
// CHECK: btl $255, %r13d
// CHECK: encoding: [0x41,0x0f,0xba,0xe5,0xff]
btl $-1, %r13d
// CHECK: btl $255, %r13d
// CHECK: encoding: [0x41,0x0f,0xba,0xe5,0xff]
btl $255, %r13d
// CHECK: btl %r13d, %r13d
// CHECK: encoding: [0x45,0x0f,0xa3,0xed]
btl %r13d, %r13d
@ -28,6 +44,14 @@ btl %r13d, %r13d
// CHECK: encoding: [0x41,0x0f,0xba,0xf5,0x00]
btrl $0, %r13d
// CHECK: btrl $255, %r13d
// CHECK: encoding: [0x41,0x0f,0xba,0xf5,0xff]
btrl $-1, %r13d
// CHECK: btrl $255, %r13d
// CHECK: encoding: [0x41,0x0f,0xba,0xf5,0xff]
btrl $255, %r13d
// CHECK: btrl %r13d, %r13d
// CHECK: encoding: [0x45,0x0f,0xb3,0xed]
btrl %r13d, %r13d
@ -36,6 +60,14 @@ btrl %r13d, %r13d
// CHECK: encoding: [0x41,0x0f,0xba,0xed,0x00]
btsl $0, %r13d
// CHECK: btsl $255, %r13d
// CHECK: encoding: [0x41,0x0f,0xba,0xed,0xff]
btsl $-1, %r13d
// CHECK: btsl $255, %r13d
// CHECK: encoding: [0x41,0x0f,0xba,0xed,0xff]
btsl $255, %r13d
// CHECK: btsl %r13d, %r13d
// CHECK: encoding: [0x45,0x0f,0xab,0xed]
btsl %r13d, %r13d

View File

@ -824,7 +824,9 @@ OperandType RecognizableInstr::typeFromString(const std::string &s,
TYPE("i8mem", TYPE_M)
TYPE("i8imm", TYPE_IMM)
TYPE("u8imm", TYPE_UIMM8)
TYPE("i16u8imm", TYPE_UIMM8)
TYPE("i32u8imm", TYPE_UIMM8)
TYPE("i64u8imm", TYPE_UIMM8)
TYPE("GR8", TYPE_R8)
TYPE("VR128", TYPE_XMM)
TYPE("VR128X", TYPE_XMM)
@ -935,7 +937,9 @@ RecognizableInstr::immediateEncodingFromString(const std::string &s,
ENCODING("i64i8imm", ENCODING_IB)
ENCODING("i8imm", ENCODING_IB)
ENCODING("u8imm", ENCODING_IB)
ENCODING("i16u8imm", ENCODING_IB)
ENCODING("i32u8imm", ENCODING_IB)
ENCODING("i64u8imm", ENCODING_IB)
// This is not a typo. Instructions like BLENDVPD put
// register IDs in 8-bit immediates nowadays.
ENCODING("FR32", ENCODING_IB)
@ -1121,7 +1125,9 @@ RecognizableInstr::relocationEncodingFromString(const std::string &s,
ENCODING("i64i8imm", ENCODING_IB)
ENCODING("i8imm", ENCODING_IB)
ENCODING("u8imm", ENCODING_IB)
ENCODING("i16u8imm", ENCODING_IB)
ENCODING("i32u8imm", ENCODING_IB)
ENCODING("i64u8imm", ENCODING_IB)
ENCODING("i64i32imm_pcrel", ENCODING_ID)
ENCODING("i16imm_pcrel", ENCODING_IW)
ENCODING("i32imm_pcrel", ENCODING_ID)