#include <limits.h>
#include "globals.h"
#include "memalloc.h"
#include "parser.h"
#include "codegen.h"
#include "fixup.h"
#include "fpfixup.h"
#include "segment.h"
#include "input.h"
#include "listing.h"
#include "reswords.h"
extern const struct opnd_class opnd_clstab[];
#if AVXSUPP
extern struct ReservedWord ResWordTable[];
extern const uint_8 vex_flags[];
#endif
const char szNull[] = {"<NULL>"};
#define OutputCodeByte( x ) OutputByte( x )
enum prefix_reg {
PREFIX_ES = 0x26,
PREFIX_CS = 0x2E,
PREFIX_SS = 0x36,
PREFIX_DS = 0x3E,
PREFIX_FS = 0x64,
PREFIX_GS = 0x65
};
uint_8 GetByteDisp(const struct code_info *CodeInfo)
{
const uint_8 fvarr[2][2][3] = {{{16, 32, 64}, {4, 4, 4}}, {{16, 32, 64}, {8, 8, 8}}};
const uint_8 hvarr[2][3] = {{8, 16, 32}, {4, 4, 4}}; const uint_8 duparr[3] = {8, 32, 64}; uint_8 n = 0;
bool evexW = (CodeInfo->evex_p1 & EVEX_P1WMASK) >> 7;
enum ttypes tuple = CodeInfo->pinstr->prefix & 0x1F;
bool evexB = (CodeInfo->evex_p2 & EVEX_P2BMASK) >> 4;
uint_8 vctln = (CodeInfo->evex_p2 & EVEX_P2LLMASK) >> 5;
switch(tuple) {
case FV: n = fvarr[evexW][evexB][vctln];
break;
case HV: n = hvarr[evexB][vctln];
break;
case FVM: n = 1 << (vctln + 4);
break;
case T1S8: case T1S16:
n = tuple - T1S8 + 1;
break;
case T1S:
n = evexW ? 8 : 4;
break;
case T1F32: case T1F64:
n = (tuple == T1F32 ? 4 : 8);
break;
case T2: case T4: case T8: if (vctln + 7 <= (evexW + 5) + (tuple - T2 + 1))
n = 0;
else
n = 1 << (tuple - T2 + evexW + 3);
break;
case HVM: case QVM: case OVM: n = 1 << (OVM - tuple + vctln + 1);
break;
case T128: n = 16;
break;
case DUP: n = duparr[vctln];
break;
default:
break;
}
return n;
}
bool Check4CompDisp8(const struct code_info *CodeInfo, int_8 *comprdsp,int *d, int disp)
{
int_32 disp32 = disp;
uint_8 n;
int_32 disp8;
if (CodeInfo->evex_flag){ n = GetByteDisp(CodeInfo);
*d = n;
if (n && !(disp32 & (n - 1))) {
disp8 = disp32 / n;
if (disp8 >= -128 && disp8 <= 127) {
*comprdsp = disp8;
return TRUE;
}
}
}
*comprdsp = 0;
return FALSE;
}
static const char sr_prefix[] =
{ PREFIX_ES, PREFIX_CS, PREFIX_SS, PREFIX_DS, PREFIX_FS, PREFIX_GS };
static void output_opc(struct code_info *CodeInfo)
{
const struct instr_item *ins = CodeInfo->pinstr;
uint_8 tmp;
uint_8 fpfix = FALSE;
int rn;
unsigned char c;
int_8 comprdsp = 0;
DebugMsg1(("output_opc enter, ins.opc/rm=%X/%X, byte1_info=%X CodeInfo->rm=%X opsiz=%u\n", ins->opcode, ins->rm_byte, ins->byte1_info, CodeInfo->rm_byte, CodeInfo->prefix.opsiz));
if (Options.line_numbers)
AddLinnumDataRef(get_curr_srcfile(), GetLineNumber());
if (ins->cpu & (P_FPU_MASK | P_MMX | P_SSEALL)) {
#if SSE4SUPP
if (CodeInfo->token != T_CRC32 &&
CodeInfo->token != T_POPCNT)
#endif
CodeInfo->prefix.opsiz = FALSE;
}
if ((CodeInfo->token == T_RDRAND) || (CodeInfo->token == T_RDSEED)){
if ((CodeInfo->opnd[OPND1].type == OP_R16) || (CodeInfo->opnd[OPND1].type == OP_AX))
CodeInfo->prefix.opsiz = TRUE;
}
if ((ins->cpu & P_CPU_MASK) > (ModuleInfo.curr_cpu & P_CPU_MASK)
|| (ins->cpu & P_FPU_MASK) > (ModuleInfo.curr_cpu & P_FPU_MASK)
|| (ins->cpu & P_EXT_MASK) > (ModuleInfo.curr_cpu & P_EXT_MASK)) {
DebugMsg(("output_opc: wrong cpu setting: instr.cpu=%X, ModuleInfo.cpu=%X\n",
ins->cpu, ModuleInfo.curr_cpu));
if (ins->cpu == P_386 &&
((InstrTable[IndexFromToken(CodeInfo->token)].cpu & P_CPU_MASK) <= P_386))
EmitError(INSTRUCTION_FORM_REQUIRES_80386);
else
EmitError(INSTRUCTION_OR_REGISTER_NOT_ACCEPTED_IN_CURRENT_CPU_MODE);
}
if ((ModuleInfo.emulator == TRUE) &&
(CodeInfo->Ofssize == USE16) &&
(ins->cpu & P_FPU_MASK) &&
(ins->allowed_prefix != AP_NO_FWAIT)) {
fpfix = TRUE;
AddFloatingPointEmulationFixup(CodeInfo);
}
#if AVXSUPP
if (CodeInfo->token == T_VMOVSS || CodeInfo->token == T_VMOVSD){
if (CodeInfo->reg3 == 0xff){
if (CodeInfo->pinstr->opcode == 0x10 && (CodeInfo->opnd[OPND2].type & OP_M))
;
else if (CodeInfo->pinstr->opcode == 0x11 && (CodeInfo->opnd[OPND1].type & OP_M) )
;
else {
EmitErr(INVALID_INSTRUCTION_OPERANDS);
}
}
}
#endif
if (CodeInfo->prefix.ins != EMPTY && (CodeInfo->token < T_VPGATHERDD || CodeInfo->token > T_VGATHERQPS)) {
tmp = InstrTable[IndexFromToken(CodeInfo->prefix.ins)].allowed_prefix;
if (tmp == AP_REP && ins->allowed_prefix == AP_REPxx)
tmp = AP_REPxx;
if (ins->allowed_prefix != tmp) {
EmitError(INSTRUCTION_PREFIX_NOT_ALLOWED);
}
else
OutputCodeByte(InstrTable[IndexFromToken(CodeInfo->prefix.ins)].opcode);
}
if (ins->cpu & P_FPU_MASK) {
if (CodeInfo->token == T_FWAIT) {
if (fpfix) {
OutputCodeByte(OP_NOP);
}
}
else if (fpfix || ins->allowed_prefix == AP_FWAIT) {
OutputCodeByte(OP_WAIT);
}
else if (ins->allowed_prefix != AP_NO_FWAIT) {
if ((ModuleInfo.curr_cpu & P_CPU_MASK) < P_286)
OutputCodeByte(OP_WAIT);
}
}
switch (ins->byte1_info) {
case F_16:
if (CodeInfo->Ofssize >= USE32) CodeInfo->prefix.opsiz = TRUE;
break;
case F_32:
if (CodeInfo->Ofssize == USE16) CodeInfo->prefix.opsiz = TRUE;
break;
case F_16A:
if (CodeInfo->Ofssize == USE32) CodeInfo->prefix.adrsiz = TRUE;
break;
case F_32A:
#if AMD64_SUPPORT
if (CodeInfo->Ofssize != USE32) CodeInfo->prefix.adrsiz = TRUE;
#else
if( CodeInfo->Ofssize == USE16 ) CodeInfo->prefix.adrsiz = TRUE;
#endif
break;
case F_0FNO66:
CodeInfo->prefix.opsiz = FALSE;
break;
#if AMD64_SUPPORT
case F_48:
case F_480F:
CodeInfo->prefix.rex |= REX_W;
break;
#endif
}
#if AVXSUPP
if ((CodeInfo->token >= T_VSHUFF32X4) && (CodeInfo->token <= T_VSHUFI64X2) &&
((CodeInfo->opnd[OPND1].type & OP_XMM) || (CodeInfo->opnd[OPND2].type & OP_XMM)))
EmitError(INVALID_COMBINATION_OF_OPCODE_AND_OPERANDS);
if ((CodeInfo->token >= T_VBROADCASTF128) && (CodeInfo->token <= T_VPBROADCASTQ)) {
if (decoflags == 0 && CodeInfo->r1type != OP_K)
CodeInfo->evex_flag = 0;
}
switch (CodeInfo->token){
case T_VADDPD:
case T_VADDSD:
case T_VDIVPD:
case T_VDIVSD:
case T_VMAXPD:
case T_VMAXSD:
case T_VMINPD:
case T_VMINSD:
case T_VMULPD:
case T_VMULSD:
case T_VSQRTSD:
case T_VSUBPD:
case T_VSUBSD:
case T_VADDPS:
case T_VADDSS:
case T_VDIVPS:
case T_VDIVSS:
case T_VMAXPS:
case T_VMAXSS:
case T_VMINPS:
case T_VMINSS:
case T_VMULPS:
case T_VMULSS:
case T_VSQRTSS:
case T_VSUBPS:
case T_VSUBSS:
case T_VCMPPD:
case T_VCMPSD:
case T_VCMPPS:
case T_VCMPSS:
case T_VXORPD:
case T_VORPS:
case T_VXORPS:
if (CodeInfo->r2type == OP_XMM || CodeInfo->r2type == OP_YMM || CodeInfo->r2type == OP_ZMM)
break;
EmitError(INVALID_INSTRUCTION_OPERANDS);
}
switch (CodeInfo->token){
case T_VPCMPD:
case T_VPCMPUD:
case T_VPCMPQ:
case T_VPCMPUQ:
case T_VPCMPW:
case T_VPCMPUW:
case T_VPCMPB:
case T_VPCMPUB:
if (CodeInfo->r1type == OP_K)
break;
EmitError(INVALID_INSTRUCTION_OPERANDS);
}
if ((CodeInfo->pinstr->prefix & 0xF00) == IZSZ || (evexflag == TRUE))
CodeInfo->evex_flag = TRUE;
if (!evex){
CodeInfo->evex_flag = FALSE;
if (ResWordTable[CodeInfo->token].flags & RWF_VEX) {
if ((CodeInfo->reg1 > 15 && CodeInfo->reg1 < 32) ||
(CodeInfo->reg2 > 15 && CodeInfo->reg2 < 32) ||
(CodeInfo->reg3 > 15 && CodeInfo->reg3 < 32) ||
CodeInfo->r1type == OP_ZMM || CodeInfo->r2type == OP_ZMM)
EmitError(INVALID_COMBINATION_OF_OPCODE_AND_OPERANDS);
}
}
if (CodeInfo->evex_flag == TRUE) {
if (!(vex_flags[CodeInfo->token - VEX_START] & VX_LL))
EmitError(INVALID_COMBINATION_OF_OPCODE_AND_OPERANDS);
}
if (CodeInfo->token == T_VCMPSD || CodeInfo->token == T_VCMPSS){
if ( (CodeInfo->r1type > OP_XMM || CodeInfo->r2type > OP_XMM) && CodeInfo->opnd[OPND1].type != OP_K )
EmitError(INVALID_OPERAND_SIZE);
}
if ((CodeInfo->token >= T_VCMPEQSD && CodeInfo->token <= T_VCMPTRUE_USSD)||
(CodeInfo->token >= T_VCMPEQSS && CodeInfo->token <= T_VCMPTRUE_USSS)){
if ((CodeInfo->r1type > OP_XMM || CodeInfo->r2type > OP_XMM) && CodeInfo->opnd[OPND1].type != OP_K )
EmitError(INVALID_OPERAND_SIZE);
}
if (!(ResWordTable[CodeInfo->token].flags & RWF_VEX)) {
#endif
switch (ins->byte1_info) {
case F_660F:
case F_660F38:
case F_660F3A:
CodeInfo->prefix.opsiz = TRUE;
break;
case F_F20F:
case F_F20F38: OutputCodeByte(0xF2); break;
case F_F3:
case F_F30F: OutputCodeByte(0xF3); break;
}
#if AVXSUPP
}
#endif
if (CodeInfo->prefix.adrsiz == TRUE && (CodeInfo->token < T_VPGATHERDD || CodeInfo->token > T_VSCATTERQPD)&&
CodeInfo->token != T_VCVTPH2PS && CodeInfo->token != T_VCVTPS2PD) {
if (CodeInfo->basereg == 0x10)
;
else
OutputCodeByte(ADRSIZ);
#ifdef DEBUG_OUT
if (fpfix)
DebugMsg(("output_opc: ERROR: FP emulation byte sequence destroyed by 32-bit address prefix!\n"));
#endif
}
if (CodeInfo->prefix.opsiz == TRUE) {
#if 1
if ((ModuleInfo.curr_cpu & P_CPU_MASK) < P_386) {
DebugMsg(("output_opc: instruction form requires 386\n"));
EmitError(INSTRUCTION_FORM_REQUIRES_80386);
}
#endif
if (CodeInfo->token == T_MOVQ && CodeInfo->basereg != 0x10) {
if (CodeInfo->opnd[OPND1].type == OP_XMM && (CodeInfo->opnd[OPND2].type & OP_MS)) {
CodeInfo->prefix.opsiz = FALSE;
OutputCodeByte(0xF3);
}
else if ((CodeInfo->opnd[OPND1].type & OP_MS) && CodeInfo->opnd[OPND2].type == OP_XMM) {
CodeInfo->prefix.opsiz = TRUE;
OutputCodeByte(OPSIZ);
}
else if ((CodeInfo->opnd[OPND1].type == OP_XMM) && (CodeInfo->opnd[OPND2].type & OP_R64)) {
CodeInfo->prefix.opsiz = TRUE;
OutputCodeByte(OPSIZ);
}
else if ((CodeInfo->opnd[OPND2].type == OP_XMM) && (CodeInfo->opnd[OPND1].type & OP_R64)) {
CodeInfo->prefix.opsiz = TRUE;
OutputCodeByte(OPSIZ);
}
}
else
OutputCodeByte(OPSIZ);
}
if (CodeInfo->prefix.RegOverride != EMPTY) {
OutputCodeByte(sr_prefix[CodeInfo->prefix.RegOverride]);
}
if (ins->opnd_dir) {
tmp = CodeInfo->rm_byte;
CodeInfo->rm_byte = (tmp & 0xc0) | ((tmp >> 3) & 0x7) | ((tmp << 3) & 0x38);
#if AMD64_SUPPORT
tmp = CodeInfo->prefix.rex;
CodeInfo->prefix.rex = (tmp & 0xFA) | ((tmp & REX_R) >> 2) | ((tmp & REX_B) << 2);
#endif
}
#if AVXSUPP
if (CodeInfo->indextype == OP_XMM || CodeInfo->indextype == OP_YMM || CodeInfo->indextype == OP_ZMM) {
if (CodeInfo->token >= T_VPGATHERDD && CodeInfo->token <= T_VSCATTERQPD)
;
else
EmitErr( AVX_INDEX_REGISTERS_NOT_ALLOWED_HERE );
}
if (CodeInfo->token >= T_VFMADD132PD && CodeInfo->token <= T_VFNMSUB231SS){
if (CodeInfo->opnd[OPND1].type == CodeInfo->opnd[OPND2].type)
;
else if (CodeInfo->opnd[OPND2].type & OP_M_ANY)
;
else
EmitError(INVALID_COMBINATION_OF_OPCODE_AND_OPERANDS);
}
if ((CodeInfo->token >= T_ADDPD && CodeInfo->token <= T_SUBPS )||
(CodeInfo->token >= T_VADDPD && CodeInfo->token <= T_VSUBPS )){
if (CodeInfo->evex_flag == TRUE) {
if (CodeInfo->opnd[OPND2].type & OP_M_ANY){
CodeInfo->prefix.rex |= EVEX_P0XMASK;
if (CodeInfo->opnd[OPND2].data32l){
CodeInfo->rm_byte &= ~MOD_11;
CodeInfo->rm_byte |= MOD_10;
}
}
}
if (CodeInfo->opnd[OPND2].type != CodeInfo->opnd[OPND1].type){
if (CodeInfo->opnd[OPND1].type & OP_M_ANY || CodeInfo->opnd[OPND2].type & OP_M_ANY)
;
else
EmitError(INVALID_OPERAND_SIZE);
}
}
if (ResWordTable[CodeInfo->token].flags & RWF_VEX) {
uint_8 lbyte = 0;
if (CodeInfo->evex_flag){
lbyte |= 0x4; }
switch (ins->byte1_info) {
case F_660F:
case F_660F38:
case F_660F3A:
lbyte |= 0x01;
break;
case F_F30F:
case F_F30F38:
lbyte |= 0x02;
break;
case F_F20F:
case F_F20F38:
lbyte |= 0x03;
break;
}
if (CodeInfo->vexregop)
lbyte |= ((16 - CodeInfo->vexregop) << 3);
else {
lbyte |= EVEX_P1VVVV;
CodeInfo->evex_p2 |= EVEX_P2VMASK;
}
if (CodeInfo->token >= T_VBROADCASTSS && CodeInfo->token <= T_VPBROADCASTMW2D)
{
if (decoflags == 0 && CodeInfo->r1type != OP_K){
if ((CodeInfo->reg1 <= 15 && CodeInfo->r1type != OP_ZMM) && ((CodeInfo->pinstr->prefix & 0xF00) != IZSZ))
CodeInfo->evex_flag = 0;
else{
CodeInfo->evex_flag = 1;
lbyte |= 4;
}
}
}
if (evexflag == TRUE)
CodeInfo->evex_flag = TRUE;
if (CodeInfo->token >= T_VPGATHERDD && CodeInfo->token <= T_VGATHERQPS)
{
if (decoflags == 0){
if (CodeInfo->reg1 <= 15 && CodeInfo->reg3 <= 15 && CodeInfo->zreg == 0)
CodeInfo->evex_flag = 0;
else EmitError(INVALID_COMBINATION_OF_OPCODE_AND_OPERANDS);
if (CodeInfo->reg1 == CodeInfo->reg3 || CodeInfo->reg1 == CodeInfo->indexreg||
CodeInfo->reg3 == CodeInfo->indexreg)
EmitError(INVALID_COMBINATION_OF_OPCODE_AND_OPERANDS);
}
}
if ((CodeInfo->token >= T_VGATHERPF0DPS && CodeInfo->token <= T_VSCATTERQPD)&&(decoflags == 0))
EmitError(INVALID_COMBINATION_OF_OPCODE_AND_OPERANDS);
if (CodeInfo->token == T_VCVTTSS2SI || CodeInfo->token == T_VCVTSS2SD){
if (CodeInfo->r2type == OP_YMM || CodeInfo->r2type == OP_ZMM )
EmitError(INVALID_COMBINATION_OF_OPCODE_AND_OPERANDS);
}
switch (CodeInfo->token){
case T_VRCP28SD:
case T_VRSQRT28SD:
if (CodeInfo->mem_type != MT_EMPTY && CodeInfo->mem_type != MT_QWORD )
goto error;
if ((CodeInfo->r1type == OP_XMM && CodeInfo->r2type == OP_XMM) &&
CodeInfo->opnd[OPND1].type == OP_XMM || CodeInfo->opnd[OPND1].type == OP_M)
break;
else goto error;
case T_VRCP28SS:
case T_VRSQRT28SS:
if (CodeInfo->mem_type != MT_EMPTY && CodeInfo->mem_type != MT_DWORD )
goto error;
if ((CodeInfo->r1type == OP_XMM && CodeInfo->r2type == OP_XMM) &&
CodeInfo->opnd[OPND1].type == OP_XMM || CodeInfo->opnd[OPND1].type == OP_M)
break;
case T_VPCLMULQDQ:
case T_VAESDECLAST:
case T_VAESENCLAST:
case T_VAESDEC:
case T_VAESENC:
if (CodeInfo->mem_type != MT_EMPTY && CodeInfo->mem_type != MT_OWORD )
goto error;
if ((CodeInfo->r1type == OP_XMM && CodeInfo->r2type == OP_XMM) &&
CodeInfo->opnd[OPND1].type == OP_XMM || CodeInfo->opnd[OPND1].type == OP_M)
break;
else goto error;
case T_VAESKEYGENASSIST:
if (CodeInfo->mem_type != MT_EMPTY && CodeInfo->mem_type != MT_OWORD )
goto error;
if ((CodeInfo->r1type == OP_XMM) &&
CodeInfo->opnd[OPND2].type == OP_XMM || CodeInfo->opnd[OPND2].type == OP_M128 ||
CodeInfo->opnd[OPND2].type == OP_M)
break;
else goto error;
case T_VRCP28PD:
case T_VRCP28PS:
case T_VRSQRT28PD:
case T_VRSQRT28PS:
case T_VEXP2PD:
case T_VEXP2PS:
if ((CodeInfo->r1type == OP_ZMM) && (CodeInfo->opnd[OPND2].type == OP_ZMM ||
CodeInfo->opnd[OPND2].type & OP_M_ANY ))
break;
else goto error;
}
switch (CodeInfo->token){
case T_VCVTSS2USI:
case T_VCVTSS2SI :
case T_VCVTSS2SD :
case T_VCVTSI2SS :
case T_VCVTSI2SD :
case T_VCVTSD2SS :
case T_VCVTSD2USI:
case T_VCVTSD2SI :
if (CodeInfo->r1type == OP_YMM || CodeInfo->opnd[OPND2].type == OP_YMM)
goto error;
}
switch (CodeInfo->token){
case T_VPINSRB:
if ((CodeInfo->opnd[OPND2].type == OP_R32 || CodeInfo->mem_type == MT_BYTE || CodeInfo->mem_type == MT_EMPTY) &&
(CodeInfo->r1type == OP_XMM && CodeInfo->r2type == OP_XMM))
; else goto error;
break;
case T_VPINSRW:
if ((CodeInfo->opnd[OPND2].type == OP_R32 || CodeInfo->mem_type == MT_WORD || CodeInfo->mem_type == MT_EMPTY) &&
(CodeInfo->r1type == OP_XMM && CodeInfo->r2type == OP_XMM))
; else goto error;
break;
case T_VPINSRD:
if ((CodeInfo->opnd[OPND2].type == OP_R32 || CodeInfo->mem_type == MT_DWORD || CodeInfo->mem_type == MT_EMPTY) &&
(CodeInfo->r1type == OP_XMM && CodeInfo->r2type == OP_XMM))
; else goto error;
break;
case T_VPINSRQ: if ((CodeInfo->opnd[OPND2].type == OP_R64 || CodeInfo->mem_type == MT_QWORD || CodeInfo->mem_type == MT_EMPTY) &&
(CodeInfo->r1type == OP_XMM && CodeInfo->r2type == OP_XMM))
; else goto error;
break;
case T_VPEXTRB:
if ((CodeInfo->opnd[OPND1].type == OP_R32 || CodeInfo->mem_type == MT_BYTE || CodeInfo->mem_type == MT_EMPTY) &&
(CodeInfo->r2type == OP_XMM ))
; else goto error;
break;
case T_VPEXTRW:
if ((CodeInfo->opnd[OPND1].type == OP_R32 || CodeInfo->mem_type == MT_WORD || CodeInfo->mem_type == MT_EMPTY) &&
(CodeInfo->r2type == OP_XMM ))
; else goto error;
break;
case T_VPEXTRD:
if ((CodeInfo->opnd[OPND1].type == OP_R32 || CodeInfo->mem_type == MT_DWORD || CodeInfo->mem_type == MT_EMPTY) &&
(CodeInfo->r2type == OP_XMM ))
; else goto error;
break;
case T_VPEXTRQ:
if ((CodeInfo->opnd[OPND1].type == OP_R64 || CodeInfo->mem_type == MT_QWORD || CodeInfo->mem_type == MT_EMPTY) &&
(CodeInfo->r2type == OP_XMM ))
; else goto error;
break;
error:
EmitError(INVALID_COMBINATION_OF_OPCODE_AND_OPERANDS);
}
if ((CodeInfo->token == T_VMOVMSKPD )||(CodeInfo->token == T_VMOVMSKPS ))
CodeInfo->prefix.rex &= ~REX_W;
if (( ins->byte1_info >= F_0F38) || ( CodeInfo->prefix.rex & ( REX_B | REX_X | REX_W ) )||
(( ins->byte1_info == F_0F) && (CodeInfo->token == T_KMOVQ )) || (ins->byte1_info == F_660F) &&
(CodeInfo->token == T_KMOVD )){
uint_8 byte1 = 0;
if (CodeInfo->evex_flag)
OutputCodeByte( 0x62 ); else{
if (CodeInfo->token == T_VPMOVMSKB){
if(ins->byte1_info == F_0F && (CodeInfo->prefix.rex & REX_B == 0)&&
(CodeInfo->prefix.rex & REX_X == 0) && (CodeInfo->prefix.rex & REX_W == 8))
goto outC5; if(CodeInfo->reg3 > 7) lbyte |= 1;
}
if ((CodeInfo->token >= T_VPSLLDQ && CodeInfo->token <= T_VPSRLQ)||
(CodeInfo->token == T_VXORPD || CodeInfo->token ==T_VXORPS)){
if (CodeInfo->r1type < OP_XMM || CodeInfo->r2type < OP_XMM)
EmitError(INVALID_INSTRUCTION_OPERANDS);
if ((CodeInfo->reg2 <= 7) && (CodeInfo->reg3 <= 7 || CodeInfo->reg3 == 255) && ((CodeInfo->opnd[OPND2].type & OP_M_ANY ) == 0))
goto outC5;
if (CodeInfo->opnd[OPND3].type == OP_NONE && CodeInfo->vexregop == 0 &&
(vex_flags[CodeInfo->token - VEX_START] & VX_NND) == 0 &&
(vex_flags[CodeInfo->token - VEX_START] & VX_NMEM) == 0)
{
EmitError(INVALID_INSTRUCTION_OPERANDS);
}
OutputCodeByte(0xC4);
CodeInfo->first_byte = 0xC4;
}
else
{
if (CodeInfo->opnd[OPND3].type == OP_NONE && CodeInfo->vexregop == 0 &&
(vex_flags[CodeInfo->token - VEX_START] & VX_NND)==0 &&
(vex_flags[CodeInfo->token - VEX_START] & VX_NMEM)==0)
{
EmitError(INVALID_INSTRUCTION_OPERANDS);
}
OutputCodeByte(0xC4);
CodeInfo->first_byte = 0xC4;
}
if (CodeInfo->opnd[OPND1].type == OP_YMM || CodeInfo->opnd[OPND2].type == OP_YMM)
lbyte |= 0x04;
else
lbyte &= ~0x04;
CodeInfo->tuple = 0;
if ((CodeInfo->token >= T_VADDPD && CodeInfo->token <= T_VMOVAPS) ||
(CodeInfo->token == T_VMOVD) ||(CodeInfo->token == T_VPANDN)||
(CodeInfo->token == T_VMOVSD)|| (CodeInfo->token == T_VMOVSS)||(CodeInfo->token == T_VPAND))
lbyte &= ~EVEX_P1WMASK; else
lbyte |= ((CodeInfo->pinstr->prefix) >> 8 & 0x80); }
switch ( ins->byte1_info ) {
case F_0F38:
case F_660F38:
case F_F20F38:
case F_F30F38:
byte1 |= 0x02;
break;
case F_0F3A:
case F_660F3A:
case F_F20F3A:
byte1 |= 0x03;
break;
default:
if ( ins->byte1_info >= F_0F )
byte1 |= 0x01;
}
byte1 |= ((CodeInfo->prefix.rex & REX_B) ? 0 : 0x20);
byte1 |= ((CodeInfo->prefix.rex & REX_X) ? 0 : 0x40);
byte1 |= ((CodeInfo->prefix.rex & REX_R) ? 0 : 0x80);
if (CodeInfo->opnd[OPND2].type & OP_M_ANY)
;
else if (CodeInfo->evex_flag && CodeInfo->reg2 <= 15)
byte1 |= EVEX_P0R1MASK;
if (CodeInfo->evex_flag) {
if (CodeInfo->token == T_VEXTRACTPS)
;
else{
if ((CodeInfo->opnd[OPND1].type & OP_M_ANY) || (CodeInfo->opnd[OPND2].type & OP_M_ANY) ||
(CodeInfo->opnd[OPND3].type & OP_M_ANY)) CodeInfo->tuple = TRUE;
lbyte &= ~EVEX_P1WMASK;
lbyte |= ((CodeInfo->pinstr->prefix) >> 8 & 0x80);
if ((CodeInfo->opnd[OPND2].type == OP_M64) || (CodeInfo->opnd[OPND1].type == OP_M64))
lbyte |= EVEX_P1WMASK;
if ((CodeInfo->opnd[OPND2].type == OP_R32) || (CodeInfo->opnd[OPND2].type == OP_EAX) ||
(CodeInfo->opnd[OPND1].type == OP_R32) || (CodeInfo->opnd[OPND1].type == OP_EAX)){
lbyte &= ~EVEX_P1WMASK;
}
if (((CodeInfo->opnd[OPND1].type & OP_M_ANY) == 0) && CodeInfo->token != T_VPEXTRD &&
(CodeInfo->token != T_VCVTPS2PD) && CodeInfo->token != T_VPEXTRB &&
(CodeInfo->token != T_VCVTPS2PH) && CodeInfo->token != T_VPEXTRW &&
CodeInfo->token != T_VPEXTRQ) { if (CodeInfo->reg1 <= 15)
byte1 |= EVEX_P0R1MASK;
else
byte1 &= ~EVEX_P0R1MASK;
if ((CodeInfo->reg1 <= 7) || (CodeInfo->reg1 >= 16 && CodeInfo->reg1 <= 23))
byte1 |= EVEX_P0RMASK;
else
byte1 &= ~EVEX_P0RMASK;
if (CodeInfo->reg3 != 0xff) {
rn = CodeInfo->reg3;
}
else if (CodeInfo->basereg != 0xff)
rn = CodeInfo->basereg;
else rn = CodeInfo->reg2;
if (rn > 15){
rn -= 15;
byte1 &= ~EVEX_P0XMASK;
}
if (CodeInfo->reg3 != 0xff && CodeInfo->basereg == 0xff);
else if (rn <= 7)byte1 |= EVEX_P0BMASK;
else byte1 &= ~EVEX_P0BMASK;
}
}
}
if (CodeInfo->token >= T_VPSCATTERDD && CodeInfo->token <= T_VSCATTERQPD){
if (CodeInfo->reg2 <= 15) byte1 |= EVEX_P0R1MASK;
else byte1 &= ~EVEX_P0R1MASK;
if (CodeInfo->reg2 <= 7 ) byte1 |= EVEX_P0RMASK;
else if (CodeInfo->reg2 >= 16 && CodeInfo->reg2 <= 23) byte1 |= EVEX_P0RMASK;
else byte1 &= ~EVEX_P0RMASK;
}
if (((CodeInfo->token == T_VMOVHPS)||(CodeInfo->token == T_VMOVLPS)) && (CodeInfo->opnd[OPND2].type & OP_XMM)){
if ((CodeInfo->reg2 > 7))
byte1 &= ~EVEX_P0RMASK;
lbyte &= ~EVEX_P1WMASK;
}
if ((CodeInfo->token == T_VMOVNTPD)||(CodeInfo->token == T_VMOVNTPS)||
(CodeInfo->token >= T_VPMOVQB)&&(CodeInfo->token <= T_VPMOVUSWB)){
if (CodeInfo->reg2 <= 15) byte1 |= EVEX_P0R1MASK;
else byte1 &= ~EVEX_P0R1MASK;
if ((CodeInfo->reg2 <= 7) || (CodeInfo->reg2 >= 16 && CodeInfo->reg2 <= 23))
byte1 |= EVEX_P0RMASK;
else byte1 &= ~EVEX_P0RMASK;
if (CodeInfo->opnd[OPND1].type & OP_M_ANY == 0){
if (CodeInfo->reg1 <= 15) byte1 |= EVEX_P0XMASK;
else byte1 &= ~EVEX_P0XMASK;
if ((CodeInfo->reg1 <= 7) || (CodeInfo->reg1 >= 16 && CodeInfo->reg1 <= 23))
byte1 |= EVEX_P0BMASK;
else byte1 &= ~EVEX_P0BMASK;
}
}
if (CodeInfo->opnd[OPND2].type & OP_I8_U){
if ((CodeInfo->token >= T_VPSLLW) && (CodeInfo->token <= T_VPSRLQ) ||
(CodeInfo->token >= T_VPSLLVD) && (CodeInfo->token <= T_VPSRLVW)){
byte1 |= EVEX_P0R1MASK;
byte1 |= EVEX_P0RMASK;
if ((CodeInfo->opnd[OPND1].type == OP_R64) || (CodeInfo->opnd[OPND1].type == OP_RAX) ||
(CodeInfo->opnd[OPND1].type == OP_R32) || (CodeInfo->opnd[OPND1].type == OP_EAX)){
if (CodeInfo->basereg != 0xFF){
if (CodeInfo->basereg <= 7)
byte1 |= EVEX_P0BMASK;
else
byte1 &= ~EVEX_P0BMASK;
}
if (CodeInfo->indexreg != 0xFF){
if (CodeInfo->indexreg <= 7)
byte1 |= EVEX_P0XMASK;
else
byte1 &= ~EVEX_P0XMASK;
}
}
else if (!CodeInfo->evex_flag)
byte1 &= ~EVEX_P0R1MASK;
}
}
if ((CodeInfo->token == T_VRNDSCALEPD) || (CodeInfo->token == T_VRNDSCALEPS)){
if (((CodeInfo->r2type &= OP_R64)||(CodeInfo->r2type &= OP_R32))&&
(CodeInfo->vexconst)) {
if (CodeInfo->indexreg != 0xff){
if (CodeInfo->reg1 <= 7)
byte1 |= EVEX_P0XMASK;
else
byte1 &= ~EVEX_P0XMASK;
}
}
}
if (((CodeInfo->token == T_VEXTRACTF32x8)||(CodeInfo->token == T_VEXTRACTF64x4))
&& !(CodeInfo->opnd[OPND1].type & OP_M_ANY)) {
if (CodeInfo->reg2 <= 15) byte1 |= EVEX_P0R1MASK;
else byte1 &= ~EVEX_P0R1MASK;
if ((CodeInfo->reg2 <= 7) || (CodeInfo->reg2 >= 16 && CodeInfo->reg2 <= 23))
byte1 |= EVEX_P0RMASK;
else
byte1 &= ~EVEX_P0RMASK;
if (CodeInfo->reg1 <= 15) byte1 |= EVEX_P0XMASK;
else byte1 &= ~EVEX_P0XMASK;
}
if (((CodeInfo->token >= T_BEXTR)&&(CodeInfo->token <= T_SHRX)||(CodeInfo->token == T_BZHI)&&
(CodeInfo->indexreg != 0xFF))){
byte1 &= 0xE3;
if (CodeInfo->indexreg > 7 && CodeInfo->indexreg <= 31)
byte1 &= ~0x10;
}
if (CodeInfo->token == T_VCVTPH2PS || CodeInfo->token == T_VCVTPD2UDQ || CodeInfo->token == T_VCVTQQ2PD||
CodeInfo->token == T_VCVTPD2DQ || CodeInfo->token == T_VCVTDQ2PD){
if ((CodeInfo->reg1 <= 7) || (CodeInfo->reg1 >= 16 && CodeInfo->reg1 <= 23))
byte1 |= EVEX_P0RMASK;
else
byte1 &= ~EVEX_P0RMASK;
if (CodeInfo->indexreg != 0xff){
if (CodeInfo->indexreg <= 7) byte1 |= EVEX_P0XMASK;
else byte1 &= ~EVEX_P0XMASK;
}
if (CodeInfo->token == T_VCVTDQ2PD || CodeInfo->token == T_VCVTPS2PD)
CodeInfo->evex_p2 &= ~EVEX_P2L1MASK;
}
if (CodeInfo->token == T_VPCMPEQQ || CodeInfo->token == T_VPCMPEQD ||
CodeInfo->token == T_VPCMPEQW || CodeInfo->token == T_VPCMPEQB){
if (CodeInfo->r1type == OP_ZMM)
EmitError(INVALID_COMBINATION_OF_OPCODE_AND_OPERANDS);
}
if (CodeInfo->token == T_VMOVQ){
if (CodeInfo->opnd[OPND1].type & OP_R64){
if (CodeInfo->evex_flag){
if (CodeInfo->reg2 <= 15) byte1 |= EVEX_P0R1MASK;
else byte1 &= ~EVEX_P0R1MASK;
}
if ((CodeInfo->reg2 <= 7) || (CodeInfo->reg2 >= 16 && CodeInfo->reg2 <= 23))
byte1 |= EVEX_P0RMASK;
else byte1 &= ~EVEX_P0RMASK;
byte1 |= EVEX_P0XMASK;
}
else if (CodeInfo->opnd[OPND1].type & OP_M64){
if (CodeInfo->evex_flag){
if (CodeInfo->reg2 <= 15) byte1 |= EVEX_P0R1MASK;
else byte1 &= ~EVEX_P0R1MASK;
}
if ((CodeInfo->reg2 <= 7) || (CodeInfo->reg2 >= 16 && CodeInfo->reg2 <= 23))
byte1 |= EVEX_P0RMASK;
else byte1 &= ~EVEX_P0RMASK;
}
}
if (CodeInfo->token == T_VCVTPS2PD || CodeInfo->token == T_VCVTPH2PS ||
CodeInfo->token == T_VCVTPS2PH | CodeInfo->token == T_VCVTQQ2PD){
if (CodeInfo->opnd[OPND2].type & OP_M_ANY || CodeInfo->opnd[OPND1].type & OP_M_ANY)
;
else {
if (CodeInfo->evex_flag){
if (CodeInfo->reg2 <= 15) byte1 |= EVEX_P0R1MASK;
else byte1 &= ~EVEX_P0R1MASK;
if ((CodeInfo->reg2 <= 7) || (CodeInfo->reg2 >= 16 && CodeInfo->reg2 <= 23))
byte1 |= EVEX_P0RMASK;
byte1 &= ~EVEX_P0XMASK | EVEX_P0BMASK | EVEX_P0R1MASK;
if (CodeInfo->reg2 <= 7)
byte1 |= EVEX_P0XMASK | EVEX_P0BMASK | EVEX_P0R1MASK;
else if (CodeInfo->reg2 <= 15)
byte1 |= EVEX_P0XMASK | EVEX_P0R1MASK;
else if (CodeInfo->reg2 <= 23)
byte1 |= EVEX_P0BMASK;
}
}
}
switch (CodeInfo->token){
case T_VGATHERPF0DPD:
case T_VGATHERPF0DPS:
case T_VGATHERPF0QPD:
case T_VGATHERPF0QPS:
case T_VGATHERPF1DPD:
case T_VGATHERPF1DPS:
case T_VGATHERPF1QPD:
case T_VGATHERPF1QPS:
case T_VSCATTERPF0DPD:
case T_VSCATTERPF1DPD:
case T_VSCATTERPF1DPS:
case T_VSCATTERPF1QPD:
case T_VSCATTERPF1QPS:
case T_VSCATTERPF0DPS:
case T_VSCATTERPF0QPS:
case T_VSCATTERPF0QPD:
if (CodeInfo->opnd[OPND1].type == OP_M)
byte1 |= EVEX_P0RMASK;
}
if (!CodeInfo->evex_flag) {
if (CodeInfo->token == T_VCVTPH2PS || CodeInfo->token == T_VCVTPS2PH) {
if (CodeInfo->opnd[OPND1].type == OP_XMM && (CodeInfo->opnd[OPND2].type == OP_XMM || CodeInfo->opnd[OPND2].type == OP_YMM))
byte1 &= 0xEF;
if (CodeInfo->opnd[OPND1].type == OP_YMM && (CodeInfo->opnd[OPND2].type == OP_XMM || CodeInfo->opnd[OPND2].type == OP_YMM))
byte1 &= 0xEF;
}
}
OutputCodeByte( byte1 );
if (CodeInfo->opnd[OPND2].type & OP_I8_U){
if (CodeInfo->token >= T_KMOVB && CodeInfo->token <= T_KMOVW)
EmitError(INVALID_COMBINATION_OF_OPCODE_AND_OPERANDS);
if ((CodeInfo->token >= T_VPSLLW) && (CodeInfo->token <= T_VPSRLQ) ||
(CodeInfo->token >= T_VPSLLVD) && (CodeInfo->token <= T_VPSRLVW)) {
c = CodeInfo->reg1;
lbyte &= 0x0f;
c = (c << 3);
c = ~c;
c &= EVEX_P1VVVV;
lbyte |= c;
if (CodeInfo->evex_flag || CodeInfo->r2type == OP_YMM)
lbyte |= 4;
if (ins->byte1_info == F_660F) lbyte |= 0x1;
CodeInfo->tuple = TRUE;
}
}
else
lbyte |= ( ( CodeInfo->prefix.rex & REX_W ) ? 0x80 : 0 );
if (CodeInfo->token == T_VMOVQ && CodeInfo->opnd[OPND1].type == OP_XMM) {
if (CodeInfo->opnd[OPND2].type & OP_R64)
{
lbyte &= 0xfd;
lbyte |= 1;
}
}
if ((CodeInfo->token == T_KSHIFTLW) || (CodeInfo->token == T_KSHIFTLQ)||
(CodeInfo->token == T_KSHIFTRW) || (CodeInfo->token == T_KSHIFTRQ)){
lbyte |= 0x80;
}
if (CodeInfo->token >= T_VPGATHERDD && CodeInfo->token <= T_VGATHERQPS){
if ((CodeInfo->opnd[OPND3].type != CodeInfo->opnd[OPND1].type)&&
(CodeInfo->evex_flag == 0))
EmitError( INVALID_USE_OF_REGISTER );
CodeInfo->tuple = TRUE;
lbyte &= ~EVEX_P1VVVV; if (CodeInfo->evex_flag){
c = EVEX_P1VVVV; }
else {
c = CodeInfo->reg3 + 1;
c = ((16 - c) << 3);
}
c &= EVEX_P1VVVV;
lbyte |= c;
if (CodeInfo->indextype == OP_YMM) lbyte |= 4;
if (( CodeInfo->prefix.rex & REX_W )) lbyte |= 0x80;
}
if ((CodeInfo->token >= T_KADDB) && (CodeInfo->token <= T_KUNPCKDQ)) {
c = CodeInfo->reg2;
lbyte &= 0xc0;
c = (c << 3);
c = ~c;
c &= EVEX_P1VVVV;
lbyte |= c;
lbyte |= 4;
if (ins->byte1_info == F_660F) lbyte |= 0x1;
}
else if ((CodeInfo->token >= T_KNOTB) && (CodeInfo->token <= T_KORTESTQ)) {
if (CodeInfo->reg2 <= 7)
lbyte |= 0x80;
if (ins->byte1_info == F_660F) lbyte |= 0x01;
}
else if ((CodeInfo->token >= T_KMOVB) && (CodeInfo->token <= T_KMOVW)) {
if ((CodeInfo->token == T_KMOVD || CodeInfo->token == T_KMOVQ))
lbyte |= 0x80;
if (ins->byte1_info == F_660F) lbyte |= 0x01;
else if (ins->byte1_info == F_0F) lbyte &= ~0x03;
else lbyte |= 0x3;
if (CodeInfo->token == T_KMOVB || CodeInfo->token == T_KMOVW || CodeInfo->token == T_KMOVD){
switch (CodeInfo->opnd[OPND2].type){
case OP_R64:
case OP_RAX:
case OP_AX:
case OP_R16:
case OP_R8:
case OP_AL:
case OP_I8:
case OP_I16:
case OP_I32:
case OP_I64:
EmitError(INVALID_COMBINATION_OF_OPCODE_AND_OPERANDS);
}
}
if (CodeInfo->token == T_KMOVQ){
switch (CodeInfo->opnd[OPND2].type){
case OP_R32:
case OP_EAX:
case OP_AX:
case OP_R16:
case OP_R8:
case OP_AL:
case OP_I8:
case OP_I16:
case OP_I32:
case OP_I64:
EmitError(INVALID_COMBINATION_OF_OPCODE_AND_OPERANDS);
}
}
}
if (CodeInfo->token < T_VCVTDQ2PD && CodeInfo->token > T_VCVTTSS2SI){
if (CodeInfo->reg2 > 15)lbyte |= EVEX_P1WMASK;
}
if ( CodeInfo->token == T_VPSCATTERQQ || CodeInfo->token == T_VSCATTERDPD || CodeInfo->token == T_VSCATTERQPD){
lbyte |= 0x80;
}
if (CodeInfo->token == T_VPGATHERDQ || CodeInfo->token == T_VPGATHERQQ ||
CodeInfo->token == T_VGATHERDPD || CodeInfo->token == T_VGATHERQPD){
lbyte |= EVEX_P1WMASK;
}
if (((CodeInfo->token <= T_VCOMPRESSPS))||((CodeInfo->token >= T_VCVTDQ2PD) &&
(CodeInfo->token <= T_VCVTTSS2SI))|| (CodeInfo->token == T_VCVTPD2DQ))
CodeInfo->evex_p2 &= ~EVEX_P1PPMASK;
if ((CodeInfo->token == T_VPCMPB) || (CodeInfo->token == T_VPCMPUB ))lbyte &= ~EVEX_P1WMASK;
if (CodeInfo->evex_flag){
if ((CodeInfo->opnd[OPND2].type == OP_M64) || (CodeInfo->opnd[OPND1].type == OP_M64))
lbyte |= EVEX_P1WMASK;
if ((CodeInfo->opnd[OPND2].type == OP_R32) || (CodeInfo->opnd[OPND2].type == OP_EAX) ||
(CodeInfo->opnd[OPND1].type == OP_R32) || (CodeInfo->opnd[OPND1].type == OP_EAX)){
lbyte &= ~EVEX_P1WMASK;
}
}
switch (CodeInfo->token){
case T_VMOVHPS:
case T_VMOVLPS:
case T_VCVTPH2PS:
case T_VCVTPS2PD:
case T_VPMOVQB:
case T_VPMOVSQB:
case T_VPMOVSWB:
case T_VPMOVWB:
case T_VPMOVUSWB:
case T_VPMOVUSQB :
case T_VGATHERQPS:
case T_VPGATHERQD:
case T_VGATHERDPS:
case T_VEXTRACTPS:
case T_VBROADCASTI32x2:
lbyte &= ~EVEX_P1WMASK;
}
switch (CodeInfo->token){
case T_VPSLLQ:
case T_VPSRLQ:
case T_VPSRAQ:
case T_VPROLQ:
case T_VPRORQ:
case T_VPBROADCASTQ:
if (CodeInfo->evex_flag)
lbyte |= EVEX_P1WMASK;
else
lbyte &= ~EVEX_P1WMASK;
}
if ((CodeInfo->token >= T_BEXTR)&&(CodeInfo->token <= T_SHRX)||(CodeInfo->token == T_BZHI)){
c = CodeInfo->reg3;
lbyte &= 0x80;
c = (c << 3);
c = ~c;
c &= EVEX_P1VVVV;
lbyte |= c;
#if AMD64_SUPPORT
lbyte |=0x80;
#endif
if (ins->byte1_info == F_660F) lbyte |= 0x1;
else if (ins->byte1_info == F_F30F38) lbyte |= 0x02; else if (ins->byte1_info == F_660F38) lbyte |= 0x01; else if (ins->byte1_info == F_F20F38) lbyte |= 0x03; }
if ((CodeInfo->token == T_BLSMSK)||(CodeInfo->token == T_BLSI)||
(CodeInfo->token == T_BLSR)){
c = CodeInfo->reg1;
lbyte &= 0x80;
c = (c << 3);
c = ~c;
c &= EVEX_P1VVVV;
lbyte |= c;
if (ins->byte1_info == F_660F) lbyte |= 0x1;
else if (ins->byte1_info == F_F20F38) lbyte |= 0x3;
}
if ((CodeInfo->token == T_PDEP)||(CodeInfo->token == T_PEXT)){
c = CodeInfo->reg2;
lbyte &= 0x80;
c = (c << 3);
c = ~c;
c &= EVEX_P1VVVV;
lbyte |= c;
if (ins->byte1_info == F_F20F38) lbyte |= 0x3;
else if (ins->byte1_info == F_F30F38)
lbyte |= 0x2;
}
if (CodeInfo->token == T_RORX)lbyte |= 0x3;
if (CodeInfo->token == T_VEXTRACTF128){
if (CodeInfo->r2type == OP_YMM)
lbyte |= 0x04;
}
switch (CodeInfo->token){
case T_VPMOVSXBW:
case T_VPMOVSXWD:
case T_VPMOVSXDQ:
case T_VPMOVZXBW:
case T_VPMOVZXWD:
case T_VPMOVZXDQ:
if((CodeInfo->r1type == OP_XMM && (CodeInfo->r2type == OP_XMM || CodeInfo->mem_type == MT_QWORD || CodeInfo->mem_type == MT_EMPTY))||
(CodeInfo->r1type == OP_YMM && (CodeInfo->r2type == OP_XMM || CodeInfo->mem_type == MT_OWORD || CodeInfo->mem_type == MT_EMPTY ))||
(CodeInfo->r1type == OP_ZMM && decoflags && (CodeInfo->r2type == OP_YMM || CodeInfo->mem_type == MT_YMMWORD || CodeInfo->mem_type == MT_EMPTY)))
lbyte &= ~EVEX_P1WMASK; else
EmitError(INVALID_COMBINATION_OF_OPCODE_AND_OPERANDS);
break;
case T_VPMOVSXBD:
case T_VPMOVSXWQ:
case T_VPMOVZXBD:
case T_VPMOVZXWQ:
if((CodeInfo->r1type == OP_XMM && (CodeInfo->r2type == OP_XMM || CodeInfo->mem_type == MT_DWORD || CodeInfo->mem_type == MT_EMPTY))||
(CodeInfo->r1type == OP_YMM && (CodeInfo->r2type == OP_XMM || CodeInfo->mem_type == MT_QWORD || CodeInfo->mem_type == MT_EMPTY ))||
(CodeInfo->r1type == OP_ZMM && decoflags && (CodeInfo->r2type == OP_XMM || CodeInfo->mem_type == MT_OWORD || CodeInfo->mem_type == MT_EMPTY)))
lbyte &= ~EVEX_P1WMASK; else
EmitError(INVALID_COMBINATION_OF_OPCODE_AND_OPERANDS);
break;
case T_VPMOVSXBQ:
case T_VPMOVZXBQ:
if((CodeInfo->r1type == OP_XMM && (CodeInfo->r2type == OP_XMM || CodeInfo->mem_type == MT_WORD || CodeInfo->mem_type == MT_EMPTY))||
(CodeInfo->r1type == OP_YMM && (CodeInfo->r2type == OP_XMM || CodeInfo->mem_type == MT_DWORD || CodeInfo->mem_type == MT_EMPTY ))||
(CodeInfo->r1type == OP_ZMM && decoflags && (CodeInfo->r2type == OP_XMM || CodeInfo->mem_type == MT_QWORD || CodeInfo->mem_type == MT_EMPTY)))
lbyte &= ~EVEX_P1WMASK; else
EmitError(INVALID_COMBINATION_OF_OPCODE_AND_OPERANDS);
break;
}
if(CodeInfo->token == T_VSCATTERQPS || CodeInfo->token == T_VPSCATTERQD ||
CodeInfo->token == T_VCVTPS2PH || CodeInfo->token == T_VCVTPH2PS ||
CodeInfo->token == T_VBROADCASTF32x2 || CodeInfo->token == T_VCVTPS2QQ ||
CodeInfo->token == T_VCVTPS2UQQ ||
(CodeInfo->token >= T_VPMOVQW && CodeInfo->token <= T_VPMOVUSDW))
lbyte &= ~EVEX_P1WMASK;
switch (CodeInfo->token) {
case T_VPSRLQ:
case T_VPSLLQ:
case T_VPSRLDQ:
lbyte |= EVEX_P1WMASK;
break;
case T_VPMULUDQ:
case T_VPERMILPD:
case T_VPADDQ:
if (CodeInfo->evex_flag == 0) lbyte &= ~EVEX_P1WMASK;
}
if (CodeInfo->token == T_VPCMPEQQ || CodeInfo->token == T_VPSLLDQ||
CodeInfo->token == T_VPCMPGTQ || CodeInfo->token == T_VPMULDQ){
if (CodeInfo->evex_flag == 0) lbyte &= ~EVEX_P1WMASK;
else lbyte |= EVEX_P1WMASK;
}
if (CodeInfo->token == T_VMOVQ) {
if (CodeInfo->opnd[OPND1].type == OP_XMM && (CodeInfo->opnd[OPND2].type == OP_XMM || (CodeInfo->opnd[OPND2].type == OP_M)) ){
lbyte &= ~0x01;
lbyte |= 0x02;
}
}
CodeInfo->evex_p1 = lbyte;
OutputCodeByte( lbyte );
if (CodeInfo->evex_flag ){
CodeInfo->evex_p2 |= decoflags;
if ((CodeInfo->r1type == OP_ZMM)|| (CodeInfo->r2type == OP_ZMM))
CodeInfo->evex_p2 |= EVEX_P2L1MASK;
else if ((CodeInfo->r1type == OP_YMM) || (CodeInfo->r2type == OP_YMM))
CodeInfo->evex_p2 |= EVEX_P2LMASK;
if (CodeInfo->evex_sae){
CodeInfo->evex_p2 &= ~0x70; c = CodeInfo->evex_sae - 0x10;
if (c == 0) c += 0x10;
CodeInfo->evex_p2 |= c;
}
if (broadflags >= 0x10 && broadflags <= 0x47) CodeInfo->evex_p2 |= 0x10;
if ((CodeInfo->token >= T_VCVTDQ2PD && CodeInfo->token <= T_VCVTTSS2SI)||
(CodeInfo->token == T_VCVTSD2SS)){
if (!CodeInfo->evex_sae){
CodeInfo->evex_p2 &= ~0x60; if (CodeInfo->opnd[OPND1].type & OP_XMM){
if (CodeInfo->r2type & (OP_XMM | OP_M64 | OP_M))
;
else EmitError(INVALID_COMBINATION_OF_OPCODE_AND_OPERANDS);
}
else if (CodeInfo->opnd[OPND1].type & OP_YMM){
if (CodeInfo->r2type & (OP_XMM | OP_M128 | OP_M))
CodeInfo->evex_p2 |= EVEX_P2LMASK;
else EmitError(INVALID_COMBINATION_OF_OPCODE_AND_OPERANDS);
}
else if (CodeInfo->opnd[OPND1].type & OP_ZMM){
if (CodeInfo->r2type & OP_YMM | OP_M256 | OP_M)
CodeInfo->evex_p2 |= EVEX_P2L1MASK;
else EmitError(INVALID_COMBINATION_OF_OPCODE_AND_OPERANDS);
}
}
}
switch (CodeInfo->token){
case T_VPGATHERDQ:
case T_VGATHERDPD:
if ((!CodeInfo->evex_flag)&& (CodeInfo->indextype == OP_ZMM || CodeInfo->r1type == OP_ZMM))
goto error1;
if (!CodeInfo->evex_flag && CodeInfo->indextype == OP_XMM);
else if ((CodeInfo->r1type == OP_XMM || CodeInfo->r1type == OP_YMM) &&
(CodeInfo->indextype == OP_XMM));
else if (CodeInfo->r1type == OP_ZMM && CodeInfo->indextype == OP_YMM)
; else goto error1;
CodeInfo->tuple = TRUE;
break;
case T_VPGATHERDD:
case T_VGATHERDPS:
case T_VPGATHERQQ:
case T_VGATHERQPD:
if ((!CodeInfo->evex_flag)&& (CodeInfo->indextype == OP_ZMM || CodeInfo->r1type == OP_ZMM))
goto error1;
if (CodeInfo->r1type == OP_XMM && CodeInfo->indextype == OP_XMM ); else if (CodeInfo->r1type == OP_YMM && CodeInfo->indextype == OP_YMM)
CodeInfo->evex_p2 |= EVEX_P2LMASK;
else if (CodeInfo->r1type == OP_ZMM && CodeInfo->indextype == OP_ZMM){
CodeInfo->evex_p2 &= ~EVEX_P2LMASK;
CodeInfo->evex_p2 |= EVEX_P2L1MASK;
}
else goto error1;
CodeInfo->tuple = TRUE;
break;
case T_VGATHERQPS:
case T_VPGATHERQD:
if ((!CodeInfo->evex_flag)&& (CodeInfo->indextype == OP_ZMM || CodeInfo->r1type == OP_ZMM))
goto error1;
if (CodeInfo->indextype == OP_XMM && CodeInfo->r1type == OP_XMM);
else if (CodeInfo->indextype == OP_YMM && CodeInfo->r1type == OP_XMM)
CodeInfo->evex_p2 |= EVEX_P2LMASK;
else if (CodeInfo->indextype == OP_ZMM && CodeInfo->r1type == OP_YMM){
CodeInfo->evex_p2 &= ~EVEX_P2LMASK;
CodeInfo->evex_p2 |= EVEX_P2L1MASK;
}
else goto error1;
CodeInfo->tuple = TRUE;
break;
case T_VPSCATTERDD:
case T_VPSCATTERQQ:
case T_VSCATTERDPS:
case T_VSCATTERQPD:
if (CodeInfo->indextype != CodeInfo->r2type) goto error1;
if (CodeInfo->indextype == OP_YMM) CodeInfo->evex_p2 |= EVEX_P2LMASK;
else if (CodeInfo->indextype == OP_ZMM){
CodeInfo->evex_p2 &= ~EVEX_P2LMASK;
CodeInfo->evex_p2 |= EVEX_P2L1MASK;
}
break;
case T_VSCATTERDPD:
case T_VPSCATTERDQ:
if ((CodeInfo->indextype == OP_XMM) && (CodeInfo->r2type == OP_ZMM)) goto error1;
else if (CodeInfo->r2type == OP_ZMM && CodeInfo->indextype != OP_YMM) goto error1;
if (CodeInfo->r2type == OP_YMM) CodeInfo->evex_p2 |= EVEX_P2LMASK;
else if (CodeInfo->r2type == OP_ZMM){
CodeInfo->evex_p2 &= ~EVEX_P2LMASK;
CodeInfo->evex_p2 |= EVEX_P2L1MASK;
}
break;
case T_VPSCATTERQD:
case T_VSCATTERQPS:
if (CodeInfo->indextype == OP_XMM || CodeInfo->indextype == OP_YMM)
if (CodeInfo->r2type != OP_XMM) goto error1;
else if (CodeInfo->r2type == OP_YMM && CodeInfo->indextype != OP_ZMM) goto error1;
if (CodeInfo->indextype == OP_YMM) CodeInfo->evex_p2 |= EVEX_P2LMASK;
else if (CodeInfo->indextype == OP_ZMM){
CodeInfo->evex_p2 &= ~EVEX_P2LMASK;
CodeInfo->evex_p2 |= EVEX_P2L1MASK;
}
break;
error1:
EmitError(INVALID_COMBINATION_OF_OPCODE_AND_OPERANDS);
}
if (CodeInfo->token >= T_VPSCATTERDD && CodeInfo->token <= T_VSCATTERQPD){
CodeInfo->tuple = TRUE;
}
if (CodeInfo->token == T_VEXTRACTPS || CodeInfo->token == T_VCVTSD2USI || CodeInfo->token == T_VCVTTSD2USI){
if (!CodeInfo->evex_sae)
CodeInfo->evex_p2 &= ~EVEX_P2L1MASK;
}
if ((CodeInfo->token == T_VEXTRACTF32x4) || (CodeInfo->token == T_VEXTRACTF64x2)||
(CodeInfo->token == T_VEXTRACTF64x4)|| (CodeInfo->token == T_VEXTRACTF32x8)||
(CodeInfo->token == T_VEXTRACTI32x4)||(CodeInfo->token == T_VEXTRACTI64x4)||
(CodeInfo->token == T_VEXTRACTI64x2)|| (CodeInfo->token == T_VEXTRACTI32x8)||
(CodeInfo->token == T_VEXTRACTPS))
{
CodeInfo->evex_p2 &= ~EVEX_P2BMASK;
if (CodeInfo->r2type == OP_YMM)
CodeInfo->evex_p2 |= EVEX_P2LMASK;
else if (CodeInfo->r2type == OP_ZMM){
CodeInfo->evex_p2 &= ~EVEX_P2LMASK;
CodeInfo->evex_p2 |= EVEX_P2L1MASK;
}
}
if (CodeInfo->evex_flag){
if (CodeInfo->token >= T_VPSLLVD && CodeInfo->token <= T_VPSRLVW);
else if (CodeInfo->token >= T_VPSLLW && CodeInfo->token <= T_VPSRLDQ);
else if (CodeInfo->token >= T_VPSLLDQ && CodeInfo->token <= T_VPSRLQ);
else if (CodeInfo->vexregop){
if (CodeInfo->reg2 <= 15) CodeInfo->evex_p2 |= EVEX_P2VMASK;
else CodeInfo->evex_p2 &= ~EVEX_P2VMASK;
}
else if ((CodeInfo->opnd[OPND2].type == OP_M || CodeInfo->opnd[OPND1].type == OP_M) && CodeInfo->indexreg != 0xFF) {
if (CodeInfo->indexreg != 0xFF && CodeInfo->indexreg <= 15 ) CodeInfo->evex_p2 |= EVEX_P2VMASK;
else CodeInfo->evex_p2 &= ~EVEX_P2VMASK;
}
if ((CodeInfo->token == T_VRNDSCALEPD) || (CodeInfo->token == T_VRNDSCALEPS)||
(CodeInfo->token == T_VCVTPS2PH))
CodeInfo->evex_p2 |= EVEX_P2VMASK;
CodeInfo->evex_p2 |= decoflags;
if (CodeInfo->token == T_VCVTDQ2PD){
if (CodeInfo->opnd[OPND1].type != OP_ZMM)
CodeInfo->evex_p2 &= ~EVEX_P2L1MASK;
}
if ((CodeInfo->token >= T_VPSLLW) && (CodeInfo->token <= T_VPSRLQ) ||
(CodeInfo->token >= T_VPSLLVD) && (CodeInfo->token <= T_VPSRLVW)||
(CodeInfo->token >= T_VPSLLVD && CodeInfo->token <= T_VPSRLVW)){
if (CodeInfo->opnd[OPND2].type & OP_I8_U) {
if (CodeInfo->reg1 <= 15)
CodeInfo->evex_p2 |= EVEX_P2VMASK;
}
else{
if (CodeInfo->reg2 <= 15)
CodeInfo->evex_p2 |= EVEX_P2VMASK;
}
}
switch (CodeInfo->token){
case T_VGATHERPF0DPD:
case T_VGATHERPF1DPD:
case T_VSCATTERPF0DPD:
case T_VSCATTERPF1DPD:
CodeInfo->evex_p2 |= EVEX_P2L1MASK;
if (CodeInfo->indexreg > 15 && CodeInfo->indexreg <= 31)
CodeInfo->evex_p2 &= ~EVEX_P2VMASK;
if (CodeInfo->indextype != OP_YMM)
EmitError(INVALID_COMBINATION_OF_OPCODE_AND_OPERANDS);
}
switch (CodeInfo->token){
case T_VGATHERPF0DPS:
case T_VGATHERPF0QPS:
case T_VGATHERPF0QPD:
case T_VGATHERPF1DPS:
case T_VGATHERPF1QPS:
case T_VGATHERPF1QPD:
case T_VSCATTERPF0DPS:
case T_VSCATTERPF0QPS:
case T_VSCATTERPF0QPD:
case T_VSCATTERPF1DPS:
case T_VSCATTERPF1QPS:
case T_VSCATTERPF1QPD:
if (CodeInfo->indexreg > 15 && CodeInfo->indexreg <= 31)
CodeInfo->evex_p2 &= ~EVEX_P2VMASK;
CodeInfo->evex_p2 |= EVEX_P2L1MASK;
if (CodeInfo->indextype != OP_ZMM)
EmitError(INVALID_COMBINATION_OF_OPCODE_AND_OPERANDS);
}
if (CodeInfo->token == T_VCVTPD2DQ || CodeInfo->token == T_VCVTTPD2DQ ||
CodeInfo->token == T_VCVTPD2PS|| CodeInfo->token == T_VCVTTPD2UDQ){
if (CodeInfo->opnd[OPND1].type == OP_YMM && CodeInfo->opnd[OPND2].type == OP_M512){
CodeInfo->evex_p2 &= ~EVEX_P2LMASK;
CodeInfo->evex_p2 |= EVEX_P2L1MASK;
}
}
if (CodeInfo->token == T_VCVTPD2UDQ){
if (CodeInfo->r1type == OP_XMM ){
CodeInfo->evex_p2 &= ~EVEX_P2L1MASK;
CodeInfo->evex_p2 |= EVEX_P2LMASK;
}
else if (CodeInfo->r1type == OP_YMM && (!CodeInfo->evex_sae )){
CodeInfo->evex_p2 &= ~EVEX_P2LMASK;
CodeInfo->evex_p2 |= EVEX_P2L1MASK;
}
}
if (CodeInfo->token == T_VFPCLASSPD || CodeInfo->token == T_VFPCLASSPS){
if (CodeInfo->mem_type == MT_ZMMWORD)
CodeInfo->evex_p2 |= EVEX_P2L1MASK;
else if (CodeInfo->mem_type == MT_YMMWORD)
CodeInfo->evex_p2 |= EVEX_P2LMASK;
}
OutputCodeByte(CodeInfo->evex_p2);
}
}
}
else {
lbyte |= ((CodeInfo->prefix.rex & REX_R) ? 0 : EVEX_P1WMASK);
if (CodeInfo->token == T_VCVTPD2PS || CodeInfo->token == T_VCVTPS2PD){
if (CodeInfo->opnd[OPND2].type == OP_M512)CodeInfo->evex_flag = 1;
lbyte |= 4;
CodeInfo->evex_p2 |= EVEX_P2L1MASK;
}
if (CodeInfo->evex_flag) {
OutputCodeByte(0x62);
if ((CodeInfo->opnd[OPND1].type & OP_M_ANY) || (CodeInfo->opnd[OPND2].type & OP_M_ANY) ||
(CodeInfo->opnd[OPND3].type & OP_M_ANY)) CodeInfo->tuple = TRUE;
lbyte &= ~EVEX_P1WMASK;
lbyte |= ((CodeInfo->pinstr->prefix) >> 8 & EVEX_P1WMASK);
if ((CodeInfo->opnd[OPND2].type == OP_M64) || (CodeInfo->opnd[OPND1].type == OP_M64))
lbyte |= EVEX_P1WMASK;
if ((CodeInfo->opnd[OPND2].type == OP_R32) || (CodeInfo->opnd[OPND2].type == OP_EAX) ||
(CodeInfo->opnd[OPND1].type == OP_R32) || (CodeInfo->opnd[OPND1].type == OP_EAX) ||
(CodeInfo->token == T_VMOVD)) {
lbyte &= ~EVEX_P1WMASK;
}
switch (ins->byte1_info) {
case F_0F38:
case F_660F38:
case F_F20F38:
CodeInfo->evex_p0 |= 0x02;
break;
case F_0F3A:
case F_660F3A:
CodeInfo->evex_p0 |= 0x03;
break;
default:
if (ins->byte1_info >= F_0F) {
CodeInfo->evex_p0 |= 0x01;
}
}
if (CodeInfo->opnd[OPND1].type & OP_M_ANY) {
if (CodeInfo->indexreg != 0xff){
if (CodeInfo->indexreg <= 7)
CodeInfo->evex_p0 |= EVEX_P0XMASK;
else
CodeInfo->evex_p0 &= ~EVEX_P0XMASK;
}
if (CodeInfo->basereg != 0xFF){
if (CodeInfo->basereg <= 7)
CodeInfo->evex_p0 |= EVEX_P0BMASK;
else
CodeInfo->evex_p0 &= ~EVEX_P0BMASK;
}
}
else if ((vex_flags[CodeInfo->token - VEX_START] & VX_NND) == 0){
CodeInfo->evex_p0 &= ~0x20; if (CodeInfo->reg3 <= 7) CodeInfo->evex_p0 |= EVEX_P0XMASK;
CodeInfo->evex_p0 |= ((CodeInfo->prefix.rex & REX_B) ? 0 : 0x20);
}
else {
CodeInfo->evex_p0 &= ~0x20; if (CodeInfo->reg2 <= 7) CodeInfo->evex_p0 |= EVEX_P0XMASK;
CodeInfo->evex_p0 |= ((CodeInfo->prefix.rex & REX_B) ? 0 : 0x20);
}
if (CodeInfo->basereg != 0xFF){
if (CodeInfo->basereg <= 7)
CodeInfo->evex_p0 |= EVEX_P0BMASK;
else
CodeInfo->evex_p0 &= ~EVEX_P0BMASK;
}
if ((CodeInfo->token >= T_VMOVLHPS) && (CodeInfo->token <= T_VMOVLPS) ||
(CodeInfo->token == T_VMOVNTDQ) || CodeInfo->token == T_VCVTTPS2UDQ ||
CodeInfo->token == T_VCVTTPD2UDQ||
(CodeInfo->token == T_VMOVUPD) || (CodeInfo->token == T_VMOVAPD) ||
(CodeInfo->token >= T_VMOVDQA32) && (CodeInfo->token <= T_VMOVDQU64) ||
(CodeInfo->token == T_VMOVAPS) || (CodeInfo->token == T_VMOVUPS)) {
if ((CodeInfo->opnd[OPND1].type & OP_XMM) || (CodeInfo->opnd[OPND1].type & OP_YMM) ||
(CodeInfo->opnd[OPND1].type & OP_ZMM)) {
if ((CodeInfo->reg1 <= 7) || (CodeInfo->reg1 >= 16 && CodeInfo->reg1 <= 23))
CodeInfo->evex_p0 |= EVEX_P0RMASK;
else CodeInfo->evex_p0 &= ~EVEX_P0RMASK;
if (CodeInfo->reg1 <= 15)
CodeInfo->evex_p0 |= EVEX_P0R1MASK;
else CodeInfo->evex_p0 &= ~EVEX_P0R1MASK;
if (CodeInfo->opnd[OPND1].type & OP_YMM) CodeInfo->evex_p2 |= EVEX_P2LMASK;
if (CodeInfo->opnd[OPND1].type & OP_ZMM) CodeInfo->evex_p2 |= EVEX_P2L1MASK;
}
else if ((CodeInfo->opnd[OPND2].type & OP_XMM) || (CodeInfo->opnd[OPND2].type & OP_YMM) ||
(CodeInfo->opnd[OPND2].type & OP_ZMM)) {
if ((CodeInfo->reg2 <= 7) || (CodeInfo->reg2 >= 16 && CodeInfo->reg2 <= 23))
CodeInfo->evex_p0 |= EVEX_P0RMASK;
else CodeInfo->evex_p0 &= ~EVEX_P0RMASK;
if (CodeInfo->reg2 <= 15)
CodeInfo->evex_p0 |= EVEX_P0R1MASK;
else CodeInfo->evex_p0 &= ~EVEX_P0R1MASK;
if (CodeInfo->opnd[OPND2].type & OP_YMM) CodeInfo->evex_p2 |= EVEX_P2LMASK;
if (CodeInfo->opnd[OPND2].type & OP_ZMM) CodeInfo->evex_p2 |= EVEX_P2L1MASK;
}
#if AMD64_SUPPORT
if ((CodeInfo->opnd[OPND2].type & OP_M_ANY) || (CodeInfo->opnd[OPND1].type & OP_M_ANY) ||
(CodeInfo->token == T_VCVTTPS2UDQ) || (CodeInfo->token == T_VCVTTPD2UDQ))
CodeInfo->evex_p0 |= EVEX_P0XMASK;
#endif
}
else { if (CodeInfo->opnd[OPND1].type & OP_M_ANY) {
if (CodeInfo->reg2 <= 15) CodeInfo->evex_p0 |= EVEX_P0R1MASK;
else CodeInfo->evex_p0 &= ~EVEX_P0R1MASK;
if ((CodeInfo->reg2 <= 7) || (CodeInfo->reg2 >= 16 && CodeInfo->reg2 <= 23))
CodeInfo->evex_p0 |= EVEX_P0RMASK;
else CodeInfo->evex_p0 &= ~EVEX_P0RMASK;
}
else if ((CodeInfo->opnd[OPND2].type & OP_M_ANY)||(CodeInfo->opnd[OPND1].type & OP_M_ANY)) {
if (CodeInfo->reg1 <= 15) CodeInfo->evex_p0 |= EVEX_P0R1MASK;
else CodeInfo->evex_p0 &= ~EVEX_P0R1MASK;
if ((CodeInfo->reg1 <= 7) || (CodeInfo->reg1 >= 16 && CodeInfo->reg1 <= 23))
CodeInfo->evex_p0 |= EVEX_P0RMASK;
else CodeInfo->evex_p0 &= ~EVEX_P0RMASK;
#if AMD64_SUPPORT
CodeInfo->evex_p0 |= EVEX_P0XMASK;
#endif
}
else {
if (CodeInfo->reg1 <= 15) CodeInfo->evex_p0 |= EVEX_P0R1MASK;
else CodeInfo->evex_p0 &= ~EVEX_P0R1MASK;
if ((CodeInfo->reg1 <= 7) || (CodeInfo->reg1 >= 16 && CodeInfo->reg1 <= 23))
CodeInfo->evex_p0 |= EVEX_P0RMASK;
else CodeInfo->evex_p0 &= ~EVEX_P0RMASK;
CodeInfo->evex_p0 &= ~0x20; CodeInfo->evex_p0 |= ((CodeInfo->prefix.rex & REX_B) ? 0 : 0x20);
}
}
if ((CodeInfo->token == T_VMOVNTPD) || (CodeInfo->token == T_VMOVNTPS)|| (CodeInfo->token == T_VMOVUPD)) {
if (CodeInfo->opnd[OPND1].type & OP_M_ANY ){
if (CodeInfo->reg2 <= 15) CodeInfo->evex_p0 |= EVEX_P0R1MASK;
else CodeInfo->evex_p0 &= ~EVEX_P0R1MASK;
if ((CodeInfo->reg2 <= 7) || (CodeInfo->reg2 >= 16 && CodeInfo->reg2 <= 23))
CodeInfo->evex_p0 |= EVEX_P0RMASK;
else CodeInfo->evex_p0 &= ~EVEX_P0RMASK;
}
else{
if (CodeInfo->reg1 <= 15) CodeInfo->evex_p0 |= EVEX_P0R1MASK;
else CodeInfo->evex_p0 &= ~EVEX_P0R1MASK;
if ((CodeInfo->reg1 <= 7) || (CodeInfo->reg1 >= 16 && CodeInfo->reg1 <= 23))
CodeInfo->evex_p0 |= EVEX_P0RMASK;
else CodeInfo->evex_p0 &= ~EVEX_P0RMASK;
}
}
if ((CodeInfo->token >= T_VMOVLHPS) && (CodeInfo->token <= T_VMOVLPS)) {
if ((CodeInfo->opnd[OPND1].type == OP_YMM) || (CodeInfo->opnd[OPND2].type == OP_YMM) ||
(CodeInfo->opnd[OPND1].type == OP_ZMM) || (CodeInfo->opnd[OPND2].type == OP_ZMM))
EmitError(INVALID_INSTRUCTION_OPERANDS);
}
if (CodeInfo->basereg == 0x10)
CodeInfo->evex_p0 |= EVEX_P0BMASK;
if (CodeInfo->token >= T_VPSLLDQ && CodeInfo->token <= T_VPSRLQ){
if (CodeInfo->opnd[OPND1].type == OP_XMM || CodeInfo->opnd[OPND1].type == OP_YMM ||
CodeInfo->opnd[OPND1].type == OP_ZMM){
if (CodeInfo->opnd[OPND2].type & OP_I8_U){
CodeInfo->evex_p0 |= EVEX_P0RMASK;
CodeInfo->evex_p0 &= ~EVEX_P0XMASK|EVEX_P0BMASK|EVEX_P0R1MASK;
if (CodeInfo->reg2 <= 7)
CodeInfo->evex_p0 |= EVEX_P0XMASK|EVEX_P0BMASK|EVEX_P0R1MASK;
else if (CodeInfo->reg2 <= 15)
CodeInfo->evex_p0 |= EVEX_P0XMASK|EVEX_P0R1MASK;
else if (CodeInfo->reg2 <= 23)
CodeInfo->evex_p0 |= EVEX_P0BMASK;
}
}
}
if (CodeInfo->token == T_VMOVD){
if (CodeInfo->opnd[OPND1].type & OP_R32){
if (CodeInfo->reg2 <= 15) CodeInfo->evex_p0 |= EVEX_P0R1MASK;
else CodeInfo->evex_p0 &= ~EVEX_P0R1MASK;
if ((CodeInfo->reg2 <= 7) || (CodeInfo->reg2 >= 16 && CodeInfo->reg2 <= 23))
CodeInfo->evex_p0 |= EVEX_P0RMASK;
else CodeInfo->evex_p0 &= ~EVEX_P0RMASK;
CodeInfo->evex_p0 |= EVEX_P0XMASK;
}
if (CodeInfo->opnd[OPND1].type & OP_M32){
if (CodeInfo->reg2 <= 15) CodeInfo->evex_p0 |= EVEX_P0R1MASK;
else CodeInfo->evex_p0 &= ~EVEX_P0R1MASK;
if ((CodeInfo->reg2 <= 7) || (CodeInfo->reg2 >= 16 && CodeInfo->reg2 <= 23))
CodeInfo->evex_p0 |= EVEX_P0RMASK;
else CodeInfo->evex_p0 &= ~EVEX_P0RMASK;
CodeInfo->evex_p0 |= EVEX_P0XMASK;
}
}
if (CodeInfo->token == T_VMOVQ || CodeInfo->token == T_VMOVSD || CodeInfo->token == T_VMOVSS){
if (CodeInfo->opnd[OPND2].type == OP_XMM && (CodeInfo->opnd[OPND1].type & OP_M_ANY))
CodeInfo->evex_p0 |= EVEX_P0XMASK;
}
else if (CodeInfo->token == T_VMOVDQU8 || CodeInfo->token == T_VMOVDQU16 ||
CodeInfo->token == T_VMOVNTPD || CodeInfo->token == T_VMOVNTPS ||
CodeInfo->token == T_VCVTTPD2UQQ || CodeInfo->token == T_VCVTTPS2UQQ){
if (CodeInfo->opnd[OPND2].type == OP_XMM || CodeInfo->opnd[OPND2].type == OP_YMM||
CodeInfo->opnd[OPND2].type == OP_ZMM)
CodeInfo->evex_p0 |= EVEX_P0XMASK;
}
else if (CodeInfo->token == T_VCVTUDQ2PD || CodeInfo->token == T_VCVTUQQ2PD || CodeInfo->token == T_VCVTUDQ2PS){
if (CodeInfo->opnd[OPND1].type == OP_XMM || CodeInfo->opnd[OPND1].type == OP_YMM||
CodeInfo->opnd[OPND1].type == OP_ZMM)
CodeInfo->evex_p0 |= EVEX_P0XMASK;
}
OutputCodeByte(CodeInfo->evex_p0);
}
else {
outC5:
if (CodeInfo->opnd[OPND3].type == OP_NONE && CodeInfo->vexregop == 0 &&
(vex_flags[CodeInfo->token - VEX_START] & VX_NND) == 0 &&
(vex_flags[CodeInfo->token - VEX_START] & VX_NMEM) == 0)
{
if(CodeInfo->opnd[OPND1].type & OP_M_ANY || CodeInfo->opnd[OPND2].type & OP_M_ANY )
;
else{
c = CodeInfo->reg1;
lbyte &= ~EVEX_P1VVVV;
c = (c << 3);
c = ~c;
c &= EVEX_P1VVVV;
lbyte |= c;
if (Parse_Pass == PASS_1)
EmitWarn( 2, AVX_REQUIRES_THREE_REGISTERS);
}
}
OutputCodeByte(0xC5);
CodeInfo->first_byte = 0xC5;
if (CodeInfo->opnd[OPND1].type == OP_YMM || CodeInfo->opnd[OPND2].type == OP_YMM || CodeInfo->token == T_VZEROALL)
lbyte |= 0x04;
else
lbyte &= ~0x04;
CodeInfo->tuple = 0;
}
if (CodeInfo->token == T_VCVTPD2DQ || CodeInfo->token == T_VCVTTPD2DQ) {
if (CodeInfo->opnd[OPND2].type & OP_M256)
lbyte |= 0x04;
}
if ((CodeInfo->token == T_LZCNT) || (CodeInfo->token == T_TZCNT))
lbyte |= 0x80;
if (CodeInfo->token == T_VMASKMOVDQU ) {
lbyte |= 0xF8;
if (ins->byte1_info == F_660F) lbyte |= 0x01;
else if (ins->byte1_info == F_0F) lbyte |= 0x3;
}
if (CodeInfo->token == T_VPGATHERDQ || CodeInfo->token == T_VPGATHERQQ ||
CodeInfo->token == T_VGATHERDPD || CodeInfo->token == T_VGATHERQPD) {
lbyte |= 0x80;
}
if (CodeInfo->token == T_VGATHERDPS || CodeInfo->token == T_VCVTTPS2QQ || CodeInfo->token == T_VCVTTPS2UQQ)
lbyte &= ~0x80;
if (CodeInfo->evex_flag) {
if ((CodeInfo->opnd[OPND2].type == OP_R32) || (CodeInfo->opnd[OPND2].type == OP_EAX))
lbyte &= ~EVEX_P1WMASK;
}
if ((CodeInfo->token >= T_KADDB) && (CodeInfo->token <= T_KUNPCKDQ)) { c = CodeInfo->reg2;
lbyte &= 0x83;
c = (c << 3);
c = ~c;
c &= EVEX_P1VVVV;
lbyte |= c;
if (vex_flags[CodeInfo->token - VEX_START] & VX_L) lbyte |= c;
}
else if ((CodeInfo->token >= T_KNOTB) && (CodeInfo->token <= T_KORTESTQ)) {
if (CodeInfo->reg1 <= 0x07)
lbyte |= 0x80;
if (ins->byte1_info == F_660F) lbyte |= 0x01;
}
else if ((CodeInfo->token >= T_KMOVB) && (CodeInfo->token <= T_KMOVW)) {
switch (CodeInfo->opnd[OPND2].type){
case OP_R64:
case OP_RAX:
case OP_AX:
case OP_R16:
case OP_R8:
case OP_AL:
case OP_I8:
case OP_I16:
case OP_I32:
case OP_I64:
EmitError(INVALID_COMBINATION_OF_OPCODE_AND_OPERANDS);
}
if (CodeInfo->reg1 <= 0x07)
lbyte |= 0x80;
if (ins->byte1_info == F_660F) lbyte |= 0x01;
else if (ins->byte1_info == F_F20F) lbyte |= 0x3;
} if ((CodeInfo->token == T_VMOVHPD) || (CodeInfo->token == T_VMOVNTDQ) ||
(CodeInfo->token >= T_VFPCLASSPD) && (CodeInfo->token <= T_VFPCLASSSS)) {
if (CodeInfo->vexregop) {
lbyte &= ~0x78;
lbyte |= ((16 - CodeInfo->vexregop) << 3);
}
else lbyte |= 0x78;
}
if (CodeInfo->evex_flag) {
if (CodeInfo->token == T_VMOVHPS || CodeInfo->token == T_VMOVLPS ||
CodeInfo->token == T_VCVTPS2QQ || CodeInfo->token == T_VCVTPS2UQQ)
lbyte &= ~EVEX_P1WMASK;
}
if ( CodeInfo->token == T_VPSRAQ || CodeInfo->token == T_VPROLQ ||
CodeInfo->token == T_VPRORQ){
if (CodeInfo->evex_flag)
lbyte |= EVEX_P1WMASK;
else
lbyte &= ~EVEX_P1WMASK;
}
if ((CodeInfo->token >= T_KADDB) && (CodeInfo->token <= T_KUNPCKDQ)) lbyte |= 0x04;
if (CodeInfo->token == T_VPMOVMSKB) {
lbyte |= EVEX_P1WMASK; if (CodeInfo->opnd[OPND1].type == OP_YMM)
lbyte |= 0x04; else if (CodeInfo->opnd[OPND1].type == OP_XMM)
lbyte &= ~0x04; lbyte &= ~0x03; lbyte |= 0x01; }
if (CodeInfo->token == T_VCVTPS2PD)
{
if (CodeInfo->evex_flag){
CodeInfo->evex_p1 &= ~EVEX_P1WMASK;
CodeInfo->evex_p1 |= 0xf0; }
else{
lbyte &= ~EVEX_P1WMASK;
lbyte |= 0xf0; if ((CodeInfo->opnd[OPND2].type == OP_XMM)|| (CodeInfo->opnd[OPND2].type & OP_M_ANY))
;
else EmitError(INVALID_INSTRUCTION_OPERANDS);
}
}
if (CodeInfo->token == T_VCVTPD2PS)
{
if (CodeInfo->evex_flag){
CodeInfo->evex_p1 |= EVEX_P1WMASK;
CodeInfo->evex_p1 |= 0xf0; }
else{
lbyte &= ~EVEX_P1WMASK;
lbyte |= 0xf0; if (CodeInfo->opnd[OPND1].type != OP_XMM)
EmitError(INVALID_INSTRUCTION_OPERANDS);
if (CodeInfo->opnd[OPND2].type == OP_M256)
lbyte |= 0x4; }
}
if (CodeInfo->token == T_VMOVQ && (CodeInfo->evex_flag == 0)){
if ((CodeInfo->opnd[OPND1].type == OP_XMM && CodeInfo->opnd[OPND2].type & OP_XMM)||
(CodeInfo->opnd[OPND1].type == OP_XMM && CodeInfo->opnd[OPND2].type & OP_M)){
lbyte &= ~0x01;
lbyte |= 0x02;
}
}
if (CodeInfo->token == T_VPEXTRW){
if ((CodeInfo->opnd[OPND1].type == OP_R32 || CodeInfo->mem_type == MT_WORD || CodeInfo->mem_type == MT_EMPTY) &&
(CodeInfo->r2type == OP_XMM ))
lbyte |= 0x01;
}
CodeInfo->evex_p1 = lbyte;
OutputCodeByte( lbyte );
if (CodeInfo->evex_flag) {
if (broadflags >= 0x10 && broadflags <= 0x47){
CodeInfo->evex_p2 |= 0x10;
if (CodeInfo->vexregop){
if (CodeInfo->reg2 <= 15) CodeInfo->evex_p2 |= EVEX_P2VMASK;
else CodeInfo->evex_p2 &= ~EVEX_P2VMASK;
}
else CodeInfo->evex_p2 |= EVEX_P2VMASK;
if ((CodeInfo->r2type == OP_XMM || CodeInfo->r1type == OP_XMM) &&
(broadflags & ~EVEX_P2AAAMASK) == 0x10){ if ((CodeInfo->mem_type != MT_QWORD) && (CodeInfo->mem_type != MT_EMPTY))
EmitError( INVALID_OPERAND_SIZE );
if ((CodeInfo->pinstr->prefix & 0xE0) == QSIZE)
CodeInfo->mem_type = MT_QWORD;
else
EmitError( MISMATCH_IN_THE_NUMBER_OF_BROADCASTING_ELEMENTS );
}
else if ((CodeInfo->r2type == OP_XMM ||CodeInfo->r1type == OP_XMM) &&
(broadflags & ~EVEX_P2AAAMASK) == 0x20){ if ((CodeInfo->mem_type != MT_DWORD) && (CodeInfo->mem_type != MT_EMPTY))
EmitError( INVALID_OPERAND_SIZE );
if ((CodeInfo->pinstr->prefix & 0xE0) == DSIZE)
CodeInfo->mem_type = MT_DWORD;
else
EmitError( MISMATCH_IN_THE_NUMBER_OF_BROADCASTING_ELEMENTS );
}
else if ((CodeInfo->r2type == OP_YMM || CodeInfo->r1type == OP_YMM) &&
(broadflags & ~EVEX_P2AAAMASK) == 0x20){ if ((CodeInfo->mem_type != MT_QWORD) && (CodeInfo->mem_type != MT_EMPTY))
EmitError( INVALID_OPERAND_SIZE );
if ((CodeInfo->pinstr->prefix & 0xE0) == QSIZE){
CodeInfo->mem_type = MT_QWORD;
CodeInfo->evex_p2 |= 0x20;
}
else
EmitError( MISMATCH_IN_THE_NUMBER_OF_BROADCASTING_ELEMENTS );
}
else if ((CodeInfo->r2type == OP_YMM || CodeInfo->r1type == OP_YMM) &&
(broadflags & ~EVEX_P2AAAMASK) == 0x30){ if ((CodeInfo->mem_type != MT_DWORD) && (CodeInfo->mem_type != MT_EMPTY) &&
(CodeInfo->mem_type != MT_QWORD) && (CodeInfo->mem_type != MT_OWORD)){
EmitError(INVALID_OPERAND_SIZE);
}
if ((CodeInfo->pinstr->prefix & 0xE0) == DSIZE){
CodeInfo->mem_type = MT_DWORD;
CodeInfo->evex_p2 |= 0x20;
}
else if ((CodeInfo->pinstr->prefix & 0xE0) == QSIZE){
CodeInfo->mem_type = MT_QWORD;
CodeInfo->evex_p2 |= 0x40;
}
else
EmitError( MISMATCH_IN_THE_NUMBER_OF_BROADCASTING_ELEMENTS );
}
else if (( CodeInfo->r2type == OP_ZMM || CodeInfo->r1type == OP_ZMM)&&
(broadflags & ~EVEX_P2AAAMASK) == 0x30){ if ((CodeInfo->pinstr->prefix & 0xE0) == QSIZE){
CodeInfo->mem_type = MT_QWORD;
CodeInfo->evex_p2 |= 0x40;
}
else if ((CodeInfo->pinstr->prefix & 0xE0) == DSIZE){
CodeInfo->mem_type = MT_DWORD;
CodeInfo->evex_p2 |= 0x40;
}
else
EmitError( MISMATCH_IN_THE_NUMBER_OF_BROADCASTING_ELEMENTS );
}
else if ((CodeInfo->r2type == OP_ZMM ||CodeInfo->r1type == OP_ZMM)&&
(broadflags & ~EVEX_P2AAAMASK) == 0x40){ if ((CodeInfo->pinstr->prefix & 0xE0) == DSIZE){
CodeInfo->mem_type = MT_DWORD;
CodeInfo->evex_p2 |= 0x40;
}
else
EmitError(MISMATCH_IN_THE_NUMBER_OF_BROADCASTING_ELEMENTS);
}
}
else{ if (CodeInfo->r2type == OP_YMM){
if (CodeInfo->mem_type == MT_YMMWORD || (CodeInfo->mem_type == MT_EMPTY)){
CodeInfo->evex_p2 |= 0x20;
if ((CodeInfo->opnd[OPND3].data32h > 0x20)||(CodeInfo->opnd[OPND3].data32h > ~0x20))
CodeInfo->tuple = TRUE;
}
else{
if (CodeInfo->token < T_VPSLLD && CodeInfo->token > T_VPRORVQ)
EmitError(INVALID_OPERAND_SIZE);
}
}
else if (CodeInfo->r2type == OP_XMM){
if ((CodeInfo->mem_type == MT_OWORD && CodeInfo->mem_type == MT_EMPTY)){
if ((CodeInfo->opnd[OPND3].data32h > 0x10)||(CodeInfo->opnd[OPND3].data32h > ~0x10))
CodeInfo->tuple = TRUE;
}
else if ((CodeInfo->token >= T_VCMPEQSD && CodeInfo->token <= T_VCMPTRUE_USSD) &&
(CodeInfo->mem_type == MT_QWORD)){
if ((CodeInfo->opnd[OPND3].data32h > 8)||(CodeInfo->opnd[OPND3].data32h > ~8))
CodeInfo->tuple = TRUE;
}
else if ((CodeInfo->token >= T_VCMPEQSS && CodeInfo->token <= T_VCMPTRUE_USSS) &&
(CodeInfo->mem_type == MT_DWORD)){
if ((CodeInfo->opnd[OPND3].data32h > 4)||(CodeInfo->opnd[OPND3].data32h > ~4))
CodeInfo->tuple = TRUE;
}
}
else if (CodeInfo->r2type == OP_ZMM){
if (CodeInfo->mem_type == MT_ZMMWORD || CodeInfo->mem_type == MT_EMPTY ||
CodeInfo->mem_type == MT_OWORD || CodeInfo->mem_type == MT_QWORD){
CodeInfo->evex_p2 |= 0x40;
if ((CodeInfo->opnd[OPND3].data32h > 0x40)||(CodeInfo->opnd[OPND3].data32h > ~0x40))
CodeInfo->tuple = TRUE;
}
}
if (CodeInfo->opnd[OPND3].data32l != -1){
if ((CodeInfo->r2type == OP_YMM) && (CodeInfo->opnd[OPND3].type != OP_ZMM)){
if ((CodeInfo->token >= T_VCMPEQPD) && (CodeInfo->token <= T_VCMPTRUE_USSS))
CodeInfo->evex_p2 |= 0x40;
if (CodeInfo->opnd[OPND3].data32l >= 0x20)
CodeInfo->tuple = TRUE;
}
}
}
if (CodeInfo->evex_sae){
CodeInfo->evex_p2 &= ~0x70; c = CodeInfo->evex_sae - 0x10;
if (c == 0) c = 0x10;
CodeInfo->evex_p2 |= c;
}
if (CodeInfo->r2type == OP_YMM) CodeInfo->evex_p2 |= EVEX_P2LMASK;
else if (CodeInfo->opnd[OPND3].type == OP_ZMM)CodeInfo->evex_p2 |= EVEX_P2L1MASK;
if ((CodeInfo->token >= T_VPGATHERDD && CodeInfo->token <= T_VGATHERQPS)){
CodeInfo->evex_p2 &= ~EVEX_P2L1MASK;
CodeInfo->evex_p2 &= ~EVEX_P2LMASK;
if (CodeInfo->r1type == OP_YMM) CodeInfo->evex_p2 |= EVEX_P2LMASK;
else if (CodeInfo->r1type == OP_ZMM) CodeInfo->evex_p2 |= EVEX_P2L1MASK;
}
if ((CodeInfo->token == T_VEXTRACTPS)||(CodeInfo->token == T_VCVTSD2USI)|| (CodeInfo->token >= T_VMOVHPD)&&(CodeInfo->token <= T_VMOVSS)) CodeInfo->evex_p2 &= ~EVEX_P2L1MASK;
if (CodeInfo->token == T_VCVTSS2USI || CodeInfo->token == T_VCVTSD2USI){
if (CodeInfo->evex_sae){
CodeInfo->evex_p2 &= ~0x70; c = CodeInfo->evex_sae - 0x10;
if (c == 0) c += 0x10;
CodeInfo->evex_p2 |= c;
}
}
if (CodeInfo->evex_flag){
if (CodeInfo->vexregop){
if (CodeInfo->vexregop <= 16) CodeInfo->evex_p2 |= EVEX_P2VMASK;
else CodeInfo->evex_p2 &= ~EVEX_P2VMASK;
}
else CodeInfo->evex_p2 |= EVEX_P2VMASK;
CodeInfo->tuple = TRUE;
CodeInfo->evex_p2 |= decoflags;
if (CodeInfo->token == T_VCVTDQ2PD || CodeInfo->token == T_VCVTPS2PD ||
CodeInfo->token == T_VMOVDQA || CodeInfo->token == T_VMOVDQU ||
CodeInfo->token == T_VCVTPD2PS){
CodeInfo->evex_p2 &= ~EVEX_P2LMASK;
CodeInfo->evex_p2 &= ~EVEX_P2L1MASK;
if (CodeInfo->r1type == OP_YMM || CodeInfo->r2type == OP_YMM)
CodeInfo->evex_p2 |= EVEX_P2LMASK;
else if (CodeInfo->r1type == OP_ZMM || CodeInfo->r2type == OP_ZMM)
CodeInfo->evex_p2 |= EVEX_P2L1MASK;
}
if (!CodeInfo->evex_sae){
switch (CodeInfo->token){
case T_VCVTPD2DQ:
case T_VCVTTPD2DQ:
case T_VCVTPD2PS:
case T_VCVTPD2UDQ:
if (CodeInfo->r1type == OP_YMM){
CodeInfo->evex_p2 &= ~EVEX_P2LMASK;
CodeInfo->evex_p2 |= EVEX_P2L1MASK;
}
else if (CodeInfo->mem_type == MT_YMMWORD)
CodeInfo->evex_p2 |= EVEX_P2LMASK;
break;
case T_VCVTPS2UDQ:
if (CodeInfo->r1type == OP_YMM)
CodeInfo->evex_p2 |= EVEX_P2LMASK;
else if (CodeInfo->r1type == OP_ZMM)
CodeInfo->evex_p2 |= EVEX_P2L1MASK;
break;
case T_VCVTDQ2PD:
if (CodeInfo->r1type == OP_ZMM){
CodeInfo->evex_p2 &= ~EVEX_P2LMASK;
CodeInfo->evex_p2 |= EVEX_P2L1MASK;
}
break;
case T_VCVTDQ2PS:
case T_VPSHUFD:
case T_VCVTPS2DQ:
case T_VCVTPD2QQ:
case T_VCVTPD2UQQ:
case T_VCVTPS2UQQ:
case T_VCVTQQ2PD:
case T_VCVTTPS2DQ:
case T_VMOVDDUP:
CodeInfo->evex_p2 &= ~EVEX_P2LMASK;
CodeInfo->evex_p2 &= ~EVEX_P2L1MASK;
if (CodeInfo->r1type == OP_YMM || CodeInfo->r2type == OP_YMM)
CodeInfo->evex_p2 |= EVEX_P2LMASK;
else if (CodeInfo->r1type == OP_ZMM || CodeInfo->r2type == OP_ZMM)
CodeInfo->evex_p2 |= EVEX_P2L1MASK;
}
}
if (CodeInfo->token == T_VCVTPS2PD || CodeInfo->token == T_VCVTUDQ2PD ||
CodeInfo->token == T_VCVTUDQ2PS ||CodeInfo->token == T_VCVTUQQ2PD){
if (CodeInfo->r1type == OP_ZMM && CodeInfo->r2type == OP_YMM){
CodeInfo->evex_p2 &= ~EVEX_P2LMASK;
CodeInfo->evex_p2 |= EVEX_P2L1MASK;
}
}
if (CodeInfo->token == T_VCVTPS2QQ || CodeInfo->token == T_VCVTPS2UQQ ||
CodeInfo->token == T_VCVTTPD2QQ || CodeInfo->token == T_VCVTTPD2UQQ ||
CodeInfo->token == T_VMOVSHDUP || CodeInfo->token == T_VMOVSLDUP ||
CodeInfo->token == T_VCVTTPS2UQQ ||CodeInfo->token == T_VCVTTPS2QQ){
if (CodeInfo->r1type == OP_YMM ){
CodeInfo->evex_p2 &= ~EVEX_P2L1MASK;
CodeInfo->evex_p2 |= EVEX_P2LMASK;
}
else if (CodeInfo->r1type == OP_ZMM ){
CodeInfo->evex_p2 &= ~EVEX_P2LMASK;
CodeInfo->evex_p2 |= EVEX_P2L1MASK;
}
}
if ((CodeInfo->token >= T_ADDPD && CodeInfo->token <= T_SUBPS) ||
CodeInfo->token == T_VCVTUDQ2PD || CodeInfo->token == T_VCVTUQQ2PD || CodeInfo->token == T_VCVTUDQ2PS||
(CodeInfo->token >= T_VADDPD && CodeInfo->token <= T_VSUBPS)||
CodeInfo->token == T_VMOVDQU8 || CodeInfo->token == T_VMOVDQU16){
if (CodeInfo->evex_flag == TRUE) {
if (CodeInfo->opnd[OPND2].type & OP_M_ANY){
if (CodeInfo->r1type == OP_YMM)CodeInfo->evex_p2 |= EVEX_P2LMASK;
else if (CodeInfo->r1type == OP_ZMM)CodeInfo->evex_p2 |= EVEX_P2L1MASK;
}
}
}
if (CodeInfo->token == T_VCVTQQ2PS ||
CodeInfo->token == T_VCVTUQQ2PD || CodeInfo->token == T_VCVTUDQ2PS ||
CodeInfo->token == T_VCVTUDQ2PD || CodeInfo->token == T_VCVTTPD2UDQ ||
CodeInfo->token == T_VCVTUQQ2PS){
if (CodeInfo->r1type == OP_XMM ){
if ((CodeInfo->token == T_VCVTTPD2UDQ || CodeInfo->token == T_VCVTUDQ2PD ||
CodeInfo->token == T_VCVTQQ2PS)&&
CodeInfo->opnd[OPND2].type & OP_M128)
;
else if (CodeInfo->opnd[OPND2].type & OP_M256){
CodeInfo->evex_p2 &= ~EVEX_P2L1MASK;
CodeInfo->evex_p2 |= EVEX_P2LMASK;
}
}
else if (CodeInfo->r1type == OP_YMM ){
if ((CodeInfo->token == T_VCVTUDQ2PD || CodeInfo->token == T_VCVTUDQ2PS||
CodeInfo->token == T_VCVTUQQ2PD) && (CodeInfo->opnd[OPND2].type & OP_M128))
;
else if (CodeInfo->token == T_VCVTUDQ2PD && CodeInfo->opnd[OPND2].type == OP_XMM)
CodeInfo->evex_p2 |= EVEX_P2LMASK;
else if (CodeInfo->token == T_VCVTUDQ2PD && CodeInfo->opnd[OPND2].type == OP_YMM)
; else if ((CodeInfo->token == T_VCVTUQQ2PD||CodeInfo->token == T_VCVTUDQ2PS) &&
CodeInfo->opnd[OPND2].type == OP_YMM)
CodeInfo->evex_p2 |= EVEX_P2LMASK;
else{
CodeInfo->evex_p2 &= ~EVEX_P2LMASK;
CodeInfo->evex_p2 |= EVEX_P2L1MASK;
}
}
}
OutputCodeByte(CodeInfo->evex_p2);
}
}
}
} else {
#endif
#if AMD64_SUPPORT
if( CodeInfo->prefix.rex != 0 ) {
if ( CodeInfo->Ofssize != USE64 ) {
EmitError( INVALID_OPERAND_SIZE );
}
OutputCodeByte( CodeInfo->prefix.rex | 0x40 );
}
#endif
if ( ins->byte1_info >= F_0F ) {
OutputCodeByte( EXTENDED_OPCODE );
switch ( ins->byte1_info ) {
case F_0F0F: OutputCodeByte( EXTENDED_OPCODE ); break;
case F_0F38:
case F_F20F38:
case F_660F38: OutputCodeByte( 0x38 ); break;
case F_0F3A:
case F_660F3A: OutputCodeByte( 0x3A ); break;
}
}
#if AVXSUPP
}
#endif
switch (ins->rm_info) {
case R_in_OP:
OutputCodeByte(ins->opcode | (CodeInfo->rm_byte & NOT_BIT_67));
break;
case no_RM:
if (CodeInfo->token == T_CLAC)
OutputCodeByte(0x01);
OutputCodeByte(ins->opcode | CodeInfo->iswide);
break;
case no_WDS:
CodeInfo->iswide = 0;
default:
if (ins->byte1_info != F_0F0F) {
if ((CodeInfo->token >= T_KADDB) && (CodeInfo->token <= T_KMOVW)){
if ((CodeInfo->token >= T_KMOVB) && (CodeInfo->token <= T_KMOVW)){
const struct instr_item *p = CodeInfo->pinstr;
int cnt;
int type1 = CodeInfo->opnd[OPND1].type;
int type2 = CodeInfo->opnd[OPND2].type;
CodeInfo->tuple = 0;
if (type1 == OP_K || type2 == OP_K)
; else
EmitError(INVALID_COMBINATION_OF_OPCODE_AND_OPERANDS);
type1 &= ~0x200;
type2 &= ~0x200;
for (cnt = 0; cnt < 5; cnt++, p++){
if ((opnd_clstab[p->opclsidx].opnd_type[OPND1] == type1) &&
(opnd_clstab[p->opclsidx].opnd_type[OPND2] == type2))
break;
}
if (cnt < 5) { OutputCodeByte(p->opcode);
}
else
OutputCodeByte(ins->opcode);
}
else
OutputCodeByte(ins->opcode);
}
else{
if (CodeInfo->token == T_VMOVDQA || CodeInfo->token == T_VMOVDQU ||
CodeInfo->token == T_VMOVDQA32 || CodeInfo->token == T_VMOVDQU32 ||
CodeInfo->token == T_VMOVDQA64 || CodeInfo->token == T_VMOVDQU64){
if (CodeInfo->opnd[OPND1].type & OP_M_ANY || CodeInfo->opnd[OPND2].type & OP_M_ANY){
if (CodeInfo->indexreg == 0xFF && CodeInfo->basereg == 0xFF){ CodeInfo->rm_byte &= ~MOD_11;
CodeInfo->rm_byte |= MOD_10;
CodeInfo->tuple = 0;
}
}
else if (CodeInfo->opnd[OPND1].type & OP_M_ANY){
if (CodeInfo->mem_type == MT_EMPTY);
else if (CodeInfo->opnd[OPND1].type == OP_M128 && CodeInfo->opnd[OPND2].type & OP_XMM);
else if (CodeInfo->opnd[OPND1].type == OP_M256 && CodeInfo->opnd[OPND2].type == OP_YMM);
else if (CodeInfo->opnd[OPND1].type == OP_M512 && CodeInfo->opnd[OPND2].type == OP_ZMM);
else
EmitError(INVALID_COMBINATION_OF_OPCODE_AND_OPERANDS);
}
}
if (CodeInfo->token == T_VMOVD){
if (CodeInfo->opnd[OPND1].type == OP_XMM && CodeInfo->opnd[OPND2].type == OP_XMM)
EmitError(INVALID_COMBINATION_OF_OPCODE_AND_OPERANDS);
}
if (CodeInfo->token == T_ADOX) {
OutputCodeByte(ins->opcode);
OutputCodeByte(0xF6);
}
else if (CodeInfo->token == T_VMOVQ){
if (CodeInfo->opnd[OPND1].type == OP_XMM && (CodeInfo->opnd[OPND2].type == OP_XMM || CodeInfo->opnd[OPND2].type == OP_M)) {
OutputCodeByte(0x7E);
}
else if (CodeInfo->first_byte == 0xC5){
if (CodeInfo->basereg == 0x10){
OutputCodeByte(0xD6);
}
else if (CodeInfo->opnd[OPND1].type == OP_XMM && CodeInfo->opnd[OPND2].type & OP_M)
OutputCodeByte(0x7E);
else if (CodeInfo->opnd[OPND1].type & OP_M64 && CodeInfo->opnd[OPND2].type == OP_XMM)
OutputCodeByte(0xD6);
}
else
OutputCodeByte(ins->opcode | CodeInfo->iswide | CodeInfo->opc_or);
}
else if (CodeInfo->token == T_MOVQ && CodeInfo->basereg != 0x10){
if (CodeInfo->opnd[OPND1].type == OP_XMM && (CodeInfo->opnd[OPND2].type & OP_MS))
OutputCodeByte(0x7E);
else if ((CodeInfo->opnd[OPND1].type & OP_MS) && CodeInfo->opnd[OPND2].type == OP_XMM)
OutputCodeByte(0xD6);
else
OutputCodeByte(ins->opcode | CodeInfo->iswide | CodeInfo->opc_or);
}
else
OutputCodeByte(ins->opcode | CodeInfo->iswide | CodeInfo->opc_or);
}
}
if ((CodeInfo->token == T_VRNDSCALEPD) || (CodeInfo->token == T_VRNDSCALEPS))CodeInfo->tuple = TRUE;
if ((CodeInfo->token >= T_KADDB) && (CodeInfo->token <= T_KUNPCKDQ)) { c = CodeInfo->reg1;
tmp = MOD_11; c = (c << 3); tmp |= c;
tmp |= CodeInfo->reg3; }
else if ((CodeInfo->token >= T_KNOTB) && (CodeInfo->token <= T_KORTESTQ)) {
tmp = MOD_11; tmp |= (CodeInfo->reg1 << 3); tmp |= CodeInfo->reg2; }
else
tmp = ins->rm_byte | CodeInfo->rm_byte;
if (CodeInfo->token == T_VCVTPS2PH){ c = CodeInfo->reg2;
if (c > 15)c -= 16;
if (c > 7)c -= 8;
c = (c << 3);
tmp |= c;
}
if (CodeInfo->basetype == T_RIP){
tmp &= ~MOD_10;
CodeInfo->tuple = 0;
}
if (CodeInfo->token == T_VEXTRACTPS){
if ((CodeInfo->opnd[OPND1].type & OP_M_ANY) && (CodeInfo->basetype != T_RIP))
CodeInfo->tuple = TRUE;
}
if (CodeInfo->tuple){
int index = -1;
int d;
if ((CodeInfo->opnd[OPND1].type & OP_M_ANY) &&
(CodeInfo->opnd[OPND1].data32l != -1)) index = OPND1;
else if ((CodeInfo->opnd[OPND2].type & OP_M_ANY) &&
(CodeInfo->opnd[OPND1].data32l != -1))
index = OPND2;
if ((index != -1) && ((Check4CompDisp8(CodeInfo, &comprdsp, &d, CodeInfo->opnd[index].data32l)) && comprdsp)){
CodeInfo->opnd[index].data32l = comprdsp;
tmp &= ~MOD_10;
tmp |= MOD_01;
}
else if (CodeInfo->opnd[OPND2].type & OP_I8_U){
if ((CodeInfo->token >= T_VPSLLW) && (CodeInfo->token <= T_VPSRLQ) ||
(CodeInfo->token == T_VRNDSCALEPD) || (CodeInfo->token == T_VRNDSCALEPS) ||
(CodeInfo->token >= T_VPSLLVD) && (CodeInfo->token <= T_VPSRLVW)){
if ((CodeInfo->vexconst) && ((Check4CompDisp8(CodeInfo, &comprdsp, &d, CodeInfo->vexconst)) && comprdsp)){
CodeInfo->opnd[OPND1].data32l = comprdsp;
tmp &= ~MOD_10;
tmp |= MOD_01;
if ((CodeInfo->token == T_VRNDSCALEPD) || (CodeInfo->token == T_VRNDSCALEPS)){
c = CodeInfo->reg2;
if (c > 15) c -= 16;
if (c > 7) c -= 8;
tmp |= c;
}
}
else{
CodeInfo->tuple = 0;
if (CodeInfo->indexreg != 0xff){
tmp &= ~NOT_BIT_345;
tmp &= ~BIT_012;
tmp |= MOD_10;
tmp |= RM_SIB;
c = CodeInfo->indexreg;
c = (c &= 0x7) << 3;
CodeInfo->sib |= c;
c = CodeInfo->basereg;
c &= 0x7;
CodeInfo->sib |= c;
CodeInfo->rm_byte = tmp;
CodeInfo->sib |= MOD_11;
CodeInfo->opnd[OPND1].data32l = CodeInfo->vexconst;
}
else {
if ((CodeInfo->opnd[OPND1].type == OP_R64) || (CodeInfo->opnd[OPND1].type == OP_RAX) ||
(CodeInfo->opnd[OPND1].type == OP_R32) || (CodeInfo->opnd[OPND1].type == OP_EAX)){
tmp &= ~MOD_11;
if (CodeInfo->vexconst){
tmp |= MOD_10;
CodeInfo->rm_byte = tmp;
CodeInfo->opnd[OPND1].data32l = CodeInfo->vexconst;
}
}
else if ((CodeInfo->opnd[OPND1].type == OP_XMM) || (CodeInfo->opnd[OPND1].type == OP_YMM) ||
(CodeInfo->opnd[OPND1].type == OP_ZMM)){
CodeInfo->tuple = 0;
if (CodeInfo->vexconst){
tmp &= ~NOT_BIT_345;
tmp &= ~BIT_012;
tmp |= MOD_10;
tmp |= RM_SIB;
if (CodeInfo->indexreg != 0xFF){
c = CodeInfo->indexreg;
c = (c &= 0x07) << 3;
CodeInfo->sib |= c;
c = CodeInfo->basereg;
c &= 0x7;
CodeInfo->sib |= c;
CodeInfo->sib &= 0xf0;
}
else{
tmp &= ~0x07;
tmp |= (CodeInfo->reg2 & 0x07);
}
CodeInfo->rm_byte = tmp;
CodeInfo->opnd[OPND1].data32l = CodeInfo->vexconst;
}
else {
if ((CodeInfo->r2type) && ((CodeInfo->token == T_VRNDSCALEPD) || (CodeInfo->token == T_VRNDSCALEPS)))
tmp &= ~0xc0;
if ((CodeInfo->token >= T_VPSLLW) && (CodeInfo->token <= T_VPSRLQ) ||
(CodeInfo->token >= T_VPSLLVD) && (CodeInfo->token <= T_VPSRLVW)) {
tmp &= ~7;
if ((CodeInfo->r2type == OP_R64) || (CodeInfo->r2type == OP_R32)) tmp &= ~0xc0;
}
c = CodeInfo->reg2;
if (c > 15) c -= 16;
if (c > 7) c -= 8;
tmp |= c;
}
}
}
}
}
}
else{
CodeInfo->tuple = 0;
if (CodeInfo->token >= T_VPGATHERDD && CodeInfo->token <= T_VSCATTERQPD){
if (CodeInfo->token != T_VGATHERDPD && CodeInfo->token != T_VGATHERQPD &&
CodeInfo->token != T_VPGATHERDQ && CodeInfo->token != T_VPGATHERQQ&&
CodeInfo->token != T_VGATHERDPS && CodeInfo->token != T_VPGATHERDD&&
CodeInfo->token != T_VGATHERQPS && CodeInfo->token != T_VPGATHERQD)
tmp &= ~0xc0;
CodeInfo->rm_byte = tmp;
}
}
}
if (CodeInfo->token == T_VCVTPS2PH || CodeInfo->token == T_VCVTSI2SS){
if (!comprdsp) CodeInfo->tuple = 0;
if (CodeInfo->indexreg != 0xFF){
c = CodeInfo->indexreg;
c = (c &= 0x07) << 3;
CodeInfo->sib |= c;
c = CodeInfo->basereg;
c &= 0x7;
CodeInfo->sib |= c;
CodeInfo->sib = 0xf0;
tmp |= RM_SIB;
}
CodeInfo->rm_byte = tmp;
}
if (CodeInfo->token == T_BLSMSK){
tmp &= ~0x38;
tmp |= 0x10;
}
if (CodeInfo->token == T_BLSR){
tmp &= ~0x38;
tmp |= 0x08;
}
if ((CodeInfo->basetype == 0xfe) && ((CodeInfo->indextype == OP_XMM) ||
(CodeInfo->indextype == OP_YMM) || (CodeInfo->indextype == OP_ZMM))){
if (CodeInfo->basereg != 0xff)
tmp &= ~0xC0; }
if (CodeInfo->isptr)
tmp &= 0xfe;
if (CodeInfo->token == T_RDPID){
tmp = NOT_BIT_012;
tmp |= CodeInfo->reg1;
}
if (CodeInfo->token == T_VMOVDQA || CodeInfo->token == T_VMOVDQU)
{
if ((CodeInfo->opnd[OPND2].type & OP_M_ANY) && (CodeInfo->opnd[OPND2].data32l >= -128) &&
(CodeInfo->opnd[OPND2].data32l < 128) && (CodeInfo->basereg != 0xff)) {
tmp &= NOT_BIT_67;
tmp |= MOD_01;
if (CodeInfo->opnd[OPND2].data32l == 0)
tmp &= NOT_BIT_6;
}
else if ((CodeInfo->opnd[OPND1].type & OP_M_ANY) && (CodeInfo->opnd[OPND1].data32l >= -128) && (CodeInfo->opnd[OPND1].data32l < 128))
{
tmp &= NOT_BIT_67;
tmp |= MOD_01;
if (CodeInfo->opnd[OPND1].data32l == 0)
tmp &= NOT_BIT_6;
}
}
switch (CodeInfo->token){
case T_VGATHERDPD:
case T_VGATHERDPS:
case T_VPGATHERDQ:
case T_VGATHERPF0DPS:
case T_VGATHERPF0QPD:
case T_VGATHERPF1DPD:
case T_VGATHERPF1QPD:
case T_VSCATTERPF0DPD:
case T_VSCATTERPF0QPD:
case T_VSCATTERPF1DPD:
case T_VSCATTERPF1QPD:
case T_VSCATTERDPD:
case T_VSCATTERQPD:
case T_VPSCATTERDQ:
case T_VGATHERQPD:
case T_VPGATHERDD:
case T_VGATHERPF0DPD:
case T_VPGATHERQQ:
case T_VGATHERPF0QPS:
case T_VGATHERPF1DPS:
case T_VGATHERPF1QPS:
case T_VSCATTERPF0DPS:
case T_VSCATTERPF0QPS:
case T_VSCATTERPF1DPS:
case T_VSCATTERPF1QPS:
case T_VSCATTERDPS:
case T_VPSCATTERDD:
case T_VPSCATTERQQ:
if (CodeInfo->evex_flag && CodeInfo->tuple == 0 )
{
if (((CodeInfo->opnd[OPND1].type & OP_M_ANY) && (CodeInfo->opnd[OPND1].data32l)) ||
((CodeInfo->opnd[OPND2].type & OP_M_ANY) && (CodeInfo->opnd[OPND2].data32l)))
{
tmp &= NOT_BIT_67;
tmp |= MOD_10;
CodeInfo->rm_byte = tmp;
}
}
break;
case T_VMOVUPD:
case T_VMOVAPD:
case T_VMOVUPS:
case T_VMOVAPS:
if (((CodeInfo->opnd[OPND1].type & OP_M_ANY) && CodeInfo->opnd[OPND1].data64 != 0) ||
((CodeInfo->opnd[OPND2].type & OP_M_ANY) && CodeInfo->opnd[OPND2].data64 != 0))
{
if (CodeInfo->evex_flag && CodeInfo->tuple == 0)
{
tmp &= NOT_BIT_67;
tmp |= MOD_10;
CodeInfo->rm_byte = tmp;
}
}
}
OutputCodeByte( tmp );
if ( CodeInfo->Ofssize == USE16 && CodeInfo->prefix.adrsiz == 0 )
return;
switch ( tmp & NOT_BIT_345 ) {
case 0x04:
case 0x44:
case 0x84:
if (CodeInfo->isptr)
OutputCodeByte(0x25);
else
OutputCodeByte( CodeInfo->sib );
}
}
return;
}
static void output_data(struct code_info *CodeInfo, enum operand_type determinant, int index)
{
int size = 0;
if ( (CodeInfo->token == T_INS && CodeInfo->opnd[OPND1].type != OP_NONE) ||
(CodeInfo->token == T_OUTS && CodeInfo->opnd[OPND2].type != OP_NONE) )
return;
if (CodeInfo->token == T_XLAT || CodeInfo->token == T_XLATB)
return;
if (CodeInfo->token == T_LODS || CodeInfo->token == T_MOVS || CodeInfo->token == T_STOS)
return;
#if AVXSUPP
if (CodeInfo->token >= VEX_START){
if ((CodeInfo->token == T_ANDN) || (CodeInfo->token == T_MULX) ||
(CodeInfo->token == T_PDEP) || (CodeInfo->token == T_PEXT)){
if ((CodeInfo->opnd[OPND2].data32l == 0) || (index == 2))
return;
}
if ((CodeInfo->token >= T_BEXTR) && (CodeInfo->token <= T_SHRX) || (CodeInfo->token == T_BZHI)) {
if (CodeInfo->opnd[OPND2].data32l == 0) return;
if ((index == 0) || (index == 2))
return;
}
if (CodeInfo->opnd[OPND2].type == OP_I8 && CodeInfo->evex_flag){
if ((CodeInfo->token >= T_VPSLLW) && (CodeInfo->token <= T_VPSRLQ) ||
(CodeInfo->token >= T_VPSLLVD) && (CodeInfo->token <= T_VPSRLVW) ||
(CodeInfo->token == T_VRNDSCALEPD) || (CodeInfo->token == T_VRNDSCALEPS))
{
if (((CodeInfo->rm_byte) >> 6) == 2)size = 4;
else if (((CodeInfo->rm_byte) >> 6) == 1)size = 2;
}
}
}
else
#endif
if ( CodeInfo->token == T_XLAT || CodeInfo->token == T_XLATB ||
CodeInfo->pinstr->allowed_prefix == AP_REP ||
CodeInfo->pinstr->allowed_prefix == AP_REPxx ) {
; }
#ifdef DEBUG_OUT
if ( CodeInfo->opnd[index].InsFixup )
DebugMsg1(("output_data(idx=%u, op=%" I32_SPEC "X [data=%" I32_SPEC "X fixup=%p typ=%u] ) enter [rm=%X]\n", index, determinant, CodeInfo->opnd[index].data32l, CodeInfo->opnd[index].InsFixup, CodeInfo->opnd[index].InsFixup->type ,CodeInfo->rm_byte ));
else
DebugMsg1(("output_data(idx=%u, op=%" I32_SPEC "X [data=%" I32_SPEC "X fixup=NULL] ) enter [rm=%X]\n", index, determinant, CodeInfo->opnd[index].data32l, CodeInfo->rm_byte ));
#endif
if ( (determinant & OP_R64 || determinant & OP_R32) && CodeInfo->opnd[index].data32l != 0) {
size = 1;
if (CodeInfo->indexreg != 0 || decoflags != 0){
if (CodeInfo->tuple == 0) size = 4;
}
}
if( determinant & OP_I8 ) {
size = 1;
} else if( determinant & OP_I16 ) {
size = 2;
} else if( determinant & OP_I32 ) {
size = 4;
} else if( determinant & OP_I48 ) {
size = 6;
#if AMD64_SUPPORT
} else if( determinant & OP_I64 ) {
size = 8;
#endif
} else if( determinant & OP_M_ANY ) {
switch( CodeInfo->rm_byte & BIT_67 ) {
case MOD_01:
size = 1;
break;
case MOD_00:
if( ( CodeInfo->Ofssize == USE16 && CodeInfo->prefix.adrsiz == 0 ) ||
( CodeInfo->Ofssize == USE32 && CodeInfo->prefix.adrsiz == 1 ) ) {
if( ( CodeInfo->rm_byte & BIT_012 ) == RM_D16 ) {
size = 2;
}
} else {
#if AMD64_SUPPORT
if (CodeInfo->Ofssize == USE64 && (CodeInfo->pinstr->opcode & 0xFC) == 0xA0 && CodeInfo->pinstr->byte1_info == 0)
{
size = 8;
}
else
#endif
switch( CodeInfo->rm_byte & BIT_012 ) {
case RM_SIB:
if( ( CodeInfo->sib & BIT_012 ) != RM_D32 ) {
break;
}
case RM_D32:
size = 4;
#if AMD64_SUPPORT
if ( CodeInfo->Ofssize == USE64 && CodeInfo->opnd[index].data64 >= 0x80000000 && CodeInfo->opnd[index].data64 < 0xffffffff80000000 )
EmitErr( INVALID_COMBINATION_OF_OPCODE_AND_OPERANDS );
#endif
}
}
break;
case MOD_10:
if( ( CodeInfo->Ofssize == USE16 && CodeInfo->prefix.adrsiz == 0 ) ||
( CodeInfo->Ofssize == USE32 && CodeInfo->prefix.adrsiz == 1 ) && (CodeInfo->evex_flag == 0)) {
size = 2;
} else {
size = 4;
}
}
}
#ifdef DEBUG_OUT
if ( size > 4 )
DebugMsg1(( "output_data: size=%u cont=%" I64_SPEC "X\n", size, CodeInfo->opnd[index].data64 ));
else if ( size )
DebugMsg1(( "output_data: size=%u cont=%" I32_SPEC "X\n", size, CodeInfo->opnd[index].data32l ));
else
DebugMsg1(( "output_data: size=0\n" ));
#endif
if (size) {
if (CodeInfo->opnd[index].InsFixup) {
if (Parse_Pass > PASS_1)
if ((1 << CodeInfo->opnd[index].InsFixup->type) & ModuleInfo.fmtopt->invalid_fixup_type) {
EmitErr(UNSUPPORTED_FIXUP_TYPE,
ModuleInfo.fmtopt->formatname,
CodeInfo->opnd[index].InsFixup->sym ? CodeInfo->opnd[index].InsFixup->sym->name : szNull);
}
if (write_to_file) {
CodeInfo->opnd[index].InsFixup->locofs = GetCurrOffset();
if(CodeInfo->isptr)
OutputBytes((unsigned char *)&CodeInfo->opnd[index].data32l, size, NULL);
else
OutputBytes((unsigned char*)&CodeInfo->opnd[index].data32l, size, CodeInfo->opnd[index].InsFixup);
return;
}
}
}
if ((CodeInfo->tuple)&&(CodeInfo->opnd[OPND2].type != OP_I8)) {
OutputByte(CodeInfo->opnd[index].data32l);
}
else
{
if (CodeInfo->token == T_VMOVDQA || CodeInfo->token == T_VMOVDQU)
{
if ((CodeInfo->opnd[OPND2].type & OP_M_ANY) && (CodeInfo->opnd[OPND2].data32l >= -128) && (CodeInfo->opnd[OPND2].data32l < 128))
{
if(CodeInfo->opnd[OPND2].data32l != 0)
OutputBytes((unsigned char *)&CodeInfo->opnd[index].data32l, 1, NULL);
}
else if ((CodeInfo->opnd[OPND1].type & OP_M_ANY) && (CodeInfo->opnd[OPND1].data32l >= -128) && (CodeInfo->opnd[OPND1].data32l < 128))
{
if (CodeInfo->opnd[OPND1].data32l != 0)
OutputBytes((unsigned char *)&CodeInfo->opnd[index].data32l, 1, NULL);
}
else
OutputBytes((unsigned char *)&CodeInfo->opnd[index].data32l, size, NULL);
}
else
OutputBytes((unsigned char *)&CodeInfo->opnd[index].data32l, size, NULL);
}
return;
}
static ret_code check_3rd_operand( struct code_info *CodeInfo )
{
if( ( opnd_clstab[CodeInfo->pinstr->opclsidx].opnd_type_3rd == OP3_NONE ) ||
( opnd_clstab[CodeInfo->pinstr->opclsidx].opnd_type_3rd == OP3_HID ) )
return( ( CodeInfo->opnd[OPND3].type == OP_NONE ) ? NOT_ERROR : ERROR );
DebugMsg1(("check_3rd_operand: tab=%X <-> codeinfo=%X\n", opnd_clstab[CodeInfo->pinstr->opclsidx].opnd_type_3rd, CodeInfo->opnd[OPND3].type ));
switch ( opnd_clstab[CodeInfo->pinstr->opclsidx].opnd_type_3rd ) {
case OP3_CL:
if ( CodeInfo->opnd[OPND3].type == OP_CL )
return( NOT_ERROR );
break;
case OP3_I8_U:
if ( ( CodeInfo->opnd[OPND3].type & OP_I ) && CodeInfo->opnd[OPND3].data32l >= -128 ) {
if ( ( CodeInfo->token == T_IMUL && CodeInfo->opnd[OPND3].data32l < 128 ) ||
( CodeInfo->token != T_IMUL && CodeInfo->opnd[OPND3].data32l < 256 ) ) {
CodeInfo->opnd[OPND3].type = OP_I8;
return( NOT_ERROR );
}
}
break;
case OP3_I:
if ( CodeInfo->opnd[OPND3].type & OP_I )
return( NOT_ERROR );
break;
case OP3_XMM0:
#if AVXSUPP
if ( CodeInfo->token >= VEX_START ) {
return( NOT_ERROR );
} else
#endif
if ( CodeInfo->opnd[OPND3].type == OP_XMM &&
CodeInfo->opnd[OPND3].data32l == 0 )
return( NOT_ERROR );
break;
}
return( ERROR );
}
static void output_3rd_operand( struct code_info *CodeInfo )
{
if( opnd_clstab[CodeInfo->pinstr->opclsidx].opnd_type_3rd == OP3_I8_U ) {
DebugMsg1(("output_3rd_operand, expected I8, op3=%" I32_SPEC "X\n", CodeInfo->opnd[OPND3].type ));
output_data( CodeInfo, OP_I8, OPND3 );
} else if( opnd_clstab[CodeInfo->pinstr->opclsidx].opnd_type_3rd == OP3_I ) {
output_data( CodeInfo, CodeInfo->opnd[OPND3].type, OPND3 );
}
else if (opnd_clstab[CodeInfo->pinstr->opclsidx].opnd_type_3rd == OP3_HID) {
DebugMsg1(("output_3rd_operand, expected OP3_HID, op3=%" I32_SPEC "X\n", CodeInfo->opnd[OPND3].type));
switch (CodeInfo->token){
case T_PCLMULLQLQDQ:
CodeInfo->opnd[OPND3].InsFixup = NULL;
OutputCodeByte(0x00);
return;
case T_PCLMULHQLQDQ:
CodeInfo->opnd[OPND3].InsFixup = NULL;
OutputCodeByte(0x01);
return;
case T_PCLMULLQHQDQ:
CodeInfo->opnd[OPND3].InsFixup = NULL;
OutputCodeByte(0x10);
return;
case T_PCLMULHQHQDQ:
CodeInfo->opnd[OPND3].InsFixup = NULL;
OutputCodeByte(0x11);
return;
}
#if AVXSUPP
if (CodeInfo->token >= VEX_START){
switch (CodeInfo->token){
case T_VPCLMULLQLQDQ:
CodeInfo->opnd[OPND3].InsFixup = NULL;
OutputCodeByte(0x00);
return;
case T_VPCLMULHQLQDQ:
CodeInfo->opnd[OPND3].InsFixup = NULL;
OutputCodeByte(0x01);
return;
case T_VPCLMULLQHQDQ:
CodeInfo->opnd[OPND3].InsFixup = NULL;
OutputCodeByte(0x10);
return;
case T_VPCLMULHQHQDQ:
CodeInfo->opnd[OPND3].InsFixup = NULL;
OutputCodeByte(0x11);
return;
}
if (CodeInfo->token >= T_VCMPEQPD && CodeInfo->token <= T_VCMPTRUE_USSS){
CodeInfo->opnd[OPND3].InsFixup = NULL;
OutputCodeByte((CodeInfo->token - T_VCMPEQPD) & 0x1F);
return;
}
else if (CodeInfo->token >= T_VPCMPEQD && CodeInfo->token <= T_VPCMPTRUED){
CodeInfo->opnd[OPND3].InsFixup = NULL;
OutputCodeByte((CodeInfo->token - T_VPCMPEQD) & 0x07);
return;
}
else if (CodeInfo->token >= T_VPCMPEQUD && CodeInfo->token <= T_VPCMPTRUEUD){
CodeInfo->opnd[OPND3].InsFixup = NULL;
OutputCodeByte((CodeInfo->token - T_VPCMPEQUD) & 0x07);
return;
}
else if (CodeInfo->token >= T_VPCMPEQQ && CodeInfo->token <= T_VPCMPTRUEQ){
CodeInfo->opnd[OPND3].InsFixup = NULL;
OutputCodeByte((CodeInfo->token - T_VPCMPEQQ) & 0x07);
return;
}
else if (CodeInfo->token >= T_VPCMPEQUQ && CodeInfo->token <= T_VPCMPTRUEUQ){
CodeInfo->opnd[OPND3].InsFixup = NULL;
OutputCodeByte((CodeInfo->token - T_VPCMPEQUQ) & 0x07);
return;
}
else if (CodeInfo->token >= T_VPCMPEQW && CodeInfo->token <= T_VPCMPTRUEW){
CodeInfo->opnd[OPND3].InsFixup = NULL;
OutputCodeByte((CodeInfo->token - T_VPCMPEQW) & 0x07);
return;
}
else if (CodeInfo->token >= T_VPCMPEQUW && CodeInfo->token <= T_VPCMPTRUEUW){
CodeInfo->opnd[OPND3].InsFixup = NULL;
OutputCodeByte((CodeInfo->token - T_VPCMPEQUW) & 0x07);
return;
}
else if (CodeInfo->token >= T_VPCMPEQB && CodeInfo->token <= T_VPCMPTRUEB){
CodeInfo->opnd[OPND3].InsFixup = NULL;
OutputCodeByte((CodeInfo->token - T_VPCMPEQB) & 0x07);
return;
}
else if (CodeInfo->token >= T_VPCMPEQUB && CodeInfo->token <= T_VPCMPTRUEUB){
CodeInfo->opnd[OPND3].InsFixup = NULL;
OutputCodeByte((CodeInfo->token - T_VPCMPEQUB) & 0x07);
return;
}
}
else
#endif
CodeInfo->opnd[OPND3].data32l = ( CodeInfo->token - T_CMPEQPD ) % 8;
CodeInfo->opnd[OPND3].InsFixup = NULL;
output_data( CodeInfo, OP_I8, OPND3 );
}
#if AVXSUPP
else if( ((CodeInfo->token >= VEX_START) && (CodeInfo->token < T_VPGATHERDD)||
(CodeInfo->token > T_VGATHERQPS))&&
opnd_clstab[CodeInfo->pinstr->opclsidx].opnd_type_3rd == OP3_XMM0 ) {
CodeInfo->opnd[OPND3].data32l = ( CodeInfo->opnd[OPND3].data32l << 4 );
if (CodeInfo->opnd[OPND3].type != OP_K)
output_data( CodeInfo, OP_I8, OPND3 );
}
#endif
return;
}
static ret_code match_phase_3( struct code_info *CodeInfo, enum operand_type opnd1 )
{
enum operand_type determinant = opnd_clstab[CodeInfo->pinstr->opclsidx].opnd_type[OPND1];
enum operand_type opnd2 = CodeInfo->opnd[OPND2].type;
enum operand_type tbl_op2;
DebugMsg1(("match_phase_3 enter, opnd1=%" I32_SPEC "X, searching op2=%" I32_SPEC "X\n", opnd1, opnd2 ));
#if AVXSUPP
if ( CodeInfo->token >= VEX_START && ( vex_flags[ CodeInfo->token - VEX_START ] & VX_L ) ) {
if ( CodeInfo->opnd[OPND1].type & (OP_K | OP_YMM | OP_ZMM | OP_M256) ) {
if ( opnd2 & OP_ZMM || opnd2 & OP_YMM || opnd2 & OP_K)
opnd2 |= OP_XMM;
else if ( opnd2 & OP_M256 )
opnd2 |= OP_M128;
else if ( opnd2 & OP_M128 )
opnd2 |= OP_M64; else if ( ( opnd2 & OP_XMM ) && !( vex_flags[ CodeInfo->token - VEX_START ] & VX_HALF ) ) {
EmitError( INSTRUCTION_OR_REGISTER_NOT_ACCEPTED_IN_CURRENT_CPU_MODE );
return( ERROR );
}
}
#if 1
else if ( CodeInfo->opnd[OPND1].type == OP_M ) {
if ( opnd2 & OP_YMM || opnd2 & OP_ZMM)
opnd2 |= OP_XMM;
}
#endif
}
#endif
do {
tbl_op2 = opnd_clstab[CodeInfo->pinstr->opclsidx].opnd_type[OPND2];
DebugMsg1(("match_phase_3: instr table op2=%" I32_SPEC "X\n", tbl_op2 ));
switch( tbl_op2 ) {
case OP_I:
if( opnd2 & tbl_op2 ) {
DebugMsg1(("match_phase_3: matched OP_I\n"));
if( opnd1 & OP_R8 ) {
CodeInfo->prefix.opsiz = FALSE;
opnd2 = OP_I8;
if( CodeInfo->opnd[OPND2].InsFixup != NULL ) {
if ( CodeInfo->opnd[OPND2].InsFixup->type != FIX_HIBYTE )
CodeInfo->opnd[OPND2].InsFixup->type = FIX_OFF8;
}
} else if( opnd1 & OP_R16 ) {
opnd2 = OP_I16;
#if AMD64_SUPPORT
} else if( opnd1 & (OP_R32 | OP_R64 ) ) {
#else
} else if( opnd1 & OP_R32 ) {
#endif
CodeInfo->prefix.opsiz = CodeInfo->Ofssize ? 0 : 1;
opnd2 = OP_I32;
} else if( opnd1 & OP_M ) {
switch( OperandSize( opnd1, CodeInfo ) ) {
case 1:
opnd2 = OP_I8;
CodeInfo->prefix.opsiz = FALSE;
break;
case 2:
opnd2 = OP_I16;
CodeInfo->prefix.opsiz = CodeInfo->Ofssize ? 1 : 0;
break;
#if AMD64_SUPPORT
case 8:
#endif
case 4:
opnd2 = OP_I32;
CodeInfo->prefix.opsiz = CodeInfo->Ofssize ? 0 : 1;
break;
default:
EmitError( INVALID_COMBINATION_OF_OPCODE_AND_OPERANDS );
}
}
output_opc( CodeInfo );
output_data( CodeInfo, opnd1, OPND1 );
output_data( CodeInfo, opnd2, OPND2 );
return( NOT_ERROR );
}
break;
case OP_I8_U:
if( opnd2 & tbl_op2 ) {
DebugMsg1(("match_phase_3: matched OP_I8_U\n"));
if ( CodeInfo->const_size_fixed && opnd2 != OP_I8 )
break;
if( CodeInfo->opnd[OPND2].data32l <= UCHAR_MAX && CodeInfo->opnd[OPND2].data32l >= SCHAR_MIN ) {
if ( CodeInfo->opnd[OPND2].InsFixup != NULL ) {
if ( CodeInfo->opnd[OPND2].InsFixup->type == FIX_OFF16 ||
CodeInfo->opnd[OPND2].InsFixup->type == FIX_OFF32 )
CodeInfo->opnd[OPND2].InsFixup->type = FIX_OFF8;
}
output_opc( CodeInfo );
output_data( CodeInfo, opnd1, OPND1 );
output_data( CodeInfo, OP_I8, OPND2 );
return( NOT_ERROR );
}
}
break;
case OP_I8:
if( ModuleInfo.NoSignExtend &&
( CodeInfo->token == T_AND ||
CodeInfo->token == T_OR ||
CodeInfo->token == T_XOR ) )
break;
if ( CodeInfo->opnd[OPND2].InsFixup != NULL && CodeInfo->opnd[OPND2].InsFixup->sym && CodeInfo->opnd[OPND2].InsFixup->sym->state != SYM_UNDEFINED )
break;
if ( CodeInfo->const_size_fixed == FALSE )
if ( ( opnd1 & ( OP_R16 | OP_M16 ) ) && (int_8)CodeInfo->opnd[OPND2].data32l == (int_16)CodeInfo->opnd[OPND2].data32l )
tbl_op2 |= OP_I16;
else if ( ( opnd1 & ( OP_RGT16 | OP_MGT16 ) ) && (int_8)CodeInfo->opnd[OPND2].data32l == (int_32)CodeInfo->opnd[OPND2].data32l )
tbl_op2 |= OP_I32;
if( opnd2 & tbl_op2 ) {
DebugMsg1(("match_phase_3: matched OP_I8\n"));
output_opc( CodeInfo );
output_data( CodeInfo, opnd1, OPND1 );
output_data( CodeInfo, OP_I8, OPND2 );
return( NOT_ERROR );
}
break;
case OP_I_1:
if( opnd2 & tbl_op2 ) {
if ( CodeInfo->opnd[OPND2].data32l == 1 ) {
DebugMsg1(("match_phase_3: matched OP_I_1\n"));
output_opc( CodeInfo );
output_data( CodeInfo, opnd1, OPND1 );
return( NOT_ERROR );
}
}
break;
default:
if (CodeInfo->token < T_VBROADCASTSS)(CodeInfo->evex_flag = 0);
if ((opnd2 & tbl_op2) || (CodeInfo->mem_type == MT_EMPTY && opnd2 == OP_I8 && CodeInfo->opnd[OPND1].type == OP_XMM) ||
((CodeInfo->evex_flag)&&(CodeInfo->token < T_VPBROADCASTB) || (CodeInfo->token > T_VPBROADCASTQ))) { if( check_3rd_operand( CodeInfo ) == ERROR )
break;
DebugMsg1(("match_phase_3: matched opnd2\n" ));
output_opc( CodeInfo );
if ( opnd1 & (OP_I_ANY | OP_M_ANY ) )
output_data( CodeInfo, opnd1, OPND1 );
if ( opnd2 & (OP_I_ANY | OP_M_ANY ) )
output_data( CodeInfo, opnd2, OPND2 );
if( opnd_clstab[CodeInfo->pinstr->opclsidx].opnd_type_3rd != OP3_NONE )
output_3rd_operand( CodeInfo );
if( CodeInfo->pinstr->byte1_info == F_0F0F )
OutputCodeByte( CodeInfo->pinstr->opcode | CodeInfo->iswide );
return( NOT_ERROR );
}
break;
}
CodeInfo->pinstr++;
} while ( opnd_clstab[CodeInfo->pinstr->opclsidx].opnd_type[OPND1] == determinant && CodeInfo->pinstr->first == FALSE );
CodeInfo->pinstr--;
DebugMsg(("match_phase_3: returns EMPTY\n"));
return( ERROR );
}
static ret_code check_operand_2( struct code_info *CodeInfo, enum operand_type opnd1 )
{
if (( (CodeInfo->token == T_MOV && CodeInfo->opnd[OPND2].type == OP_R64) || CodeInfo->opnd[OPND2].type == OP_R32 || CodeInfo->opnd[OPND2].type == OP_R16 || CodeInfo->opnd[OPND2].type == OP_R8) && CodeInfo->isptr && CodeInfo->opnd[OPND2].data32h > 0)
{
CodeInfo->opnd[OPND2].type = OP_A;
}
if( CodeInfo->opnd[OPND2].type == OP_NONE ) {
if (opnd_clstab[CodeInfo->pinstr->opclsidx].opnd_type[OPND2] != OP_NONE){
if (CodeInfo->token == T_VGETEXPPD || CodeInfo->token == T_VGETEXPPS)
;
else
return(ERROR);
}
if ( opnd1 == OP_M ) {
const struct instr_item *next = CodeInfo->pinstr+1;
if ( ( opnd_clstab[next->opclsidx].opnd_type[OPND1] & OP_M ) &&
next->first == FALSE )
if ( CodeInfo->undef_sym == FALSE &&
( CodeInfo->opnd[OPND1].InsFixup == NULL ||
CodeInfo->opnd[OPND1].InsFixup->sym == NULL ||
CodeInfo->opnd[OPND1].InsFixup->sym->state != SYM_UNDEFINED ) ) {
DebugMsg(("check_operand_2: error: undef_sym=%u Fixup[0]=%X [%s]\n",
CodeInfo->undef_sym, CodeInfo->opnd[OPND1].InsFixup,
CodeInfo->opnd[OPND1].InsFixup ? CodeInfo->opnd[OPND1].InsFixup->sym ? CodeInfo->opnd[OPND1].InsFixup->sym->name : "NULL" : "NULL" ));
EmitErr( INSTRUCTION_OPERAND_MUST_HAVE_SIZE );
}
}
output_opc( CodeInfo );
output_data( CodeInfo, opnd1, OPND1 );
if ( CodeInfo->Ofssize == USE64 && CodeInfo->opnd[OPND1].InsFixup && CodeInfo->opnd[OPND1].InsFixup->type == FIX_RELOFF32 )
CodeInfo->opnd[OPND1].InsFixup->addbytes = GetCurrOffset() - CodeInfo->opnd[OPND1].InsFixup->locofs;
return( NOT_ERROR );
}
if ( match_phase_3( CodeInfo, opnd1 ) == NOT_ERROR ) {
#if AMD64_SUPPORT
if ( CodeInfo->Ofssize == USE64 ) {
if ( CodeInfo->opnd[OPND1].InsFixup && CodeInfo->opnd[OPND1].InsFixup->type == FIX_RELOFF32 )
CodeInfo->opnd[OPND1].InsFixup->addbytes = GetCurrOffset() - CodeInfo->opnd[OPND1].InsFixup->locofs;
if ( CodeInfo->opnd[OPND2].InsFixup && CodeInfo->opnd[OPND2].InsFixup->type == FIX_RELOFF32 )
CodeInfo->opnd[OPND2].InsFixup->addbytes = GetCurrOffset() - CodeInfo->opnd[OPND2].InsFixup->locofs;
}
#endif
return( NOT_ERROR );
}
return( ERROR );
}
ret_code codegen( struct code_info *CodeInfo, uint_32 oldofs )
{
ret_code retcode = ERROR;
enum operand_type opnd1;
enum operand_type tbl_op1;
if( ( CodeInfo->pinstr->cpu & P_PM ) > ( ModuleInfo.curr_cpu & P_PM ) ) {
EmitError( INSTRUCTION_OR_REGISTER_NOT_ACCEPTED_IN_CURRENT_CPU_MODE );
return( ERROR );
}
opnd1 = CodeInfo->opnd[OPND1].type;
if( opnd1 & OP_I ) {
if( opnd1 == OP_I8 ) {
opnd1 = OP_IGE8;
} else if( opnd1 == OP_I16 ) {
opnd1 = OP_IGE16;
}
}
#if AVXSUPP
if (CodeInfo->token >= VEX_START) {
if (vex_flags[CodeInfo->token - VEX_START] & VX_L) {
if (opnd1 & (OP_K | OP_ZMM | OP_YMM | OP_M256 | OP_M512)) {
if (CodeInfo->opnd[OPND2].type & OP_XMM && !(vex_flags[CodeInfo->token - VEX_START] & VX_HALF)) {
EmitErr(INVALID_INSTRUCTION_OPERANDS);
return(ERROR);
}
if (opnd1 & OP_XMM || opnd1 & OP_YMM || opnd1 & OP_K || opnd1 & OP_ZMM)
opnd1 |= OP_XMM;
else{
opnd1 |= OP_M128;
opnd1 |= OP_M;
}
}
}
if ((CodeInfo->token >= T_VCMPPD && CodeInfo->token <= T_VCMPTRUE_USSS) || (CodeInfo->token >= T_VPCMPD) && (CodeInfo->token <= T_VINSERTI64x4) || (CodeInfo->token >= T_VPMOVSXBD) && (CodeInfo->token <= T_VUNPCKLPS) || (CodeInfo->token >= T_VPBROADCASTB && CodeInfo->token <= T_VBROADCASTF64x4) || (CodeInfo->token == T_VCVTPS2PH) || (CodeInfo->token == T_VCVTPH2PS) || (CodeInfo->token == T_VMOVDDUP) || (CodeInfo->token >= T_VDBPSADBW) && (CodeInfo->token <= T_VFPCLASSSS) || (CodeInfo->token >= T_VCVTPD2DQ) && (CodeInfo->token <= T_VMOVDDUP) || (CodeInfo->token >= T_VPGATHERDD) && (CodeInfo->token <= T_VSCATTERQPD))
opnd1 |= OP_XMM;
}
#endif
#if AMD64_SUPPORT
DebugMsg1(("codegen(ofs=%X): %s opnd1=%X codeinfo: ofssize=%u wide=%u rm=%Xh sib=%Xh rex=%Xh opsiz=%u\n",
CurrSeg->sym.offset, GetResWName( CodeInfo->token, NULL ),
opnd1, CodeInfo->Ofssize, CodeInfo->iswide,
CodeInfo->rm_byte, CodeInfo->sib,
CodeInfo->prefix.rex, CodeInfo->prefix.opsiz ));
#endif
if ((CodeInfo->token == T_VMOVD || CodeInfo->token == T_VMOVQ) &&
((CodeInfo->opnd[1].type & OP_YMM || CodeInfo->opnd[1].type & OP_ZMM) ||
(CodeInfo->opnd[0].type & OP_YMM || CodeInfo->opnd[0].type & OP_ZMM))) {
EmitError(INVALID_INSTRUCTION_OPERANDS);
}
if (CodeInfo->Ofssize == USE64 && CodeInfo->token == T_XCHG && CodeInfo->opnd[0].type == OP_EAX && CodeInfo->opnd[1].type == OP_EAX)
{
if (Options.line_numbers)
AddLinnumDataRef(get_curr_srcfile(), GetLineNumber());
OutputCodeByte(0x87);
OutputCodeByte(0xc0);
return(NOT_ERROR);
}
if (CodeInfo->token == T_SARX || CodeInfo->token == T_SHLX || CodeInfo->token == T_SHRX)
{
if((CodeInfo->opnd[0].type & OP_R) == 0)
EmitError(INVALID_INSTRUCTION_OPERANDS);
if (((CodeInfo->opnd[1].type & OP_R) == 0) && ((CodeInfo->opnd[1].type & OP_M) == 0))
EmitError(INVALID_INSTRUCTION_OPERANDS);
if ((CodeInfo->opnd[2].type & OP_I) == 0)
EmitError(INVALID_INSTRUCTION_OPERANDS);
}
if (CodeInfo->token == T_VPBROADCASTB ||
CodeInfo->token == T_VPBROADCASTW ||
CodeInfo->token == T_VPBROADCASTD ||
CodeInfo->token == T_VPBROADCASTQ) {
if (CodeInfo->opnd[1].type & OP_R) {
EmitError(INVALID_INSTRUCTION_OPERANDS);
}
}
if (CodeInfo->token == T_CRC32)
{
if ( ((CodeInfo->opnd[0].type & OP_R64) != 0 && (CodeInfo->opnd[1].type & OP_R16) != 0) ||
((CodeInfo->opnd[0].type & OP_R64) != 0 && (CodeInfo->opnd[1].type & OP_R32) != 0))
{
EmitError(INVALID_INSTRUCTION_OPERANDS);
}
if (CodeInfo->opnd[1].type == OP_M)
{
EmitWarn(2, SIZE_NOT_SPECIFIED_ASSUMING, "BYTE");
}
}
if (CodeInfo->token == T_MOVQ && CodeInfo->opnd[0].type == OP_XMM)
{
if (CodeInfo->opnd[1].type == OP_R32 || CodeInfo->opnd[1].type == OP_EAX)
{
EmitError(INVALID_INSTRUCTION_OPERANDS);
return(ERROR);
}
}
if (CodeInfo->token == T_JMP && CodeInfo->mem_type == MT_EMPTY)
{
if (CodeInfo->opnd[0].type == OP_IGE8)
{
if (CurrWordSize == 2)
CodeInfo->mem_type = MT_WORD;
else if (CurrWordSize == 4)
CodeInfo->mem_type = MT_DWORD;
else if (CurrWordSize == 8)
CodeInfo->mem_type = MT_QWORD;
}
}
if (( (CodeInfo->token == T_MOV && CodeInfo->opnd[OPND1].type == OP_R64) || CodeInfo->opnd[OPND1].type == OP_R32 || CodeInfo->opnd[OPND1].type == OP_R16 || CodeInfo->opnd[OPND1].type == OP_R8) && CodeInfo->isptr && CodeInfo->opnd[OPND1].data32h > 0)
{
CodeInfo->opnd[OPND1].type = OP_A;
opnd1 = OP_A;
}
if ((CodeInfo->token >= T_KADDB) && (CodeInfo->token <= T_KUNPCKDQ)) {
if (CodeInfo->opnd[OPND1].type == OP_K && CodeInfo->opnd[OPND2].type == OP_K && CodeInfo->opnd[OPND3].type == OP_K)
;
else {
EmitError(INVALID_INSTRUCTION_OPERANDS);
return(ERROR);
}
}
do {
tbl_op1 = opnd_clstab[CodeInfo->pinstr->opclsidx].opnd_type[OPND1];
if ( tbl_op1 == OP_NONE && opnd1 == OP_NONE ) {
output_opc( CodeInfo );
if ( CurrFile[LST] )
LstWrite( LSTTYPE_CODE, oldofs, NULL );
return( NOT_ERROR );
} else if ( opnd1 & tbl_op1 ) {
switch( tbl_op1 ) {
case OP_I32:
case OP_I16:
retcode = check_operand_2( CodeInfo, tbl_op1 );
break;
case OP_I8_U:
if( CodeInfo->opnd[OPND1].data32l <= UCHAR_MAX && CodeInfo->opnd[OPND1].data32l >= SCHAR_MIN ) {
retcode = check_operand_2( CodeInfo, OP_I8 );
}
break;
case OP_I_3:
if ( CodeInfo->opnd[OPND1].data32l == 3 ) {
retcode = check_operand_2( CodeInfo, OP_NONE );
}
break;
default:
retcode = check_operand_2( CodeInfo, CodeInfo->opnd[OPND1].type );
break;
}
if(retcode == NOT_ERROR) {
if (CurrFile[LST])
{
LstWrite(LSTTYPE_CODE, oldofs, NULL);
}
return( NOT_ERROR );
}
}
CodeInfo->pinstr++;
} while ( CodeInfo->pinstr->first == FALSE );
DebugMsg(("codegen: no matching format found\n"));
EmitError( INVALID_INSTRUCTION_OPERANDS );
return( ERROR );
}