diff options
author | H. Peter Anvin <hpa@zytor.com> | 2005-01-15 22:15:51 +0000 |
---|---|---|
committer | H. Peter Anvin <hpa@zytor.com> | 2005-01-15 22:15:51 +0000 |
commit | e2c80181b6a6338f0381fc9c44fae32d8b8a20fc (patch) | |
tree | f9919ba3c0489d886c9a79e73257ef6a4584aafc /disasm.c | |
parent | 5180bc8a598aa5bff7bfb3726771e5bf348e61a2 (diff) | |
download | nasm-e2c80181b6a6338f0381fc9c44fae32d8b8a20fc.tar.gz nasm-e2c80181b6a6338f0381fc9c44fae32d8b8a20fc.tar.bz2 nasm-e2c80181b6a6338f0381fc9c44fae32d8b8a20fc.zip |
Apply Nindent to all .c and .h files
Diffstat (limited to 'disasm.c')
-rw-r--r-- | disasm.c | 1333 |
1 files changed, 738 insertions, 595 deletions
@@ -33,72 +33,73 @@ extern struct itemplate **itable[]; #define SEG_NODISP 64 #define SEG_SIGNED 128 -static int whichreg(long regflags, int regval) +static int whichreg(long regflags, int regval) { #include "regdis.c" if (!(REG_AL & ~regflags)) - return R_AL; + return R_AL; if (!(REG_AX & ~regflags)) - return R_AX; + return R_AX; if (!(REG_EAX & ~regflags)) - return R_EAX; + return R_EAX; if (!(REG_DL & ~regflags)) - return R_DL; + return R_DL; if (!(REG_DX & ~regflags)) - return R_DX; + return R_DX; if (!(REG_EDX & ~regflags)) - return R_EDX; + return R_EDX; if (!(REG_CL & ~regflags)) - return R_CL; + return R_CL; if (!(REG_CX & ~regflags)) - return R_CX; + return R_CX; if (!(REG_ECX & ~regflags)) - return R_ECX; + return R_ECX; if (!(FPU0 & ~regflags)) - return R_ST0; + return R_ST0; if (!(REG_CS & ~regflags)) return (regval == 1) ? R_CS : 0; if (!(REG_DESS & ~regflags)) - return (regval == 0 || regval == 2 || regval == 3 ? sreg[regval] : 0); + return (regval == 0 || regval == 2 + || regval == 3 ? sreg[regval] : 0); if (!(REG_FSGS & ~regflags)) - return (regval == 4 || regval == 5 ? sreg[regval] : 0); + return (regval == 4 || regval == 5 ? sreg[regval] : 0); if (!(REG_SEG67 & ~regflags)) - return (regval == 6 || regval == 7 ? sreg[regval] : 0); + return (regval == 6 || regval == 7 ? sreg[regval] : 0); /* All the entries below look up regval in an 8-entry array */ if (regval < 0 || regval > 7) - return 0; - - if (!((REGMEM|BITS8) & ~regflags)) - return reg8[regval]; - if (!((REGMEM|BITS16) & ~regflags)) - return reg16[regval]; - if (!((REGMEM|BITS32) & ~regflags)) - return reg32[regval]; + return 0; + + if (!((REGMEM | BITS8) & ~regflags)) + return reg8[regval]; + if (!((REGMEM | BITS16) & ~regflags)) + return reg16[regval]; + if (!((REGMEM | BITS32) & ~regflags)) + return reg32[regval]; if (!(REG_SREG & ~regflags)) - return sreg[regval]; + return sreg[regval]; if (!(REG_CREG & ~regflags)) - return creg[regval]; + return creg[regval]; if (!(REG_DREG & ~regflags)) - return dreg[regval]; + return dreg[regval]; if (!(REG_TREG & ~regflags)) - return treg[regval]; + return treg[regval]; if (!(FPUREG & ~regflags)) - return fpureg[regval]; + return fpureg[regval]; if (!(MMXREG & ~regflags)) - return mmxreg[regval]; + return mmxreg[regval]; if (!(XMMREG & ~regflags)) - return xmmreg[regval]; + return xmmreg[regval]; return 0; } -static const char *whichcond(int condval) +static const char *whichcond(int condval) { static int conds[] = { - C_O, C_NO, C_C, C_NC, C_Z, C_NZ, C_NA, C_A, - C_S, C_NS, C_PE, C_PO, C_L, C_NL, C_NG, C_G + C_O, C_NO, C_C, C_NC, C_Z, C_NZ, C_NA, C_A, + C_S, C_NS, C_PE, C_PO, C_L, C_NL, C_NG, C_G }; return conditions[conds[condval]]; } @@ -106,139 +107,203 @@ static const char *whichcond(int condval) /* * Process an effective address (ModRM) specification. */ -static unsigned char *do_ea (unsigned char *data, int modrm, int asize, - int segsize, operand *op) +static unsigned char *do_ea(unsigned char *data, int modrm, int asize, + int segsize, operand * op) { int mod, rm, scale, index, base; mod = (modrm >> 6) & 03; rm = modrm & 07; - if (mod == 3) { /* pure register version */ - op->basereg = rm; - op->segment |= SEG_RMREG; - return data; + if (mod == 3) { /* pure register version */ + op->basereg = rm; + op->segment |= SEG_RMREG; + return data; } op->addr_size = 0; if (asize == 16) { - /* - * <mod> specifies the displacement size (none, byte or - * word), and <rm> specifies the register combination. - * Exception: mod=0,rm=6 does not specify [BP] as one might - * expect, but instead specifies [disp16]. - */ - op->indexreg = op->basereg = -1; - op->scale = 1; /* always, in 16 bits */ - switch (rm) { - case 0: op->basereg = R_BX; op->indexreg = R_SI; break; - case 1: op->basereg = R_BX; op->indexreg = R_DI; break; - case 2: op->basereg = R_BP; op->indexreg = R_SI; break; - case 3: op->basereg = R_BP; op->indexreg = R_DI; break; - case 4: op->basereg = R_SI; break; - case 5: op->basereg = R_DI; break; - case 6: op->basereg = R_BP; break; - case 7: op->basereg = R_BX; break; - } - if (rm == 6 && mod == 0) { /* special case */ - op->basereg = -1; - if (segsize != 16) - op->addr_size = 16; - mod = 2; /* fake disp16 */ - } - switch (mod) { - case 0: - op->segment |= SEG_NODISP; - break; - case 1: - op->segment |= SEG_DISP8; - op->offset = (signed char) *data++; - break; - case 2: - op->segment |= SEG_DISP16; - op->offset = *data++; - op->offset |= ((unsigned) *data++) << 8; - break; - } - return data; + /* + * <mod> specifies the displacement size (none, byte or + * word), and <rm> specifies the register combination. + * Exception: mod=0,rm=6 does not specify [BP] as one might + * expect, but instead specifies [disp16]. + */ + op->indexreg = op->basereg = -1; + op->scale = 1; /* always, in 16 bits */ + switch (rm) { + case 0: + op->basereg = R_BX; + op->indexreg = R_SI; + break; + case 1: + op->basereg = R_BX; + op->indexreg = R_DI; + break; + case 2: + op->basereg = R_BP; + op->indexreg = R_SI; + break; + case 3: + op->basereg = R_BP; + op->indexreg = R_DI; + break; + case 4: + op->basereg = R_SI; + break; + case 5: + op->basereg = R_DI; + break; + case 6: + op->basereg = R_BP; + break; + case 7: + op->basereg = R_BX; + break; + } + if (rm == 6 && mod == 0) { /* special case */ + op->basereg = -1; + if (segsize != 16) + op->addr_size = 16; + mod = 2; /* fake disp16 */ + } + switch (mod) { + case 0: + op->segment |= SEG_NODISP; + break; + case 1: + op->segment |= SEG_DISP8; + op->offset = (signed char)*data++; + break; + case 2: + op->segment |= SEG_DISP16; + op->offset = *data++; + op->offset |= ((unsigned)*data++) << 8; + break; + } + return data; } else { - /* - * Once again, <mod> specifies displacement size (this time - * none, byte or *dword*), while <rm> specifies the base - * register. Again, [EBP] is missing, replaced by a pure - * disp32 (this time that's mod=0,rm=*5*). However, rm=4 - * indicates not a single base register, but instead the - * presence of a SIB byte... - */ - op->indexreg = -1; - switch (rm) { - case 0: op->basereg = R_EAX; break; - case 1: op->basereg = R_ECX; break; - case 2: op->basereg = R_EDX; break; - case 3: op->basereg = R_EBX; break; - case 5: op->basereg = R_EBP; break; - case 6: op->basereg = R_ESI; break; - case 7: op->basereg = R_EDI; break; - } - if (rm == 5 && mod == 0) { - op->basereg = -1; - if (segsize != 32) - op->addr_size = 32; - mod = 2; /* fake disp32 */ - } - if (rm == 4) { /* process SIB */ - scale = (*data >> 6) & 03; - index = (*data >> 3) & 07; - base = *data & 07; - data++; - - op->scale = 1 << scale; - switch (index) { - case 0: op->indexreg = R_EAX; break; - case 1: op->indexreg = R_ECX; break; - case 2: op->indexreg = R_EDX; break; - case 3: op->indexreg = R_EBX; break; - case 4: op->indexreg = -1; break; - case 5: op->indexreg = R_EBP; break; - case 6: op->indexreg = R_ESI; break; - case 7: op->indexreg = R_EDI; break; - } - - switch (base) { - case 0: op->basereg = R_EAX; break; - case 1: op->basereg = R_ECX; break; - case 2: op->basereg = R_EDX; break; - case 3: op->basereg = R_EBX; break; - case 4: op->basereg = R_ESP; break; - case 6: op->basereg = R_ESI; break; - case 7: op->basereg = R_EDI; break; - case 5: - if (mod == 0) { - mod = 2; - op->basereg = -1; - } else - op->basereg = R_EBP; - break; - } - } - switch (mod) { - case 0: - op->segment |= SEG_NODISP; - break; - case 1: - op->segment |= SEG_DISP8; - op->offset = (signed char) *data++; - break; - case 2: - op->segment |= SEG_DISP32; - op->offset = *data++; - op->offset |= ((unsigned) *data++) << 8; - op->offset |= ((long) *data++) << 16; - op->offset |= ((long) *data++) << 24; - break; - } - return data; + /* + * Once again, <mod> specifies displacement size (this time + * none, byte or *dword*), while <rm> specifies the base + * register. Again, [EBP] is missing, replaced by a pure + * disp32 (this time that's mod=0,rm=*5*). However, rm=4 + * indicates not a single base register, but instead the + * presence of a SIB byte... + */ + op->indexreg = -1; + switch (rm) { + case 0: + op->basereg = R_EAX; + break; + case 1: + op->basereg = R_ECX; + break; + case 2: + op->basereg = R_EDX; + break; + case 3: + op->basereg = R_EBX; + break; + case 5: + op->basereg = R_EBP; + break; + case 6: + op->basereg = R_ESI; + break; + case 7: + op->basereg = R_EDI; + break; + } + if (rm == 5 && mod == 0) { + op->basereg = -1; + if (segsize != 32) + op->addr_size = 32; + mod = 2; /* fake disp32 */ + } + if (rm == 4) { /* process SIB */ + scale = (*data >> 6) & 03; + index = (*data >> 3) & 07; + base = *data & 07; + data++; + + op->scale = 1 << scale; + switch (index) { + case 0: + op->indexreg = R_EAX; + break; + case 1: + op->indexreg = R_ECX; + break; + case 2: + op->indexreg = R_EDX; + break; + case 3: + op->indexreg = R_EBX; + break; + case 4: + op->indexreg = -1; + break; + case 5: + op->indexreg = R_EBP; + break; + case 6: + op->indexreg = R_ESI; + break; + case 7: + op->indexreg = R_EDI; + break; + } + + switch (base) { + case 0: + op->basereg = R_EAX; + break; + case 1: + op->basereg = R_ECX; + break; + case 2: + op->basereg = R_EDX; + break; + case 3: + op->basereg = R_EBX; + break; + case 4: + op->basereg = R_ESP; + break; + case 6: + op->basereg = R_ESI; + break; + case 7: + op->basereg = R_EDI; + break; + case 5: + if (mod == 0) { + mod = 2; + op->basereg = -1; + } else + op->basereg = R_EBP; + break; + } + } + switch (mod) { + case 0: + op->segment |= SEG_NODISP; + break; + case 1: + op->segment |= SEG_DISP8; + op->offset = (signed char)*data++; + break; + case 2: + op->segment |= SEG_DISP32; + op->offset = *data++; + op->offset |= ((unsigned)*data++) << 8; + op->offset |= ((long)*data++) << 16; + op->offset |= ((long)*data++) << 24; + break; + } + return data; } } @@ -246,228 +311,253 @@ static unsigned char *do_ea (unsigned char *data, int modrm, int asize, * Determine whether the instruction template in t corresponds to the data * stream in data. Return the number of bytes matched if so. */ -static int matches (struct itemplate *t, unsigned char *data, int asize, - int osize, int segsize, int rep, insn *ins) +static int matches(struct itemplate *t, unsigned char *data, int asize, + int osize, int segsize, int rep, insn * ins) { - unsigned char * r = (unsigned char *)(t->code); - unsigned char * origdata = data; - int a_used = FALSE, o_used = FALSE; - int drep = 0; - - if ( rep == 0xF2 ) - drep = P_REPNE; - else if ( rep == 0xF3 ) - drep = P_REP; - - while (*r) - { - int c = *r++; - if (c >= 01 && c <= 03) { - while (c--) - if (*r++ != *data++) - return FALSE; - } - if (c == 04) { - switch (*data++) { - case 0x07: ins->oprs[0].basereg = 0; break; - case 0x17: ins->oprs[0].basereg = 2; break; - case 0x1F: ins->oprs[0].basereg = 3; break; - default: return FALSE; - } - } - if (c == 05) { - switch (*data++) { - case 0xA1: ins->oprs[0].basereg = 4; break; - case 0xA9: ins->oprs[0].basereg = 5; break; - default: return FALSE; - } - } - if (c == 06) { - switch (*data++) { - case 0x06: ins->oprs[0].basereg = 0; break; - case 0x0E: ins->oprs[0].basereg = 1; break; - case 0x16: ins->oprs[0].basereg = 2; break; - case 0x1E: ins->oprs[0].basereg = 3; break; - default: return FALSE; - } - } - if (c == 07) { - switch (*data++) { - case 0xA0: ins->oprs[0].basereg = 4; break; - case 0xA8: ins->oprs[0].basereg = 5; break; - default: return FALSE; - } - } - if (c >= 010 && c <= 012) { - int t = *r++, d = *data++; - if (d < t || d > t+7) - return FALSE; - else { - ins->oprs[c-010].basereg = d-t; - ins->oprs[c-010].segment |= SEG_RMREG; - } - } - if (c == 017) - if (*data++) - return FALSE; - if (c >= 014 && c <= 016) { - ins->oprs[c-014].offset = (signed char) *data++; - ins->oprs[c-014].segment |= SEG_SIGNED; - } - if (c >= 020 && c <= 022) - ins->oprs[c-020].offset = *data++; - if (c >= 024 && c <= 026) - ins->oprs[c-024].offset = *data++; - if (c >= 030 && c <= 032) { - ins->oprs[c-030].offset = *data++; - ins->oprs[c-030].offset |= (((unsigned) *data++) << 8); - } - if (c >= 034 && c <= 036) { - ins->oprs[c-034].offset = *data++; - ins->oprs[c-034].offset |= (((unsigned) *data++) << 8); - if (osize == 32) { - ins->oprs[c-034].offset |= (((long) *data++) << 16); - ins->oprs[c-034].offset |= (((long) *data++) << 24); - } - if (segsize != asize) - ins->oprs[c-034].addr_size = asize; - } - if (c >= 040 && c <= 042) { - ins->oprs[c-040].offset = *data++; - ins->oprs[c-040].offset |= (((unsigned) *data++) << 8); - ins->oprs[c-040].offset |= (((long) *data++) << 16); - ins->oprs[c-040].offset |= (((long) *data++) << 24); - } - if (c >= 044 && c <= 046) { - ins->oprs[c-044].offset = *data++; - ins->oprs[c-044].offset |= (((unsigned) *data++) << 8); - if (asize == 32) { - ins->oprs[c-044].offset |= (((long) *data++) << 16); - ins->oprs[c-044].offset |= (((long) *data++) << 24); - } - if (segsize != asize) - ins->oprs[c-044].addr_size = asize; - } - if (c >= 050 && c <= 052) { - ins->oprs[c-050].offset = (signed char) *data++; - ins->oprs[c-050].segment |= SEG_RELATIVE; - } - if (c >= 060 && c <= 062) { - ins->oprs[c-060].offset = *data++; - ins->oprs[c-060].offset |= (((unsigned) *data++) << 8); - ins->oprs[c-060].segment |= SEG_RELATIVE; - ins->oprs[c-060].segment &= ~SEG_32BIT; - } - if (c >= 064 && c <= 066) { - ins->oprs[c-064].offset = *data++; - ins->oprs[c-064].offset |= (((unsigned) *data++) << 8); - if (osize == 32) { - ins->oprs[c-064].offset |= (((long) *data++) << 16); - ins->oprs[c-064].offset |= (((long) *data++) << 24); - ins->oprs[c-064].segment |= SEG_32BIT; - } else - ins->oprs[c-064].segment &= ~SEG_32BIT; - ins->oprs[c-064].segment |= SEG_RELATIVE; - if (segsize != osize) { - ins->oprs[c-064].type = - (ins->oprs[c-064].type & NON_SIZE) - | ((osize == 16) ? BITS16 : BITS32); - } - } - if (c >= 070 && c <= 072) { - ins->oprs[c-070].offset = *data++; - ins->oprs[c-070].offset |= (((unsigned) *data++) << 8); - ins->oprs[c-070].offset |= (((long) *data++) << 16); - ins->oprs[c-070].offset |= (((long) *data++) << 24); - ins->oprs[c-070].segment |= SEG_32BIT | SEG_RELATIVE; - } - if (c >= 0100 && c < 0130) { - int modrm = *data++; - ins->oprs[c & 07].basereg = (modrm >> 3) & 07; - ins->oprs[c & 07].segment |= SEG_RMREG; - data = do_ea (data, modrm, asize, segsize, - &ins->oprs[(c >> 3) & 07]); - } - if (c >= 0130 && c <= 0132) { - ins->oprs[c-0130].offset = *data++; - ins->oprs[c-0130].offset |= (((unsigned) *data++) << 8); - } - if (c >= 0140 && c <= 0142) { - ins->oprs[c-0140].offset = *data++; - ins->oprs[c-0140].offset |= (((unsigned) *data++) << 8); - ins->oprs[c-0140].offset |= (((long) *data++) << 16); - ins->oprs[c-0140].offset |= (((long) *data++) << 24); - } - 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]); - } - if (c >= 0300 && c <= 0302) { - if (asize) - ins->oprs[c-0300].segment |= SEG_32BIT; - else - ins->oprs[c-0300].segment &= ~SEG_32BIT; - a_used = TRUE; - } - if (c == 0310) { - if (asize == 32) - return FALSE; - else - a_used = TRUE; - } - if (c == 0311) { - if (asize == 16) - return FALSE; - else - a_used = TRUE; - } - if (c == 0312) { - if (asize != segsize) - return FALSE; - else - a_used = TRUE; - } - if (c == 0320) { - if (osize == 32) - return FALSE; - else - o_used = TRUE; - } - if (c == 0321) { - if (osize == 16) - return FALSE; - else - o_used = TRUE; - } - if (c == 0322) { - if (osize != segsize) - return FALSE; - else - o_used = TRUE; - } - if (c == 0330) { - int t = *r++, d = *data++; - if (d < t || d > t+15) - return FALSE; - else - ins->condition = d - t; - } - if (c == 0331) { - if ( rep ) - return FALSE; - } - if (c == 0332) { - if (drep == P_REP) - drep = P_REPE; - } - if (c == 0333) { - if ( rep != 0xF3 ) - return FALSE; - drep = 0; - } + unsigned char *r = (unsigned char *)(t->code); + unsigned char *origdata = data; + int a_used = FALSE, o_used = FALSE; + int drep = 0; + + if (rep == 0xF2) + drep = P_REPNE; + else if (rep == 0xF3) + drep = P_REP; + + while (*r) { + int c = *r++; + if (c >= 01 && c <= 03) { + while (c--) + if (*r++ != *data++) + return FALSE; + } + if (c == 04) { + switch (*data++) { + case 0x07: + ins->oprs[0].basereg = 0; + break; + case 0x17: + ins->oprs[0].basereg = 2; + break; + case 0x1F: + ins->oprs[0].basereg = 3; + break; + default: + return FALSE; + } + } + if (c == 05) { + switch (*data++) { + case 0xA1: + ins->oprs[0].basereg = 4; + break; + case 0xA9: + ins->oprs[0].basereg = 5; + break; + default: + return FALSE; + } + } + if (c == 06) { + switch (*data++) { + case 0x06: + ins->oprs[0].basereg = 0; + break; + case 0x0E: + ins->oprs[0].basereg = 1; + break; + case 0x16: + ins->oprs[0].basereg = 2; + break; + case 0x1E: + ins->oprs[0].basereg = 3; + break; + default: + return FALSE; + } + } + if (c == 07) { + switch (*data++) { + case 0xA0: + ins->oprs[0].basereg = 4; + break; + case 0xA8: + ins->oprs[0].basereg = 5; + break; + default: + return FALSE; + } + } + if (c >= 010 && c <= 012) { + int t = *r++, d = *data++; + if (d < t || d > t + 7) + return FALSE; + else { + ins->oprs[c - 010].basereg = d - t; + ins->oprs[c - 010].segment |= SEG_RMREG; + } + } + if (c == 017) + if (*data++) + return FALSE; + if (c >= 014 && c <= 016) { + ins->oprs[c - 014].offset = (signed char)*data++; + ins->oprs[c - 014].segment |= SEG_SIGNED; + } + if (c >= 020 && c <= 022) + ins->oprs[c - 020].offset = *data++; + if (c >= 024 && c <= 026) + ins->oprs[c - 024].offset = *data++; + if (c >= 030 && c <= 032) { + ins->oprs[c - 030].offset = *data++; + ins->oprs[c - 030].offset |= (((unsigned)*data++) << 8); + } + if (c >= 034 && c <= 036) { + ins->oprs[c - 034].offset = *data++; + ins->oprs[c - 034].offset |= (((unsigned)*data++) << 8); + if (osize == 32) { + ins->oprs[c - 034].offset |= (((long)*data++) << 16); + ins->oprs[c - 034].offset |= (((long)*data++) << 24); + } + if (segsize != asize) + ins->oprs[c - 034].addr_size = asize; + } + if (c >= 040 && c <= 042) { + ins->oprs[c - 040].offset = *data++; + ins->oprs[c - 040].offset |= (((unsigned)*data++) << 8); + ins->oprs[c - 040].offset |= (((long)*data++) << 16); + ins->oprs[c - 040].offset |= (((long)*data++) << 24); + } + if (c >= 044 && c <= 046) { + ins->oprs[c - 044].offset = *data++; + ins->oprs[c - 044].offset |= (((unsigned)*data++) << 8); + if (asize == 32) { + ins->oprs[c - 044].offset |= (((long)*data++) << 16); + ins->oprs[c - 044].offset |= (((long)*data++) << 24); + } + if (segsize != asize) + ins->oprs[c - 044].addr_size = asize; + } + if (c >= 050 && c <= 052) { + ins->oprs[c - 050].offset = (signed char)*data++; + ins->oprs[c - 050].segment |= SEG_RELATIVE; + } + if (c >= 060 && c <= 062) { + ins->oprs[c - 060].offset = *data++; + ins->oprs[c - 060].offset |= (((unsigned)*data++) << 8); + ins->oprs[c - 060].segment |= SEG_RELATIVE; + ins->oprs[c - 060].segment &= ~SEG_32BIT; + } + if (c >= 064 && c <= 066) { + ins->oprs[c - 064].offset = *data++; + ins->oprs[c - 064].offset |= (((unsigned)*data++) << 8); + if (osize == 32) { + ins->oprs[c - 064].offset |= (((long)*data++) << 16); + ins->oprs[c - 064].offset |= (((long)*data++) << 24); + ins->oprs[c - 064].segment |= SEG_32BIT; + } else + ins->oprs[c - 064].segment &= ~SEG_32BIT; + ins->oprs[c - 064].segment |= SEG_RELATIVE; + if (segsize != osize) { + ins->oprs[c - 064].type = + (ins->oprs[c - 064].type & NON_SIZE) + | ((osize == 16) ? BITS16 : BITS32); + } + } + if (c >= 070 && c <= 072) { + ins->oprs[c - 070].offset = *data++; + ins->oprs[c - 070].offset |= (((unsigned)*data++) << 8); + ins->oprs[c - 070].offset |= (((long)*data++) << 16); + ins->oprs[c - 070].offset |= (((long)*data++) << 24); + ins->oprs[c - 070].segment |= SEG_32BIT | SEG_RELATIVE; + } + if (c >= 0100 && c < 0130) { + int modrm = *data++; + ins->oprs[c & 07].basereg = (modrm >> 3) & 07; + ins->oprs[c & 07].segment |= SEG_RMREG; + data = do_ea(data, modrm, asize, segsize, + &ins->oprs[(c >> 3) & 07]); + } + if (c >= 0130 && c <= 0132) { + ins->oprs[c - 0130].offset = *data++; + ins->oprs[c - 0130].offset |= (((unsigned)*data++) << 8); + } + if (c >= 0140 && c <= 0142) { + ins->oprs[c - 0140].offset = *data++; + ins->oprs[c - 0140].offset |= (((unsigned)*data++) << 8); + ins->oprs[c - 0140].offset |= (((long)*data++) << 16); + ins->oprs[c - 0140].offset |= (((long)*data++) << 24); + } + 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]); + } + if (c >= 0300 && c <= 0302) { + if (asize) + ins->oprs[c - 0300].segment |= SEG_32BIT; + else + ins->oprs[c - 0300].segment &= ~SEG_32BIT; + a_used = TRUE; + } + if (c == 0310) { + if (asize == 32) + return FALSE; + else + a_used = TRUE; + } + if (c == 0311) { + if (asize == 16) + return FALSE; + else + a_used = TRUE; + } + if (c == 0312) { + if (asize != segsize) + return FALSE; + else + a_used = TRUE; + } + if (c == 0320) { + if (osize == 32) + return FALSE; + else + o_used = TRUE; + } + if (c == 0321) { + if (osize == 16) + return FALSE; + else + o_used = TRUE; + } + if (c == 0322) { + if (osize != segsize) + return FALSE; + else + o_used = TRUE; + } + if (c == 0330) { + int t = *r++, d = *data++; + if (d < t || d > t + 15) + return FALSE; + else + ins->condition = d - t; + } + if (c == 0331) { + if (rep) + return FALSE; + } + if (c == 0332) { + if (drep == P_REP) + drep = P_REPE; + } + if (c == 0333) { + if (rep != 0xF3) + return FALSE; + drep = 0; + } } /* @@ -477,15 +567,15 @@ static int matches (struct itemplate *t, unsigned char *data, int asize, if (drep) ins->prefixes[ins->nprefix++] = drep; if (!a_used && asize != segsize) - ins->prefixes[ins->nprefix++] = (asize == 16 ? P_A16 : P_A32); + ins->prefixes[ins->nprefix++] = (asize == 16 ? P_A16 : P_A32); if (!o_used && osize != segsize) - ins->prefixes[ins->nprefix++] = (osize == 16 ? P_O16 : P_O32); + ins->prefixes[ins->nprefix++] = (osize == 16 ? P_O16 : P_O32); return data - origdata; } -long disasm (unsigned char *data, char *output, int outbufsize, int segsize, - long offset, int autosync, unsigned long prefer) +long disasm(unsigned char *data, char *output, int outbufsize, int segsize, + long offset, int autosync, unsigned long prefer) { struct itemplate **p, **best_p; int length, best_length = 0; @@ -504,251 +594,304 @@ long disasm (unsigned char *data, char *output, int outbufsize, int segsize, rep = lock = 0; origdata = data; for (;;) { - if (*data == 0xF3 || *data == 0xF2) - rep = *data++; - else if (*data == 0xF0) - lock = *data++; - else if (*data == 0x2E || *data == 0x36 || *data == 0x3E || - *data == 0x26 || *data == 0x64 || *data == 0x65) { - switch (*data++) { - case 0x2E: segover = "cs"; break; - case 0x36: segover = "ss"; break; - case 0x3E: segover = "ds"; break; - case 0x26: segover = "es"; break; - case 0x64: segover = "fs"; break; - case 0x65: segover = "gs"; break; - } - } else if (*data == 0x66) - osize = 48 - segsize, data++; - else if (*data == 0x67) - asize = 48 - segsize, data++; - else - break; + if (*data == 0xF3 || *data == 0xF2) + rep = *data++; + else if (*data == 0xF0) + lock = *data++; + else if (*data == 0x2E || *data == 0x36 || *data == 0x3E || + *data == 0x26 || *data == 0x64 || *data == 0x65) { + switch (*data++) { + case 0x2E: + segover = "cs"; + break; + case 0x36: + segover = "ss"; + break; + case 0x3E: + segover = "ds"; + break; + case 0x26: + segover = "es"; + break; + case 0x64: + segover = "fs"; + break; + case 0x65: + segover = "gs"; + break; + } + } else if (*data == 0x66) + osize = 48 - segsize, data++; + else if (*data == 0x67) + asize = 48 - segsize, data++; + else + break; } tmp_ins.oprs[0].segment = tmp_ins.oprs[1].segment = - tmp_ins.oprs[2].segment = - tmp_ins.oprs[0].addr_size = tmp_ins.oprs[1].addr_size = - tmp_ins.oprs[2].addr_size = (segsize == 16 ? 0 : SEG_32BIT); + tmp_ins.oprs[2].segment = + tmp_ins.oprs[0].addr_size = tmp_ins.oprs[1].addr_size = + tmp_ins.oprs[2].addr_size = (segsize == 16 ? 0 : SEG_32BIT); tmp_ins.condition = -1; - best = ~0UL; /* Worst possible */ + best = ~0UL; /* Worst possible */ best_p = NULL; for (p = itable[*data]; *p; p++) { - if ( (length = matches(*p, data, asize, osize, - segsize, rep, &tmp_ins)) ) { - works = TRUE; - /* - * Final check to make sure the types of r/m match up. - */ - 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) && - !(REGNORM & ~(*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))) { - works = FALSE; - break; - } - } - - if (works) { - goodness = ((*p)->flags & IF_PFMASK) ^ prefer; - if ( goodness < best ) { - /* This is the best one found so far */ - best = goodness; - best_p = p; - best_length = length; - ins = tmp_ins; - } - } - } + if ((length = matches(*p, data, asize, osize, + segsize, rep, &tmp_ins))) { + works = TRUE; + /* + * Final check to make sure the types of r/m match up. + */ + 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) && + !(REGNORM & ~(*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))) { + works = FALSE; + break; + } + } + + if (works) { + goodness = ((*p)->flags & IF_PFMASK) ^ prefer; + if (goodness < best) { + /* This is the best one found so far */ + best = goodness; + best_p = p; + best_length = length; + ins = tmp_ins; + } + } + } } if (!best_p) - return 0; /* no instruction was matched */ + return 0; /* no instruction was matched */ /* Pick the best match */ - p = best_p; + p = best_p; length = best_length; slen = 0; /* TODO: snprintf returns the value that the string would have if - * the buffer were long enough, and not the actual length of - * the returned string, so each instance of using the return - * value of snprintf should actually be checked to assure that - * the return value is "sane." Maybe a macro wrapper could - * be used for that purpose. - */ + * the buffer were long enough, and not the actual length of + * the returned string, so each instance of using the return + * value of snprintf should actually be checked to assure that + * the return value is "sane." Maybe a macro wrapper could + * be used for that purpose. + */ if (lock) - slen += snprintf(output+slen, outbufsize-slen, "lock "); + slen += snprintf(output + slen, outbufsize - slen, "lock "); for (i = 0; i < ins.nprefix; i++) - switch (ins.prefixes[i]) { - case P_REP: slen += snprintf(output+slen, outbufsize-slen, "rep "); break; - case P_REPE: slen += snprintf(output+slen, outbufsize-slen, "repe "); break; - case P_REPNE: slen += snprintf(output+slen, outbufsize-slen, "repne "); break; - case P_A16: slen += snprintf(output+slen, outbufsize-slen, "a16 "); break; - case P_A32: slen += snprintf(output+slen, outbufsize-slen, "a32 "); break; - case P_O16: slen += snprintf(output+slen, outbufsize-slen, "o16 "); break; - case P_O32: slen += snprintf(output+slen, outbufsize-slen, "o32 "); break; - } + switch (ins.prefixes[i]) { + case P_REP: + slen += snprintf(output + slen, outbufsize - slen, "rep "); + break; + case P_REPE: + slen += snprintf(output + slen, outbufsize - slen, "repe "); + break; + case P_REPNE: + slen += snprintf(output + slen, outbufsize - slen, "repne "); + break; + case P_A16: + slen += snprintf(output + slen, outbufsize - slen, "a16 "); + break; + case P_A32: + slen += snprintf(output + slen, outbufsize - slen, "a32 "); + break; + case P_O16: + slen += snprintf(output + slen, outbufsize - slen, "o16 "); + break; + case P_O32: + slen += snprintf(output + slen, outbufsize - slen, "o32 "); + break; + } for (i = 0; i < elements(ico); i++) - if ((*p)->opcode == ico[i]) { - slen += snprintf(output+slen, outbufsize-slen, "%s%s", icn[i], - whichcond(ins.condition)); - break; - } + if ((*p)->opcode == ico[i]) { + slen += + snprintf(output + slen, outbufsize - slen, "%s%s", icn[i], + whichcond(ins.condition)); + break; + } if (i >= elements(ico)) - slen += snprintf(output+slen, outbufsize-slen, "%s", insn_names[(*p)->opcode]); + slen += + snprintf(output + slen, outbufsize - slen, "%s", + insn_names[(*p)->opcode]); colon = FALSE; - length += data - origdata; /* fix up for prefixes */ - for (i=0; i<(*p)->operands; i++) { - output[slen++] = (colon ? ':' : i==0 ? ' ' : ','); - - if (ins.oprs[i].segment & SEG_RELATIVE) { - ins.oprs[i].offset += offset + length; - /* - * sort out wraparound - */ - if (!(ins.oprs[i].segment & SEG_32BIT)) - ins.oprs[i].offset &= 0xFFFF; - /* - * add sync marker, if autosync is on - */ - if (autosync) - add_sync (ins.oprs[i].offset, 0L); - } - - if ((*p)->opd[i] & 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); - if ( (*p)->opd[i] & 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])) { - output[slen++] = '1'; - } else if ( (*p)->opd[i] & IMMEDIATE ) { - if ( (*p)->opd[i] & 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; - output[slen++] = '-'; - } else - output[slen++] = '+'; - } - } else if ( (*p)->opd[i] & BITS16 ) { - slen += snprintf(output+slen, outbufsize-slen, "word "); - } else if ( (*p)->opd[i] & BITS32 ) { - slen += snprintf(output+slen, outbufsize-slen, "dword "); - } else if ( (*p)->opd[i] & NEAR ) { - slen += snprintf(output+slen, outbufsize-slen, "near "); - } else if ( (*p)->opd[i] & SHORT ) { - slen += snprintf(output+slen, outbufsize-slen, "short "); - } - slen += snprintf(output+slen, outbufsize-slen, "0x%lx", ins.oprs[i].offset); - } else if ( !(MEM_OFFS & ~(*p)->opd[i]) ) { - slen += snprintf(output+slen, outbufsize-slen, "[%s%s%s0x%lx]", - (segover ? segover : ""), - (segover ? ":" : ""), - (ins.oprs[i].addr_size == 32 ? "dword " : - ins.oprs[i].addr_size == 16 ? "word " : ""), - ins.oprs[i].offset); - segover = NULL; - } else if ( !(REGMEM & ~(*p)->opd[i]) ) { - int started = FALSE; - if ( (*p)->opd[i] & BITS8 ) - slen += snprintf(output+slen, outbufsize-slen, "byte "); - if ( (*p)->opd[i] & BITS16 ) - slen += snprintf(output+slen, outbufsize-slen, "word "); - if ( (*p)->opd[i] & BITS32 ) - slen += snprintf(output+slen, outbufsize-slen, "dword "); - if ( (*p)->opd[i] & BITS64 ) - slen += snprintf(output+slen, outbufsize-slen, "qword "); - if ( (*p)->opd[i] & BITS80 ) - slen += snprintf(output+slen, outbufsize-slen, "tword "); - if ( (*p)->opd[i] & FAR ) - slen += snprintf(output+slen, outbufsize-slen, "far "); - if ( (*p)->opd[i] & NEAR ) - slen += snprintf(output+slen, outbufsize-slen, "near "); - output[slen++] = '['; - if (ins.oprs[i].addr_size) - slen += snprintf(output+slen, outbufsize-slen, "%s", - (ins.oprs[i].addr_size == 32 ? "dword " : - ins.oprs[i].addr_size == 16 ? "word " : "")); - if (segover) { - slen += snprintf(output+slen, outbufsize-slen, "%s:", segover); - segover = NULL; - } - if (ins.oprs[i].basereg != -1) { - slen += snprintf(output+slen, outbufsize-slen, "%s", - reg_names[(ins.oprs[i].basereg - - EXPR_REG_START)]); - started = TRUE; - } - if (ins.oprs[i].indexreg != -1) { - if (started) - output[slen++] = '+'; - slen += snprintf(output+slen, outbufsize-slen, "%s", - reg_names[(ins.oprs[i].indexreg - - EXPR_REG_START)]); - if (ins.oprs[i].scale > 1) - slen += snprintf(output+slen, outbufsize-slen, "*%d", ins.oprs[i].scale); - started = TRUE; - } - if (ins.oprs[i].segment & SEG_DISP8) { - int sign = '+'; - if (ins.oprs[i].offset & 0x80) { - ins.oprs[i].offset = - (signed char) ins.oprs[i].offset; - sign = '-'; - } - slen += snprintf(output+slen, outbufsize-slen, "%c0x%lx", sign, - ins.oprs[i].offset); - } else if (ins.oprs[i].segment & SEG_DISP16) { - if (started) - output[slen++] = '+'; - slen += snprintf(output+slen, outbufsize-slen, "0x%lx", ins.oprs[i].offset); - } else if (ins.oprs[i].segment & SEG_DISP32) { - if (started) - output[slen++] = '+'; - slen += snprintf(output+slen, outbufsize-slen, "0x%lx", ins.oprs[i].offset); - } - output[slen++] = ']'; - } else { - slen += snprintf(output+slen, outbufsize-slen, "<operand%d>", i); - } + length += data - origdata; /* fix up for prefixes */ + for (i = 0; i < (*p)->operands; i++) { + output[slen++] = (colon ? ':' : i == 0 ? ' ' : ','); + + if (ins.oprs[i].segment & SEG_RELATIVE) { + ins.oprs[i].offset += offset + length; + /* + * sort out wraparound + */ + if (!(ins.oprs[i].segment & SEG_32BIT)) + ins.oprs[i].offset &= 0xFFFF; + /* + * add sync marker, if autosync is on + */ + if (autosync) + add_sync(ins.oprs[i].offset, 0L); + } + + if ((*p)->opd[i] & 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); + if ((*p)->opd[i] & 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])) { + output[slen++] = '1'; + } else if ((*p)->opd[i] & IMMEDIATE) { + if ((*p)->opd[i] & 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; + output[slen++] = '-'; + } else + output[slen++] = '+'; + } + } else if ((*p)->opd[i] & BITS16) { + slen += + snprintf(output + slen, outbufsize - slen, "word "); + } else if ((*p)->opd[i] & BITS32) { + slen += + snprintf(output + slen, outbufsize - slen, "dword "); + } else if ((*p)->opd[i] & NEAR) { + slen += + snprintf(output + slen, outbufsize - slen, "near "); + } else if ((*p)->opd[i] & SHORT) { + slen += + snprintf(output + slen, outbufsize - slen, "short "); + } + slen += + snprintf(output + slen, outbufsize - slen, "0x%lx", + ins.oprs[i].offset); + } else if (!(MEM_OFFS & ~(*p)->opd[i])) { + slen += + snprintf(output + slen, outbufsize - slen, "[%s%s%s0x%lx]", + (segover ? segover : ""), (segover ? ":" : ""), + (ins.oprs[i].addr_size == + 32 ? "dword " : ins.oprs[i].addr_size == + 16 ? "word " : ""), ins.oprs[i].offset); + segover = NULL; + } else if (!(REGMEM & ~(*p)->opd[i])) { + int started = FALSE; + if ((*p)->opd[i] & BITS8) + slen += + snprintf(output + slen, outbufsize - slen, "byte "); + if ((*p)->opd[i] & BITS16) + slen += + snprintf(output + slen, outbufsize - slen, "word "); + if ((*p)->opd[i] & BITS32) + slen += + snprintf(output + slen, outbufsize - slen, "dword "); + if ((*p)->opd[i] & BITS64) + slen += + snprintf(output + slen, outbufsize - slen, "qword "); + if ((*p)->opd[i] & BITS80) + slen += + snprintf(output + slen, outbufsize - slen, "tword "); + if ((*p)->opd[i] & FAR) + slen += snprintf(output + slen, outbufsize - slen, "far "); + if ((*p)->opd[i] & NEAR) + slen += + snprintf(output + slen, outbufsize - slen, "near "); + output[slen++] = '['; + if (ins.oprs[i].addr_size) + slen += snprintf(output + slen, outbufsize - slen, "%s", + (ins.oprs[i].addr_size == 32 ? "dword " : + ins.oprs[i].addr_size == + 16 ? "word " : "")); + if (segover) { + slen += + snprintf(output + slen, outbufsize - slen, "%s:", + segover); + segover = NULL; + } + if (ins.oprs[i].basereg != -1) { + slen += snprintf(output + slen, outbufsize - slen, "%s", + reg_names[(ins.oprs[i].basereg - + EXPR_REG_START)]); + started = TRUE; + } + if (ins.oprs[i].indexreg != -1) { + if (started) + output[slen++] = '+'; + slen += snprintf(output + slen, outbufsize - slen, "%s", + reg_names[(ins.oprs[i].indexreg - + EXPR_REG_START)]); + if (ins.oprs[i].scale > 1) + slen += + snprintf(output + slen, outbufsize - slen, "*%d", + ins.oprs[i].scale); + started = TRUE; + } + if (ins.oprs[i].segment & SEG_DISP8) { + int sign = '+'; + if (ins.oprs[i].offset & 0x80) { + ins.oprs[i].offset = -(signed char)ins.oprs[i].offset; + sign = '-'; + } + slen += + snprintf(output + slen, outbufsize - slen, "%c0x%lx", + sign, ins.oprs[i].offset); + } else if (ins.oprs[i].segment & SEG_DISP16) { + if (started) + output[slen++] = '+'; + slen += + snprintf(output + slen, outbufsize - slen, "0x%lx", + ins.oprs[i].offset); + } else if (ins.oprs[i].segment & SEG_DISP32) { + if (started) + output[slen++] = '+'; + slen += + snprintf(output + slen, outbufsize - slen, "0x%lx", + ins.oprs[i].offset); + } + output[slen++] = ']'; + } else { + slen += + snprintf(output + slen, outbufsize - slen, "<operand%d>", + i); + } } output[slen] = '\0'; - if (segover) { /* unused segment override */ - char *p = output; - int count = slen+1; - while (count--) - p[count+3] = p[count]; - strncpy (output, segover, 2); - output[2] = ' '; + if (segover) { /* unused segment override */ + char *p = output; + int count = slen + 1; + while (count--) + p[count + 3] = p[count]; + strncpy(output, segover, 2); + output[2] = ' '; } return length; } -long eatbyte (unsigned char *data, char *output, int outbufsize) +long eatbyte(unsigned char *data, char *output, int outbufsize) { snprintf(output, outbufsize, "db 0x%02X", *data); return 1; |