x86: handle undocumented immediates for (v)cmpps/pd/ss/sd instructions

This commit is contained in:
Nguyen Anh Quynh 2014-12-26 17:54:11 +08:00
parent d319c114db
commit 9f694cc934
4 changed files with 100 additions and 56 deletions

View File

@ -142,25 +142,25 @@ static void printf512mem(MCInst *MI, unsigned OpNo, SStream *O)
static void printSSECC(MCInst *MI, unsigned Op, SStream *OS)
{
int64_t Imm = MCOperand_getImm(MCInst_getOperand(MI, Op)) & 0xf;
int64_t Imm = MCOperand_getImm(MCInst_getOperand(MI, Op)) & 7;
switch (Imm) {
default: break; // never reach
case 0: SStream_concat0(OS, "eq"); break;
case 1: SStream_concat0(OS, "lt"); break;
case 2: SStream_concat0(OS, "le"); break;
case 3: SStream_concat0(OS, "unord"); break;
case 4: SStream_concat0(OS, "neq"); break;
case 5: SStream_concat0(OS, "nlt"); break;
case 6: SStream_concat0(OS, "nle"); break;
case 7: SStream_concat0(OS, "ord"); break;
case 8: SStream_concat0(OS, "eq_uq"); break;
case 9: SStream_concat0(OS, "nge"); break;
case 0xa: SStream_concat0(OS, "ngt"); break;
case 0xb: SStream_concat0(OS, "false"); break;
case 0xc: SStream_concat0(OS, "neq_oq"); break;
case 0xd: SStream_concat0(OS, "ge"); break;
case 0xe: SStream_concat0(OS, "gt"); break;
case 0xf: SStream_concat0(OS, "true"); break;
case 0: SStream_concat0(OS, "eq"); op_addSseCC(MI, X86_SSE_CC_EQ); break;
case 1: SStream_concat0(OS, "lt"); op_addSseCC(MI, X86_SSE_CC_LT); break;
case 2: SStream_concat0(OS, "le"); op_addSseCC(MI, X86_SSE_CC_LE); break;
case 3: SStream_concat0(OS, "unord"); op_addSseCC(MI, X86_SSE_CC_UNORD); break;
case 4: SStream_concat0(OS, "neq"); op_addSseCC(MI, X86_SSE_CC_NEQ); break;
case 5: SStream_concat0(OS, "nlt"); op_addSseCC(MI, X86_SSE_CC_NLT); break;
case 6: SStream_concat0(OS, "nle"); op_addSseCC(MI, X86_SSE_CC_NLE); break;
case 7: SStream_concat0(OS, "ord"); op_addSseCC(MI, X86_SSE_CC_ORD); break;
case 8: SStream_concat0(OS, "eq_uq"); op_addSseCC(MI, X86_SSE_CC_EQ_UQ); break;
case 9: SStream_concat0(OS, "nge"); op_addSseCC(MI, X86_SSE_CC_NGE); break;
case 0xa: SStream_concat0(OS, "ngt"); op_addSseCC(MI, X86_SSE_CC_NGT); break;
case 0xb: SStream_concat0(OS, "false"); op_addSseCC(MI, X86_SSE_CC_FALSE); break;
case 0xc: SStream_concat0(OS, "neq_oq"); op_addSseCC(MI, X86_SSE_CC_NEQ_OQ); break;
case 0xd: SStream_concat0(OS, "ge"); op_addSseCC(MI, X86_SSE_CC_GE); break;
case 0xe: SStream_concat0(OS, "gt"); op_addSseCC(MI, X86_SSE_CC_GT); break;
case 0xf: SStream_concat0(OS, "true"); op_addSseCC(MI, X86_SSE_CC_TRUE); break;
}
}
@ -169,38 +169,38 @@ static void printAVXCC(MCInst *MI, unsigned Op, SStream *O)
int64_t Imm = MCOperand_getImm(MCInst_getOperand(MI, Op)) & 0x1f;
switch (Imm) {
default: break;//printf("Invalid avxcc argument!\n"); break;
case 0: SStream_concat0(O, "eq"); break;
case 1: SStream_concat0(O, "lt"); break;
case 2: SStream_concat0(O, "le"); break;
case 3: SStream_concat0(O, "unord"); break;
case 4: SStream_concat0(O, "neq"); break;
case 5: SStream_concat0(O, "nlt"); break;
case 6: SStream_concat0(O, "nle"); break;
case 7: SStream_concat0(O, "ord"); break;
case 8: SStream_concat0(O, "eq_uq"); break;
case 9: SStream_concat0(O, "nge"); break;
case 0xa: SStream_concat0(O, "ngt"); break;
case 0xb: SStream_concat0(O, "false"); break;
case 0xc: SStream_concat0(O, "neq_oq"); break;
case 0xd: SStream_concat0(O, "ge"); break;
case 0xe: SStream_concat0(O, "gt"); break;
case 0xf: SStream_concat0(O, "true"); break;
case 0x10: SStream_concat0(O, "eq_os"); break;
case 0x11: SStream_concat0(O, "lt_oq"); break;
case 0x12: SStream_concat0(O, "le_oq"); break;
case 0x13: SStream_concat0(O, "unord_s"); break;
case 0x14: SStream_concat0(O, "neq_us"); break;
case 0x15: SStream_concat0(O, "nlt_uq"); break;
case 0x16: SStream_concat0(O, "nle_uq"); break;
case 0x17: SStream_concat0(O, "ord_s"); break;
case 0x18: SStream_concat0(O, "eq_us"); break;
case 0x19: SStream_concat0(O, "nge_uq"); break;
case 0x1a: SStream_concat0(O, "ngt_uq"); break;
case 0x1b: SStream_concat0(O, "false_os"); break;
case 0x1c: SStream_concat0(O, "neq_os"); break;
case 0x1d: SStream_concat0(O, "ge_oq"); break;
case 0x1e: SStream_concat0(O, "gt_oq"); break;
case 0x1f: SStream_concat0(O, "true_us"); break;
case 0: SStream_concat0(O, "eq"); op_addAvxCC(MI, X86_AVX_CC_EQ); break;
case 1: SStream_concat0(O, "lt"); op_addAvxCC(MI, X86_AVX_CC_LT); break;
case 2: SStream_concat0(O, "le"); op_addAvxCC(MI, X86_AVX_CC_LE); break;
case 3: SStream_concat0(O, "unord"); op_addAvxCC(MI, X86_AVX_CC_UNORD); break;
case 4: SStream_concat0(O, "neq"); op_addAvxCC(MI, X86_AVX_CC_NEQ); break;
case 5: SStream_concat0(O, "nlt"); op_addAvxCC(MI, X86_AVX_CC_NLT); break;
case 6: SStream_concat0(O, "nle"); op_addAvxCC(MI, X86_AVX_CC_NLE); break;
case 7: SStream_concat0(O, "ord"); op_addAvxCC(MI, X86_AVX_CC_ORD); break;
case 8: SStream_concat0(O, "eq_uq"); op_addAvxCC(MI, X86_AVX_CC_EQ_UQ); break;
case 9: SStream_concat0(O, "nge"); op_addAvxCC(MI, X86_AVX_CC_NGE); break;
case 0xa: SStream_concat0(O, "ngt"); op_addAvxCC(MI, X86_AVX_CC_NGT); break;
case 0xb: SStream_concat0(O, "false"); op_addAvxCC(MI, X86_AVX_CC_FALSE); break;
case 0xc: SStream_concat0(O, "neq_oq"); op_addAvxCC(MI, X86_AVX_CC_NEQ_OQ); break;
case 0xd: SStream_concat0(O, "ge"); op_addAvxCC(MI, X86_AVX_CC_GE); break;
case 0xe: SStream_concat0(O, "gt"); op_addAvxCC(MI, X86_AVX_CC_GT); break;
case 0xf: SStream_concat0(O, "true"); op_addAvxCC(MI, X86_AVX_CC_TRUE); break;
case 0x10: SStream_concat0(O, "eq_os"); op_addAvxCC(MI, X86_AVX_CC_EQ_OS); break;
case 0x11: SStream_concat0(O, "lt_oq"); op_addAvxCC(MI, X86_AVX_CC_LT_OQ); break;
case 0x12: SStream_concat0(O, "le_oq"); op_addAvxCC(MI, X86_AVX_CC_LE_OQ); break;
case 0x13: SStream_concat0(O, "unord_s"); op_addAvxCC(MI, X86_AVX_CC_UNORD_S); break;
case 0x14: SStream_concat0(O, "neq_us"); op_addAvxCC(MI, X86_AVX_CC_NEQ_US); break;
case 0x15: SStream_concat0(O, "nlt_uq"); op_addAvxCC(MI, X86_AVX_CC_NLT_UQ); break;
case 0x16: SStream_concat0(O, "nle_uq"); op_addAvxCC(MI, X86_AVX_CC_NLE_UQ); break;
case 0x17: SStream_concat0(O, "ord_s"); op_addAvxCC(MI, X86_AVX_CC_ORD_S); break;
case 0x18: SStream_concat0(O, "eq_us"); op_addAvxCC(MI, X86_AVX_CC_EQ_US); break;
case 0x19: SStream_concat0(O, "nge_uq"); op_addAvxCC(MI, X86_AVX_CC_NGE_UQ); break;
case 0x1a: SStream_concat0(O, "ngt_uq"); op_addAvxCC(MI, X86_AVX_CC_NGT_UQ); break;
case 0x1b: SStream_concat0(O, "false_os"); op_addAvxCC(MI, X86_AVX_CC_FALSE_OS); break;
case 0x1c: SStream_concat0(O, "neq_os"); op_addAvxCC(MI, X86_AVX_CC_NEQ_OS); break;
case 0x1d: SStream_concat0(O, "ge_oq"); op_addAvxCC(MI, X86_AVX_CC_GE_OQ); break;
case 0x1e: SStream_concat0(O, "gt_oq"); op_addAvxCC(MI, X86_AVX_CC_GT_OQ); break;
case 0x1f: SStream_concat0(O, "true_us"); op_addAvxCC(MI, X86_AVX_CC_TRUE_US); break;
}
}

View File

@ -210,6 +210,56 @@ 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 = 0;
switch (MCInst_getOpcode(mcInst)) {
default: break; // never reach
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(mcInst, NewOpc);
}
} else if (type == TYPE_IMM5) {
// Check for immediates that printAVXCC can't handle.
if (immediate >= 32) {
unsigned NewOpc = 0;
switch (MCInst_getOpcode(mcInst)) {
default: break; // 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(mcInst, NewOpc);
}
}
switch (type) {

View File

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

View File

@ -155,7 +155,7 @@ static void printf512mem(MCInst *MI, unsigned OpNo, SStream *O)
static void printSSECC(MCInst *MI, unsigned Op, SStream *OS)
{
int64_t Imm = MCOperand_getImm(MCInst_getOperand(MI, Op)) & 0xf;
int64_t Imm = MCOperand_getImm(MCInst_getOperand(MI, Op)) & 7;
switch (Imm) {
default: break; // never reach
case 0: SStream_concat0(OS, "eq"); op_addSseCC(MI, X86_SSE_CC_EQ); break;