* \150..\153 - an immediate dword or signed byte for operand 0..3
* \154..\157 - or 2 (s-field) into opcode byte if operand 0..3
* is a signed byte rather than a dword. Opcode byte follows.
- * \160..\163 - this instruction uses DREX rather than REX, with the
- * OC0 field set to 0, and the dest field taken from
- * operand 0..3.
- * \164..\167 - this instruction uses DREX rather than REX, with the
- * OC0 field set to 1, and the dest field taken from
- * operand 0..3.
- * \171 - placement of DREX suffix in the absence of an EA
* \172\ab - the register number from operand a in bits 7..4, with
* the 4-bit immediate from operand b in bits 3..0.
* \173\xab - the register number from operand a in bits 7..4, with
length++;
break;
- case4(0160):
- length++;
- ins->rex |= REX_D;
- ins->drexdst = regval(opx);
- break;
-
- case4(0164):
- length++;
- ins->rex |= REX_D|REX_OC;
- ins->drexdst = regval(opx);
- break;
-
- case 0171:
- break;
-
case 0172:
case 0173:
case 0174:
case4(0260):
ins->rex |= REX_V;
- ins->drexdst = regval(opx);
+ ins->vexreg = regval(opx);
ins->vex_cm = *codes++;
ins->vex_wlp = *codes++;
break;
case 0270:
ins->rex |= REX_V;
- ins->drexdst = 0;
+ ins->vexreg = 0;
ins->vex_cm = *codes++;
ins->vex_wlp = *codes++;
break;
break;
}
- if (bits != 64 && ((ins->rex & bad32) || ins->drexdst > 7)) {
+ if (bits != 64 && ((ins->rex & bad32) || ins->vexreg > 7)) {
errfunc(ERR_NONFATAL, "invalid operands in non-64-bit mode");
return -1;
}
length += 3;
else
length += 2;
- } else if (ins->rex & REX_D) {
- if (ins->rex & REX_H) {
- errfunc(ERR_NONFATAL, "cannot use high register in drex instruction");
- return -1;
- }
- if (bits != 64 && ((ins->rex & (REX_R|REX_W|REX_X|REX_B)) ||
- ins->drexdst > 7)) {
- errfunc(ERR_NONFATAL, "invalid operands in non-64-bit mode");
- return -1;
- }
- length++;
} else if (ins->rex & REX_REAL) {
if (ins->rex & REX_H) {
errfunc(ERR_NONFATAL, "cannot use high register in rex instruction");
}
#define EMIT_REX() \
- if (!(ins->rex & (REX_D|REX_V)) && (ins->rex & REX_REAL) && (bits == 64)) { \
+ if (!(ins->rex & REX_V) && (ins->rex & REX_REAL) && (bits == 64)) { \
ins->rex = (ins->rex & REX_REAL)|REX_P; \
out(offset, segment, &ins->rex, OUT_RAWDATA, 1, NO_SEG, NO_SEG); \
ins->rex = 0; \
offset++;
break;
- case4(0160):
- case4(0164):
- break;
-
- case 0171:
- bytes[0] =
- (ins->drexdst << 4) |
- (ins->rex & REX_OC ? 0x08 : 0) |
- (ins->rex & (REX_R|REX_X|REX_B));
- ins->rex = 0;
- out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
- offset++;
- break;
-
case 0172:
c = *codes++;
opx = &ins->oprs[c >> 3];
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)) |
- ((~ins->drexdst & 15)<< 3) | (ins->vex_wlp & 07);
+ ((~ins->vexreg & 15)<< 3) | (ins->vex_wlp & 07);
out(offset, segment, &bytes, OUT_RAWDATA, 3, NO_SEG, NO_SEG);
offset += 3;
} else {
bytes[0] = 0xc5;
bytes[1] = ((~ins->rex & REX_R) << (7-2)) |
- ((~ins->drexdst & 15) << 3) | (ins->vex_wlp & 07);
+ ((~ins->vexreg & 15) << 3) | (ins->vex_wlp & 07);
out(offset, segment, &bytes, OUT_RAWDATA, 2, NO_SEG, NO_SEG);
offset += 2;
}
if (ea_data.sib_present)
*p++ = ea_data.sib;
- /* DREX suffixes come between the SIB and the displacement */
- if (ins->rex & REX_D) {
- *p++ = (ins->drexdst << 4) |
- (ins->rex & REX_OC ? 0x08 : 0) |
- (ins->rex & (REX_R|REX_X|REX_B));
- ins->rex = 0;
- }
-
s = p - bytes;
out(offset, segment, bytes, OUT_RAWDATA, s, NO_SEG, NO_SEG);
}
/*
- * Process a DREX suffix
- */
-static uint8_t *do_drex(uint8_t *data, insn *ins)
-{
- uint8_t drex = *data++;
- operand *dst = &ins->oprs[ins->drexdst];
-
- if ((drex & 8) != ((ins->rex & REX_OC) ? 8 : 0))
- return NULL; /* OC0 mismatch */
- ins->rex = (ins->rex & ~7) | (drex & 7);
-
- dst->segment = SEG_RMREG;
- dst->basereg = drex >> 4;
- return data;
-}
-
-
-/*
* Process an effective address (ModRM) specification.
*/
static uint8_t *do_ea(uint8_t *data, int modrm, int asize,
if (mod != 3 && asize != 16 && rm == 4)
sib = *data++;
- if (ins->rex & REX_D) {
- data = do_drex(data, ins);
- if (!data)
- return NULL;
- }
rex = ins->rex;
if (mod == 3) { /* pure register version */
}
break;
- case4(0160):
- ins->rex |= REX_D;
- ins->drexdst = op1;
- break;
-
- case4(0164):
- ins->rex |= REX_D|REX_OC;
- ins->drexdst = op1;
- break;
-
- case 0171:
- data = do_drex(data, ins);
- if (!data)
- return false;
- break;
-
case 0172:
{
uint8_t ximm = *data++;
int vexwlp = *r++;
ins->rex |= REX_V;
- if ((prefix->rex & (REX_V|REX_D|REX_P)) != REX_V)
+ if ((prefix->rex & (REX_V|REX_P)) != REX_V)
return false;
if ((vexm & 0x1f) != prefix->vex_m)
if (!vex_ok && (ins->rex & REX_V))
return false;
- /* REX cannot be combined with DREX or VEX */
- if ((ins->rex & (REX_D|REX_V)) && (prefix->rex & REX_P))
+ /* REX cannot be combined with VEX */
+ if ((ins->rex & REX_V) && (prefix->rex & REX_P))
return false;
/*
# r = register field in the modr/m
# m = modr/m
# v = VEX "v" field
-# d = DREX "dst" field
# i = immediate
# s = register field of is4/imz2 field
# - = implicit (unencoded) operand
push(@codes, defined($oppos{'v'}) ? 0260+($oppos{'v'} & 3) : 0270,
($c << 6)+$m, ($w << 4)+($l << 2)+$p);
$prefix_ok = 0;
- } elsif ($op =~ /^\/drex([01])$/) {
- my $oc0 = $1;
- if (!defined($oppos{'d'})) {
- die "$fname: $line: DREX without a 'd' operand\n";
- }
- # Note the use of *unshift* here, as opposed to *push*.
- # This is because NASM want this byte code at the start of
- # the instruction sequence, but the AMD documentation puts
- # this at (roughly) the position of the drex byte itself.
- # This allows us to match the AMD documentation and still
- # do the right thing.
- unshift(@codes, 0160+($oppos{'d'} & 3)+($oc0 ? 4 : 0));
- unshift(@codes, 05) if ($oppos{'d'} & 4);
} elsif ($op =~ /^(ib\,s|ib|ibx|ib\,w|iw|iwd|id|idx|iwdq|rel|rel8|rel16|rel32|iq|seg|ibw|ibd|ibd,s)$/) {
if (!defined($oppos{'i'})) {
die "$fname: $line: $op without 'i' operand\n";
#define REX_L 0x20 /* Use LOCK prefix instead of REX.R */
#define REX_P 0x40 /* REX prefix present/required */
#define REX_H 0x80 /* High register present, REX forbidden */
-#define REX_D 0x0100 /* Instruction uses DREX instead of REX */
-#define REX_OC 0x0200 /* DREX suffix has the OC0 bit set */
-#define REX_V 0x0400 /* Instruction uses VEX/XOP instead of REX */
-#define REX_NH 0x0800 /* Instruction which doesn't use high regs */
+#define REX_V 0x0100 /* Instruction uses VEX/XOP instead of REX */
+#define REX_NH 0x0200 /* Instruction which doesn't use high regs */
/*
* REX_V "classes" (prefixes which behave like VEX)
int32_t times; /* repeat count (TIMES prefix) */
bool forw_ref; /* is there a forward reference? */
int rex; /* Special REX Prefix */
- int drexdst; /* Destination register for DREX/VEX suffix */
+ int vexreg; /* Register encoded in VEX prefix */
int vex_cm; /* Class and M field for VEX prefix */
int vex_wlp; /* W, P and L information for VEX prefix */
} insn;