/* ----------------------------------------------------------------------- *
*
- * Copyright 1996-2013 The NASM Authors - All Rights Reserved
+ * Copyright 1996-2014 The NASM Authors - All Rights Reserved
* See the file AUTHORS included with the NASM distribution for
* the specific copyright holders.
*
MERR_BADHLE,
MERR_ENCMISMATCH,
MERR_BADBND,
+ MERR_BADREPNE,
/*
* Matching success; the conditional ones first
*/
if (is_byte && c == 0371 && ins->prefixes[PPS_REP] == P_BND) {
/* jmp short (opcode eb) cannot be used with bnd prefix. */
ins->prefixes[PPS_REP] = P_none;
+ errfunc(ERR_WARNING | ERR_WARN_BND | ERR_PASS2 ,
+ "jmp short does not init bnd regs - bnd prefix dropped.");
}
return is_byte;
c = 0x66;
break;
case P_EVEX:
- /* EVEX */
- break;
+ case P_VEX3:
+ case P_VEX2:
+ case P_NOBND:
case P_none:
break;
default:
error(ERR_NONFATAL, "instruction not supported in %d-bit mode",
bits);
break;
+ case MERR_ENCMISMATCH:
+ error(ERR_NONFATAL, "specific encoding scheme not available");
+ break;
case MERR_BADBND:
error(ERR_NONFATAL, "bnd prefix is not allowed");
break;
+ case MERR_BADREPNE:
+ error(ERR_NONFATAL, "%s prefix is not allowed",
+ (has_prefix(instruction, PPS_REP, P_REPNE) ?
+ "repne" : "repnz"));
+ break;
default:
error(ERR_NONFATAL,
"invalid combination of opcode and operands");
case P_A64:
case P_O64:
case P_EVEX:
+ case P_VEX3:
+ case P_VEX2:
+ case P_NOBND:
case P_none:
break;
default:
}
}
- /*
- * if a separate form of MIB (ICC style) is used,
- * the index reg info is merged into mem operand
- */
- if (mib_index != R_none) {
- opy->indexreg = mib_index;
- opy->scale = 1;
- opy->hintbase = mib_index;
- opy->hinttype = EAH_NOTBASE;
- }
-
- /*
- * only for mib operands, make a single reg index [reg*1].
- * gas uses this form to explicitly denote index register.
- */
- if (itemp_has(temp, IF_MIB) &&
- (opy->indexreg == -1 && opy->hintbase == opy->basereg &&
- opy->hinttype == EAH_NOTBASE)) {
- opy->indexreg = opy->basereg;
- opy->basereg = -1;
- opy->scale = 1;
+ if (itemp_has(temp, IF_MIB)) {
+ opy->eaflags |= EAF_MIB;
+ /*
+ * if a separate form of MIB (ICC style) is used,
+ * the index reg info is merged into mem operand
+ */
+ if (mib_index != R_none) {
+ opy->indexreg = mib_index;
+ opy->scale = 1;
+ opy->hintbase = mib_index;
+ opy->hinttype = EAH_NOTBASE;
+ }
}
if (process_ea(opy, &ea_data, bits,
ins->rex &= ~REX_P; /* Don't force REX prefix due to high reg */
}
+ switch (ins->prefixes[PPS_VEX]) {
+ case P_EVEX:
+ if (!(ins->rex & REX_EV))
+ return -1;
+ break;
+ case P_VEX3:
+ case P_VEX2:
+ if (!(ins->rex & REX_V))
+ return -1;
+ break;
+ default:
+ break;
+ }
+
if (ins->rex & (REX_V | REX_EV)) {
int bad32 = REX_R|REX_W|REX_X|REX_B;
}
if (ins->rex & REX_EV)
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)
length += 3;
else
length += 2;
bad_hle_warn(ins, hleok);
+ /*
+ * when BND prefix is set by DEFAULT directive,
+ * BND prefix is added to every appropriate instruction line
+ * unless it is overridden by NOBND prefix.
+ */
+ if (globalbnd &&
+ (itemp_has(temp, IF_BND) && !has_prefix(ins, PPS_REP, P_NOBND)))
+ ins->prefixes[PPS_REP] = P_BND;
+
return length;
}
static inline unsigned int emit_rex(insn *ins, int32_t segment, int64_t offset, int bits)
{
if (bits == 64) {
- if ((ins->rex & REX_REAL) && !(ins->rex & (REX_V | REX_EV))) {
- ins->rex = (ins->rex & REX_REAL) | REX_P;
- out(offset, segment, &ins->rex, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
- ins->rex = 0;
+ if ((ins->rex & REX_REAL) &&
+ !(ins->rex & (REX_V | REX_EV)) &&
+ !ins->rex_done) {
+ int rex = (ins->rex & REX_REAL) | REX_P;
+ out(offset, segment, &rex, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
+ ins->rex_done = true;
return 1;
}
}
uint8_t opex = 0;
enum ea_type eat = EA_SCALAR;
+ ins->rex_done = false;
+
while (*codes) {
c = *codes++;
op1 = (c & 3) + ((opex & 1) << 2);
case4(0260):
case 0270:
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) {
bytes[0] = (ins->vex_cm >> 6) ? 0x8f : 0xc4;
bytes[1] = (ins->vex_cm & 31) | ((~ins->rex & 7) << 5);
bytes[2] = ((ins->rex & REX_W) << (7-3)) |
{
int val;
- if (!is_register(o->basereg))
- errfunc(ERR_PANIC, "invalid operand passed to op_evexflags()");
-
val = nasm_regvals[o->basereg];
return evexflags(val, o->decoflags, mask, byte);
return MERR_INVALOP;
/*
+ * {evex} available?
+ */
+ switch (instruction->prefixes[PPS_VEX]) {
+ case P_EVEX:
+ if (!itemp_has(itemp, IF_EVEX))
+ return MERR_ENCMISMATCH;
+ break;
+ case P_VEX3:
+ case P_VEX2:
+ if (!itemp_has(itemp, IF_VEX))
+ return MERR_ENCMISMATCH;
+ break;
+ default:
+ break;
+ }
+
+ /*
* Check that no spurious colons or TOs are present
*/
for (i = 0; i < itemp->operands; i++)
*/
return MERR_BRNUMMISMATCH;
}
- } else if (is_register(instruction->oprs[i].basereg) &&
- nasm_regvals[instruction->oprs[i].basereg] >= 16 &&
- !itemp_has(itemp, IF_AVX512)) {
- return MERR_ENCMISMATCH;
- } else if (instruction->prefixes[PPS_EVEX] &&
- !itemp_has(itemp, IF_AVX512)) {
- return MERR_ENCMISMATCH;
}
}
return MOK_JUMP;
/*
- * Check if BND prefix is allowed
+ * Check if BND prefix is allowed.
+ * Other 0xF2 (REPNE/REPNZ) prefix is prohibited.
*/
if (!itemp_has(itemp, IF_BND) &&
- has_prefix(instruction, PPS_REP, P_BND))
+ (has_prefix(instruction, PPS_REP, P_BND) ||
+ has_prefix(instruction, PPS_REP, P_NOBND)))
return MERR_BADBND;
+ else if (itemp_has(itemp, IF_BND) &&
+ (has_prefix(instruction, PPS_REP, P_REPNE) ||
+ has_prefix(instruction, PPS_REP, P_REPNZ)))
+ return MERR_BADREPNE;
return MOK_GOOD;
}
{
bool forw_ref = !!(input->opflags & OPFLAG_UNKNOWN);
int addrbits = ins->addr_size;
+ int eaflags = input->eaflags;
output->type = EA_SCALAR;
output->rip = false;
input->type |= MEMORY;
}
- if (input->eaflags & EAF_BYTEOFFS ||
- (input->eaflags & EAF_WORDOFFS &&
+ if (bits == 64 &&
+ !(IP_REL & ~input->type) && (eaflags & EAF_MIB)) {
+ nasm_error(ERR_NONFATAL, "RIP-relative addressing is prohibited for mib.");
+ return -1;
+ }
+
+ if (eaflags & EAF_BYTEOFFS ||
+ (eaflags & EAF_WORDOFFS &&
input->disp_size != (addrbits != 16 ? 32 : 16))) {
nasm_error(ERR_WARNING | ERR_PASS1, "displacement size ignored on absolute address");
}
base = (bt & 7);
if (base != REG_NUM_EBP && o == 0 &&
seg == NO_SEG && !forw_ref &&
- !(input->eaflags & (EAF_BYTEOFFS | EAF_WORDOFFS)))
+ !(eaflags & (EAF_BYTEOFFS | EAF_WORDOFFS)))
mod = 0;
else if (IS_MOD_01())
mod = 1;
t = bt, bt = it, it = t;
x = bx, bx = ix, ix = x;
}
- if (bt == it) /* convert EAX+2*EAX to 3*EAX */
- bt = -1, bx = 0, s++;
+
if (bt == -1 && s == 1 && !(hb == i && ht == EAH_NOTBASE)) {
/* make single reg base, unless hint */
bt = it, bx = ix, it = -1, ix = 0;
}
- if (((s == 2 && it != REG_NUM_ESP && !(input->eaflags & EAF_TIMESTWO)) ||
- s == 3 || s == 5 || s == 9) && bt == -1)
- bt = it, bx = ix, s--; /* convert 3*EAX to EAX+2*EAX */
- if (it == -1 && (bt & 7) != REG_NUM_ESP &&
- (input->eaflags & EAF_TIMESTWO))
- it = bt, ix = bx, bt = -1, bx = 0, s = 1;
- /* convert [NOSPLIT EAX] to sib format with 0x0 displacement */
+ if (eaflags & EAF_MIB) {
+ /* only for mib operands */
+ if (it == -1 && (hb == b && ht == EAH_NOTBASE)) {
+ /*
+ * make a single reg index [reg*1].
+ * gas uses this form for an explicit index register.
+ */
+ it = bt, ix = bx, bt = -1, bx = 0, s = 1;
+ }
+ if ((ht == EAH_SUMMED) && bt == -1) {
+ /* separate once summed index into [base, index] */
+ bt = it, bx = ix, s--;
+ }
+ } else {
+ if (((s == 2 && it != REG_NUM_ESP &&
+ (!(eaflags & EAF_TIMESTWO) || (ht == EAH_SUMMED))) ||
+ s == 3 || s == 5 || s == 9) && bt == -1) {
+ /* convert 3*EAX to EAX+2*EAX */
+ bt = it, bx = ix, s--;
+ }
+ if (it == -1 && (bt & 7) != REG_NUM_ESP &&
+ (eaflags & EAF_TIMESTWO) &&
+ (hb == b && ht == EAH_NOTBASE)) {
+ /*
+ * convert [NOSPLIT EAX*1]
+ * to sib format with 0x0 displacement - [EAX*1+0].
+ */
+ it = bt, ix = bx, bt = -1, bx = 0, s = 1;
+ }
+ }
if (s == 1 && it == REG_NUM_ESP) {
/* swap ESP into base if scale is 1 */
t = it, it = bt, bt = t;
rm = (bt & 7);
if (rm != REG_NUM_EBP && o == 0 &&
seg == NO_SEG && !forw_ref &&
- !(input->eaflags & (EAF_BYTEOFFS | EAF_WORDOFFS)))
+ !(eaflags & (EAF_BYTEOFFS | EAF_WORDOFFS)))
mod = 0;
else if (IS_MOD_01())
mod = 1;
base = (bt & 7);
if (base != REG_NUM_EBP && o == 0 &&
seg == NO_SEG && !forw_ref &&
- !(input->eaflags & (EAF_BYTEOFFS | EAF_WORDOFFS)))
+ !(eaflags & (EAF_BYTEOFFS | EAF_WORDOFFS)))
mod = 0;
else if (IS_MOD_01())
mod = 1;
goto err; /* so panic if it does */
if (o == 0 && seg == NO_SEG && !forw_ref && rm != 6 &&
- !(input->eaflags & (EAF_BYTEOFFS | EAF_WORDOFFS)))
+ !(eaflags & (EAF_BYTEOFFS | EAF_WORDOFFS)))
mod = 0;
else if (IS_MOD_01())
mod = 1;