Add {rex} prefix, simplify prefix handling, better error messages

Add a {rex} prefix to force REX encoding (typically a redundant 40h
prefix).

For prefix parsing, we can use t_inttwo to encode the prefix slot
number.

Give more verbose error messages for encoding mismatches.
This commit is contained in:
H. Peter Anvin 2021-04-27 11:37:42 -07:00
parent 5368e45794
commit 2469b8b66e
12 changed files with 204 additions and 121 deletions

View File

@ -935,15 +935,13 @@ int64_t assemble(int32_t segment, int64_t start, int bits, insn *instruction)
nasm_nonfatal("instruction not supported in %d-bit mode", bits); nasm_nonfatal("instruction not supported in %d-bit mode", bits);
break; break;
case MERR_ENCMISMATCH: case MERR_ENCMISMATCH:
nasm_nonfatal("specific encoding scheme not available"); nasm_nonfatal("instruction not encodable with %s prefix",
prefix_name(instruction->prefixes[PPS_REX]));
break; break;
case MERR_BADBND: case MERR_BADBND:
nasm_nonfatal("bnd prefix is not allowed");
break;
case MERR_BADREPNE: case MERR_BADREPNE:
nasm_nonfatal("%s prefix is not allowed", nasm_nonfatal("%s prefix is not allowed",
(has_prefix(instruction, PPS_REP, P_REPNE) ? prefix_name(instruction->prefixes[PPS_REP]));
"repne" : "repnz"));
break; break;
case MERR_REGSETSIZE: case MERR_REGSETSIZE:
nasm_nonfatal("invalid register set size"); nasm_nonfatal("invalid register set size");
@ -1644,16 +1642,22 @@ static int64_t calcsize(int32_t segment, int64_t offset, int bits,
ins->rex &= ~REX_P; /* Don't force REX prefix due to high reg */ ins->rex &= ~REX_P; /* Don't force REX prefix due to high reg */
} }
switch (ins->prefixes[PPS_VEX]) { switch (ins->prefixes[PPS_REX]) {
case P_EVEX: case P_EVEX:
if (!(ins->rex & REX_EV)) if (!(ins->rex & REX_EV))
return -1; return -1;
break; break;
case P_VEX:
case P_VEX3: case P_VEX3:
case P_VEX2: case P_VEX2:
if (!(ins->rex & REX_V)) if (!(ins->rex & REX_V))
return -1; return -1;
break; break;
case P_REX:
if (ins->rex & (REX_V|REX_EV))
return -1;
ins->rex |= REX_P; /* Force REX prefix */
break;
default: default:
break; break;
} }
@ -1687,16 +1691,19 @@ static int64_t calcsize(int32_t segment, int64_t offset, int bits,
nasm_nonfatal("invalid high-16 register in non-AVX-512"); nasm_nonfatal("invalid high-16 register in non-AVX-512");
return -1; return -1;
} }
if (ins->rex & REX_EV) if (ins->rex & REX_EV) {
length += 4; length += 4;
else if (ins->vex_cm != 1 || (ins->rex & (REX_W|REX_X|REX_B)) || } else if (ins->vex_cm != 1 || (ins->rex & (REX_W|REX_X|REX_B)) ||
ins->prefixes[PPS_VEX] == P_VEX3) ins->prefixes[PPS_REX] == P_VEX3) {
if (ins->prefixes[PPS_REX] == P_VEX2)
nasm_nonfatal("instruction not encodable with {vex2} prefix");
length += 3; length += 3;
else } else {
length += 2; length += 2;
}
} else if (ins->rex & REX_MASK) { } else if (ins->rex & REX_MASK) {
if (ins->rex & REX_H) { if (ins->rex & REX_H) {
nasm_nonfatal("cannot use high register in rex instruction"); nasm_nonfatal("cannot use high byte register in rex instruction");
return -1; return -1;
} else if (bits == 64) { } else if (bits == 64) {
length++; length++;
@ -1849,6 +1856,8 @@ static int emit_prefix(struct out_data *data, const int bits, insn *ins)
case P_OSP: case P_OSP:
c = 0x66; c = 0x66;
break; break;
case P_REX:
case P_VEX:
case P_EVEX: case P_EVEX:
case P_VEX3: case P_VEX3:
case P_VEX2: case P_VEX2:
@ -1994,7 +2003,7 @@ static void gencode(struct out_data *data, insn *ins)
case 0172: case 0172:
{ {
int mask = ins->prefixes[PPS_VEX] == P_EVEX ? 7 : 15; int mask = ins->prefixes[PPS_REX] == P_EVEX ? 7 : 15;
const struct operand *opy; const struct operand *opy;
c = *codes++; c = *codes++;
@ -2054,7 +2063,7 @@ static void gencode(struct out_data *data, insn *ins)
case 0270: case 0270:
codes += 2; codes += 2;
if (ins->vex_cm != 1 || (ins->rex & (REX_W|REX_X|REX_B)) || if (ins->vex_cm != 1 || (ins->rex & (REX_W|REX_X|REX_B)) ||
ins->prefixes[PPS_VEX] == P_VEX3) { ins->prefixes[PPS_REX] == P_VEX3) {
bytes[0] = (ins->vex_cm >> 6) ? 0x8f : 0xc4; bytes[0] = (ins->vex_cm >> 6) ? 0x8f : 0xc4;
bytes[1] = (ins->vex_cm & 31) | ((~ins->rex & 7) << 5); bytes[1] = (ins->vex_cm & 31) | ((~ins->rex & 7) << 5);
bytes[2] = ((ins->rex & REX_W) << (7-3)) | bytes[2] = ((ins->rex & REX_W) << (7-3)) |
@ -2383,11 +2392,12 @@ static enum match_result find_match(const struct itemplate **tempp,
int i; int i;
/* broadcasting uses a different data element size */ /* broadcasting uses a different data element size */
for (i = 0; i < instruction->operands; i++) for (i = 0; i < instruction->operands; i++) {
if (i == broadcast) if (i == broadcast)
xsizeflags[i] = instruction->oprs[i].decoflags & BRSIZE_MASK; xsizeflags[i] = instruction->oprs[i].decoflags & BRSIZE_MASK;
else else
xsizeflags[i] = instruction->oprs[i].type & SIZE_MASK; xsizeflags[i] = instruction->oprs[i].type & SIZE_MASK;
}
merr = MERR_INVALOP; merr = MERR_INVALOP;
@ -2507,18 +2517,24 @@ static enum match_result matches(const struct itemplate *itemp,
return MERR_INVALOP; return MERR_INVALOP;
/* /*
* {evex} available? * {rex/vexn/evex} available?
*/ */
switch (instruction->prefixes[PPS_VEX]) { switch (instruction->prefixes[PPS_REX]) {
case P_EVEX: case P_EVEX:
if (!itemp_has(itemp, IF_EVEX)) if (!itemp_has(itemp, IF_EVEX))
return MERR_ENCMISMATCH; return MERR_ENCMISMATCH;
break; break;
case P_VEX:
case P_VEX3: case P_VEX3:
case P_VEX2: case P_VEX2:
if (!itemp_has(itemp, IF_VEX)) if (!itemp_has(itemp, IF_VEX))
return MERR_ENCMISMATCH; return MERR_ENCMISMATCH;
break; break;
case P_REX:
if (itemp_has(itemp, IF_VEX) || itemp_has(itemp, IF_EVEX) ||
bits != 64)
return MERR_ENCMISMATCH;
break;
default: default:
break; break;
} }
@ -2667,6 +2683,9 @@ static enum match_result matches(const struct itemplate *itemp,
* considered a wildcard match rather than an error. * considered a wildcard match rather than an error.
*/ */
opsizemissing = true; opsizemissing = true;
} else if (is_class(REG_HIGH, type) &&
instruction->prefixes[PPS_REX]) {
return MERR_ENCMISMATCH;
} }
} else if (is_broadcast && } else if (is_broadcast &&
(brcast_num != (brcast_num !=
@ -2764,13 +2783,14 @@ static enum match_result matches(const struct itemplate *itemp,
static enum ea_type process_ea(operand *input, ea *output, int bits, static enum ea_type process_ea(operand *input, ea *output, int bits,
int rfield, opflags_t rflags, insn *ins, int rfield, opflags_t rflags, insn *ins,
const char **errmsg) const char **errmsgp)
{ {
bool forw_ref = !!(input->opflags & OPFLAG_UNKNOWN); bool forw_ref = !!(input->opflags & OPFLAG_UNKNOWN);
int addrbits = ins->addr_size; int addrbits = ins->addr_size;
int eaflags = input->eaflags; int eaflags = input->eaflags;
const char *errmsg = NULL;
*errmsg = "invalid effective address"; /* Default error message */ errmsg = NULL;
output->type = EA_SCALAR; output->type = EA_SCALAR;
output->rip = false; output->rip = false;
@ -2793,7 +2813,7 @@ static enum ea_type process_ea(operand *input, ea *output, int bits,
/* broadcasting is not available with a direct register operand. */ /* broadcasting is not available with a direct register operand. */
if (input->decoflags & BRDCAST_MASK) { if (input->decoflags & BRDCAST_MASK) {
*errmsg = "broadcast not allowed with register operand"; errmsg = "broadcast not allowed with register operand";
goto err; goto err;
} }
@ -2809,7 +2829,7 @@ static enum ea_type process_ea(operand *input, ea *output, int bits,
/* Embedded rounding or SAE is not available with a mem ref operand. */ /* Embedded rounding or SAE is not available with a mem ref operand. */
if (input->decoflags & (ER | SAE)) { if (input->decoflags & (ER | SAE)) {
*errmsg = "embedded rounding is available only with " errmsg = "embedded rounding is available only with "
"register-register operations"; "register-register operations";
goto err; goto err;
} }
@ -2838,7 +2858,7 @@ static enum ea_type process_ea(operand *input, ea *output, int bits,
} }
if (bits == 64 && !(IP_REL & ~input->type) && (eaflags & EAF_SIB)) { if (bits == 64 && !(IP_REL & ~input->type) && (eaflags & EAF_SIB)) {
*errmsg = "instruction requires SIB encoding, cannot be RIP-relative"; errmsg = "instruction requires SIB encoding, cannot be RIP-relative";
goto err; goto err;
} }
@ -3224,6 +3244,14 @@ static enum ea_type process_ea(operand *input, ea *output, int bits,
return output->type; return output->type;
err: err:
if (!errmsg) {
/* Default error message */
static char invalid_address_msg[40];
snprintf(invalid_address_msg, sizeof invalid_address_msg,
"invalid %d-bit effective address", bits);
errmsg = invalid_address_msg;
}
*errmsgp = errmsg;
return output->type = EA_INVALID; return output->type = EA_INVALID;
} }

View File

@ -55,50 +55,6 @@ static int end_expression_next(void);
static struct tokenval tokval; static struct tokenval tokval;
static int prefix_slot(int prefix)
{
switch (prefix) {
case P_WAIT:
return PPS_WAIT;
case R_CS:
case R_DS:
case R_SS:
case R_ES:
case R_FS:
case R_GS:
return PPS_SEG;
case P_LOCK:
return PPS_LOCK;
case P_REP:
case P_REPE:
case P_REPZ:
case P_REPNE:
case P_REPNZ:
case P_XACQUIRE:
case P_XRELEASE:
case P_BND:
case P_NOBND:
return PPS_REP;
case P_O16:
case P_O32:
case P_O64:
case P_OSP:
return PPS_OSIZE;
case P_A16:
case P_A32:
case P_A64:
case P_ASP:
return PPS_ASIZE;
case P_EVEX:
case P_VEX3:
case P_VEX2:
return PPS_VEX;
default:
nasm_panic("Invalid value %d passed to prefix_slot()", prefix);
return -1;
}
}
static void process_size_override(insn *result, operand *op) static void process_size_override(insn *result, operand *op)
{ {
if (tasm_compatible_mode) { if (tasm_compatible_mode) {
@ -185,7 +141,7 @@ static void process_size_override(insn *result, operand *op)
} }
/* /*
* Brace decorators are are parsed here. opmask and zeroing * Braced keywords are are parsed here. opmask and zeroing
* decorators can be placed in any order. e.g. zmm1 {k2}{z} or zmm2 * decorators can be placed in any order. e.g. zmm1 {k2}{z} or zmm2
* {z}{k3} decorator(s) are placed at the end of an operand. * {z}{k3} decorator(s) are placed at the end of an operand.
*/ */
@ -715,42 +671,51 @@ restart_parse:
if (i == TOKEN_EOS) if (i == TOKEN_EOS)
goto fail; goto fail;
while (i == TOKEN_PREFIX || while (i) {
(i == TOKEN_REG && IS_SREG(tokval.t_integer))) { int slot = PPS_SEG;
first = false;
/* if (i == TOKEN_PREFIX) {
* Handle special case: the TIMES prefix. slot = tokval.t_inttwo;
*/
if (i == TOKEN_PREFIX && tokval.t_integer == P_TIMES) {
expr *value;
i = stdscan(NULL, &tokval); if (slot == PPS_TIMES) {
value = evaluate(stdscan, NULL, &tokval, NULL, pass_stable(), NULL); /* TIMES is a very special prefix */
i = tokval.t_type; expr *value;
if (!value) /* Error in evaluator */
goto fail; i = stdscan(NULL, &tokval);
if (!is_simple(value)) { value = evaluate(stdscan, NULL, &tokval, NULL,
nasm_nonfatal("non-constant argument supplied to TIMES"); pass_stable(), NULL);
result->times = 1L; i = tokval.t_type;
} else { if (!value) /* Error in evaluator */
result->times = value->value; goto fail;
if (value->value < 0) { if (!is_simple(value)) {
nasm_nonfatalf(ERR_PASS2, "TIMES value %"PRId64" is negative", value->value); nasm_nonfatal("non-constant argument supplied to TIMES");
result->times = 0; result->times = 1;
} else {
result->times = value->value;
if (value->value < 0) {
nasm_nonfatalf(ERR_PASS2, "TIMES value %"PRId64" is negative", value->value);
result->times = 0;
}
} }
first = false;
continue;
} }
} else if (i == TOKEN_REG && IS_SREG(tokval.t_integer)) {
slot = PPS_SEG;
first = false;
} else { } else {
int slot = prefix_slot(tokval.t_integer); break; /* Not a prefix */
if (result->prefixes[slot]) {
if (result->prefixes[slot] == tokval.t_integer)
nasm_warn(WARN_OTHER, "instruction has redundant prefixes");
else
nasm_nonfatal("instruction has conflicting prefixes");
}
result->prefixes[slot] = tokval.t_integer;
i = stdscan(NULL, &tokval);
} }
if (result->prefixes[slot]) {
if (result->prefixes[slot] == tokval.t_integer)
nasm_warn(WARN_OTHER, "instruction has redundant prefixes");
else
nasm_nonfatal("instruction has conflicting prefixes");
}
result->prefixes[slot] = tokval.t_integer;
i = stdscan(NULL, &tokval);
first = false;
} }
if (i != TOKEN_INSN) { if (i != TOKEN_INSN) {

View File

@ -1,6 +1,6 @@
## -------------------------------------------------------------------------- ## --------------------------------------------------------------------------
## ##
## Copyright 1996-2016 The NASM Authors - All Rights Reserved ## Copyright 1996-2021 The NASM Authors - All Rights Reserved
## See the file AUTHORS included with the NASM distribution for ## See the file AUTHORS included with the NASM distribution for
## the specific copyright holders. ## the specific copyright holders.
## ##
@ -46,28 +46,45 @@
% TOKEN_QMARK, 0, 0, 0 % TOKEN_QMARK, 0, 0, 0
? ?
% TOKEN_PREFIX, 0, 0, P_* % TOKEN_PREFIX, PPS_ASIZE, 0, P_*
a16 a16
a32 a32
a64 a64
asp asp
% TOKEN_PREFIX, PPS_LOCK, 0, P_*
lock lock
% TOKEN_PREFIX, PPS_OSIZE, 0, P_*
o16 o16
o32 o32
o64 o64
osp osp
% TOKEN_PREFIX, PPS_REP, 0, P_*
rep rep
repe repe
repne repne
repnz repnz
repz repz
times
wait
xacquire xacquire
xrelease xrelease
bnd bnd
nobnd nobnd
% TOKEN_PREFIX, PPS_TIMES, 0, P_*
times
% TOKEN_PREFIX, PPS_WAIT, 0, P_*
wait
% TOKEN_PREFIX, PPS_REX, TFLAG_BRC, P_*
rex
evex
vex
vex3
vex2
% TOKEN_SIZE, SIZE_*, 0, S_* % TOKEN_SIZE, SIZE_*, 0, S_*
byte byte
word word
@ -154,11 +171,6 @@ rz-sae
sae sae
z z
% TOKEN_PREFIX, 0, TFLAG_BRC, P_*
evex
vex3
vex2
# Multi-character operators. Used in ppscan(). # Multi-character operators. Used in ppscan().
% TOKEN_SHR, 0, 0, 0 % TOKEN_SHR, 0, 0, 0
>> >>

View File

@ -1,6 +1,6 @@
/* ----------------------------------------------------------------------- * /* ----------------------------------------------------------------------- *
* *
* Copyright 1996-2016 The NASM Authors - All Rights Reserved * Copyright 1996-2021 The NASM Authors - All Rights Reserved
* See the file AUTHORS included with the NASM distribution for * See the file AUTHORS included with the NASM distribution for
* the specific copyright holders. * the specific copyright holders.
* *
@ -46,14 +46,15 @@
int globalbits = 0; int globalbits = 0;
/* /*
* Common list of prefix names; ideally should be auto-generated * Common list of prefix names; ideally should be auto-generated
* from tokens.dat * from tokens.dat. This MUST match the enum in include/nasm.h.
*/ */
const char *prefix_name(int token) const char *prefix_name(int token)
{ {
static const char *prefix_names[] = { static const char *prefix_names[] = {
"a16", "a32", "a64", "asp", "lock", "o16", "o32", "o64", "osp", "a16", "a32", "a64", "asp", "lock", "o16", "o32", "o64", "osp",
"rep", "repe", "repne", "repnz", "repz", "times", "wait", "rep", "repe", "repne", "repnz", "repz", "times", "wait",
"xacquire", "xrelease", "bnd" "xacquire", "xrelease", "bnd", "nobnd", "{rex}", "{evex}", "{vex}",
"{vex3}", "{vex2}"
}; };
unsigned int prefix = token-PREFIX_ENUM_START; unsigned int prefix = token-PREFIX_ENUM_START;

View File

@ -619,7 +619,9 @@ enum prefixes { /* instruction prefixes */
P_XRELEASE, P_XRELEASE,
P_BND, P_BND,
P_NOBND, P_NOBND,
P_REX,
P_EVEX, P_EVEX,
P_VEX,
P_VEX3, P_VEX3,
P_VEX2, P_VEX2,
PREFIX_ENUM_LIMIT PREFIX_ENUM_LIMIT
@ -715,14 +717,15 @@ enum ea_type {
* the introduction of HLE. * the introduction of HLE.
*/ */
enum prefix_pos { enum prefix_pos {
PPS_WAIT, /* WAIT (technically not a prefix!) */ PPS_TIMES = -1, /* TIMES (not a slot, handled separately) */
PPS_REP, /* REP/HLE prefix */ PPS_WAIT = 0, /* WAIT (technically not a prefix!) */
PPS_LOCK, /* LOCK prefix */ PPS_REP, /* REP/HLE prefix */
PPS_SEG, /* Segment override prefix */ PPS_LOCK, /* LOCK prefix */
PPS_OSIZE, /* Operand size prefix */ PPS_SEG, /* Segment override prefix */
PPS_ASIZE, /* Address size prefix */ PPS_OSIZE, /* Operand size prefix */
PPS_VEX, /* VEX type */ PPS_ASIZE, /* Address size prefix */
MAXPREFIX /* Total number of prefix slots */ PPS_REX, /* REX/VEX type */
MAXPREFIX /* Total number of prefix slots */
}; };
/* /*

View File

@ -1,9 +1,39 @@
bits 64 bits 64
add eax,edx
{rex} add eax,edx
add al,dl
{rex} add al,dl
add ah,dl
comisd xmm0,xmm1
{rex} comisd xmm0,xmm1
vcomisd xmm0,xmm31 vcomisd xmm0,xmm31
vcomisd xmm0,xmm1 vcomisd xmm0,xmm1
{vex} vcomisd xmm0,xmm1
{vex2} vcomisd xmm0,xmm1 {vex2} vcomisd xmm0,xmm1
{vex3} vcomisd xmm0,xmm1 {vex3} vcomisd xmm0,xmm1
{evex} vcomisd xmm0,xmm1 {evex} vcomisd xmm0,xmm1
{vex2} vcomisd xmm0,xmm1
{vex3} vcomisd xmm0,xmm1
{evex} vcomisd xmm0,xmm1
{vex} vcomisd xmm0,[r8+rax*1]
{vex3} vcomisd xmm0,[r8+rax*1]
{evex} vcomisd xmm0,[r8+rax*1]
{vex} vcomisd xmm0,[rax+r8*2]
{vex3} vcomisd xmm0,[rax+r8*2]
{evex} vcomisd xmm0,[rax+r8*2]
;; These errors may be caught in different passes, so
;; some shadows the others...
%ifdef ERROR %ifdef ERROR
%if ERROR <= 1
{vex2} vcomisd xmm0,[rax+r8*2]
{rex} add ah,dl
bits 32
mov eax,[r8d]
%endif
%if ERROR <= 2
{rex} vcomisd xmm0,xmm1
{vex} add eax,edx
{vex3} add eax,edx {vex3} add eax,edx
%endif
%endif %endif

View File

@ -1,9 +1,39 @@
bits 64 bits 64
add eax,edx
{rex} add eax,edx
add al,dl
{rex} add al,dl
add ah,dl
comisd xmm0,xmm1
{rex} comisd xmm0,xmm1
vcomisd xmm0,xmm31 vcomisd xmm0,xmm31
vcomisd xmm0,xmm1 vcomisd xmm0,xmm1
{vex} vcomisd xmm0,xmm1
{vex2} vcomisd xmm0,xmm1 {vex2} vcomisd xmm0,xmm1
{vex3} vcomisd xmm0,xmm1 {vex3} vcomisd xmm0,xmm1
{evex} vcomisd xmm0,xmm1 {evex} vcomisd xmm0,xmm1
{vex2} vcomisd xmm0,xmm1
{vex3} vcomisd xmm0,xmm1
{evex} vcomisd xmm0,xmm1
{vex} vcomisd xmm0,[r8+rax*1]
{vex3} vcomisd xmm0,[r8+rax*1]
{evex} vcomisd xmm0,[r8+rax*1]
{vex} vcomisd xmm0,[rax+r8*2]
{vex3} vcomisd xmm0,[rax+r8*2]
{evex} vcomisd xmm0,[rax+r8*2]
;; These errors may be caught in different passes, so
;; some shadows the others...
%ifdef ERROR %ifdef ERROR
%if ERROR <= 1
{vex2} vcomisd xmm0,[rax+r8*2]
{rex} add ah,dl
bits 32
mov eax,[r8d]
%endif
%if ERROR <= 2
{rex} vcomisd xmm0,xmm1
{vex} add eax,edx
{vex3} add eax,edx {vex3} add eax,edx
%endif
%endif %endif

Binary file not shown.

View File

@ -1,6 +1,6 @@
[ [
{ {
"description": "Test VEX2/VEX3/EVEX prefix", "description": "Test explicit REX/VEX2/VEX3/EVEX prefix",
"id": "vex", "id": "vex",
"format": "bin", "format": "bin",
"source": "vex.asm", "source": "vex.asm",
@ -10,11 +10,20 @@
] ]
}, },
{ {
"description": "Test VEX3 prefix error", "description": "Test early REX/VEX prefix errors",
"ref": "vex", "ref": "vex",
"option": "-Ox -DERROR -o vex.bin.err", "option": "-Ox -DERROR=1 -o vex1.bin.err",
"target": [ "target": [
{ "stderr": "vex.stderr" } { "stderr": "vex1.stderr" }
],
"error": "expected"
},
{
"description": "Test late REX/VEX prefix errors",
"ref": "vex",
"option": "-Ox -DERROR=2 -o vex2.bin.err",
"target": [
{ "stderr": "vex2.stderr" }
], ],
"error": "expected" "error": "expected"
} }

View File

@ -1 +0,0 @@
./travis/test/vex.asm:8: error: specific encoding scheme not available

3
travis/test/vex1.stderr Normal file
View File

@ -0,0 +1,3 @@
./travis/test/vex.asm:29: error: instruction not encodable with {vex2} prefix
./travis/test/vex.asm:30: error: cannot use high byte register in rex instruction
./travis/test/vex.asm:32: error: invalid operands in non-64-bit mode

3
travis/test/vex2.stderr Normal file
View File

@ -0,0 +1,3 @@
./travis/test/vex.asm:35: error: instruction not encodable with {rex} prefix
./travis/test/vex.asm:36: error: instruction not encodable with {vex} prefix
./travis/test/vex.asm:37: error: instruction not encodable with {vex3} prefix