Teach disassembler to handle illegal immediates on (v)cmpps/pd/ss/sd instructions. Instead of rejecting we'll just generate the _alt forms that don't try to alter the mnemonic. While I'm here, merge some common code in the Instruction printers for the condition code replacement and fix the mask on SSE to be 3-bits instead of 4.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@224846 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Craig Topper 2014-12-26 06:36:28 +00:00
parent 50d894e4d3
commit 654a66dbd3
6 changed files with 84 additions and 71 deletions

View File

@ -350,6 +350,54 @@ static void translateImmediate(MCInst &mcInst, uint64_t immediate,
case ENCODING_IO:
break;
}
} else if (type == TYPE_IMM3) {
// Check for immediates that printSSECC can't handle.
if (immediate >= 8) {
unsigned NewOpc;
switch (mcInst.getOpcode()) {
default: llvm_unreachable("unexpected opcode");
case X86::CMPPDrmi: NewOpc = X86::CMPPDrmi_alt; break;
case X86::CMPPDrri: NewOpc = X86::CMPPDrri_alt; break;
case X86::CMPPSrmi: NewOpc = X86::CMPPSrmi_alt; break;
case X86::CMPPSrri: NewOpc = X86::CMPPSrri_alt; break;
case X86::CMPSDrm: NewOpc = X86::CMPSDrm_alt; break;
case X86::CMPSDrr: NewOpc = X86::CMPSDrr_alt; break;
case X86::CMPSSrm: NewOpc = X86::CMPSSrm_alt; break;
case X86::CMPSSrr: NewOpc = X86::CMPSSrr_alt; break;
}
// Switch opcode to the one that doesn't get special printing.
mcInst.setOpcode(NewOpc);
}
} else if (type == TYPE_IMM5) {
// Check for immediates that printAVXCC can't handle.
if (immediate >= 32) {
unsigned NewOpc;
switch (mcInst.getOpcode()) {
default: llvm_unreachable("unexpected opcode");
case X86::VCMPPDrmi: NewOpc = X86::VCMPPDrmi_alt; break;
case X86::VCMPPDrri: NewOpc = X86::VCMPPDrri_alt; break;
case X86::VCMPPSrmi: NewOpc = X86::VCMPPSrmi_alt; break;
case X86::VCMPPSrri: NewOpc = X86::VCMPPSrri_alt; break;
case X86::VCMPSDrm: NewOpc = X86::VCMPSDrm_alt; break;
case X86::VCMPSDrr: NewOpc = X86::VCMPSDrr_alt; break;
case X86::VCMPSSrm: NewOpc = X86::VCMPSSrm_alt; break;
case X86::VCMPSSrr: NewOpc = X86::VCMPSSrr_alt; break;
case X86::VCMPPDYrmi: NewOpc = X86::VCMPPDYrmi_alt; break;
case X86::VCMPPDYrri: NewOpc = X86::VCMPPDYrri_alt; break;
case X86::VCMPPSYrmi: NewOpc = X86::VCMPPSYrmi_alt; break;
case X86::VCMPPSYrri: NewOpc = X86::VCMPPSYrri_alt; break;
case X86::VCMPPDZrmi: NewOpc = X86::VCMPPDZrmi_alt; break;
case X86::VCMPPDZrri: NewOpc = X86::VCMPPDZrri_alt; break;
case X86::VCMPPSZrmi: NewOpc = X86::VCMPPSZrmi_alt; break;
case X86::VCMPPSZrri: NewOpc = X86::VCMPPSZrri_alt; break;
case X86::VCMPSDZrm: NewOpc = X86::VCMPSDZrmi_alt; break;
case X86::VCMPSDZrr: NewOpc = X86::VCMPSDZrri_alt; break;
case X86::VCMPSSZrm: NewOpc = X86::VCMPSSZrmi_alt; break;
case X86::VCMPSSZrr: NewOpc = X86::VCMPSSZrri_alt; break;
}
// Switch opcode to the one that doesn't get special printing.
mcInst.setOpcode(NewOpc);
}
}
switch (type) {

View File

@ -1737,12 +1737,6 @@ static int readOperands(struct InternalInstruction* insn) {
}
if (readImmediate(insn, 1))
return -1;
if (Op.type == TYPE_IMM3 &&
insn->immediates[insn->numImmediatesConsumed - 1] > 7)
return -1;
if (Op.type == TYPE_IMM5 &&
insn->immediates[insn->numImmediatesConsumed - 1] > 31)
return -1;
if (Op.type == TYPE_XMM128 ||
Op.type == TYPE_XMM256)
sawRegImm = 1;

View File

@ -72,35 +72,9 @@ void X86ATTInstPrinter::printInst(const MCInst *MI, raw_ostream &OS,
printAnnotation(OS, Annot);
}
void X86ATTInstPrinter::printSSECC(const MCInst *MI, unsigned Op,
raw_ostream &O) {
int64_t Imm = MI->getOperand(Op).getImm() & 0xf;
static void printSSEAVXCC(int64_t Imm, raw_ostream &O) {
switch (Imm) {
default: llvm_unreachable("Invalid ssecc argument!");
case 0: O << "eq"; break;
case 1: O << "lt"; break;
case 2: O << "le"; break;
case 3: O << "unord"; break;
case 4: O << "neq"; break;
case 5: O << "nlt"; break;
case 6: O << "nle"; break;
case 7: O << "ord"; break;
case 8: O << "eq_uq"; break;
case 9: O << "nge"; break;
case 0xa: O << "ngt"; break;
case 0xb: O << "false"; break;
case 0xc: O << "neq_oq"; break;
case 0xd: O << "ge"; break;
case 0xe: O << "gt"; break;
case 0xf: O << "true"; break;
}
}
void X86ATTInstPrinter::printAVXCC(const MCInst *MI, unsigned Op,
raw_ostream &O) {
int64_t Imm = MI->getOperand(Op).getImm() & 0x1f;
switch (Imm) {
default: llvm_unreachable("Invalid avxcc argument!");
default: llvm_unreachable("Invalid ssecc/avxcc argument!");
case 0: O << "eq"; break;
case 1: O << "lt"; break;
case 2: O << "le"; break;
@ -136,6 +110,18 @@ void X86ATTInstPrinter::printAVXCC(const MCInst *MI, unsigned Op,
}
}
void X86ATTInstPrinter::printSSECC(const MCInst *MI, unsigned Op,
raw_ostream &O) {
int64_t Imm = MI->getOperand(Op).getImm() & 0x7;
printSSEAVXCC(Imm, O);
}
void X86ATTInstPrinter::printAVXCC(const MCInst *MI, unsigned Op,
raw_ostream &O) {
int64_t Imm = MI->getOperand(Op).getImm() & 0x1f;
printSSEAVXCC(Imm, O);
}
void X86ATTInstPrinter::printRoundingControl(const MCInst *MI, unsigned Op,
raw_ostream &O) {
int64_t Imm = MI->getOperand(Op).getImm() & 0x3;

View File

@ -50,33 +50,7 @@ void X86IntelInstPrinter::printInst(const MCInst *MI, raw_ostream &OS,
EmitAnyX86InstComments(MI, *CommentStream, getRegisterName);
}
void X86IntelInstPrinter::printSSECC(const MCInst *MI, unsigned Op,
raw_ostream &O) {
int64_t Imm = MI->getOperand(Op).getImm() & 0xf;
switch (Imm) {
default: llvm_unreachable("Invalid ssecc argument!");
case 0: O << "eq"; break;
case 1: O << "lt"; break;
case 2: O << "le"; break;
case 3: O << "unord"; break;
case 4: O << "neq"; break;
case 5: O << "nlt"; break;
case 6: O << "nle"; break;
case 7: O << "ord"; break;
case 8: O << "eq_uq"; break;
case 9: O << "nge"; break;
case 0xa: O << "ngt"; break;
case 0xb: O << "false"; break;
case 0xc: O << "neq_oq"; break;
case 0xd: O << "ge"; break;
case 0xe: O << "gt"; break;
case 0xf: O << "true"; break;
}
}
void X86IntelInstPrinter::printAVXCC(const MCInst *MI, unsigned Op,
raw_ostream &O) {
int64_t Imm = MI->getOperand(Op).getImm() & 0x1f;
static void printSSEAVXCC(int64_t Imm, raw_ostream &O) {
switch (Imm) {
default: llvm_unreachable("Invalid avxcc argument!");
case 0: O << "eq"; break;
@ -114,6 +88,18 @@ void X86IntelInstPrinter::printAVXCC(const MCInst *MI, unsigned Op,
}
}
void X86IntelInstPrinter::printSSECC(const MCInst *MI, unsigned Op,
raw_ostream &O) {
int64_t Imm = MI->getOperand(Op).getImm() & 0x7;
printSSEAVXCC(Imm, O);
}
void X86IntelInstPrinter::printAVXCC(const MCInst *MI, unsigned Op,
raw_ostream &O) {
int64_t Imm = MI->getOperand(Op).getImm() & 0x1f;
printSSEAVXCC(Imm, O);
}
void X86IntelInstPrinter::printRoundingControl(const MCInst *MI, unsigned Op,
raw_ostream &O) {
int64_t Imm = MI->getOperand(Op).getImm() & 0x3;

View File

@ -1,10 +0,0 @@
# RUN: llvm-mc --disassemble %s -triple=x86_64-apple-darwin9 2>&1 | grep "invalid instruction encoding"
# This instruction would decode as cmpordps if the immediate byte was less than 8.
0x0f 0xc2 0xc7 0x08
# This instruction would decode as cmpordpd if the immediate byte was less than 8.
0x66 0x0f 0xc2 0xc7 0x08
# This instruction would decode as cmpordss if the immediate byte was less than 8.
0xf3 0x0f 0xc2 0xc7 0x08
# This instruction would decode as cmpordsd if the immediate byte was less than 8.
0xf2 0x0f 0xc2 0xc7 0x08

View File

@ -714,3 +714,12 @@
# CHECK: vpermq $-18, %ymm2, %ymm2
0xc4 0xe3 0xfd 0x00 0xd2 0xee
# CHECK: cmpps $8, %xmm7, %xmm0
0x0f 0xc2 0xc7 0x08
# CHECK: cmppd $8, %xmm7, %xmm0
0x66 0x0f 0xc2 0xc7 0x08
# CHECK: cmpss $8, %xmm7, %xmm0
0xf3 0x0f 0xc2 0xc7 0x08
# CHECK: cmpsd $8, %xmm7, %xmm0
0xf2 0x0f 0xc2 0xc7 0x08