diff options
author | H. Peter Anvin <hpa@zytor.com> | 2007-09-17 15:49:30 -0700 |
---|---|---|
committer | H. Peter Anvin <hpa@zytor.com> | 2007-09-17 15:49:30 -0700 |
commit | 7eb4a387939955c1c0b41fbc8b1216419082321f (patch) | |
tree | 74cb142c9ba6f8cd82a07679e8f447dd726c6b7d | |
parent | 3a7edd73a35ee09ee3cbf783f4d7b7148884603a (diff) | |
download | nasm-7eb4a387939955c1c0b41fbc8b1216419082321f.tar.gz nasm-7eb4a387939955c1c0b41fbc8b1216419082321f.tar.bz2 nasm-7eb4a387939955c1c0b41fbc8b1216419082321f.zip |
Initial support for four arguments per instruction
For SSE5, we will need to support four arguments per instruction.
-rw-r--r-- | assemble.c | 245 | ||||
-rw-r--r-- | disasm.c | 54 | ||||
-rw-r--r-- | insns.dat | 162 | ||||
-rw-r--r-- | insns.h | 18 | ||||
-rw-r--r-- | insns.pl | 69 | ||||
-rw-r--r-- | nasm.h | 3 |
6 files changed, 310 insertions, 241 deletions
@@ -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)) { + 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 - 0130].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 - 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)) { @@ -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) @@ -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 @@ -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 */ @@ -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"; } @@ -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) */ |