Initial support for four arguments per instruction

For SSE5, we will need to support four arguments per instruction.
This commit is contained in:
H. Peter Anvin 2007-09-17 15:49:30 -07:00
parent 3a7edd73a3
commit 7eb4a38793
6 changed files with 325 additions and 256 deletions

View File

@ -12,39 +12,36 @@
* (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.
* \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.)
* \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 +727,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 +808,48 @@ 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 0170:
length++;
break;
case 0300:
case 0301:
case 0302:
case 0303:
length += chsize(&ins->oprs[c - 0300], bits);
break;
case 0310:
@ -1020,21 +1038,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 +1069,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 +1089,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 +1108,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 +1124,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 +1137,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 +1150,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 +1164,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 +1179,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 +1189,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 +1206,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 +1227,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 +1241,95 @@ 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)) {
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 &&
(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);
offset += 2;
}
break;
case 0133:
case 0134:
case 0135:
EMIT_REX();
codes++;
bytes[0] = *codes++;
if (is_sbyte(ins, c - 0133, 16))
bytes[0] |= 2; /* s-bit */
out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
offset++;
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, 32)) {
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 - 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 - 0140].segment, ins->oprs[c - 0130].wrt);
offset += 2;
}
break;
case 0144:
case 0145:
case 0146:
case 0147:
EMIT_REX();
codes++;
bytes[0] = *codes++;
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 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 - 0140].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 0170:
bytes[0] = 0;
out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
offset += 1;
break;
case 0300:
case 0301:
case 0302:
case 0303:
if (chsize(&ins->oprs[c - 0300], bits)) {
*bytes = 0x67;
out(offset, segment, bytes,
@ -1537,7 +1576,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;
@ -1579,7 +1618,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 +1630,54 @@ static int matches(const struct itemplate *itemp, insn * instruction, int bits)
case IF_AR2:
i = 2;
break;
#if 0 /* Need to reorganize instruction flags to fit IF_AR3 */
case IF_AR3:
i = 3;
break;
#endif
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;
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;
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)) {

View File

@ -341,12 +341,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 +419,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 +428,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 +448,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 +468,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 +495,33 @@ 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);
} 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 == 0170) {
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) {
} else if (c >= 0300 && c <= 0303) {
a_used = TRUE;
} else if (c == 0310) {
if (asize != 16)

162
insns.dat
View File

@ -47,14 +47,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 +80,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 +113,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 +175,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 +238,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
@ -497,38 +497,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 +564,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 +618,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 +658,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
@ -788,12 +788,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
@ -987,9 +987,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
@ -1121,12 +1121,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
@ -1182,10 +1182,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
@ -1203,11 +1203,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
@ -1235,12 +1235,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
@ -1287,12 +1287,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
@ -1360,12 +1360,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

18
insns.h
View File

@ -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,7 +21,7 @@
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 */
int32_t opd[MAX_OPERANDS]; /* bit flags for operand types */
const char *code; /* the code it assembles to */
uint32_t flags; /* some flags */
};
@ -66,12 +66,14 @@ 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_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 */

View File

@ -203,45 +203,52 @@ if ( !defined($output) || $output eq 'n' ) {
printf STDERR "Done: %d instructions\n", $insns;
sub format {
local ($opcode, $operands, $codes, $flags) = @_;
local $num, $nd = 0;
my ($opcode, $operands, $codes, $flags) = @_;
my $num, $nd = 0;
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;
$num = 3;
$operands = '0,0,0', $num = 0 if $operands eq 'void';
$operands .= ',0', $num-- while $operands !~ /,.*,/;
$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);
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;
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);
}
# 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;
my ($codes) = @_;
my $word, @range;
while (1) {
die "couldn't get code in '$codes'" if $codes !~ /^(\\[^\\]+)(\\.*)?$/;
@ -251,8 +258,8 @@ sub startbyte {
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=8, last if $word =~ /^\\1[0123]$/ && $codes =~/^\\x(..)/;
return (0) if $word eq "\\170";
$start=hex $1, $r=16, last if $word =~ /^\\330$/ && $codes =~ /^\\x(..)/;
return () if $word eq "\\0" || $word eq "\\340";
}

3
nasm.h
View File

@ -607,6 +607,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,7 +617,7 @@ 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) */