summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--assemble.c331
-rw-r--r--disasm.c274
-rw-r--r--doc/nasmdoc.src44
-rw-r--r--insns.dat354
-rw-r--r--insns.h31
-rw-r--r--insns.pl214
-rw-r--r--nasm.h30
-rw-r--r--parser.c39
-rw-r--r--perllib/phash.ph4
-rwxr-xr-xpptok.pl4
-rw-r--r--test/fmsub.asm16
-rw-r--r--tokens.dat1
-rwxr-xr-xtokhash.pl4
13 files changed, 936 insertions, 410 deletions
diff --git a/assemble.c b/assemble.c
index 54522712..e5384548 100644
--- a/assemble.c
+++ b/assemble.c
@@ -12,39 +12,43 @@
* (POP is never used for CS) depending on operand 0
* \5, \7 - the second byte of POP/PUSH codes for FS, GS, depending
* on operand 0
- * \10, \11, \12 - a literal byte follows in the code stream, to be added
- * to the register value of operand 0, 1 or 2
- * \17 - 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.)
- * \14, \15, \16 - a signed byte immediate operand, from operand 0, 1 or 2
- * \20, \21, \22 - a byte immediate operand, from operand 0, 1 or 2
- * \24, \25, \26 - an unsigned byte immediate operand, from operand 0, 1 or 2
- * \30, \31, \32 - a word immediate operand, from operand 0, 1 or 2
- * \34, \35, \36 - select between \3[012] and \4[012] depending on 16/32 bit
+ * \10..\13 - a literal byte follows in the code stream, to be added
+ * to the register value of operand 0..3
+ * \14..\17 - a signed byte immediate operand, from operand 0..3
+ * \20..\23 - a byte immediate operand, from operand 0..3
+ * \24..\27 - an unsigned byte immediate operand, from operand 0..3
+ * \30..\33 - a word immediate operand, from operand 0..3
+ * \34..\37 - select between \3[0-3] and \4[0-3] depending on 16/32 bit
* assembly mode or the operand-size override on the operand
- * \37 - a word constant, from the _segment_ part of operand 0
- * \40, \41, \42 - a long immediate operand, from operand 0, 1 or 2
- * \44, \45, \46 - select between \3[012], \4[012] and \5[456]
+ * \40..\43 - a long immediate operand, from operand 0..3
+ * \44..\47 - select between \3[0-3], \4[0-3] and \5[4-7]
* depending on assembly mode or the address-size override
* on the operand.
- * \50, \51, \52 - a byte relative operand, from operand 0, 1 or 2
- * \54, \55, \56 - a qword immediate operand, from operand 0, 1 or 2
- * \60, \61, \62 - a word relative operand, from operand 0, 1 or 2
- * \64, \65, \66 - select between \6[012] and \7[012] depending on 16/32 bit
+ * \50..\53 - a byte relative operand, from operand 0..3
+ * \54..\57 - a qword immediate operand, from operand 0..3
+ * \60..\63 - a word relative operand, from operand 0..3
+ * \64..\67 - select between \6[0-3] and \7[0-3] depending on 16/32 bit
* assembly mode or the operand-size override on the operand
- * \70, \71, \72 - a long relative operand, from operand 0, 1 or 2
+ * \70..\73 - a long relative operand, from operand 0..3
+ * \74..\77 - a word constant, from the _segment_ part of operand 0..3
* \1ab - a ModRM, calculated on EA in operand a, with the spare
* field the register value of operand b.
- * \130,\131,\132 - an immediate word or signed byte for operand 0, 1, or 2
- * \133,\134,\135 - or 2 (s-field) into next opcode byte if operand 0, 1, or 2
+ * \140..\143 - an immediate word or signed byte for operand 0..3
+ * \144..\147 - or 2 (s-field) into next opcode byte if operand 0..3
* is a signed byte rather than a word.
- * \140,\141,\142 - an immediate dword or signed byte for operand 0, 1, or 2
- * \143,\144,\145 - or 2 (s-field) into next opcode byte if operand 0, 1, or 2
+ * \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.
- * \150,\151,\152 - an immediate qword or signed byte for operand 0, 1, or 2
- * \153,\154,\155 - or 2 (s-field) into next opcode byte if operand 0, 1, or 2
- * is a signed byte rather than a qword.
+ * \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
@@ -730,73 +734,79 @@ static int32_t calcsize(int32_t segment, int32_t offset, int bits,
case 010:
case 011:
case 012:
+ case 013:
ins->rex |=
op_rexflags(&ins->oprs[c - 010], REX_B|REX_H|REX_P|REX_W);
codes++, length++;
break;
- case 017:
- length++;
- break;
case 014:
case 015:
case 016:
+ case 017:
length++;
break;
case 020:
case 021:
case 022:
+ case 023:
length++;
break;
case 024:
case 025:
case 026:
+ case 027:
length++;
break;
case 030:
case 031:
case 032:
+ case 033:
length += 2;
break;
case 034:
case 035:
case 036:
+ case 037:
if (ins->oprs[c - 034].type & (BITS16 | BITS32 | BITS64))
length += (ins->oprs[c - 034].type & BITS16) ? 2 : 4;
else
length += (bits == 16) ? 2 : 4;
break;
- case 037:
- length += 2;
- break;
case 040:
case 041:
case 042:
+ case 043:
length += 4;
break;
case 044:
case 045:
case 046:
+ case 047:
length += ((ins->oprs[c - 044].addr_size ?
ins->oprs[c - 044].addr_size : bits) >> 3);
break;
case 050:
case 051:
case 052:
+ case 053:
length++;
break;
case 054:
case 055:
case 056:
+ case 057:
length += 8; /* MOV reg64/imm */
break;
case 060:
case 061:
case 062:
+ case 063:
length += 2;
break;
case 064:
case 065:
case 066:
+ case 067:
if (ins->oprs[c - 064].type & (BITS16 | BITS32 | BITS64))
length += (ins->oprs[c - 064].type & BITS16) ? 2 : 4;
else
@@ -805,33 +815,66 @@ static int32_t calcsize(int32_t segment, int32_t offset, int bits,
case 070:
case 071:
case 072:
+ case 073:
length += 4;
break;
- case 0130:
- case 0131:
- case 0132:
- length += is_sbyte(ins, c - 0130, 16) ? 1 : 2;
- break;
- case 0133:
- case 0134:
- case 0135:
- codes += 2;
- length++;
+ case 074:
+ case 075:
+ case 076:
+ case 077:
+ length += 2;
break;
case 0140:
case 0141:
case 0142:
- length += is_sbyte(ins, c - 0140, 32) ? 1 : 4;
+ case 0143:
+ length += is_sbyte(ins, c - 0140, 16) ? 1 : 2;
break;
- case 0143:
case 0144:
case 0145:
+ case 0146:
+ case 0147:
codes += 2;
length++;
break;
+ case 0150:
+ case 0151:
+ case 0152:
+ case 0153:
+ length += is_sbyte(ins, c - 0150, 32) ? 1 : 4;
+ break;
+ case 0154:
+ case 0155:
+ case 0156:
+ case 0157:
+ codes += 2;
+ length++;
+ break;
+ case 0160:
+ case 0161:
+ case 0162:
+ case 0163:
+ length++;
+ ins->rex |= REX_D;
+ ins->drexdst = regval(&ins->oprs[c & 3]);
+ break;
+ case 0164:
+ case 0165:
+ case 0166:
+ case 0167:
+ length++;
+ ins->rex |= REX_D|REX_OC;
+ ins->drexdst = regval(&ins->oprs[c & 3]);
+ break;
+ case 0170:
+ length++;
+ break;
+ case 0171:
+ break;
case 0300:
case 0301:
case 0302:
+ case 0303:
length += chsize(&ins->oprs[c - 0300], bits);
break;
case 0310:
@@ -927,7 +970,19 @@ 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;
+ }
+ if (bits != 64 && ((ins->rex & (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");
return -1;
@@ -937,8 +992,8 @@ static int32_t calcsize(int32_t segment, int32_t offset, int bits,
cpu >= IF_X86_64)) {
length++;
} else {
- errfunc(ERR_NONFATAL, "invalid operands in non-64-bit mode");
- return -1;
+ errfunc(ERR_NONFATAL, "invalid operands in non-64-bit mode");
+ return -1;
}
}
@@ -946,7 +1001,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; \
@@ -1020,21 +1075,17 @@ static void gencode(int32_t segment, int32_t offset, int bits,
case 010:
case 011:
case 012:
+ case 013:
EMIT_REX();
bytes[0] = *codes++ + ((regval(&ins->oprs[c - 010])) & 7);
out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
offset += 1;
break;
- case 017:
- bytes[0] = 0;
- out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
- offset += 1;
- break;
-
case 014:
case 015:
case 016:
+ case 017:
if (ins->oprs[c - 014].offset < -128
|| ins->oprs[c - 014].offset > 127) {
errfunc(ERR_WARNING, "signed byte value exceeds bounds");
@@ -1055,6 +1106,7 @@ static void gencode(int32_t segment, int32_t offset, int bits,
case 020:
case 021:
case 022:
+ case 023:
if (ins->oprs[c - 020].offset < -256
|| ins->oprs[c - 020].offset > 255) {
errfunc(ERR_WARNING, "byte value exceeds bounds");
@@ -1074,6 +1126,7 @@ static void gencode(int32_t segment, int32_t offset, int bits,
case 024:
case 025:
case 026:
+ case 027:
if (ins->oprs[c - 024].offset < 0
|| ins->oprs[c - 024].offset > 255)
errfunc(ERR_WARNING, "unsigned byte value exceeds bounds");
@@ -1092,6 +1145,7 @@ static void gencode(int32_t segment, int32_t offset, int bits,
case 030:
case 031:
case 032:
+ case 033:
if (ins->oprs[c - 030].segment == NO_SEG &&
ins->oprs[c - 030].wrt == NO_SEG &&
(ins->oprs[c - 030].offset < -65536L ||
@@ -1107,6 +1161,7 @@ static void gencode(int32_t segment, int32_t offset, int bits,
case 034:
case 035:
case 036:
+ case 037:
if (ins->oprs[c - 034].type & (BITS16 | BITS32))
size = (ins->oprs[c - 034].type & BITS16) ? 2 : 4;
else
@@ -1119,20 +1174,10 @@ static void gencode(int32_t segment, int32_t offset, int bits,
offset += size;
break;
- case 037:
- if (ins->oprs[0].segment == NO_SEG)
- errfunc(ERR_NONFATAL, "value referenced by FAR is not"
- " relocatable");
- data = 0L;
- out(offset, segment, &data, OUT_ADDRESS + 2,
- outfmt->segbase(1 + ins->oprs[0].segment),
- ins->oprs[0].wrt);
- offset += 2;
- break;
-
case 040:
case 041:
case 042:
+ case 043:
data = ins->oprs[c - 040].offset;
out(offset, segment, &data, OUT_ADDRESS + 4,
ins->oprs[c - 040].segment, ins->oprs[c - 040].wrt);
@@ -1142,6 +1187,7 @@ static void gencode(int32_t segment, int32_t offset, int bits,
case 044:
case 045:
case 046:
+ case 047:
data = ins->oprs[c - 044].offset;
size = ((ins->oprs[c - 044].addr_size ?
ins->oprs[c - 044].addr_size : bits) >> 3);
@@ -1155,6 +1201,7 @@ static void gencode(int32_t segment, int32_t offset, int bits,
case 050:
case 051:
case 052:
+ case 053:
if (ins->oprs[c - 050].segment != segment)
errfunc(ERR_NONFATAL,
"short relative jump outside segment");
@@ -1169,6 +1216,7 @@ static void gencode(int32_t segment, int32_t offset, int bits,
case 054:
case 055:
case 056:
+ case 057:
data = (int64_t)ins->oprs[c - 054].offset;
out(offset, segment, &data, OUT_ADDRESS + 8,
ins->oprs[c - 054].segment, ins->oprs[c - 054].wrt);
@@ -1178,6 +1226,7 @@ static void gencode(int32_t segment, int32_t offset, int bits,
case 060:
case 061:
case 062:
+ case 063:
if (ins->oprs[c - 060].segment != segment) {
data = ins->oprs[c - 060].offset;
out(offset, segment, &data,
@@ -1194,6 +1243,7 @@ static void gencode(int32_t segment, int32_t offset, int bits,
case 064:
case 065:
case 066:
+ case 067:
if (ins->oprs[c - 064].type & (BITS16 | BITS32 | BITS64))
size = (ins->oprs[c - 064].type & BITS16) ? 2 : 4;
else
@@ -1214,6 +1264,7 @@ static void gencode(int32_t segment, int32_t offset, int bits,
case 070:
case 071:
case 072:
+ case 073:
if (ins->oprs[c - 070].segment != segment) {
data = ins->oprs[c - 070].offset;
out(offset, segment, &data,
@@ -1227,70 +1278,115 @@ static void gencode(int32_t segment, int32_t offset, int bits,
offset += 4;
break;
- case 0130:
- case 0131:
- case 0132:
- data = ins->oprs[c - 0130].offset;
- if (is_sbyte(ins, c - 0130, 16)) {
+ case 074:
+ case 075:
+ case 076:
+ case 077:
+ if (ins->oprs[c - 074].segment == NO_SEG)
+ errfunc(ERR_NONFATAL, "value referenced by FAR is not"
+ " relocatable");
+ data = 0L;
+ out(offset, segment, &data, OUT_ADDRESS + 2,
+ outfmt->segbase(1 + ins->oprs[c - 074].segment),
+ ins->oprs[c - 074].wrt);
+ offset += 2;
+ break;
+
+ case 0140:
+ case 0141:
+ case 0142:
+ case 0143:
+ data = ins->oprs[c - 0140].offset;
+ if (is_sbyte(ins, c - 0140, 16)) {
bytes[0] = data;
out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG,
NO_SEG);
offset++;
} else {
- if (ins->oprs[c - 0130].segment == NO_SEG &&
- ins->oprs[c - 0130].wrt == NO_SEG &&
+ if (ins->oprs[c - 0140].segment == NO_SEG &&
+ ins->oprs[c - 0140].wrt == NO_SEG &&
(data < -65536L || data > 65535L)) {
errfunc(ERR_WARNING, "word value exceeds bounds");
}
out(offset, segment, &data, OUT_ADDRESS + 2,
- ins->oprs[c - 0130].segment, ins->oprs[c - 0130].wrt);
+ ins->oprs[c - 0140].segment, ins->oprs[c - 0140].wrt);
offset += 2;
}
break;
- case 0133:
- case 0134:
- case 0135:
+ case 0144:
+ case 0145:
+ case 0146:
+ case 0147:
EMIT_REX();
codes++;
bytes[0] = *codes++;
- if (is_sbyte(ins, c - 0133, 16))
+ if (is_sbyte(ins, c - 0144, 16))
bytes[0] |= 2; /* s-bit */
out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
offset++;
break;
- case 0140:
- case 0141:
- case 0142:
- data = ins->oprs[c - 0140].offset;
- if (is_sbyte(ins, c - 0140, 32)) {
+ case 0150:
+ case 0151:
+ case 0152:
+ case 0153:
+ data = ins->oprs[c - 0150].offset;
+ if (is_sbyte(ins, c - 0150, 32)) {
bytes[0] = data;
out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG,
NO_SEG);
offset++;
} else {
out(offset, segment, &data, OUT_ADDRESS + 4,
- ins->oprs[c - 0140].segment, ins->oprs[c - 0140].wrt);
+ ins->oprs[c - 0150].segment, ins->oprs[c - 0150].wrt);
offset += 4;
}
break;
- case 0143:
- case 0144:
- case 0145:
+ case 0154:
+ case 0155:
+ case 0156:
+ case 0157:
EMIT_REX();
codes++;
bytes[0] = *codes++;
- if (is_sbyte(ins, c - 0143, 32))
+ if (is_sbyte(ins, c - 0154, 32))
bytes[0] |= 2; /* s-bit */
out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
offset++;
break;
+ case 0160:
+ case 0161:
+ case 0162:
+ case 0163:
+ case 0164:
+ case 0165:
+ case 0166:
+ case 0167:
+ 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:
+ case 0303:
if (chsize(&ins->oprs[c - 0300], bits)) {
*bytes = 0x67;
out(offset, segment, bytes,
@@ -1448,6 +1544,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);
@@ -1537,7 +1642,7 @@ static int rexflags(int val, int32_t flags, int mask)
static int matches(const struct itemplate *itemp, insn * instruction, int bits)
{
- int i, size[3], asize, oprs, ret;
+ int i, size[MAX_OPERANDS], asize, oprs, ret;
ret = 100;
@@ -1564,7 +1669,12 @@ static int matches(const struct itemplate *itemp, insn * instruction, int bits)
* Check that the operand flags all match up
*/
for (i = 0; i < itemp->operands; i++) {
- if (itemp->opd[i] & ~instruction->oprs[i].type ||
+ if (itemp->opd[i] & SAME_AS) {
+ int j = itemp->opd[i] & ~SAME_AS;
+ if (instruction->oprs[i].type != instruction->oprs[j].type ||
+ instruction->oprs[i].basereg != instruction->oprs[j].basereg)
+ return 0;
+ } else if (itemp->opd[i] & ~instruction->oprs[i].type ||
((itemp->opd[i] & SIZE_MASK) &&
((itemp->opd[i] ^ instruction->oprs[i].type) & SIZE_MASK))) {
if ((itemp->opd[i] & ~instruction->oprs[i].type & ~SIZE_MASK) ||
@@ -1579,7 +1689,7 @@ static int matches(const struct itemplate *itemp, insn * instruction, int bits)
* Check operand sizes
*/
if (itemp->flags & IF_ARMASK) {
- size[0] = size[1] = size[2] = 0;
+ memset(size, 0, sizeof size);
switch (itemp->flags & IF_ARMASK) {
case IF_AR0:
@@ -1591,34 +1701,59 @@ static int matches(const struct itemplate *itemp, insn * instruction, int bits)
case IF_AR2:
i = 2;
break;
+ case IF_AR3:
+ i = 3;
+ break;
default:
break; /* Shouldn't happen */
}
- if (itemp->flags & IF_SB) {
+ switch (itemp->flags & IF_SMASK) {
+ case IF_SB:
size[i] = BITS8;
- } else if (itemp->flags & IF_SW) {
+ break;
+ case IF_SW:
size[i] = BITS16;
- } else if (itemp->flags & IF_SD) {
+ break;
+ case IF_SD:
size[i] = BITS32;
- } else if (itemp->flags & IF_SQ) {
+ break;
+ case IF_SQ:
size[i] = BITS64;
+ break;
+ case IF_SO:
+ size[i] = BITS128;
+ break;
+ default:
+ break;
}
} else {
asize = 0;
- if (itemp->flags & IF_SB) {
+ switch (itemp->flags & IF_SMASK) {
+ case IF_SB:
asize = BITS8;
oprs = itemp->operands;
- } else if (itemp->flags & IF_SW) {
+ break;
+ case IF_SW:
asize = BITS16;
oprs = itemp->operands;
- } else if (itemp->flags & IF_SD) {
+ break;
+ case IF_SD:
asize = BITS32;
oprs = itemp->operands;
- } else if (itemp->flags & IF_SQ) {
+ break;
+ case IF_SQ:
asize = BITS64;
oprs = itemp->operands;
+ break;
+ case IF_SO:
+ asize = BITS128;
+ oprs = itemp->operands;
+ break;
+ default:
+ break;
}
- size[0] = size[1] = size[2] = asize;
+ for (i = 0; i < MAX_OPERANDS; i++)
+ size[i] = asize;
}
if (itemp->flags & (IF_SM | IF_SM2)) {
diff --git a/disasm.c b/disasm.c
index 0452c295..a6c1c729 100644
--- a/disasm.c
+++ b/disasm.c
@@ -167,16 +167,46 @@ static const char *whichcond(int condval)
}
/*
+ * 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,
- int segsize, operand * op, int rex)
+ int segsize, operand * op, insn *ins)
{
int mod, rm, scale, index, base;
+ int rex;
+ uint8_t sib = 0;
mod = (modrm >> 6) & 03;
rm = modrm & 07;
+ if (mod != 3 && rm == 4 && asize != 16)
+ 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 */
op->basereg = rm+(rex & REX_B ? 8 : 0);
op->segment |= SEG_RMREG;
@@ -282,10 +312,9 @@ static uint8_t *do_ea(uint8_t *data, int modrm, int asize,
}
if (rm == 4) { /* process SIB */
- scale = (*data >> 6) & 03;
- index = (*data >> 3) & 07;
- base = *data & 07;
- data++;
+ scale = (sib >> 6) & 03;
+ index = (sib >> 3) & 07;
+ base = sib & 07;
op->scale = 1 << scale;
@@ -341,12 +370,12 @@ static int matches(const struct itemplate *t, uint8_t *data,
uint8_t lock = prefix->lock;
int osize = prefix->osize;
int asize = prefix->asize;
+ int i;
- ins->oprs[0].segment = ins->oprs[1].segment =
- ins->oprs[2].segment =
- ins->oprs[0].addr_size = ins->oprs[1].addr_size =
- ins->oprs[2].addr_size = (segsize == 64 ? SEG_64BIT :
- segsize == 32 ? SEG_32BIT : 0);
+ for (i = 0; i < MAX_OPERANDS; i++) {
+ ins->oprs[i].segment = ins->oprs[i].addr_size =
+ (segsize == 64 ? SEG_64BIT : segsize == 32 ? SEG_32BIT : 0);
+ }
ins->condition = -1;
ins->rex = prefix->rex;
@@ -419,7 +448,7 @@ static int matches(const struct itemplate *t, uint8_t *data,
default:
return FALSE;
}
- } else if (c >= 010 && c <= 012) {
+ } else if (c >= 010 && c <= 013) {
int t = *r++, d = *data++;
if (d < t || d > t + 7)
return FALSE;
@@ -428,20 +457,17 @@ static int matches(const struct itemplate *t, uint8_t *data,
(ins->rex & REX_B ? 8 : 0);
ins->oprs[c - 010].segment |= SEG_RMREG;
}
- } else if (c == 017) {
- if (*data++)
- return FALSE;
- } else if (c >= 014 && c <= 016) {
+ } else if (c >= 014 && c <= 017) {
ins->oprs[c - 014].offset = (int8_t)*data++;
ins->oprs[c - 014].segment |= SEG_SIGNED;
- } else if (c >= 020 && c <= 022) {
+ } else if (c >= 020 && c <= 023) {
ins->oprs[c - 020].offset = *data++;
- } else if (c >= 024 && c <= 026) {
+ } else if (c >= 024 && c <= 027) {
ins->oprs[c - 024].offset = *data++;
- } else if (c >= 030 && c <= 032) {
+ } else if (c >= 030 && c <= 033) {
ins->oprs[c - 030].offset = getu16(data);
data += 2;
- } else if (c >= 034 && c <= 036) {
+ } else if (c >= 034 && c <= 037) {
if (osize == 32) {
ins->oprs[c - 034].offset = getu32(data);
data += 4;
@@ -451,10 +477,10 @@ static int matches(const struct itemplate *t, uint8_t *data,
}
if (segsize != asize)
ins->oprs[c - 034].addr_size = asize;
- } else if (c >= 040 && c <= 042) {
+ } else if (c >= 040 && c <= 043) {
ins->oprs[c - 040].offset = getu32(data);
data += 4;
- } else if (c >= 044 && c <= 046) {
+ } else if (c >= 044 && c <= 047) {
switch (asize) {
case 16:
ins->oprs[c - 044].offset = getu16(data);
@@ -471,18 +497,18 @@ static int matches(const struct itemplate *t, uint8_t *data,
}
if (segsize != asize)
ins->oprs[c - 044].addr_size = asize;
- } else if (c >= 050 && c <= 052) {
+ } else if (c >= 050 && c <= 053) {
ins->oprs[c - 050].offset = gets8(data++);
ins->oprs[c - 050].segment |= SEG_RELATIVE;
- } else if (c >= 054 && c <= 056) {
+ } else if (c >= 054 && c <= 057) {
ins->oprs[c - 054].offset = getu64(data);
data += 8;
- } else if (c >= 060 && c <= 062) {
+ } else if (c >= 060 && c <= 063) {
ins->oprs[c - 060].offset = gets16(data);
data += 2;
ins->oprs[c - 060].segment |= SEG_RELATIVE;
ins->oprs[c - 060].segment &= ~SEG_32BIT;
- } else if (c >= 064 && c <= 066) {
+ } else if (c >= 064 && c <= 067) {
if (osize == 16) {
ins->oprs[c - 064].offset = getu16(data);
data += 2;
@@ -498,30 +524,44 @@ static int matches(const struct itemplate *t, uint8_t *data,
(ins->oprs[c - 064].type & ~SIZE_MASK)
| ((osize == 16) ? BITS16 : BITS32);
}
- } else if (c >= 070 && c <= 072) {
+ } else if (c >= 070 && c <= 073) {
ins->oprs[c - 070].offset = getu32(data);
data += 4;
ins->oprs[c - 070].segment |= SEG_32BIT | SEG_RELATIVE;
- } else if (c >= 0100 && c < 0130) {
+ } else if (c >= 0100 && c < 0140) {
int modrm = *data++;
- ins->oprs[c & 07].basereg = ((modrm >> 3)&7)+
- (ins->rex & REX_R ? 8 : 0);
ins->oprs[c & 07].segment |= SEG_RMREG;
data = do_ea(data, modrm, asize, segsize,
- &ins->oprs[(c >> 3) & 07], ins->rex);
- } else if (c >= 0130 && c <= 0132) {
- ins->oprs[c - 0130].offset = getu16(data);
+ &ins->oprs[(c >> 3) & 07], ins);
+ if (!data)
+ return FALSE;
+ ins->oprs[c & 07].basereg = ((modrm >> 3)&7)+
+ (ins->rex & REX_R ? 8 : 0);
+ } else if (c >= 0140 && c <= 0143) {
+ ins->oprs[c - 0140].offset = getu16(data);
data += 2;
- } else if (c >= 0140 && c <= 0142) {
- ins->oprs[c - 0140].offset = getu32(data);
+ } else if (c >= 0150 && c <= 0153) {
+ ins->oprs[c - 0150].offset = getu32(data);
data += 4;
+ } else if (c >= 0160 && c <= 0167) {
+ ins->rex |= (c & 4) ? REX_D|REX_OC : REX_D;
+ ins->drexdst = c & 3;
+ } else if (c == 0170) {
+ if (*data++)
+ return FALSE;
+ } else if (c == 0171) {
+ data = do_drex(data, ins);
+ if (!data)
+ return FALSE;
} else if (c >= 0200 && c <= 0277) {
int modrm = *data++;
if (((modrm >> 3) & 07) != (c & 07))
return FALSE; /* spare field doesn't match up */
data = do_ea(data, modrm, asize, segsize,
- &ins->oprs[(c >> 3) & 07], ins->rex);
- } else if (c >= 0300 && c <= 0302) {
+ &ins->oprs[(c >> 3) & 07], ins);
+ if (!data)
+ return FALSE;
+ } else if (c >= 0300 && c <= 0303) {
a_used = TRUE;
} else if (c == 0310) {
if (asize != 16)
@@ -605,6 +645,10 @@ static int matches(const struct itemplate *t, uint8_t *data,
}
}
+ /* REX cannot be combined with DREX */
+ if ((ins->rex & REX_D) && (prefix->rex))
+ return FALSE;
+
/*
* Check for unused rep or a/o prefixes.
*/
@@ -627,9 +671,11 @@ int32_t disasm(uint8_t *data, char *output, int outbufsize, int segsize,
int32_t offset, int autosync, uint32_t prefer)
{
const struct itemplate * const *p, * const *best_p;
+ const struct disasm_index *ix;
+ uint8_t *dp;
int length, best_length = 0;
char *segover;
- int i, slen, colon;
+ int i, slen, colon, n;
uint8_t *origdata;
int works;
insn tmp_ins, ins;
@@ -684,7 +730,14 @@ int32_t disasm(uint8_t *data, char *output, int outbufsize, int segsize,
best_p = NULL;
best_pref = INT_MAX;
- for (p = itable[*data]; *p; p++) {
+ dp = data;
+ ix = itable + *dp++;
+ while (ix->n == (size_t)-1) {
+ ix = (const struct disasm_index *)ix->p + *dp++;
+ }
+
+ p = (const struct itemplate * const *)ix->p;
+ for (n = ix->n; n; n--, p++) {
if ((length = matches(*p, data, &prefix, segsize, &tmp_ins))) {
works = TRUE;
/*
@@ -692,19 +745,21 @@ int32_t disasm(uint8_t *data, char *output, int outbufsize, int segsize,
* XXX: Need to make sure this is actually correct.
*/
for (i = 0; i < (*p)->operands; i++) {
- if (
- /* If it's a mem-only EA but we have a register, die. */
- ((tmp_ins.oprs[i].segment & SEG_RMREG) &&
- !(MEMORY & ~(*p)->opd[i])) ||
- /* If it's a reg-only EA but we have a memory ref, die. */
- (!(tmp_ins.oprs[i].segment & SEG_RMREG) &&
- !(REG_EA & ~(*p)->opd[i]) &&
- !((*p)->opd[i] & REG_SMASK)) ||
- /* Register type mismatch (eg FS vs REG_DESS): die. */
- ((((*p)->opd[i] & (REGISTER | FPUREG)) ||
- (tmp_ins.oprs[i].segment & SEG_RMREG)) &&
- !whichreg((*p)->opd[i],
- tmp_ins.oprs[i].basereg, tmp_ins.rex))) {
+ if (!((*p)->opd[i] & SAME_AS) &&
+ (
+ /* If it's a mem-only EA but we have a register, die. */
+ ((tmp_ins.oprs[i].segment & SEG_RMREG) &&
+ !(MEMORY & ~(*p)->opd[i])) ||
+ /* If it's a reg-only EA but we have a memory ref, die. */
+ (!(tmp_ins.oprs[i].segment & SEG_RMREG) &&
+ !(REG_EA & ~(*p)->opd[i]) &&
+ !((*p)->opd[i] & REG_SMASK)) ||
+ /* Register type mismatch (eg FS vs REG_DESS): die. */
+ ((((*p)->opd[i] & (REGISTER | FPUREG)) ||
+ (tmp_ins.oprs[i].segment & SEG_RMREG)) &&
+ !whichreg((*p)->opd[i],
+ tmp_ins.oprs[i].basereg, tmp_ins.rex))
+ )) {
works = FALSE;
break;
}
@@ -793,107 +848,116 @@ int32_t disasm(uint8_t *data, char *output, int outbufsize, int segsize,
colon = FALSE;
length += data - origdata; /* fix up for prefixes */
for (i = 0; i < (*p)->operands; i++) {
+ opflags_t t = (*p)->opd[i];
+ const operand *o = &ins.oprs[i];
+ int64_t offs;
+
+ if (t & SAME_AS) {
+ o = &ins.oprs[t & ~SAME_AS];
+ t = (*p)->opd[t & ~SAME_AS];
+ }
+
output[slen++] = (colon ? ':' : i == 0 ? ' ' : ',');
- if (ins.oprs[i].segment & SEG_RELATIVE) {
- ins.oprs[i].offset += offset + length;
+ offs = o->offset;
+ if (o->segment & SEG_RELATIVE) {
+ offs += offset + length;
/*
* sort out wraparound
*/
- if (!(ins.oprs[i].segment & (SEG_32BIT|SEG_64BIT)))
- ins.oprs[i].offset &= 0xffff;
+ if (!(o->segment & (SEG_32BIT|SEG_64BIT)))
+ offs &= 0xffff;
/*
* add sync marker, if autosync is on
*/
if (autosync)
- add_sync(ins.oprs[i].offset, 0L);
+ add_sync(offs, 0L);
}
- if ((*p)->opd[i] & COLON)
+ if (t & COLON)
colon = TRUE;
else
colon = FALSE;
- if (((*p)->opd[i] & (REGISTER | FPUREG)) ||
- (ins.oprs[i].segment & SEG_RMREG)) {
- ins.oprs[i].basereg = whichreg((*p)->opd[i],
- ins.oprs[i].basereg, ins.rex);
- if ((*p)->opd[i] & TO)
+ if ((t & (REGISTER | FPUREG)) ||
+ (o->segment & SEG_RMREG)) {
+ enum reg_enum reg;
+ reg = whichreg(t, o->basereg, ins.rex);
+ if (t & TO)
slen += snprintf(output + slen, outbufsize - slen, "to ");
slen += snprintf(output + slen, outbufsize - slen, "%s",
- reg_names[ins.oprs[i].basereg -
- EXPR_REG_START]);
- } else if (!(UNITY & ~(*p)->opd[i])) {
+ reg_names[reg - EXPR_REG_START]);
+ } else if (!(UNITY & ~t)) {
output[slen++] = '1';
- } else if ((*p)->opd[i] & IMMEDIATE) {
- if ((*p)->opd[i] & BITS8) {
+ } else if (t & IMMEDIATE) {
+ if (t & BITS8) {
slen +=
snprintf(output + slen, outbufsize - slen, "byte ");
- if (ins.oprs[i].segment & SEG_SIGNED) {
- if (ins.oprs[i].offset < 0) {
- ins.oprs[i].offset *= -1;
+ if (o->segment & SEG_SIGNED) {
+ if (offs < 0) {
+ offs *= -1;
output[slen++] = '-';
} else
output[slen++] = '+';
}
- } else if ((*p)->opd[i] & BITS16) {
+ } else if (t & BITS16) {
slen +=
snprintf(output + slen, outbufsize - slen, "word ");
- } else if ((*p)->opd[i] & BITS32) {
+ } else if (t & BITS32) {
slen +=
snprintf(output + slen, outbufsize - slen, "dword ");
- } else if ((*p)->opd[i] & BITS64) {
+ } else if (t & BITS64) {
slen +=
snprintf(output + slen, outbufsize - slen, "qword ");
- } else if ((*p)->opd[i] & NEAR) {
+ } else if (t & NEAR) {
slen +=
snprintf(output + slen, outbufsize - slen, "near ");
- } else if ((*p)->opd[i] & SHORT) {
+ } else if (t & SHORT) {
slen +=
snprintf(output + slen, outbufsize - slen, "short ");
}
slen +=
snprintf(output + slen, outbufsize - slen, "0x%"PRIx64"",
- ins.oprs[i].offset);
- } else if (!(MEM_OFFS & ~(*p)->opd[i])) {
+ offs);
+ } else if (!(MEM_OFFS & ~t)) {
slen +=
snprintf(output + slen, outbufsize - slen, "[%s%s%s0x%"PRIx64"]",
(segover ? segover : ""),
(segover ? ":" : ""),
- (ins.oprs[i].addr_size ==
- 32 ? "dword " : ins.oprs[i].addr_size ==
- 16 ? "word " : ""), ins.oprs[i].offset);
+ (o->addr_size ==
+ 32 ? "dword " : o->addr_size ==
+ 16 ? "word " : ""), offs);
segover = NULL;
- } else if (!(REGMEM & ~(*p)->opd[i])) {
+ } else if (!(REGMEM & ~t)) {
int started = FALSE;
- if ((*p)->opd[i] & BITS8)
+ if (t & BITS8)
slen +=
snprintf(output + slen, outbufsize - slen, "byte ");
- if ((*p)->opd[i] & BITS16)
+ if (t & BITS16)
slen +=
snprintf(output + slen, outbufsize - slen, "word ");
- if ((*p)->opd[i] & BITS32)
+ if (t & BITS32)
slen +=
snprintf(output + slen, outbufsize - slen, "dword ");
- if ((*p)->opd[i] & BITS64)
+ if (t & BITS64)
slen +=
snprintf(output + slen, outbufsize - slen, "qword ");
- if ((*p)->opd[i] & BITS80)
+ if (t & BITS80)
slen +=
snprintf(output + slen, outbufsize - slen, "tword ");
- if ((*p)->opd[i] & FAR)
+ if (t & FAR)
slen += snprintf(output + slen, outbufsize - slen, "far ");
- if ((*p)->opd[i] & NEAR)
+ if (t & NEAR)
slen +=
snprintf(output + slen, outbufsize - slen, "near ");
output[slen++] = '[';
- if (ins.oprs[i].addr_size)
+ if (o->addr_size)
slen += snprintf(output + slen, outbufsize - slen, "%s",
- (ins.oprs[i].addr_size == 64 ? "qword " :
- ins.oprs[i].addr_size == 32 ? "dword " :
- ins.oprs[i].addr_size == 16 ? "word " :
+ (o->addr_size == 64 ? "qword " :
+ o->addr_size == 32 ? "dword " :
+ o->addr_size == 16 ? "word " :
""));
- if (ins.oprs[i].eaflags & EAF_REL)
+ if (o->eaflags & EAF_REL)
slen += snprintf(output + slen, outbufsize - slen, "rel ");
if (segover) {
slen +=
@@ -901,27 +965,27 @@ int32_t disasm(uint8_t *data, char *output, int outbufsize, int segsize,
segover);
segover = NULL;
}
- if (ins.oprs[i].basereg != -1) {
+ if (o->basereg != -1) {
slen += snprintf(output + slen, outbufsize - slen, "%s",
- reg_names[(ins.oprs[i].basereg -
+ reg_names[(o->basereg -
EXPR_REG_START)]);
started = TRUE;
}
- if (ins.oprs[i].indexreg != -1) {
+ if (o->indexreg != -1) {
if (started)
output[slen++] = '+';
slen += snprintf(output + slen, outbufsize - slen, "%s",
- reg_names[(ins.oprs[i].indexreg -
+ reg_names[(o->indexreg -
EXPR_REG_START)]);
- if (ins.oprs[i].scale > 1)
+ if (o->scale > 1)
slen +=
snprintf(output + slen, outbufsize - slen, "*%d",
- ins.oprs[i].scale);
+ o->scale);
started = TRUE;
}
- if (ins.oprs[i].segment & SEG_DISP8) {
+ if (o->segment & SEG_DISP8) {
int minus = 0;
- int8_t offset = ins.oprs[i].offset;
+ int8_t offset = offs;
if (offset < 0) {
minus = 1;
offset = -offset;
@@ -929,9 +993,9 @@ int32_t disasm(uint8_t *data, char *output, int outbufsize, int segsize,
slen +=
snprintf(output + slen, outbufsize - slen, "%s0x%"PRIx8"",
minus ? "-" : "+", offset);
- } else if (ins.oprs[i].segment & SEG_DISP16) {
+ } else if (o->segment & SEG_DISP16) {
int minus = 0;
- int16_t offset = ins.oprs[i].offset;
+ int16_t offset = offs;
if (offset < 0) {
minus = 1;
offset = -offset;
@@ -939,9 +1003,9 @@ int32_t disasm(uint8_t *data, char *output, int outbufsize, int segsize,
slen +=
snprintf(output + slen, outbufsize - slen, "%s0x%"PRIx16"",
minus ? "-" : started ? "+" : "", offset);
- } else if (ins.oprs[i].segment & SEG_DISP32) {
+ } else if (o->segment & SEG_DISP32) {
char *prefix = "";
- int32_t offset = ins.oprs[i].offset;
+ int32_t offset = offs;
if (offset < 0) {
offset = -offset;
prefix = "-";
diff --git a/doc/nasmdoc.src b/doc/nasmdoc.src
index 13ae013d..2530b2b5 100644
--- a/doc/nasmdoc.src
+++ b/doc/nasmdoc.src
@@ -1115,19 +1115,19 @@ indicate what size of \i{memory operand} it refers to.
\H{pseudop} \i{Pseudo-Instructions}
Pseudo-instructions are things which, though not real x86 machine
-instructions, are used in the instruction field anyway because
-that's the most convenient place to put them. The current
-pseudo-instructions are \i\c{DB}, \i\c{DW}, \i\c{DD}, \i\c{DQ} and
-\i\c{DT}, their \i{uninitialized} counterparts \i\c{RESB},
-\i\c{RESW}, \i\c{RESD}, \i\c{RESQ} and \i\c{REST}, the \i\c{INCBIN}
+instructions, are used in the instruction field anyway because that's
+the most convenient place to put them. The current pseudo-instructions
+are \i\c{DB}, \i\c{DW}, \i\c{DD}, \i\c{DQ}, \i\c{DT} and \i\c{DO};
+their \i{uninitialized} counterparts \i\c{RESB}, \i\c{RESW},
+\i\c{RESD}, \i\c{RESQ}, \i\c{REST} and \i\c{RESO}; the \i\c{INCBIN}
command, the \i\c{EQU} command, and the \i\c{TIMES} prefix.
\S{db} \c{DB} and friends: Declaring initialized Data
-\i\c{DB}, \i\c{DW}, \i\c{DD}, \i\c{DQ} and \i\c{DT} are used, much
-as in MASM, to declare initialized data in the output file. They can
-be invoked in a wide range of ways:
+\i\c{DB}, \i\c{DW}, \i\c{DD}, \i\c{DQ}, \i\c{DT} and \i\c{DO} are
+used, much as in MASM, to declare initialized data in the output
+file. They can be invoked in a wide range of ways:
\I{floating-point}\I{character constant}\I{string constant}
\c db 0x55 ; just the byte 0x55
@@ -1144,20 +1144,20 @@ be invoked in a wide range of ways:
\c dq 1.234567e20 ; double-precision float
\c dt 1.234567e20 ; extended-precision float
-\c{DT} does not accept \i{numeric constants} as operands.
+\c{DT} and \c{DO} do not accept \i{numeric constants} as operands.
\S{resb} \c{RESB} and friends: Declaring \i{Uninitialized} Data
-\i\c{RESB}, \i\c{RESW}, \i\c{RESD}, \i\c{RESQ} and \i\c{REST} are
-designed to be used in the BSS section of a module: they declare
-\e{uninitialized} storage space. Each takes a single operand, which
-is the number of bytes, words, doublewords or whatever to reserve.
-As stated in \k{qsother}, NASM does not support the MASM/TASM syntax
-of reserving uninitialized space by writing \I\c{?}\c{DW ?} or
-similar things: this is what it does instead. The operand to a
-\c{RESB}-type pseudo-instruction is a \i\e{critical expression}: see
-\k{crit}.
+\i\c{RESB}, \i\c{RESW}, \i\c{RESD}, \i\c{RESQ}, \i\c{REST} and
+\i\c{RESO} are designed to be used in the BSS section of a module:
+they declare \e{uninitialized} storage space. Each takes a single
+operand, which is the number of bytes, words, doublewords or whatever
+to reserve. As stated in \k{qsother}, NASM does not support the
+MASM/TASM syntax of reserving uninitialized space by writing
+\I\c{?}\c{DW ?} or similar things: this is what it does instead. The
+operand to a \c{RESB}-type pseudo-instruction is a \i\e{critical
+expression}: see \k{crit}.
For example:
@@ -1560,11 +1560,11 @@ invent one using the macro processor.
When assembling with the optimizer set to level 2 or higher (see
\k{opt-On}), NASM will use size specifiers (\c{BYTE}, \c{WORD},
-\c{DWORD}, \c{QWORD}, or \c{TWORD}), but will give them the smallest
-possible size. The keyword \c{STRICT} can be used to inhibit
+\c{DWORD}, \c{QWORD}, \c{TWORD} or \c{OWORD}), but will give them the
+smallest possible size. The keyword \c{STRICT} can be used to inhibit
optimization and force a particular operand to be emitted in the
-specified size. For example, with the optimizer on, and in
-\c{BITS 16} mode,
+specified size. For example, with the optimizer on, and in \c{BITS 16}
+mode,
\c push dword 33
diff --git a/insns.dat b/insns.dat
index 5043b0b3..61af07f5 100644
--- a/insns.dat
+++ b/insns.dat
@@ -14,6 +14,22 @@
; see the comment at the top of assemble.c. For a detailed description
; of the flags (fourth field), please see insns.h.
;
+
+; Special instructions...
+DB ignore ignore ignore
+DW ignore ignore ignore
+DD ignore ignore ignore
+DQ ignore ignore ignore
+DT ignore ignore ignore
+DO ignore ignore ignore
+RESB imm \340 8086
+RESW ignore ignore ignore
+RESD ignore ignore ignore
+RESQ ignore ignore ignore
+REST ignore ignore ignore
+RESO ignore ignore ignore
+
+; Conventional instructions
AAA void \1\x37 8086,NOLONG
AAD void \2\xD5\x0A 8086,NOLONG
AAD imm \1\xD5\24 8086,SB,NOLONG
@@ -47,14 +63,14 @@ ADC reg_eax,imm \321\1\x15\41 386,SM
ADC reg_rax,sbyte \321\1\x83\202\15 X64,SM,ND
ADC reg_rax,imm \321\1\x15\41 X64,SM
ADC rm8,imm \300\1\x80\202\21 8086,SM
-ADC rm16,imm \320\300\134\1\x81\202\131 8086,SM
-ADC rm32,imm \321\300\144\1\x81\202\141 386,SM
-ADC rm64,imm \324\300\144\1\x81\202\141 X64,SM
+ADC rm16,imm \320\300\145\1\x81\202\141 8086,SM
+ADC rm32,imm \321\300\155\1\x81\202\151 386,SM
+ADC rm64,imm \324\300\155\1\x81\202\151 X64,SM
ADC mem,imm8 \300\1\x80\202\21 8086,SM
-ADC mem,imm16 \320\300\134\1\x81\202\131 8086,SM
-ADC mem,imm32 \321\300\144\1\x81\202\141 386,SM
-ADD mem,reg8 \300\17\101 8086,SM
-ADD reg8,reg8 \17\101 8086
+ADC mem,imm16 \320\300\145\1\x81\202\141 8086,SM
+ADC mem,imm32 \321\300\155\1\x81\202\151 386,SM
+ADD mem,reg8 \300\170\101 8086,SM
+ADD reg8,reg8 \170\101 8086
ADD mem,reg16 \320\300\1\x01\101 8086,SM
ADD reg16,reg16 \320\1\x01\101 8086
ADD mem,reg32 \321\300\1\x01\101 386,SM
@@ -80,12 +96,12 @@ ADD reg_eax,imm \321\1\x05\41 386,SM
ADD reg_rax,sbyte \321\1\x83\200\15 X64,SM,ND
ADD reg_rax,imm \323\1\x05\41 X64,SM
ADD rm8,imm \300\1\x80\200\21 8086,SM
-ADD rm16,imm \320\300\134\1\x81\200\131 8086,SM
-ADD rm32,imm \321\300\144\1\x81\200\141 386,SM
-ADD rm64,imm \324\300\144\1\x81\200\141 X64,SM
+ADD rm16,imm \320\300\145\1\x81\200\141 8086,SM
+ADD rm32,imm \321\300\155\1\x81\200\151 386,SM
+ADD rm64,imm \324\300\155\1\x81\200\151 X64,SM
ADD mem,imm8 \300\1\x80\200\21 8086,SM
-ADD mem,imm16 \320\300\134\1\x81\200\131 8086,SM
-ADD mem,imm32 \321\300\144\1\x81\200\141 386,SM
+ADD mem,imm16 \320\300\145\1\x81\200\141 8086,SM
+ADD mem,imm32 \321\300\155\1\x81\200\151 386,SM
AND mem,reg8 \300\1\x20\101 8086,SM
AND reg8,reg8 \1\x20\101 8086
AND mem,reg16 \320\300\1\x21\101 8086,SM
@@ -113,12 +129,12 @@ AND reg_eax,imm \321\1\x25\41 386,SM
AND reg_rax,sbyte \321\1\x83\204\15 X64,SM,ND
AND reg_rax,imm \324\1\x25\41 X64,SM
AND rm8,imm \300\1\x80\204\21 8086,SM
-AND rm16,imm \320\300\134\1\x81\204\131 8086,SM
-AND rm32,imm \321\300\144\1\x81\204\141 386,SM
-AND rm64,imm \324\300\144\1\x81\204\141 X64,SM
+AND rm16,imm \320\300\145\1\x81\204\141 8086,SM
+AND rm32,imm \321\300\155\1\x81\204\151 386,SM
+AND rm64,imm \324\300\155\1\x81\204\151 X64,SM
AND mem,imm8 \300\1\x80\204\21 8086,SM
-AND mem,imm16 \320\300\134\1\x81\204\131 8086,SM
-AND mem,imm32 \321\300\144\1\x81\204\141 386,SM
+AND mem,imm16 \320\300\145\1\x81\204\141 8086,SM
+AND mem,imm32 \321\300\155\1\x81\204\151 386,SM
ARPL mem,reg16 \300\1\x63\101 286,PROT,SM,NOLONG
ARPL reg16,reg16 \1\x63\101 286,PROT,NOLONG
BOUND reg16,mem \320\301\1\x62\110 186,NOLONG
@@ -175,13 +191,13 @@ BTS rm32,imm \321\300\2\x0F\xBA\205\25 386,SB
BTS rm64,imm \324\300\2\x0F\xBA\205\25 X64,SB
CALL imm \322\1\xE8\64 8086
CALL imm|near \322\1\xE8\64 8086
-CALL imm|far \322\1\x9A\34\37 8086,ND,NOLONG
+CALL imm|far \322\1\x9A\34\74 8086,ND,NOLONG
CALL imm16 \320\1\xE8\64 8086
CALL imm16|near \320\1\xE8\64 8086
-CALL imm16|far \320\1\x9A\34\37 8086,ND,NOLONG
+CALL imm16|far \320\1\x9A\34\74 8086,ND,NOLONG
CALL imm32 \321\1\xE8\64 386
CALL imm32|near \321\1\xE8\64 386
-CALL imm32|far \321\1\x9A\34\37 386,ND,NOLONG
+CALL imm32|far \321\1\x9A\34\74 386,ND,NOLONG
CALL imm:imm \322\1\x9A\35\30 8086,NOLONG
CALL imm16:imm \320\1\x9A\31\30 8086,NOLONG
CALL imm:imm16 \320\1\x9A\31\30 8086,NOLONG
@@ -238,12 +254,12 @@ CMP reg_eax,imm \321\1\x3D\41 386,SM
CMP reg_rax,sbyte \321\1\x83\207\15 X64,SM,ND
CMP reg_rax,imm \321\1\x3D\41 X64,SM
CMP rm8,imm \300\1\x80\207\21 8086,SM
-CMP rm16,imm \320\300\134\1\x81\207\131 8086,SM
-CMP rm32,imm \321\300\144\1\x81\207\141 386,SM
-CMP rm64,imm \324\300\144\1\x81\207\141 X64,SM
+CMP rm16,imm \320\300\145\1\x81\207\141 8086,SM
+CMP rm32,imm \321\300\155\1\x81\207\151 386,SM
+CMP rm64,imm \324\300\155\1\x81\207\151 X64,SM
CMP mem,imm8 \300\1\x80\207\21 8086,SM
-CMP mem,imm16 \320\300\134\1\x81\207\131 8086,SM
-CMP mem,imm32 \321\300\144\1\x81\207\141 386,SM
+CMP mem,imm16 \320\300\145\1\x81\207\141 8086,SM
+CMP mem,imm32 \321\300\155\1\x81\207\151 386,SM
CMPSB void \335\1\xA6 8086
CMPSD void \335\321\1\xA7 386
CMPSQ void \335\324\1\xA7 X64
@@ -270,8 +286,6 @@ CWD void \320\1\x99 8086
CWDE void \321\1\x98 386
DAA void \1\x27 8086,NOLONG
DAS void \1\x2F 8086,NOLONG
-DB ignore ignore ignore
-DD ignore ignore ignore
DEC reg16 \320\10\x48 8086,NOLONG
DEC reg32 \321\10\x48 386,NOLONG
DEC rm8 \300\1\xFE\201 8086
@@ -282,9 +296,6 @@ DIV rm8 \300\1\xF6\206 8086
DIV rm16 \320\300\1\xF7\206 8086
DIV rm32 \321\300\1\xF7\206 386
DIV rm64 \324\300\1\xF7\206 X64
-DQ ignore ignore ignore
-DT ignore ignore ignore
-DW ignore ignore ignore
EMMS void \2\x0F\x77 PENT,MMX
ENTER imm,imm \1\xC8\30\25 186
EQU imm \0 8086
@@ -497,38 +508,38 @@ IMUL reg64,reg64 \324\2\x0F\xAF\110 X64
IMUL reg16,mem,imm8 \320\301\1\x6B\110\16 186,SM
IMUL reg16,mem,sbyte \320\301\1\x6B\110\16 186,SM,ND
IMUL reg16,mem,imm16 \320\301\1\x69\110\32 186,SM
-IMUL reg16,mem,imm \320\301\135\1\x69\110\132 186,SM,ND
+IMUL reg16,mem,imm \320\301\146\1\x69\110\142 186,SM,ND
IMUL reg16,reg16,imm8 \320\1\x6B\110\16 186
IMUL reg16,reg16,sbyte \320\1\x6B\110\16 186,SM,ND
IMUL reg16,reg16,imm16 \320\1\x69\110\32 186
-IMUL reg16,reg16,imm \320\135\1\x69\110\132 186,SM,ND
+IMUL reg16,reg16,imm \320\146\1\x69\110\142 186,SM,ND
IMUL reg32,mem,imm8 \321\301\1\x6B\110\16 386,SM
IMUL reg32,mem,sbyte \321\301\1\x6B\110\16 386,SM,ND
IMUL reg32,mem,imm32 \321\301\1\x69\110\42 386,SM
-IMUL reg32,mem,imm \321\301\145\1\x69\110\142 386,SM,ND
+IMUL reg32,mem,imm \321\301\156\1\x69\110\152 386,SM,ND
IMUL reg32,reg32,imm8 \321\1\x6B\110\16 386
IMUL reg32,reg32,sbyte \321\1\x6B\110\16 386,SM,ND
IMUL reg32,reg32,imm32 \321\1\x69\110\42 386
-IMUL reg32,reg32,imm \321\145\1\x69\110\142 386,SM,ND
+IMUL reg32,reg32,imm \321\156\1\x69\110\152 386,SM,ND
IMUL reg64,mem,imm8 \324\301\1\x6B\110\16 X64,SM
IMUL reg64,mem,sbyte \324\301\1\x6B\110\16 X64,SM,ND
IMUL reg64,mem,imm32 \324\301\1\x69\110\42 X64,SM
-IMUL reg64,mem,imm \324\301\145\1\x69\110\142 X64,SM,ND
+IMUL reg64,mem,imm \324\301\156\1\x69\110\152 X64,SM,ND
IMUL reg64,reg64,imm8 \324\1\x6B\110\16 X64
IMUL reg64,reg64,sbyte \324\1\x6B\110\16 X64,SM,ND
IMUL reg64,reg64,imm32 \324\1\x69\110\42 X64
-IMUL reg64,reg64,imm \324\145\1\x69\110\142 X64,SM,ND
+IMUL reg64,reg64,imm \324\156\1\x69\110\152 X64,SM,ND
IMUL reg16,imm8 \320\1\x6B\100\15 186
IMUL reg16,sbyte \320\1\x6B\100\15 186,SM,ND
IMUL reg16,imm16 \320\1\x69\100\31 186
-IMUL reg16,imm \320\134\1\x69\100\131 186,SM,ND
+IMUL reg16,imm \320\145\1\x69\100\141 186,SM,ND
IMUL reg32,imm8 \321\1\x6B\100\15 386
IMUL reg32,sbyte \321\1\x6B\100\15 386,SM,ND
IMUL reg32,imm32 \321\1\x69\100\41 386
-IMUL reg32,imm \321\144\1\x69\100\141 386,SM,ND
+IMUL reg32,imm \321\155\1\x69\100\151 386,SM,ND
IMUL reg64,sbyte \324\1\x6B\100\15 X64,SM,ND
IMUL reg64,imm32 \324\1\x69\100\41 X64
-IMUL reg64,imm \324\144\1\x69\100\141 X64,SM,ND
+IMUL reg64,imm \324\155\1\x69\100\151 X64,SM,ND
IN reg_al,imm \1\xE4\25 8086,SB
IN reg_ax,imm \320\1\xE5\25 8086,SB
IN reg_eax,imm \321\1\xE5\25 386,SB
@@ -564,13 +575,13 @@ JMP imm|short \1\xEB\50 8086
JMP imm \371\1\xEB\50 8086,ND
JMP imm \322\1\xE9\64 8086
JMP imm|near \322\1\xE9\64 8086,ND
-JMP imm|far \322\1\xEA\34\37 8086,ND,NOLONG
+JMP imm|far \322\1\xEA\34\74 8086,ND,NOLONG
JMP imm16 \320\1\xE9\64 8086
JMP imm16|near \320\1\xE9\64 8086,ND
-JMP imm16|far \320\1\xEA\34\37 8086,ND,NOLONG
+JMP imm16|far \320\1\xEA\34\74 8086,ND,NOLONG
JMP imm32 \321\1\xE9\64 386
JMP imm32|near \321\1\xE9\64 386,ND
-JMP imm32|far \321\1\xEA\34\37 386,ND,NOLONG
+JMP imm32|far \321\1\xEA\34\74 386,ND,NOLONG
JMP imm:imm \322\1\xEA\35\30 8086,NOLONG
JMP imm16:imm \320\1\xEA\31\30 8086,NOLONG
JMP imm:imm16 \320\1\xEA\31\30 8086,NOLONG
@@ -618,9 +629,9 @@ LGDT mem \300\2\x0F\x01\202 286,PRIV
LGS reg16,mem \320\301\2\x0F\xB5\110 386
LGS reg32,mem \321\301\2\x0F\xB5\110 386
LIDT mem \300\2\x0F\x01\203 286,PRIV
-LLDT mem \300\1\x0F\17\202 286,PROT,PRIV
-LLDT mem16 \300\1\x0F\17\202 286,PROT,PRIV
-LLDT reg16 \1\x0F\17\202 286,PROT,PRIV
+LLDT mem \300\1\x0F\170\202 286,PROT,PRIV
+LLDT mem16 \300\1\x0F\170\202 286,PROT,PRIV
+LLDT reg16 \1\x0F\170\202 286,PROT,PRIV
LMSW mem \300\2\x0F\x01\206 286,PRIV
LMSW mem16 \300\2\x0F\x01\206 286,PRIV
LMSW reg16 \2\x0F\x01\206 286,PRIV
@@ -658,9 +669,9 @@ LSL reg64,mem \324\301\2\x0F\x03\110 X64,SM
LSL reg64,reg64 \324\2\x0F\x03\110 X64,PROT
LSS reg16,mem \320\301\2\x0F\xB2\110 386
LSS reg32,mem \321\301\2\x0F\xB2\110 386
-LTR mem \300\1\x0F\17\203 286,PROT,PRIV
-LTR mem16 \300\1\x0F\17\203 286,PROT,PRIV,NOLONG
-LTR reg16 \1\x0F\17\203 286,PROT,PRIV,NOLONG
+LTR mem \300\1\x0F\170\203 286,PROT,PRIV
+LTR mem16 \300\1\x0F\170\203 286,PROT,PRIV,NOLONG
+LTR reg16 \1\x0F\170\203 286,PROT,PRIV,NOLONG
MFENCE void \3\x0F\xAE\xF0 X64,AMD
MONITOR void \3\x0F\x01\xC8 PRESCOTT
MONITOR reg_eax,reg_ecx,reg_edx \3\x0F\x01\xC8 PRESCOTT,ND
@@ -791,12 +802,12 @@ OR reg_eax,imm \321\1\x0D\41 386,SM
OR reg_rax,sbyte \321\1\x83\201\15 X64,SM,ND
OR reg_rax,imm \321\1\x0D\41 X64,SM
OR rm8,imm \300\1\x80\201\21 8086,SM
-OR rm16,imm \320\300\134\1\x81\201\131 8086,SM
-OR rm32,imm \321\300\144\1\x81\201\141 386,SM
-OR rm64,imm \324\300\144\1\x81\201\141 X64,SM
+OR rm16,imm \320\300\145\1\x81\201\141 8086,SM
+OR rm32,imm \321\300\155\1\x81\201\151 386,SM
+OR rm64,imm \324\300\155\1\x81\201\151 X64,SM
OR mem,imm8 \300\1\x80\201\21 8086,SM
-OR mem,imm16 \320\300\134\1\x81\201\131 8086,SM
-OR mem,imm32 \321\300\144\1\x81\201\141 386,SM
+OR mem,imm16 \320\300\145\1\x81\201\141 8086,SM
+OR mem,imm32 \321\300\155\1\x81\201\151 386,SM
OUT imm,reg_al \1\xE6\24 8086,SB
OUT imm,reg_ax \320\1\xE7\24 8086,SB
OUT imm,reg_eax \321\1\xE7\24 386,SB
@@ -990,9 +1001,9 @@ PUSH reg_dess \6 8086,NOLONG
PUSH reg_fsgs \1\x0F\7 386
PUSH imm8 \1\x6A\14 186
PUSH sbyte \1\x6A\14 186,ND
-PUSH imm16 \320\133\1\x68\130 186
-PUSH imm32 \321\143\1\x68\140 386,NOLONG
-PUSH imm64 \321\143\1\x68\140 X64
+PUSH imm16 \320\144\1\x68\140 186
+PUSH imm32 \321\154\1\x68\150 386,NOLONG
+PUSH imm64 \321\154\1\x68\150 X64
PUSH imm \1\x68\34 186
PUSHA void \322\1\x60 186,NOLONG
PUSHAD void \321\1\x60 386,NOLONG
@@ -1032,11 +1043,6 @@ RDMSR void \2\x0F\x32 PENT,PRIV
RDPMC void \2\x0F\x33 P6
RDTSC void \2\x0F\x31 PENT
RDTSCP void \3\x0F\x01\xF9 X64
-RESB imm \340 8086
-RESD ignore ignore ignore
-RESQ ignore ignore ignore
-REST ignore ignore ignore
-RESW ignore ignore ignore
RET void \1\xC3 8086
RET imm \1\xC2\30 8086,SW
RETF void \1\xCB 8086
@@ -1124,12 +1130,12 @@ SBB reg_eax,imm \321\1\x1D\41 386,SM
SBB reg_rax,sbyte \321\1\x83\203\15 X64,SM,ND
SBB reg_rax,imm \321\1\x1D\41 X64,SM
SBB rm8,imm \300\1\x80\203\21 8086,SM
-SBB rm16,imm \320\300\134\1\x81\203\131 8086,SM
-SBB rm32,imm \321\300\144\1\x81\203\141 386,SM
-SBB rm64,imm \324\300\144\1\x81\203\141 X64,SM
+SBB rm16,imm \320\300\145\1\x81\203\141 8086,SM
+SBB rm32,imm \321\300\155\1\x81\203\151 386,SM
+SBB rm64,imm \324\300\155\1\x81\203\151 X64,SM
SBB mem,imm8 \300\1\x80\203\21 8086,SM
-SBB mem,imm16 \320\300\134\1\x81\203\131 8086,SM
-SBB mem,imm32 \321\300\144\1\x81\203\141 386,SM
+SBB mem,imm16 \320\300\145\1\x81\203\141 8086,SM
+SBB mem,imm32 \321\300\155\1\x81\203\151 386,SM
SCASB void \335\1\xAE 8086
SCASD void \335\321\1\xAF 386
SCASQ void \335\324\1\xAF X64
@@ -1185,10 +1191,10 @@ SHRD reg32,reg32,reg_cl \321\2\x0F\xAD\101 386
SHRD mem,reg64,reg_cl \300\324\2\x0F\xAD\101 X64,SM
SHRD reg64,reg64,reg_cl \324\2\x0F\xAD\101 X64
SIDT mem \300\2\x0F\x01\201 286
-SLDT mem \300\1\x0F\17\200 286
-SLDT mem16 \300\1\x0F\17\200 286
-SLDT reg16 \320\1\x0F\17\200 286
-SLDT reg32 \321\1\x0F\17\200 386
+SLDT mem \300\1\x0F\170\200 286
+SLDT mem16 \300\1\x0F\170\200 286
+SLDT reg16 \320\1\x0F\170\200 286
+SLDT reg32 \321\1\x0F\170\200 386
SKINIT void \3\x0F\x01\xDE X64
SMI void \1\xF1 386,UNDOC
SMINT void \2\x0F\x38 P6,CYRIX
@@ -1206,11 +1212,11 @@ STOSB void \1\xAA 8086
STOSD void \321\1\xAB 386
STOSQ void \324\1\xAB X64
STOSW void \320\1\xAB 8086
-STR mem \300\1\x0F\17\201 286,PROT
-STR mem16 \300\1\x0F\17\201 286,PROT
-STR reg16 \320\1\x0F\17\201 286,PROT
-STR reg32 \321\1\x0F\17\201 386,PROT
-STR reg64 \324\1\x0F\17\201 X64
+STR mem \300\1\x0F\170\201 286,PROT
+STR mem16 \300\1\x0F\170\201 286,PROT
+STR reg16 \320\1\x0F\170\201 286,PROT
+STR reg32 \321\1\x0F\170\201 386,PROT
+STR reg64 \324\1\x0F\170\201 X64
SUB mem,reg8 \300\1\x28\101 8086,SM
SUB reg8,reg8 \1\x28\101 8086
SUB mem,reg16 \320\300\1\x29\101 8086,SM
@@ -1238,12 +1244,12 @@ SUB reg_eax,imm \321\1\x2D\41 386,SM
SUB reg_rax,sbyte \321\1\x83\205\15 X64,SM,ND
SUB reg_rax,imm \321\1\x2D\41 X64,SM
SUB rm8,imm \300\1\x80\205\21 8086,SM
-SUB rm16,imm \320\300\134\1\x81\205\131 8086,SM
-SUB rm32,imm \321\300\144\1\x81\205\141 386,SM
-SUB rm64,imm \324\300\144\1\x81\205\141 X64,SM
+SUB rm16,imm \320\300\145\1\x81\205\141 8086,SM
+SUB rm32,imm \321\300\155\1\x81\205\151 386,SM
+SUB rm64,imm \324\300\155\1\x81\205\151 X64,SM
SUB mem,imm8 \300\1\x80\205\21 8086,SM
-SUB mem,imm16 \320\300\134\1\x81\205\131 8086,SM
-SUB mem,imm32 \321\300\144\1\x81\205\141 386,SM
+SUB mem,imm16 \320\300\145\1\x81\205\141 8086,SM
+SUB mem,imm32 \321\300\155\1\x81\205\151 386,SM
SVDC mem80,reg_sreg \300\2\x0F\x78\101 486,CYRIX,SMM
SVLDT mem80 \300\2\x0F\x7A\200 486,CYRIX,SMM
SVTS mem80 \300\2\x0F\x7C\200 486,CYRIX,SMM
@@ -1290,12 +1296,12 @@ UMOV reg16,mem \320\301\2\x0F\x13\110 386,UNDOC,SM
UMOV reg16,reg16 \320\2\x0F\x13\110 386,UNDOC
UMOV reg32,mem \321\301\2\x0F\x13\110 386,UNDOC,SM
UMOV reg32,reg32 \321\2\x0F\x13\110 386,UNDOC
-VERR mem \300\1\x0F\17\204 286,PROT
-VERR mem16 \300\1\x0F\17\204 286,PROT
-VERR reg16 \1\x0F\17\204 286,PROT
-VERW mem \300\1\x0F\17\205 286,PROT
-VERW mem16 \300\1\x0F\17\205 286,PROT
-VERW reg16 \1\x0F\17\205 286,PROT
+VERR mem \300\1\x0F\170\204 286,PROT
+VERR mem16 \300\1\x0F\170\204 286,PROT
+VERR reg16 \1\x0F\170\204 286,PROT
+VERW mem \300\1\x0F\170\205 286,PROT
+VERW mem16 \300\1\x0F\170\205 286,PROT
+VERW reg16 \1\x0F\170\205 286,PROT
WAIT void \1\x9B 8086
FWAIT void \1\x9B 8086
WBINVD void \2\x0F\x09 486,PRIV
@@ -1363,12 +1369,12 @@ XOR reg_eax,imm \321\1\x35\41 386,SM
XOR reg_rax,sbyte \321\1\x83\206\15 X64,SM,ND
XOR reg_rax,imm \321\1\x35\41 X64,SM
XOR rm8,imm \300\1\x80\206\21 8086,SM
-XOR rm16,imm \320\300\134\1\x81\206\131 8086,SM
-XOR rm32,imm \321\300\144\1\x81\206\141 386,SM
-XOR rm64,imm \324\300\144\1\x81\206\141 X64,SM
+XOR rm16,imm \320\300\145\1\x81\206\141 8086,SM
+XOR rm32,imm \321\300\155\1\x81\206\151 386,SM
+XOR rm64,imm \324\300\155\1\x81\206\151 X64,SM
XOR mem,imm8 \300\1\x80\206\21 8086,SM
-XOR mem,imm16 \320\300\134\1\x81\206\131 8086,SM
-XOR mem,imm32 \321\300\144\1\x81\206\141 386,SM
+XOR mem,imm16 \320\300\145\1\x81\206\141 8086,SM
+XOR mem,imm32 \321\300\155\1\x81\206\151 386,SM
XSTORE void \3\x0F\xA7\xC0 P6,CYRIX
CMOVcc reg16,mem \320\301\1\x0F\330\x40\110 P6,SM
CMOVcc reg16,reg16 \320\1\x0F\330\x40\110 P6
@@ -2023,3 +2029,169 @@ PCMPGTQ xmmreg,xmmrm \366\3\x0F\x38\x37\110 SSE42
POPCNT reg16,rm16 \320\333\2\x0F\xB8\110 NEHALEM
POPCNT reg32,rm32 \321\333\2\x0F\xB8\110 NEHALEM
POPCNT reg64,rm32 \324\333\2\x0F\xB8\110 NEHALEM,X64
+
+; AMD SSE5 instructions
+
+; Four operands with DREX
+FMADDPS xmmreg,=0,xmmreg,xmmrm \160\2\x0F\x24\170\132 SSE5,AMD
+FMADDPS xmmreg,=0,xmmrm,xmmreg \164\2\x0F\x24\170\123 SSE5,AMD
+FMADDPS xmmreg,xmmreg,xmmrm,=0 \160\3\x0F\x24\x04\121 SSE5,AMD
+FMADDPS xmmreg,xmmrm,xmmreg,=0 \164\3\x0F\x24\x04\112 SSE5,AMD
+FMADDPD xmmreg,=0,xmmreg,xmmrm \160\3\x0F\x24\x01\132 SSE5,AMD
+FMADDPD xmmreg,=0,xmmrm,xmmreg \164\3\x0F\x24\x01\123 SSE5,AMD
+FMADDPD xmmreg,xmmreg,xmmrm,=0 \160\3\x0F\x24\x05\121 SSE5,AMD
+FMADDPD xmmreg,xmmrm,xmmreg,=0 \164\3\x0F\x24\x05\112 SSE5,AMD
+FMADDSS xmmreg,=0,xmmreg,xmmrm \160\3\x0F\x24\x02\132 SSE5,AMD
+FMADDSS xmmreg,=0,xmmrm,xmmreg \164\3\x0F\x24\x02\123 SSE5,AMD
+FMADDSS xmmreg,xmmreg,xmmrm,=0 \160\3\x0F\x24\x06\121 SSE5,AMD
+FMADDSS xmmreg,xmmrm,xmmreg,=0 \164\3\x0F\x24\x06\112 SSE5,AMD
+FMADDSD xmmreg,=0,xmmreg,xmmrm \160\3\x0F\x24\x03\132 SSE5,AMD
+FMADDSD xmmreg,=0,xmmrm,xmmreg \164\3\x0F\x24\x03\123 SSE5,AMD
+FMADDSD xmmreg,xmmreg,xmmrm,=0 \160\3\x0F\x24\x07\121 SSE5,AMD
+FMADDSD xmmreg,xmmrm,xmmreg,=0 \164\3\x0F\x24\x07\112 SSE5,AMD
+FMSUBPS xmmreg,=0,xmmreg,xmmrm \160\3\x0F\x24\x08\132 SSE5,AMD
+FMSUBPS xmmreg,=0,xmmrm,xmmreg \164\3\x0F\x24\x08\123 SSE5,AMD
+FMSUBPS xmmreg,xmmreg,xmmrm,=0 \160\3\x0F\x24\x0C\121 SSE5,AMD
+FMSUBPS xmmreg,xmmrm,xmmreg,=0 \164\3\x0F\x24\x0C\112 SSE5,AMD
+FMSUBPD xmmreg,=0,xmmreg,xmmrm \160\3\x0F\x24\x09\132 SSE5,AMD
+FMSUBPD xmmreg,=0,xmmrm,xmmreg \164\3\x0F\x24\x09\123 SSE5,AMD
+FMSUBPD xmmreg,xmmreg,xmmrm,=0 \160\3\x0F\x24\x0D\121 SSE5,AMD
+FMSUBPD xmmreg,xmmrm,xmmreg,=0 \164\3\x0F\x24\x0D\112 SSE5,AMD
+FMSUBSS xmmreg,=0,xmmreg,xmmrm \160\3\x0F\x24\x0A\132 SSE5,AMD
+FMSUBSS xmmreg,=0,xmmrm,xmmreg \164\3\x0F\x24\x0A\123 SSE5,AMD
+FMSUBSS xmmreg,xmmreg,xmmrm,=0 \160\3\x0F\x24\x0E\121 SSE5,AMD
+FMSUBSS xmmreg,xmmrm,xmmreg,=0 \164\3\x0F\x24\x0E\112 SSE5,AMD
+FMSUBSD xmmreg,=0,xmmreg,xmmrm \160\3\x0F\x24\x0B\132 SSE5,AMD
+FMSUBSD xmmreg,=0,xmmrm,xmmreg \164\3\x0F\x24\x0B\123 SSE5,AMD
+FMSUBSD xmmreg,xmmreg,xmmrm,=0 \160\3\x0F\x24\x0F\121 SSE5,AMD
+FMSUBSD xmmreg,xmmrm,xmmreg,=0 \164\3\x0F\x24\x0F\112 SSE5,AMD
+FMNADDPS xmmreg,=0,xmmreg,xmmrm \160\3\x0F\x24\x10\132 SSE5,AMD
+FMNADDPS xmmreg,=0,xmmrm,xmmreg \164\3\x0F\x24\x10\123 SSE5,AMD
+FMNADDPS xmmreg,xmmreg,xmmrm,=0 \160\3\x0F\x24\x14\121 SSE5,AMD
+FMNADDPS xmmreg,xmmrm,xmmreg,=0 \164\3\x0F\x24\x14\112 SSE5,AMD
+FMNADDPD xmmreg,=0,xmmreg,xmmrm \160\3\x0F\x24\x11\132 SSE5,AMD
+FMNADDPD xmmreg,=0,xmmrm,xmmreg \164\3\x0F\x24\x11\123 SSE5,AMD
+FMNADDPD xmmreg,xmmreg,xmmrm,=0 \160\3\x0F\x24\x15\121 SSE5,AMD
+FMNADDPD xmmreg,xmmrm,xmmreg,=0 \164\3\x0F\x24\x15\112 SSE5,AMD
+FMNADDSS xmmreg,=0,xmmreg,xmmrm \160\3\x0F\x24\x12\132 SSE5,AMD
+FMNADDSS xmmreg,=0,xmmrm,xmmreg \164\3\x0F\x24\x12\123 SSE5,AMD
+FMNADDSS xmmreg,xmmreg,xmmrm,=0 \160\3\x0F\x24\x16\121 SSE5,AMD
+FMNADDSS xmmreg,xmmrm,xmmreg,=0 \164\3\x0F\x24\x16\112 SSE5,AMD
+FMNADDSD xmmreg,=0,xmmreg,xmmrm \160\3\x0F\x24\x13\132 SSE5,AMD
+FMNADDSD xmmreg,=0,xmmrm,xmmreg \164\3\x0F\x24\x13\123 SSE5,AMD
+FMNADDSD xmmreg,xmmreg,xmmrm,=0 \160\3\x0F\x24\x17\121 SSE5,AMD
+FMNADDSD xmmreg,xmmrm,xmmreg,=0 \164\3\x0F\x24\x17\112 SSE5,AMD
+FMNSUBPS xmmreg,=0,xmmreg,xmmrm \160\3\x0F\x24\x18\132 SSE5,AMD
+FMNSUBPS xmmreg,=0,xmmrm,xmmreg \164\3\x0F\x24\x18\123 SSE5,AMD
+FMNSUBPS xmmreg,xmmreg,xmmrm,=0 \160\3\x0F\x24\x1C\121 SSE5,AMD
+FMNSUBPS xmmreg,xmmrm,xmmreg,=0 \164\3\x0F\x24\x1C\112 SSE5,AMD
+FMNSUBPD xmmreg,=0,xmmreg,xmmrm \160\3\x0F\x24\x19\132 SSE5,AMD
+FMNSUBPD xmmreg,=0,xmmrm,xmmreg \164\3\x0F\x24\x19\123 SSE5,AMD
+FMNSUBPD xmmreg,xmmreg,xmmrm,=0 \160\3\x0F\x24\x1D\121 SSE5,AMD
+FMNSUBPD xmmreg,xmmrm,xmmreg,=0 \164\3\x0F\x24\x1D\112 SSE5,AMD
+FMNSUBSS xmmreg,=0,xmmreg,xmmrm \160\3\x0F\x24\x1A\132 SSE5,AMD
+FMNSUBSS xmmreg,=0,xmmrm,xmmreg \164\3\x0F\x24\x1A\123 SSE5,AMD
+FMNSUBSS xmmreg,xmmreg,xmmrm,=0 \160\3\x0F\x24\x1E\121 SSE5,AMD
+FMNSUBSS xmmreg,xmmrm,xmmreg,=0 \164\3\x0F\x24\x1E\112 SSE5,AMD
+FMNSUBSD xmmreg,=0,xmmreg,xmmrm \160\3\x0F\x24\x1B\132 SSE5,AMD
+FMNSUBSD xmmreg,=0,xmmrm,xmmreg \164\3\x0F\x24\x1B\123 SSE5,AMD
+FMNSUBSD xmmreg,xmmreg,xmmrm,=0 \160\3\x0F\x24\x1F\121 SSE5,AMD
+FMNSUBSD xmmreg,xmmrm,xmmreg,=0 \164\3\x0F\x24\x1F\112 SSE5,AMD
+COMPS xmmreg,xmmreg,xmmrm,imm \160\3\x0F\x25\x2C\121\27 SSE5,AMD
+COMPD xmmreg,xmmreg,xmmrm,imm \160\3\x0F\x25\x2D\121\27 SSE5,AMD
+COMSS xmmreg,xmmreg,xmmrm,imm \160\3\x0F\x25\x2E\121\27 SSE5,AMD
+COMSD xmmreg,xmmreg,xmmrm,imm \160\3\x0F\x25\x2F\121\27 SSE5,AMD
+PCOMB xmmreg,xmmreg,xmmrm,imm \160\3\x0F\x25\x4C\121\27 SSE5,AMD
+PCOMW xmmreg,xmmreg,xmmrm,imm \160\3\x0F\x25\x4D\121\27 SSE5,AMD
+PCOMD xmmreg,xmmreg,xmmrm,imm \160\3\x0F\x25\x4E\121\27 SSE5,AMD
+PCOMQ xmmreg,xmmreg,xmmrm,imm \160\3\x0F\x25\x4F\121\27 SSE5,AMD
+PCOMUB xmmreg,xmmreg,xmmrm,imm \160\3\x0F\x25\x6C\121\27 SSE5,AMD
+PCOMUW xmmreg,xmmreg,xmmrm,imm \160\3\x0F\x25\x6D\121\27 SSE5,AMD
+PCOMUD xmmreg,xmmreg,xmmrm,imm \160\3\x0F\x25\x6E\121\27 SSE5,AMD
+PCOMUQ xmmreg,xmmreg,xmmrm,imm \160\3\x0F\x25\x6F\121\27 SSE5,AMD
+PERMPS xmmreg,=0,xmmreg,xmmrm \160\3\x0F\x24\x20\132 SSE5,AMD
+PERMPS xmmreg,=0,xmmrm,xmmreg \164\3\x0F\x24\x20\123 SSE5,AMD
+PERMPS xmmreg,xmmreg,xmmrm,=0 \160\3\x0F\x24\x24\121 SSE5,AMD
+PERMPS xmmreg,xmmrm,xmmreg,=0 \164\3\x0F\x24\x24\112 SSE5,AMD
+PERMPD xmmreg,=0,xmmreg,xmmrm \160\3\x0F\x24\x21\132 SSE5,AMD
+PERMPD xmmreg,=0,xmmrm,xmmreg \164\3\x0F\x24\x21\123 SSE5,AMD
+PERMPD xmmreg,xmmreg,xmmrm,=0 \160\3\x0F\x24\x25\121 SSE5,AMD
+PERMPD xmmreg,xmmrm,xmmreg,=0 \164\3\x0F\x24\x25\112 SSE5,AMD
+PCMOV xmmreg,=0,xmmreg,xmmrm \160\3\x0F\x24\x22\132 SSE5,AMD
+PCMOV xmmreg,=0,xmmrm,xmmreg \164\3\x0F\x24\x22\123 SSE5,AMD
+PCMOV xmmreg,xmmreg,xmmrm,=0 \160\3\x0F\x24\x26\121 SSE5,AMD
+PCMOV xmmreg,xmmrm,xmmreg,=0 \164\3\x0F\x24\x26\112 SSE5,AMD
+PPERM xmmreg,=0,xmmreg,xmmrm \160\3\x0F\x24\x23\132 SSE5,AMD
+PPERM xmmreg,=0,xmmrm,xmmreg \164\3\x0F\x24\x23\123 SSE5,AMD
+PPERM xmmreg,xmmreg,xmmrm,=0 \160\3\x0F\x24\x27\121 SSE5,AMD
+PPERM xmmreg,xmmrm,xmmreg,=0 \164\3\x0F\x24\x27\112 SSE5,AMD
+PMACSSWW xmmreg,xmmreg,xmmrm,=0 \160\3\x0F\x24\x85\121 SSE5,AMD
+PMACSWW xmmreg,xmmreg,xmmrm,=0 \160\3\x0F\x24\x95\121 SSE5,AMD
+PMACSSWD xmmreg,xmmreg,xmmrm,=0 \160\3\x0F\x24\x86\121 SSE5,AMD
+PMACSWD xmmreg,xmmreg,xmmrm,=0 \160\3\x0F\x24\x96\121 SSE5,AMD
+PMACSSDD xmmreg,xmmreg,xmmrm,=0 \160\3\x0F\x24\x8E\121 SSE5,AMD
+PMACSDD xmmreg,xmmreg,xmmrm,=0 \160\3\x0F\x24\x9E\121 SSE5,AMD
+PMACSSDQL xmmreg,xmmreg,xmmrm,=0 \160\3\x0F\x24\x87\121 SSE5,AMD
+PMACSDQL xmmreg,xmmreg,xmmrm,=0 \160\3\x0F\x24\x97\121 SSE5,AMD
+PMACSSDQH xmmreg,xmmreg,xmmrm,=0 \160\3\x0F\x24\x8F\121 SSE5,AMD
+PMACSDQH xmmreg,xmmreg,xmmrm,=0 \160\3\x0F\x24\x9F\121 SSE5,AMD
+PMADCSSWD xmmreg,xmmreg,xmmrm,=0 \160\3\x0F\x24\xA6\121 SSE5,AMD
+PMADCSWD xmmreg,xmmreg,xmmrm,=0 \160\3\x0F\x24\xB6\121 SSE5,AMD
+
+; Three operands with DREX
+PROTB xmmreg,xmmreg,xmmrm \160\3\x0F\x24\x40\121 SSE5,AMD
+PROTB xmmreg,xmmrm,xmmreg \164\3\x0F\x24\x40\112 SSE5,AMD
+PROTW xmmreg,xmmreg,xmmrm \160\3\x0F\x24\x41\121 SSE5,AMD
+PROTW xmmreg,xmmrm,xmmreg \164\3\x0F\x24\x41\112 SSE5,AMD
+PROTD xmmreg,xmmreg,xmmrm \160\3\x0F\x24\x42\121 SSE5,AMD
+PROTD xmmreg,xmmrm,xmmreg \164\3\x0F\x24\x42\112 SSE5,AMD
+PROTQ xmmreg,xmmreg,xmmrm \160\3\x0F\x24\x43\121 SSE5,AMD
+PROTQ xmmreg,xmmrm,xmmreg \164\3\x0F\x24\x43\112 SSE5,AMD
+PSHLB xmmreg,xmmreg,xmmrm \160\3\x0F\x24\x44\121 SSE5,AMD
+PSHLB xmmreg,xmmrm,xmmreg \164\3\x0F\x24\x44\112 SSE5,AMD
+PSHLW xmmreg,xmmreg,xmmrm \160\3\x0F\x24\x45\121 SSE5,AMD
+PSHLW xmmreg,xmmrm,xmmreg \164\3\x0F\x24\x45\112 SSE5,AMD
+PSHLD xmmreg,xmmreg,xmmrm \160\3\x0F\x24\x46\121 SSE5,AMD
+PSHLD xmmreg,xmmrm,xmmreg \164\3\x0F\x24\x46\112 SSE5,AMD
+PSHLQ xmmreg,xmmreg,xmmrm \160\3\x0F\x24\x47\121 SSE5,AMD
+PSHLQ xmmreg,xmmrm,xmmreg \164\3\x0F\x24\x47\112 SSE5,AMD
+PSHAB xmmreg,xmmreg,xmmrm \160\3\x0F\x24\x48\121 SSE5,AMD
+PSHAB xmmreg,xmmrm,xmmreg \164\3\x0F\x24\x48\112 SSE5,AMD
+PSHAW xmmreg,xmmreg,xmmrm \160\3\x0F\x24\x49\121 SSE5,AMD
+PSHAW xmmreg,xmmrm,xmmreg \164\3\x0F\x24\x49\112 SSE5,AMD
+PSHAD xmmreg,xmmreg,xmmrm \160\3\x0F\x24\x4A\121 SSE5,AMD
+PSHAD xmmreg,xmmrm,xmmreg \164\3\x0F\x24\x4A\112 SSE5,AMD
+PSHAQ xmmreg,xmmreg,xmmrm \160\3\x0F\x24\x4B\121 SSE5,AMD
+PSHAQ xmmreg,xmmrm,xmmreg \164\3\x0F\x24\x4B\112 SSE5,AMD
+
+; Non-DREX
+FRCZPS xmmreg,xmmrm \3\x0F\x7A\x10\110 SSE5,AMD
+FRCZPD xmmreg,xmmrm \3\x0F\x7A\x11\110 SSE5,AMD
+FRCZSS xmmreg,xmmrm \3\x0F\x7A\x12\110 SSE5,AMD
+FRCZSD xmmreg,xmmrm \3\x0F\x7A\x13\110 SSE5,AMD
+CVTPH2PS xmmreg,xmmrm \3\x0F\x7A\x30\110 SSE5,AMD,SQ
+CVTPS2PH xmmrm,xmmreg \3\x0F\x7A\x31\101 SSE5,AMD,SQ
+PHADDBW xmmreg,xmmrm \3\x0F\x7A\x41\110 SSE5,AMD
+PHADDBD xmmreg,xmmrm \3\x0F\x7A\x42\110 SSE5,AMD
+PHADDBQ xmmreg,xmmrm \3\x0F\x7A\x43\110 SSE5,AMD
+PHADDWD xmmreg,xmmrm \3\x0F\x7A\x46\110 SSE5,AMD
+PHADDWQ xmmreg,xmmrm \3\x0F\x7A\x47\110 SSE5,AMD
+PHADDDQ xmmreg,xmmrm \3\x0F\x7A\x4B\110 SSE5,AMD
+PHADDUBW xmmreg,xmmrm \3\x0F\x7A\x51\110 SSE5,AMD
+PHADDUBD xmmreg,xmmrm \3\x0F\x7A\x52\110 SSE5,AMD
+PHADDUBQ xmmreg,xmmrm \3\x0F\x7A\x53\110 SSE5,AMD
+PHADDUWD xmmreg,xmmrm \3\x0F\x7A\x56\110 SSE5,AMD
+PHADDUWQ xmmreg,xmmrm \3\x0F\x7A\x57\110 SSE5,AMD
+PHADDUDQ xmmreg,xmmrm \3\x0F\x7A\x5B\110 SSE5,AMD
+PHSUBBW xmmreg,xmmrm \3\x0F\x7A\x61\110 SSE5,AMD
+PHSUBWD xmmreg,xmmrm \3\x0F\x7A\x62\110 SSE5,AMD
+PHSUBDQ xmmreg,xmmrm \3\x0F\x7A\x63\110 SSE5,AMD
+PROTB xmmreg,xmmrm,imm \3\x0F\x7B\x40\110\26 SSE5,AMD
+PROTW xmmreg,xmmrm,imm \3\x0F\x7B\x41\110\26 SSE5,AMD
+PROTD xmmreg,xmmrm,imm \3\x0F\x7B\x42\110\26 SSE5,AMD
+PROTQ xmmreg,xmmrm,imm \3\x0F\x7B\x43\110\26 SSE5,AMD
+PTEST xmmreg,xmmrm \366\3\x0F\x38\x17\110 SSE5,AMD
+ROUNDPS xmmreg,xmmrm,imm \366\3\x0F\x3A\x08\110\26 SSE5,AMD
+ROUNDPD xmmreg,xmmrm,imm \366\3\x0F\x3A\x08\110\26 SSE5,AMD
+ROUNDSS xmmreg,xmmrm,imm \366\3\x0F\x3A\x08\110\26 SSE5,AMD
+ROUNDSD xmmreg,xmmrm,imm \366\3\x0F\x3A\x08\110\26 SSE5,AMD
diff --git a/insns.h b/insns.h
index 4deccf94..b025c7a5 100644
--- a/insns.h
+++ b/insns.h
@@ -9,7 +9,7 @@
#ifndef NASM_INSNS_H
#define NASM_INSNS_H
-#include "insnsi.h" /* instruction opcode enum */
+#include "nasm.h"
/* max length of any instruction, register name etc. */
#if MAX_INSLEN > 9 /* MAX_INSLEN defined in insnsi.h */
@@ -21,14 +21,23 @@
struct itemplate {
enum opcode opcode; /* the token, passed from "parser.c" */
int operands; /* number of operands */
- int32_t opd[3]; /* bit flags for operand types */
+ opflags_t opd[MAX_OPERANDS]; /* bit flags for operand types */
const char *code; /* the code it assembles to */
uint32_t flags; /* some flags */
};
+/* Disassembler table structure */
+/* If n == -1, then p points to another table of 256
+ struct disasm_index, otherwise p points to a list of n
+ struct itemplates to consider. */
+struct disasm_index {
+ const void *p;
+ int n;
+};
+
/* Tables for the assembler and disassembler, respectively */
extern const struct itemplate * const nasm_instructions[];
-extern const struct itemplate * const * const itable[];
+extern const struct disasm_index itable[256];
/*
* this define is used to signify the end of an itemplate
@@ -66,12 +75,15 @@ extern const struct itemplate * const * const itable[];
#define IF_SM2 0x00000002UL /* size match first two operands */
#define IF_SB 0x00000004UL /* unsized operands can't be non-byte */
#define IF_SW 0x00000008UL /* unsized operands can't be non-word */
-#define IF_SD 0x00000010UL /* unsized operands can't be non-dword */
-#define IF_SQ 0x00000020UL /* unsized operands can't be non-qword */
-#define IF_AR0 0x00000040UL /* SB, SW, SD applies to argument 0 */
-#define IF_AR1 0x00000080UL /* SB, SW, SD applies to argument 1 */
-#define IF_AR2 0x000000C0UL /* SB, SW, SD applies to argument 2 */
-#define IF_ARMASK 0x000000C0UL /* mask for unsized argument spec */
+#define IF_SD 0x0000000CUL /* unsized operands can't be non-dword */
+#define IF_SQ 0x00000010UL /* unsized operands can't be non-qword */
+#define IF_SO 0x00000014UL /* unsized operands can't be non-oword */
+#define IF_SMASK 0x0000001CUL /* mask for unsized argument size */
+#define IF_AR0 0x00000020UL /* SB, SW, SD applies to argument 0 */
+#define IF_AR1 0x00000040UL /* SB, SW, SD applies to argument 1 */
+#define IF_AR2 0x00000060UL /* SB, SW, SD applies to argument 2 */
+#define IF_AR3 0x00000080UL /* SB, SW, SD applies to argument 2 */
+#define IF_ARMASK 0x000000E0UL /* mask for unsized argument spec */
#define IF_PRIV 0x00000100UL /* it's a privileged instruction */
#define IF_SMM 0x00000200UL /* it's only valid in SMM */
#define IF_PROT 0x00000400UL /* it's protected mode only */
@@ -88,6 +100,7 @@ extern const struct itemplate * const * const itable[];
#define IF_SSSE3 0x00200000UL /* it's an SSSE3 instruction */
#define IF_SSE41 0x00400000UL /* it's an SSE4.1 instruction */
#define IF_SSE42 0x00800000UL /* it's an SSE4.2 instruction */
+#define IF_SSE5 0x00800000UL /* HACK NEED TO REORGANIZE THESE BITS */
#define IF_PMASK 0xFF000000UL /* the mask for processor types */
#define IF_PLEVEL 0x0F000000UL /* the mask for processor instr. level */
/* also the highest possible processor */
diff --git a/insns.pl b/insns.pl
index 421f16aa..356c183d 100644
--- a/insns.pl
+++ b/insns.pl
@@ -7,6 +7,10 @@
# redistributable under the licence given in the file "Licence"
# distributed in the NASM archive.
+# Opcode prefixes which need their own opcode tables
+# LONGER PREFIXES FIRST!
+@disasm_prefixes = qw(0F0F 0F24 0F25 0F38 0F3A 0F7A 0F);
+
print STDERR "Reading insns.dat...\n";
@args = ();
@@ -26,6 +30,8 @@ foreach $arg ( @ARGV ) {
$fname = "insns.dat" unless $fname = $args[0];
open (F, $fname) || die "unable to open $fname";
+%dinstables = ();
+
$line = 0;
$insns = 0;
while (<F>) {
@@ -50,9 +56,11 @@ while (<F>) {
}
if ($formatted && !$nd) {
push @big, $formatted;
- foreach $i (&startbyte($_[2])) {
- $aname = sprintf "dd_%02X",$i;
- push @$aname, $#big;
+ foreach $i (startseq($_[2])) {
+ if (!defined($dinstables{$i})) {
+ $dinstables{$i} = [];
+ }
+ push(@{$dinstables{$i}}, $#big);
}
}
}
@@ -102,26 +110,42 @@ if ( !defined($output) || $output eq 'd' ) {
print D "\n";
print D "static const struct itemplate instrux[] = {\n";
+ $n = 0;
foreach $j (@big) {
- print D " $j\n";
+ printf D " /* %4d */ %s\n", $n++, $j;
}
- print D " ITEMPLATE_END\n};\n\n";
-
- for ($c=0; $c<256; $c++) {
- $h = sprintf "%02X", $c;
- print D "static const struct itemplate * const itable_${h}[] = {\n";
- $aname = "dd_$h";
- foreach $j (@$aname) {
+ print D "};\n";
+
+ foreach $h (sort(keys(%dinstables))) {
+ print D "\nstatic const struct itemplate * const itable_${h}[] = {\n";
+ foreach $j (@{$dinstables{$h}}) {
print D " instrux + $j,\n";
}
- print D " NULL\n};\n\n";
- }
-
- print D "const struct itemplate * const * const itable[] = {\n";
- for ($c=0; $c<256; $c++) {
- printf D " itable_%02X,\n", $c;
+ print D "};\n";
}
+
+ foreach $h (@disasm_prefixes, '') {
+ $is_prefix{$h} = 1;
+ print D "\n";
+ print D "static " unless ($h eq '');
+ print D "const struct disasm_index ";
+ print D ($h eq '') ? 'itable' : "itable_$h";
+ print D "[256] = {\n";
+ for ($c = 0; $c < 256; $c++) {
+ $nn = sprintf("%s%02X", $h, $c);
+ if ($is_prefix{$nn}) {
+ die "$0: ambiguous decoding of $nn\n"
+ if (defined($dinstables{$nn}));
+ printf D " { itable_%s, -1 },\n", $nn;
+ } elsif (defined($dinstables{$nn})) {
+ printf D " { itable_%s, %u },\n",
+ $nn, scalar(@{$dinstables{$nn}});
+ } else {
+ printf D " { NULL, 0 },\n";
+ }
+ }
print D "};\n";
+ }
close D;
}
@@ -203,60 +227,130 @@ if ( !defined($output) || $output eq 'n' ) {
printf STDERR "Done: %d instructions\n", $insns;
sub format {
- local ($opcode, $operands, $codes, $flags) = @_;
- local $num, $nd = 0;
-
- return (undef, undef) if $operands eq "ignore";
+ my ($opcode, $operands, $codes, $flags) = @_;
+ my $num, $nd = 0;
- # format the operands
- $operands =~ s/:/|colon,/g;
- $operands =~ s/mem(\d+)/mem|bits$1/g;
- $operands =~ s/mem/memory/g;
- $operands =~ s/memory_offs/mem_offs/g;
- $operands =~ s/imm(\d+)/imm|bits$1/g;
- $operands =~ s/imm/immediate/g;
- $operands =~ s/rm(\d+)/rm_gpr|bits$1/g;
- $operands =~ s/mmxrm/rm_mmx/g;
- $operands =~ s/xmmrm/rm_xmm/g;
- $num = 3;
- $operands = '0,0,0', $num = 0 if $operands eq 'void';
- $operands .= ',0', $num-- while $operands !~ /,.*,/;
- $operands =~ tr/a-z/A-Z/;
+ return (undef, undef) if $operands eq "ignore";
+
+ # format the operands
+ $operands =~ s/:/|colon,/g;
+ $operands =~ s/mem(\d+)/mem|bits$1/g;
+ $operands =~ s/mem/memory/g;
+ $operands =~ s/memory_offs/mem_offs/g;
+ $operands =~ s/imm(\d+)/imm|bits$1/g;
+ $operands =~ s/imm/immediate/g;
+ $operands =~ s/rm(\d+)/rm_gpr|bits$1/g;
+ $operands =~ s/mmxrm/rm_mmx/g;
+ $operands =~ s/xmmrm/rm_xmm/g;
+ $operands =~ s/\=([0-9]+)/same_as|$1/g;
+ if ($operands eq 'void') {
+ @ops = ();
+ } else {
+ @ops = split(/\,/, $operands);
+ }
+ $num = scalar(@ops);
+ while (scalar(@ops) < 4) {
+ push(@ops, '0');
+ }
+ $operands = join(',', @ops);
+ $operands =~ tr/a-z/A-Z/;
+
+ # format the flags
+ $flags =~ s/,/|IF_/g;
+ $flags =~ s/(\|IF_ND|IF_ND\|)//, $nd = 1 if $flags =~ /IF_ND/;
+ $flags = "IF_" . $flags;
+
+ ("{I_$opcode, $num, {$operands}, \"$codes\", $flags},", $nd);
+}
- # format the flags
- $flags =~ s/,/|IF_/g;
- $flags =~ s/(\|IF_ND|IF_ND\|)//, $nd = 1 if $flags =~ /IF_ND/;
- $flags = "IF_" . $flags;
+sub hexlist($$$) {
+ my($prefix, $start, $n) = @_;
+ my $i;
+ my @l = ();
- ("{I_$opcode, $num, {$operands}, \"$codes\", $flags},", $nd);
+ for ($i = 0; $i < $n; $i++) {
+ push(@l, sprintf("%s%02X", $prefix, $start+$i));
+ }
+ return @l;
}
# Here we determine the range of possible starting bytes for a given
# instruction. We need only consider the codes:
# \1 \2 \3 mean literal bytes, of course
# \4 \5 \6 \7 mean PUSH/POP of segment registers: special case
-# \10 \11 \12 mean byte plus register value
-# \17 means byte zero
+# \1[0123] mean byte plus register value
+# \170 means byte zero
# \330 means byte plus condition code
# \0 or \340 mean give up and return empty set
-sub startbyte {
- local ($codes) = @_;
- local $word, @range;
+sub startseq($) {
+ my ($codestr) = @_;
+ my $word, @range;
+ my @codes = ();
+ my $c = $codestr;
+ my $c0, $c1, $i;
+ my $prefix = '';
+
+ # Although these are C-syntax strings, by convention they should have
+ # only octal escapes (for directives) and hexadecimal escapes
+ # (for verbatim bytes)
+ while ($c ne '') {
+ if ($c =~ /^\\x([0-9a-f]+)(.*)$/i) {
+ push(@codes, hex $1);
+ $c = $2;
+ next;
+ } elsif ($c =~ /^\\([0-7]{1,3})(.*)$/) {
+ push(@codes, oct $1);
+ $c = $2;
+ next;
+ } else {
+ die "$0: unknown code format in \"$codestr\"\n";
+ }
+ }
+
+ while ($c0 = shift(@codes)) {
+ $c1 = $codes[0];
+ if ($c0 == 01 || $c0 == 02 || $c0 == 03 || $c0 == 0170) {
+ # Fixed byte string
+ my $fbs = $prefix;
+ while (1) {
+ if ($c0 == 01 || $c0 == 02 || $c0 == 03) {
+ while ($c0--) {
+ $fbs .= sprintf("%02X", shift(@codes));
+ }
+ } elsif ($c0 == 0170) {
+ $fbs .= '00';
+ } else {
+ last;
+ }
+ $c0 = shift(@codes);
+ }
+
+ foreach $pfx (@disasm_prefixes) {
+ if ($fbs =~ /^$pfx(.*)$/) {
+ $prefix = $pfx;
+ $fbs = $1;
+ last;
+ }
+ }
- while (1) {
- die "couldn't get code in '$codes'" if $codes !~ /^(\\[^\\]+)(\\.*)?$/;
- $word = $1, $codes = $2;
- return (hex $1) if $word =~ /^\\[123]$/ && $codes =~ /^\\x(..)/;
- return (0x07, 0x17, 0x1F) if $word eq "\\4";
- return (0xA1, 0xA9) if $word eq "\\5";
- return (0x06, 0x0E, 0x16, 0x1E) if $word eq "\\6";
- return (0xA0, 0xA8) if $word eq "\\7";
- $start=hex $1, $r=8, last if $word =~ /^\\1[012]$/ && $codes =~/^\\x(..)/;
- return (0) if $word eq "\\17";
- $start=hex $1, $r=16, last if $word =~ /^\\330$/ && $codes =~ /^\\x(..)/;
- return () if $word eq "\\0" || $word eq "\\340";
+ if ($fbs ne '') {
+ return ($prefix.substr($fbs,0,2));
+ }
+ } elsif ($c0 == 04) {
+ return ("07", "17", "1F");
+ } elsif ($c0 == 05) {
+ return ("A1", "A9");
+ } elsif ($c0 == 06) {
+ return ("06", "0E", "16", "1E");
+ } elsif ($c0 == 07) {
+ return ("A0", "A8");
+ } elsif ($c0 >= 010 && $c0 <= 013) {
+ return hexlist($prefix, $c1, 8);
+ } elsif ($c0 == 0330) {
+ return hexlist($prefix, $c1, 16);
+ } elsif ($c0 == 0 || $c0 == 0340) {
+ return ();
+ }
}
- @range = ();
- push @range, $start++ while ($r-- > 0);
- @range;
+ return ();
}
diff --git a/nasm.h b/nasm.h
index 4ae93b61..f4afad36 100644
--- a/nasm.h
+++ b/nasm.h
@@ -375,7 +375,7 @@ enum {
*
* The bits are assigned as follows:
*
- * Bits 0-7: sizes
+ * Bits 0-7, 29: sizes
* 0: 8 bits (BYTE)
* 1: 16 bits (WORD)
* 2: 32 bits (DWORD)
@@ -384,6 +384,7 @@ enum {
* 5: FAR
* 6: NEAR
* 7: SHORT
+ * 29: 128 bits (OWORD)
*
* Bits 8-11 modifiers
* 8: TO
@@ -438,21 +439,29 @@ enum {
* 25: RM_MMX (MMXREG)
* 26: RM_XMM (XMMREG)
*
- * Bits 27-31 are currently unallocated.
+ * Bits 27-29 & 31 are currently unallocated.
+ *
+ * 30: SAME_AS
+ * Special flag only used in instruction patterns; means this operand
+ * has to be identical to another operand. Currently only supported
+ * for registers.
*/
+typedef uint32_t opflags_t;
+
/* Size, and other attributes, of the operand */
#define BITS8 0x00000001L
#define BITS16 0x00000002L
#define BITS32 0x00000004L
#define BITS64 0x00000008L /* x64 and FPU only */
#define BITS80 0x00000010L /* FPU only */
+#define BITS128 0x20000000L
#define FAR 0x00000020L /* grotty: this means 16:16 or */
/* 16:32, like in CALL/JMP */
#define NEAR 0x00000040L
#define SHORT 0x00000080L /* and this means what it says :) */
-#define SIZE_MASK 0x000000FFL /* all the size attributes */
+#define SIZE_MASK 0x200000FFL /* all the size attributes */
/* Modifiers */
#define MODIFIER_MASK 0x00000f00L
@@ -527,6 +536,9 @@ enum {
#define UNITY 0x00012000L /* for shift/rotate instructions */
#define SBYTE 0x00022000L /* for op r16/32,immediate instrs. */
+/* special flags */
+#define SAME_AS 0x40000000L
+
/* Register names automatically generated from regs.dat */
#include "regs.h"
@@ -540,6 +552,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 */
@@ -607,6 +621,7 @@ typedef struct extop { /* extended operand */
} extop;
#define MAXPREFIX 4
+#define MAX_OPERANDS 4
typedef struct { /* an instruction itself */
char *label; /* the label defined, or NULL */
@@ -616,12 +631,13 @@ typedef struct { /* an instruction itself */
enum ccode condition; /* the condition code, if Jcc/SETcc */
int operands; /* how many operands? 0-3
* (more if db et al) */
- operand oprs[3]; /* the operands, defined as above */
+ operand oprs[MAX_OPERANDS]; /* the operands, defined as above */
extop *eops; /* extended operands */
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 };
@@ -945,8 +961,8 @@ struct dfmt {
*/
enum special_tokens {
- S_ABS, S_BYTE, S_DWORD, S_FAR, S_LONG, S_NEAR, S_NOSPLIT, S_QWORD, S_REL,
- S_SHORT, S_STRICT, S_TO, S_TWORD, S_WORD
+ S_ABS, S_BYTE, S_DWORD, S_FAR, S_LONG, S_NEAR, S_NOSPLIT,
+ S_OWORD, S_QWORD, S_REL, S_SHORT, S_STRICT, S_TO, S_TWORD, S_WORD
};
/*
diff --git a/parser.c b/parser.c
index 1c7b8d9b..ca12a097 100644
--- a/parser.c
+++ b/parser.c
@@ -175,23 +175,25 @@ insn *parse_line(int pass, char *buffer, insn * result,
* For the moment, EQU has the same difficulty, so we'll
* include that.
*/
- if (result->opcode == I_RESB || result->opcode == I_RESW || result->opcode == I_RESD || result->opcode == I_RESQ || result->opcode == I_REST || result->opcode == I_EQU || result->opcode == I_INCBIN) { /* fbk */
+ if (result->opcode == I_RESB || result->opcode == I_RESW ||
+ result->opcode == I_RESD || result->opcode == I_RESQ ||
+ result->opcode == I_REST || result->opcode == I_RESO ||
+ result->opcode == I_EQU || result->opcode == I_INCBIN) {
critical = pass0;
} else
critical = (pass == 2 ? 2 : 0);
- if (result->opcode == I_DB ||
- result->opcode == I_DW ||
- result->opcode == I_DD ||
- result->opcode == I_DQ ||
- result->opcode == I_DT || result->opcode == I_INCBIN) {
+ if (result->opcode == I_DB || result->opcode == I_DW ||
+ result->opcode == I_DD || result->opcode == I_DQ ||
+ result->opcode == I_DT || result->opcode == I_DO ||
+ result->opcode == I_INCBIN) {
extop *eop, **tail = &result->eops, **fixptr;
int oper_num = 0;
result->eops_float = FALSE;
/*
- * Begin to read the DB/DW/DD/DQ/DT/INCBIN operands.
+ * Begin to read the DB/DW/DD/DQ/DT/DO/INCBIN operands.
*/
while (1) {
i = stdscan(NULL, &tokval);
@@ -234,6 +236,8 @@ insn *parse_line(int pass, char *buffer, insn * result,
eop->stringlen = 8;
else if (result->opcode == I_DT)
eop->stringlen = 10;
+ else if (result->opcode == I_DO)
+ eop->stringlen = 16;
else {
error(ERR_NONFATAL, "floating-point constant"
" encountered in `D%c' instruction",
@@ -245,8 +249,7 @@ insn *parse_line(int pass, char *buffer, insn * result,
*/
eop->stringlen = 0;
}
- eop =
- nasm_realloc(eop, sizeof(extop) + eop->stringlen);
+ eop = nasm_realloc(eop, sizeof(extop) + eop->stringlen);
tail = &eop->next;
*fixptr = eop;
eop->stringval = (char *)eop + sizeof(extop);
@@ -339,10 +342,10 @@ insn *parse_line(int pass, char *buffer, insn * result,
return result;
}
- /* right. Now we begin to parse the operands. There may be up to three
+ /* right. Now we begin to parse the operands. There may be up to four
* of these, separated by commas, and terminated by a zero token. */
- for (operand = 0; operand < 3; operand++) {
+ for (operand = 0; operand < MAX_OPERANDS; operand++) {
expr *value; /* used most of the time */
int mref; /* is this going to be a memory ref? */
int bracket; /* is it a [] mref, or a & mref? */
@@ -384,6 +387,11 @@ insn *parse_line(int pass, char *buffer, insn * result,
result->oprs[operand].type |= BITS80;
setsize = 1;
break;
+ case S_OWORD:
+ if (!setsize)
+ result->oprs[operand].type |= BITS128;
+ setsize = 1;
+ break;
case S_TO:
result->oprs[operand].type |= TO;
break;
@@ -440,6 +448,9 @@ insn *parse_line(int pass, char *buffer, insn * result,
case S_TWORD:
result->oprs[operand].type |= BITS80;
break;
+ case S_OWORD:
+ result->oprs[operand].type |= BITS128;
+ break;
default:
error(ERR_NONFATAL,
"invalid operand size specification");
@@ -751,7 +762,7 @@ insn *parse_line(int pass, char *buffer, insn * result,
result->oprs[operand++].type = 0;
/*
- * Transform RESW, RESD, RESQ, REST into RESB.
+ * Transform RESW, RESD, RESQ, REST, RESO into RESB.
*/
switch (result->opcode) {
case I_RESW:
@@ -770,6 +781,10 @@ insn *parse_line(int pass, char *buffer, insn * result,
result->opcode = I_RESB;
result->oprs[0].offset *= 10;
break;
+ case I_RESO:
+ result->opcode = I_RESB;
+ result->oprs[0].offset *= 16;
+ break;
default:
break;
}
diff --git a/perllib/phash.ph b/perllib/phash.ph
index 60334272..3bb3a05b 100644
--- a/perllib/phash.ph
+++ b/perllib/phash.ph
@@ -42,8 +42,8 @@ sub prehash($$$) {
foreach $c (unpack("C*", $key)) {
$ko1 = $k1; $ko2 = $k2;
- $k1 = int32(rot($ko1,$s0)-rot($ko2, $s1)+$c);
- $k2 = int32(rot($ko2,$s2)-rot($ko1, $s3)+$c);
+ $k1 = int32(rot($ko1,$s0)^int32(rot($ko2, $s1)+$c));
+ $k2 = int32(rot($ko2,$s2)^int32(rot($ko1, $s3)+$c));
}
# Create a bipartite graph...
diff --git a/pptok.pl b/pptok.pl
index a0425b7c..a835bf3e 100755
--- a/pptok.pl
+++ b/pptok.pl
@@ -191,8 +191,8 @@ if ($what eq 'c') {
print OUT " while ((c = *p++) != 0) {\n";
print OUT " uint32_t kn1, kn2;\n";
print OUT " c |= 0x20; /* convert to lower case */\n";
- printf OUT " kn1 = rot(k1,%2d) - rot(k2,%2d) + c;\n", ${$sv}[0], ${$sv}[1];
- printf OUT " kn2 = rot(k2,%2d) - rot(k1,%2d) + c;\n", ${$sv}[2], ${$sv}[3];
+ printf OUT " kn1 = rot(k1,%2d)^(rot(k2,%2d) + c);\n", ${$sv}[0], ${$sv}[1];
+ printf OUT " kn2 = rot(k2,%2d)^(rot(k1,%2d) + c);\n", ${$sv}[2], ${$sv}[3];
print OUT " k1 = kn1; k2 = kn2;\n";
print OUT " }\n";
print OUT "\n";
diff --git a/test/fmsub.asm b/test/fmsub.asm
new file mode 100644
index 00000000..7f087cd7
--- /dev/null
+++ b/test/fmsub.asm
@@ -0,0 +1,16 @@
+ bits 64
+
+ fmsubps xmm0,xmm0,xmm1,xmm2
+ fmsubps xmm0,xmm0,xmm1,[rax]
+ fmsubps xmm0,xmm0,xmm1,[rax+0x77]
+ fmsubps xmm0,xmm0,xmm1,[rax+0x7777]
+ fmsubps xmm1,xmm2,xmm3,xmm1
+ fmsubps xmm1,xmm2,[rax],xmm1
+ fmsubps xmm1,xmm2,[rax+0x77],xmm1
+ fmsubps xmm1,xmm2,[rax+0x7777],xmm1
+ fmsubps xmm0,[rax],xmm2,xmm0
+ fmsubps xmm0,[rax+0x77],xmm2,xmm0
+ fmsubps xmm0,[rax+0x7777],xmm2,xmm0
+ fmsubps xmm14,[rax],xmm2,xmm14
+ fmsubps xmm14,[rax+0x77],xmm2,xmm14
+ fmsubps xmm14,[rax+0x7777],xmm2,xmm14
diff --git a/tokens.dat b/tokens.dat
index 6acaba49..c84b8fb3 100644
--- a/tokens.dat
+++ b/tokens.dat
@@ -23,6 +23,7 @@ far
long
near
nosplit
+oword
qword
rel
short
diff --git a/tokhash.pl b/tokhash.pl
index 5f1a9f4c..9d5888be 100755
--- a/tokhash.pl
+++ b/tokhash.pl
@@ -187,8 +187,8 @@ print " const char *p = token;\n";
print "\n";
print " while ((c = *p++) != 0) {\n";
-printf " uint32_t kn1 = rot(k1,%2d) - rot(k2,%2d) + c;\n", ${$sv}[0], ${$sv}[1];
-printf " uint32_t kn2 = rot(k2,%2d) - rot(k1,%2d) + c;\n", ${$sv}[2], ${$sv}[3];
+printf " uint32_t kn1 = rot(k1,%2d)^(rot(k2,%2d) + c);\n", ${$sv}[0], ${$sv}[1];
+printf " uint32_t kn2 = rot(k2,%2d)^(rot(k1,%2d) + c);\n", ${$sv}[2], ${$sv}[3];
print " k1 = kn1; k2 = kn2;\n";
print " }\n";
print "\n";