From 401c07e20d14130a2d147468a408fce9edd1faff Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Mon, 17 Sep 2007 16:55:04 -0700 Subject: [PATCH] Initial support for generating DREX suffixes Initial support for generating DREX suffixes. Not used yet. No disassembler support yet, and no support for "operand X must match operand Y." --- assemble.c | 64 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-- nasm.h | 5 ++++- 2 files changed, 66 insertions(+), 3 deletions(-) diff --git a/assemble.c b/assemble.c index f1b4dbb..a140c72 100644 --- a/assemble.c +++ b/assemble.c @@ -39,9 +39,16 @@ * \150..\153 - an immediate dword or signed byte for operand 0..3 * \154..\157 - or 2 (s-field) into next opcode byte if operand 0..3 * is a signed byte rather than a dword. + * \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. * \170 - encodes the literal byte 0. (Some compilers don't take * kindly to a zero byte in the _middle_ of a compile time * string constant, so I had to put this hack in.) + * \171 - placement of DREX suffix in the absence of an EA * \2ab - a ModRM, calculated on EA in operand a, with the spare * field equal to digit b. * \30x - might be an 0x67 byte, depending on the address size of @@ -843,9 +850,25 @@ static int32_t calcsize(int32_t segment, int32_t offset, int bits, codes += 2; length++; break; + case 0160: + case 0161: + case 0162: + case 0163: + length++; + ins->rex |= REX_D; + break; + case 0164: + case 0165: + case 0166: + case 0167: + length++; + ins->rex |= REX_D|REX_OC; + break; case 0170: length++; break; + case 0171: + break; case 0300: case 0301: case 0302: @@ -945,7 +968,14 @@ static int32_t calcsize(int32_t segment, int32_t offset, int bits, } ins->rex &= rex_mask; - if (ins->rex & REX_REAL) { + + if (ins->rex & REX_D) { + if (ins->rex & REX_H) { + errfunc(ERR_NONFATAL, "cannot use high register in drex instruction"); + return -1; + } + length++; + } else if (ins->rex & REX_REAL) { if (ins->rex & REX_H) { errfunc(ERR_NONFATAL, "cannot use high register in rex instruction"); return -1; @@ -964,7 +994,7 @@ static int32_t calcsize(int32_t segment, int32_t offset, int bits, } #define EMIT_REX() \ - if((ins->rex & REX_REAL) && (bits == 64)) { \ + if (!(ins->rex & REX_D) && (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; \ @@ -1320,12 +1350,33 @@ static void gencode(int32_t segment, int32_t offset, int bits, offset++; break; + case 0160: + case 0161: + case 0162: + case 0163: + case 0164: + case 0165: + case 0166: + case 0167: + ins->drexdst = regval(&ins->oprs[c & 3]); + break; + case 0170: bytes[0] = 0; out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG, NO_SEG); offset += 1; 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 0300: case 0301: case 0302: @@ -1487,6 +1538,15 @@ static void gencode(int32_t segment, int32_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/nasm.h b/nasm.h index 7c5a1b7..93c35de 100644 --- a/nasm.h +++ b/nasm.h @@ -540,6 +540,8 @@ enum ccode { /* condition code names */ /* * REX flags */ +#define REX_OC 0x0200 /* DREX suffix has the OC0 bit set */ +#define REX_D 0x0100 /* Instruction uses DREX instead of REX */ #define REX_H 0x80 /* High register present, REX forbidden */ #define REX_P 0x40 /* REX prefix present/required */ #define REX_L 0x20 /* Use LOCK prefix instead of REX.R */ @@ -622,7 +624,8 @@ typedef struct { /* an instruction itself */ int eops_float; /* true if DD and floating */ int32_t times; /* repeat count (TIMES prefix) */ int forw_ref; /* is there a forward reference? */ - uint8_t rex; /* Special REX Prefix */ + int rex; /* Special REX Prefix */ + int drexdst; /* Destination register for DREX suffix */ } insn; enum geninfo { GI_SWITCH }; -- 2.7.4