From fc561203fde370a5ab9db2d089053de51f8a5e04 Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Thu, 7 Jul 2011 16:58:22 -0700 Subject: [PATCH] Remove support for DREX encoding The DREX encoding never hit production silicon, and has been replaced by VEX/XOP encoding, so remove support for it. Signed-off-by: H. Peter Anvin --- assemble.c | 67 ++++++-------------------------------------------------------- disasm.c | 45 +++-------------------------------------- insns.pl | 14 ------------- nasm.h | 8 +++----- 4 files changed, 12 insertions(+), 122 deletions(-) diff --git a/assemble.c b/assemble.c index ed5ef8ea..17def3aa 100644 --- a/assemble.c +++ b/assemble.c @@ -66,13 +66,6 @@ * \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 @@ -908,21 +901,6 @@ static int64_t calcsize(int32_t segment, int64_t offset, int bits, 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: @@ -940,14 +918,14 @@ static int64_t calcsize(int32_t segment, int64_t offset, int bits, 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; @@ -1178,7 +1156,7 @@ static int64_t calcsize(int32_t segment, int64_t offset, int bits, 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; } @@ -1186,17 +1164,6 @@ static int64_t calcsize(int32_t segment, int64_t offset, int bits, 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"); @@ -1219,7 +1186,7 @@ static int64_t calcsize(int32_t segment, int64_t offset, int bits, } #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; \ @@ -1499,20 +1466,6 @@ static void gencode(int32_t segment, int64_t offset, int bits, 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]; @@ -1588,13 +1541,13 @@ static void gencode(int32_t segment, int64_t offset, int bits, 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; } @@ -1858,14 +1811,6 @@ static void gencode(int32_t segment, int64_t offset, int bits, 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); diff --git a/disasm.c b/disasm.c index 59439666..5c9d6db7 100644 --- a/disasm.c +++ b/disasm.c @@ -197,24 +197,6 @@ static enum reg_enum whichreg(opflags_t regflags, int regval, int rex) } /* - * 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, @@ -231,11 +213,6 @@ 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 */ @@ -621,22 +598,6 @@ static int matches(const struct itemplate *t, uint8_t *data, } 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++; @@ -705,7 +666,7 @@ static int matches(const struct itemplate *t, uint8_t *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) @@ -945,8 +906,8 @@ static int matches(const struct itemplate *t, uint8_t *data, 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; /* diff --git a/insns.pl b/insns.pl index 0b297579..6db1c82c 100755 --- a/insns.pl +++ b/insns.pl @@ -649,7 +649,6 @@ sub startseq($$) { # 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 @@ -811,19 +810,6 @@ sub byte_code_compile($$) { 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"; diff --git a/nasm.h b/nasm.h index 453a57cf..f8f62be9 100644 --- a/nasm.h +++ b/nasm.h @@ -439,10 +439,8 @@ enum ccode { /* condition code names */ #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) @@ -558,7 +556,7 @@ typedef struct insn { /* an instruction itself */ 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; -- 2.11.4.GIT