mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-26 04:32:44 +01:00
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.
llvm-svn: 224846
This commit is contained in:
parent
fd4d1d892e
commit
1568430176
@ -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) {
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user