home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / OBJASM.ZIP / ODISASM.C < prev    next >
C/C++ Source or Header  |  1991-01-12  |  59KB  |  1,962 lines

  1. #include <stdio.h>
  2. #include <string.h>
  3. #include "o.h"
  4.  
  5. /*
  6. ** Local Prototypes
  7. */
  8. char *reg_format( int, char *, char *, char *, char * );
  9. int check_getc( unsigned long * );
  10. int check_getw( unsigned long * );
  11. int check_getl( unsigned long * );
  12. int check_getv( unsigned long *, int );
  13. int get_checkc( unsigned long * );
  14. void instr_opcode( char * );
  15. void instr_operand( char * );
  16. int check_forward( INST_T [], int );
  17. int mod0( int, int, char *, char *, unsigned char, int, int * );
  18. int mod1( int, int, char *, char *, unsigned char );
  19. int mod2( int, int, char *, char *, unsigned char, int, int * );
  20. int mod3( int, char *, unsigned char, int, int * );
  21. int do_sib( char *, unsigned char * );
  22. int do_mod_rm( char *, unsigned char, unsigned char, int, int, int );
  23. int byte_immed( char *, int, int );
  24. int word_immed( char *, int );
  25.  
  26. char    *regs[4][8] = {
  27.       "al",  "cl",  "dl",  "bl",  "ah",  "ch",  "dh",  "bh",
  28.       "ax",  "cx",  "dx",  "bx",  "sp",  "bp" , "si",  "di",
  29.      "eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi",
  30.       "??",  "??",  "??",  "??",  "??",  "??",  "??",  "??"
  31. };
  32.  
  33. char    *sregs [] = { "es" , "cs" , "ss" , "ds" , "fs" , "gs"  };
  34. char    *sregsc[] = { "es:", "cs:", "ss:", "ds:", "fs:", "gs:" };
  35.  
  36. char    *cr_regs[] = { "cr0",    "", "cr2", "cr3", "", "",    "",    "" };
  37. char    *dr_regs[] = { "dr0", "dr1", "dr2", "dr3", "", "", "dr6", "dr7" };
  38. char    *tr_regs[] = {    "",    "",    "",    "", "", "", "tr6", "tr7" };
  39.  
  40. char    *addr_mode[] = { "[bx+si", "[bx+di", "[bp+si", "[bp+di",
  41.                             "[si",    "[di",    "[bp",    "[bx" };
  42.  
  43. char    *addr_386m[] = {   "[eax",   "[ecx",   "[edx",   "[ebx",
  44.                            "[esp",   "[ebp",   "[esi",   "[edi" };
  45.  
  46. char    *sib_scale[] = {  "", "*2", "*4", "*8" };
  47.  
  48. char    *op_grp[10][8] = {
  49.      "add",   "or",  "adc",  "sbb",  "and",  "sub",  "xor",  "cmp",
  50.      "rol",  "ror",  "rcl",  "rcr",  "shl",  "shr",     "",  "sar",
  51.     "test",     "",  "not",  "neg",  "mul", "imul",  "div", "idiv",
  52.      "inc",  "dec",     "",     "",     "",     "",     "",     "",
  53.      "inc",  "dec", "call", "call",  "jmp",  "jmp", "push",     "",
  54.     "sldt",  "str", "lldt",  "ltr", "verr", "verw",     "",     "",
  55.     "sgdt", "sidt", "lgdt", "lidt", "smsw",     "", "lmsw",     "",
  56.         "",     "",     "",     "",   "bt",  "bts",  "btr",  "btc",
  57.      "pop",     "",     "",     "",     "",     "",     "",     "",
  58.      "mov",     "",     "",     "",     "",     "",     "",     ""
  59. };
  60.  
  61. char    *sz_text[] = { "byte ptr ", "word ptr ", "dword ptr ",
  62.                        "qword ptr ", "tbyte ptr "              };
  63.  
  64. char *dir_fmt[] = {
  65.     "%s,%s",                    /* 0 = mem,reg */
  66.     "%s,%s",                    /* 1 = reg,mem */
  67.     "%s",                       /* 2 = mem */
  68.     "%s,%s,%s",                 /* 3 = reg,mem,third */
  69.     "%s,%s,%s"                  /* 4 = mem,reg,third */
  70. };
  71.  
  72. typedef struct modrm_s MODRM_CLASS;
  73.  
  74. struct modrm_s {
  75.     int     dir;
  76.     int     size;
  77.     int     method;
  78.     int     group;
  79.     int     size_needed;
  80.     int     type;
  81. };
  82.  
  83.  
  84. /*
  85. ** These mod r/m classes are not in any particular order, but the
  86. ** instruction table indexes these entries with it's mod_rm_type field.
  87. */
  88. MODRM_CLASS modrm_class[] = {
  89.     0,  0,  1,  0,  FALSE,  UNKNOWN,    /*  0 Math instructions (byte) M,reg */
  90.     0,  1,  1,  0,  FALSE,  UNKNOWN,    /*  1 Math instructions (word) M,reg (and ARPL) */
  91.     1,  0,  1,  0,  FALSE,  UNKNOWN,    /*  2 Math instructions (byte) reg,M */
  92.     1,  1,  1,  0,  FALSE,  UNKNOWN,    /*  3 Math instructions (word) reg,M */
  93.     0,  0,  5,  1,  TRUE,   UNKNOWN,    /*  4 Group 1 (math) byte */
  94.     0,  1,  6,  1,  TRUE,   UNKNOWN,    /*  5 Group 1 (math) word */
  95.     0,  1,  7,  1,  TRUE,   UNKNOWN,    /*  6 Group 1 (math) signed byte */
  96.     0,  1,  2,  0,  TRUE,   UNKNOWN,    /*  7 Segment register unloading */
  97.     1,  1,  2,  0,  TRUE,   UNKNOWN,    /*  8 Segment register loading */
  98.     1,  1,  1,  0,  FALSE,  UNKNOWN,    /*  9 LEA instruction */
  99.     2,  1,  0,  9,  FALSE,  UNKNOWN,    /* 10 POP mod 0 r/m instruction */
  100.     0,  0,  5,  2,  FALSE,  UNKNOWN,    /* 11 Group 2 (rotates) byte */
  101.     0,  1,  5,  2,  FALSE,  UNKNOWN,    /* 12 Group 2 (rotates) word */
  102.     0,  0,  3,  2,  TRUE,   UNKNOWN,    /* 13 Group 2 (rotates) byte by 1 */
  103.     0,  1,  3,  2,  TRUE,   UNKNOWN,    /* 14 Group 2 (rotates) word by 1 */
  104.     0,  0,  4,  2,  TRUE,   UNKNOWN,    /* 15 Group 2 (rotates) byte by CL */
  105.     0,  1,  4,  2,  TRUE,   UNKNOWN,    /* 16 Group 2 (rotates) word by CL */
  106.     1,  2,  1,  0,  FALSE,  UNKNOWN,    /* 17 LES,LDS,BOUND,LSS,LFS,LGS */
  107.     0,  0,  5, 10,  TRUE,   UNKNOWN,    /* 18 Move immediate (byte) */
  108.     0,  1,  6, 10,  TRUE,   UNKNOWN,    /* 19 Move immediate (word) */
  109.     2,  0,  0,  3,  FALSE,  UNKNOWN,    /* 20 Group 3 (special) byte */
  110.     2,  1,  0,  3,  FALSE,  UNKNOWN,    /* 21 Group 3 (special) word */
  111.     2,  0,  0,  4,  TRUE,   UNKNOWN,    /* 22 Group 4 (inc/dec) byte */
  112.     2,  1,  0,  5,  FALSE,  UNKNOWN,    /* 23 Group 5 (special) word/dword */
  113.     3,  1,  8,  0,  FALSE,  UNKNOWN,    /* 24 IMUL (3 parms [reg,mem,immed word]) */
  114.     3,  1,  9,  0,  FALSE,  UNKNOWN,    /* 25 IMUL (3 parms [reg,mem,immed signed byte]) */
  115.     2,  1,  0,  6,  FALSE,  UNKNOWN,    /* 26 Group 6 (special 286/386 instructions) */
  116.     2,  3,  0,  7,  TRUE,   FWORD_PTR,  /* 27 Group 7 (special 286/386 instructions) */
  117.     1,  1,  1,  0,  TRUE,   UNKNOWN,    /* 28 LAR,LSL reg,M (word) */
  118.     0,  0,  5,  8,  TRUE,   BYTE_PTR,   /* 29 Group 8 (386-bit) byte */
  119.     2,  0,  0,  0,  TRUE,   BYTE_PTR,   /* 30 386 Set cc Instructions */
  120.     0,  2, 10,  0,  FALSE,  UNKNOWN,    /* 31 386 Mov r32,crX */
  121.     1,  2, 10,  0,  FALSE,  UNKNOWN,    /* 32 386 Mov crX,r32 */
  122.     0,  2, 11,  0,  FALSE,  UNKNOWN,    /* 33 386 Mov r32,drX */
  123.     1,  2, 11,  0,  FALSE,  UNKNOWN,    /* 34 386 Mov drX,r32 */
  124.     0,  2, 12,  0,  FALSE,  UNKNOWN,    /* 35 386 Mov r32,trX */
  125.     1,  2, 12,  0,  FALSE,  UNKNOWN,    /* 36 386 Mov trX,r32 */
  126.     1,  1,  1,  0,  TRUE,   BYTE_PTR,   /* 37 386 Movsx, Movzx */
  127.     1,  1,  1,  0,  TRUE,   WORD_PTR,   /* 38 386 Movsx, Movzx */
  128.     4,  1,  9,  0,  TRUE,   UNKNOWN,    /* 39 386 Shld,Shrd mem/reg,reg,imm byte */
  129.     4,  1, 13,  0,  TRUE,   UNKNOWN,    /* 40 386 Shld,Shrd mem/reg,reg,cl */
  130. };
  131.  
  132.  
  133. extern int pub_compare();
  134. extern int ext_compare();
  135.  
  136. int over_seg     = -1;      /*   -1  = No overiding segment yet      */
  137.  
  138. static  int over_opsize  = FALSE;   /* FALSE = No overiding operand size yet */
  139. static  int over_adrsize = FALSE;   /* FALSE = No overiding address size yet */
  140. static  int size_large   = FALSE;   /* Within a WORD address size            */
  141. static  int addr_large   = FALSE;   /* Special Addressing Modes              */
  142. static  int size_bytes   = 2;       /* Default WORD size                     */
  143. static  int addr_bytes   = 2;       /* Default WORD size                     */
  144.  
  145. static  char    fp_opcode[8] = {0};     /* 7 + \0 */
  146. static  char    fp_wait = FALSE;        /* No preceeding "wait" */
  147.  
  148. void inst_init()
  149. {
  150.     over_seg     = -1;              /* Setup for the next instruction */
  151.     over_opsize  = FALSE;
  152.     over_adrsize = FALSE;
  153.  
  154.     if ( segment_mode == 386 ) {
  155.         size_large = TRUE;
  156.         addr_large = TRUE;
  157.     } else {
  158.         size_large = FALSE;
  159.         addr_large = FALSE;
  160.     }
  161.     size_bytes = segment_bytes;
  162.     addr_bytes = segment_bytes;
  163. }
  164.  
  165.  
  166. char *reg_format( reg, output_string, base_text, base_fmt, extra_fmt )
  167.     int             reg;
  168.     char            *output_string;
  169.     char            *base_text;
  170.     char            *base_fmt;
  171.     char            *extra_fmt;
  172. {
  173.     if ( reg == NREG ) {
  174.         sprintf( output_string, base_fmt, base_text );
  175.     } else {
  176.         if ( reg < 9 ) {        /* Byte sized half register */
  177.             sprintf( output_string, extra_fmt, base_text, regs[0][reg-1] );
  178.         } else {
  179.             if ( reg < 17 ) {   /* Word/DWord sized general register */
  180.                 if ( size_large ) {
  181.                     sprintf( output_string, extra_fmt, base_text, 
  182.                                                             regs[2][reg-9] );
  183.                 } else {
  184.                     sprintf( output_string, extra_fmt, base_text, 
  185.                                                             regs[1][reg-9] );
  186.                 }
  187.             } else {
  188.                 sprintf( output_string, extra_fmt, base_text, sregs[reg-17] );
  189.             }
  190.         }
  191.     }
  192.     return( output_string );
  193. }
  194.  
  195. int check_getc( result )
  196.     unsigned long   *result;
  197. {
  198.     int             ch;
  199.  
  200.     ch = buff_getc();
  201.  
  202.     if ( ch == EOF ) {
  203.         return( TRUE );
  204.     } else {
  205.         *result = (unsigned long)ch;
  206.         return( FALSE );
  207.     }
  208. }
  209.  
  210. int check_getw( result )
  211.     unsigned long   *result;
  212. {
  213.     int             ch;
  214.  
  215.     ch = buff_getc();
  216.     if ( ch == EOF ) {
  217.         return( TRUE );
  218.     }
  219.     *result = ch;
  220.     ch = buff_getc();
  221.     if ( ch == EOF ) {
  222.         return( TRUE );
  223.     }
  224.     *result += ch << 8;
  225.     return( FALSE );
  226. }
  227.  
  228. int check_getl( result )
  229.     unsigned long   *result;
  230. {
  231.     int             ch;
  232.  
  233.     ch = buff_getc();
  234.     if ( ch == EOF ) {
  235.         return( TRUE );
  236.     }
  237.     *result = (unsigned long)((unsigned char)ch);
  238.  
  239.     ch = buff_getc();
  240.     if ( ch == EOF ) {
  241.         return( TRUE );
  242.     }
  243.     *result += (unsigned long)((unsigned char)ch) << 8;
  244.  
  245.     ch = buff_getc();
  246.     if ( ch == EOF ) {
  247.         return( TRUE );
  248.     }
  249.     *result += (unsigned long)((unsigned char)ch) << 16;
  250.     ch = buff_getc();
  251.     if ( ch == EOF ) {
  252.         return( TRUE );
  253.     }
  254.     *result += (unsigned long)((unsigned char)ch) << 24;
  255.  
  256.     return( FALSE );
  257. }
  258.  
  259. int check_getv( value, flag )
  260.     unsigned long   *value;
  261.     int             flag;
  262. {
  263.     int             result;
  264.  
  265.     if ( flag ) {
  266.         result = check_getl( value );
  267.     } else {
  268.         result = check_getw( value );
  269.     }
  270.     return( result );
  271. }
  272.  
  273. int get_checkc( offset )
  274.     unsigned long   *offset;
  275. {
  276.     int     dcheck;
  277.  
  278.     dcheck = data_check( 1 );
  279.  
  280.     if ( dcheck != NORMAL && dcheck != BAD ) {
  281.         return( TRUE );                 /* Must be no labels or fixups */
  282.     }
  283.     return( check_getc( offset ) );
  284. }
  285.  
  286. void instr_opcode( text )
  287.     char    *text;
  288. {
  289.     if ( pass == 3 ) {
  290.         out_opcode( text );
  291.     }
  292.     tab_offset = 0;
  293.     inst_init();            /* Reset for next instruction */
  294. }
  295.  
  296. void instr_operand( text )
  297.     char    *text;
  298. {
  299.     if ( pass == 3 ) {
  300.         out_operand( text );
  301.     }
  302. }
  303.  
  304. int stub( byte, text, class )
  305.     unsigned char   byte;
  306.     char            *text;
  307.     int             class;
  308. {
  309.     return( 0 );
  310.  
  311.     byte;               /* Prevent unused variable warnings */
  312.     text;               /* Prevent unused variable warnings */
  313.     class;              /* Prevent unused variable warnings */
  314. }
  315.  
  316. int in_out( byte, text, class )
  317.     unsigned char   byte;
  318.     char            *text;
  319.     int             class;
  320. {
  321.     int             dir;
  322.     int             size;
  323.     char            temp[50];
  324.  
  325.     dir  = ( byte & 0x02 ) >> 1;
  326.     size = ( byte & 0x01 );
  327.  
  328.     if ( size == 1 && size_large ) {
  329.         size = 2;
  330.     }
  331.     instr_opcode(text);
  332.  
  333.     if ( dir == 0 ) {
  334.         sprintf( temp, "%s,dx", regs[size][0] );
  335.     } else {
  336.         sprintf( temp, "dx,%s", regs[size][0] );
  337.     }
  338.     instr_operand(temp);
  339.  
  340.     return(1);
  341.  
  342.     class;              /* Prevent unused variable warnings */
  343. }
  344.  
  345. int string_byte( byte, text, class )
  346.     unsigned char   byte;
  347.     char            *text;
  348.     int             class;
  349. {
  350.     char            opcode[10];
  351.     char            operand[50];
  352.     int             size;
  353.     int             mode;
  354.     char            *format;
  355.  
  356.     size = byte & 0x01;
  357.     if ( size == 1 && size_large ) {
  358.         size = 2;
  359.     }
  360.  
  361.     switch( byte ) {
  362.         case 0xA4:
  363.         case 0xA5:
  364.             format = "%ses:[di],%s%s[si]";
  365.             mode = 0;
  366.             break;
  367.         case 0xA6:
  368.         case 0xA7:
  369.             format = "%ses:[di],%s%s[si]";
  370.             mode = 0;
  371.             break;
  372.         case 0xAA:
  373.         case 0xAB:
  374.             mode = 2;
  375.             break;
  376.         case 0xAC:
  377.         case 0xAD:
  378.             format = "%s%s[si]";
  379.             mode = 1;
  380.             break;
  381.         case 0xAE:
  382.         case 0xAF:
  383.             mode = 2;
  384.             break;
  385.     }
  386.  
  387.     strcpy( opcode, text );
  388.  
  389.     if ( over_seg == -1 ) {
  390.         switch( size ) {
  391.             case 0:     strcat(opcode,"b");     break;
  392.             case 1:     strcat(opcode,"w");     break;
  393.             case 2:     strcat(opcode,"d");     break;
  394.         }
  395.         instr_opcode(opcode);
  396.         return(1);
  397.     } else {
  398.         switch( mode ) {
  399.             case 0:
  400.                 sprintf( operand, format, sz_text[size],
  401.                                             sz_text[size], sregsc[over_seg] );
  402.                 break;
  403.             case 1:
  404.                 sprintf( operand, format, sz_text[size], sregsc[over_seg] );
  405.                 break;
  406.             case 2:                 /* No segment overide on */
  407.                 return( 0 );        /* SCAS instructions     */
  408.                 break;
  409.         }
  410.         instr_opcode( opcode );
  411.         instr_operand( operand );
  412.         return(1);
  413.     }
  414.  
  415.     class;                  /* Prevent unused variable warnings */
  416. }
  417.  
  418. int one_byte( byte, text, class )
  419.     unsigned char   byte;
  420.     char            *text;
  421.     int             class;
  422. {
  423.     char            line[50];
  424.  
  425.     if ( strlen(text) == 0 ) {
  426.         return(0);
  427.     }
  428.  
  429.     reg_format( class, line, text, "%s", "%s\t%s" );
  430.  
  431.     instr_opcode(line);
  432.     return(1);
  433.  
  434.     byte;               /* Prevent unused variable warnings */
  435. }
  436.  
  437. int two_byte( byte, text, class )
  438.     unsigned char   byte;
  439.     char            *text;
  440.     int             class;
  441. {
  442.     unsigned long   offset;
  443.     char            line[50];
  444.     char            temp[50];
  445.  
  446.     if ( get_checkc( &offset ) ) {
  447.         return( 0 );
  448.     }
  449.  
  450.     reg_format( class, line, text, "%s\t", "%s\t%s," );
  451.  
  452.     out_hexize( offset, temp, 1 );      /* Convert 1 byte into hex */
  453.     strcat( line, temp );
  454.  
  455.     instr_opcode( line );
  456.  
  457.     return(2);
  458.  
  459.     byte;                   /* Prevent unused varaible warnings */
  460. }
  461.  
  462. int two_ubyte( byte, text, class )
  463.     unsigned char   byte;
  464.     char            *text;
  465.     int             class;
  466. {
  467.     unsigned long   offset;
  468.     char            line[50];
  469.  
  470.     if ( get_checkc( &offset ) ) {
  471.         return( 0 );
  472.     }
  473.  
  474.     if ( offset <= 127L ) {
  475.         sprintf( line, "%s+0%02lXh", text, offset );
  476.     } else {
  477.         sprintf( line, "%s-0%02lXh", text, 0x0100L - offset );
  478.     }
  479.     instr_opcode( line );
  480.  
  481.     return(2);
  482.  
  483.     byte;               /* Prevent unused variable warnings */
  484.     class;              /* Prevent unused variable warnings */
  485. }
  486.  
  487. int three_byte( byte, text, class )
  488.     unsigned char   byte;
  489.     char            *text;
  490.     int             class;
  491. {
  492.     unsigned long   offset;
  493.     int             dummy;
  494.     int             data_size;
  495.     int             size_tmp;
  496.     char            line[50];
  497.     char            temp[50];
  498.  
  499.     if ( over_seg != -1 ) {         /* No segment overide allowed */
  500.         return( 0 );
  501.     }
  502.  
  503.     reg_format( class, line, text, "%s\t", "%s\t%s," );
  504.  
  505.     size_tmp = size_large;
  506.  
  507.     if ( byte == 0xC2 || byte == 0xCA ) {       /* <RET jjkk>/<RETF jjkk> */
  508.         size_tmp = FALSE;
  509.         size_bytes = 2;
  510.     }
  511.  
  512.     data_size = size_bytes;
  513.  
  514.     switch( data_check( 1 ) ) {
  515.         case BAD:       return( 0 );
  516.         case LABEL:     return( 0 );
  517.         case FIXUP:     if ( fix_rec->word_sized 
  518.                                 && fix_rec->extended == size_tmp ) {
  519.                             get_fix( temp, 2, TRUE, size_bytes,
  520.                                                     NEAR, FALSE, &dummy, DS );
  521.                             strcat( line, temp );
  522.                             adjust_assumes();
  523.                             instr_opcode( line );
  524.                             return( data_size+1 );
  525.                         } else {
  526.                             return( 0 );
  527.                         }
  528.         case NORMAL:    if ( check_getv( &offset, size_tmp ) ) {
  529.                             return( 0 );
  530.                         }
  531.                         out_hexize( offset, temp, size_bytes );
  532.                         strcat( line, temp );
  533.                         instr_opcode(line);
  534.                         return( data_size+1 );
  535.     }
  536. }
  537.  
  538. int five_byte( byte, text, class )
  539.     unsigned char   byte;
  540.     char            *text;
  541.     int             class;
  542. {
  543.     unsigned long   offset;
  544.     unsigned long   segment;
  545.     int             size_known;
  546.     char            line[50];
  547.     char            temp[50];
  548.     int             data_size;
  549.  
  550.     if ( over_seg != -1 ) {         /* No segment overide allowed */
  551.         return(0);
  552.     }
  553.  
  554.     data_size = size_bytes;
  555.  
  556.     switch( data_check( 1 ) ) {
  557.         case BAD:
  558.             return( 0 );
  559.         case LABEL:
  560.             return( 0 );
  561.         case FIXUP:
  562.             if ( fix_rec->form != POINTER || fix_rec->extended != size_large ) {
  563.                 return( 0 );
  564.             }
  565.             get_fix( temp, 1, FALSE, size_bytes, NEAR, TRUE, &size_known, CS );
  566.             sprintf( line, "far ptr %s", temp );
  567.             break;
  568.         case NORMAL:
  569.             if ( check_getv( &offset, size_large ) ) {
  570.                 return( 0 );
  571.             }
  572.             if ( data_check(3) != NORMAL ) {
  573.                 return( 0 );
  574.             }
  575.             if ( check_getw( &segment ) ) {
  576.                 return( 0 );
  577.             }
  578.             out_hexize( segment, temp, 2 );      /* Convert 2 byte into hex */
  579.             strcpy( line, temp );
  580.             strcat( line, ":" );
  581.             out_hexize( offset, temp, size_bytes ); /* Convert 2/4 bytes into hex */
  582.             strcat( line, temp );
  583.             break; 
  584.     }
  585.  
  586.     adjust_assumes();
  587.  
  588.     instr_opcode( text );
  589.     instr_operand( line );
  590.  
  591.  
  592.     return( 3 + data_size );
  593.  
  594.     byte;               /* Prevent unused variable warnings */
  595.     class;              /* Prevent unused variable warnings */
  596. }
  597.  
  598. int one_a( byte, text, class )
  599.     unsigned char   byte;
  600.     char            *text;
  601.     int             class;
  602. {
  603.     char            line[50];
  604.  
  605.     if ( size_large ) {
  606.         reg_format( class, line, text, "%s\teax", "%s\teax,%s" );
  607.     } else {
  608.         reg_format( class, line, text, "%s\tax", "%s\tax,%s" );
  609.     }
  610.  
  611.     instr_opcode(line);
  612.     return(1);
  613.  
  614.     byte;                   /* Prevent unused varaible warnings */
  615. }
  616.  
  617. int two_a( byte, text, class )
  618.     unsigned char   byte;
  619.     char            *text;
  620.     int             class;
  621. {
  622.     int             size;
  623.     unsigned long   offset;
  624.     char            line[50];
  625.  
  626.     size = (byte & 0x01);
  627.  
  628.     if ( check_getc( &offset ) ) {
  629.         return( 0 );
  630.     }
  631.  
  632.     if ( size == 0 ) {
  633.         sprintf( line, "0%02lXh,al", offset );
  634.     } else {
  635.         sprintf( line, "0%02lXh,ax", offset );
  636.     }
  637.     instr_opcode( text );
  638.     instr_operand(line);
  639.  
  640.     return(2);
  641.  
  642.     byte;               /* Prevent unused variable warnings */
  643.     class;              /* Prevent unused variable warnings */
  644. }
  645.  
  646. int three_a( byte, text, class )
  647.     unsigned char   byte;
  648.     char            *text;
  649.     int             class;
  650. {
  651.     int             dir;
  652.     int             reg_size;
  653.     int             data_size;
  654.     int             type;
  655.     int             size_known;
  656.     unsigned long   offset;
  657.     char            line[50];
  658.     char            seg_text[10];
  659.     char            temp[50];
  660.     char            temp2[15];
  661.     int             ref_seg;
  662.  
  663.     data_size = addr_bytes;
  664.  
  665.     dir  = ( byte & 0x02 ) >> 1;
  666.     reg_size = ( byte & 0x01 );
  667.  
  668.     if ( reg_size == 1 && size_large ) {
  669.         reg_size = 2;
  670.     }
  671.     type = reg_size_to_type(reg_size);
  672.  
  673.     if ( over_seg != -1 ) {                 /* Any previous segment overide? */
  674.         ref_seg = 17+over_seg;
  675.         strcpy( seg_text, sregsc[over_seg] );
  676.     } else {
  677.         ref_seg = DS;
  678.         seg_text[0] = '\0';
  679.     }
  680.  
  681.     switch( data_check( 1 ) ) {
  682.         case BAD:
  683.             return( 0 );
  684.         case LABEL:     
  685.             return( 0 );
  686.         case FIXUP:
  687.             if ( fix_rec->word_sized && fix_rec->extended == addr_large ) {
  688.                 get_fix( temp, 0, FALSE, size_bytes, type, TRUE,
  689.                                                         &size_known, ref_seg );
  690.             } else {
  691.                 return( 0 );
  692.             }
  693.             strcpy( line, "" );
  694.             if ( compatibility == 2 ) {
  695.                 strcat( line, seg_text );
  696.                 strcat( line, " " );
  697.                 if ( !size_known ) {
  698.                     strcat( line, type_to_text(type) );
  699.                 }
  700.             } else {
  701.                 if ( !size_known ) {
  702.                     strcat( line, type_to_text(type) );
  703.                 }
  704.                 strcat( line, seg_text );
  705.             }
  706.             strcat( line, temp );
  707.             break;
  708.         case NORMAL:
  709.             if ( check_getv( &offset, addr_large ) ) {
  710.                 return( 0 );
  711.             }
  712.             out_hexize( offset, temp2, addr_bytes );    /* Make hex digits */
  713.  
  714.             if ( compatibility == 2 ) {
  715.                 sprintf( line, "%s .%s", seg_text, temp2 );
  716.             } else {
  717.                 if ( over_seg == -1 ) {
  718.                     sprintf( line, "ds:[%s]", temp2 );
  719.                 } else {
  720.                     sprintf( line, "%s[%s]", seg_text, temp2 );
  721.                 }
  722.             }
  723.             break;
  724.     }
  725.  
  726.     if ( dir == 0 ) {
  727.         sprintf( temp, "%s,%s", regs[reg_size][0], line );
  728.     } else {
  729.         sprintf( temp, "%s,%s", line, regs[reg_size][0] );
  730.     }
  731.  
  732.     adjust_assumes();
  733.  
  734.     instr_opcode( text );
  735.     instr_operand( temp );
  736.  
  737.     return( 1 + data_size );
  738.  
  739.     class;              /* Prevent unused variable warnings */
  740. }
  741.  
  742. int enter( byte, text, class )
  743.     unsigned char   byte;
  744.     char            *text;
  745.     int             class;
  746. {
  747.     unsigned long   num_bytes;
  748.     unsigned long   nest_level;
  749.     char            line[50];
  750.  
  751.     switch( data_check(1) ) {
  752.         case BAD:
  753.         case LABEL:
  754.         case FIXUP:
  755.             return( 0 );
  756.         case NORMAL:
  757.             if ( check_getw(&num_bytes) ) {
  758.                 return( 0 );
  759.             }
  760.             if ( check_getc(&nest_level) ) {
  761.                 return( 0 );
  762.             }
  763.             sprintf( line, "0%04lXh,0%02lXh", num_bytes, nest_level );
  764.             break;
  765.     }
  766.     instr_opcode( text );
  767.     instr_operand( line );
  768.  
  769.     return(4);
  770.  
  771.     byte;               /* Prevent unused variable warnings */
  772.     class;              /* Prevent unused variable warnings */
  773. }
  774.  
  775. int check_forward( inst_table, method )
  776.     INST_T          inst_table[];
  777.     int             method;
  778. {
  779.     unsigned long   byte;
  780.     int             data;
  781.     int             valid;
  782.     extern char     *buff_cur;
  783.     char            *buff_save;
  784.  
  785.     buff_save = buff_cur;
  786.     /*
  787.     ** The next byte must be a valid instruction
  788.     */
  789.     if ( get_checkc( &byte ) ) {
  790.         return( 0 );
  791.     }
  792.     data = (unsigned char)byte;
  793.  
  794. #ifdef DEBUG
  795.     printf("Checking forward with byte [%02X]\n", data );
  796. #endif
  797.  
  798.     inst_offset += 1;
  799.  
  800.     if ( method == 0 && pass == 3 ) {
  801.         pass = 2;               /* Temporarily disable output */
  802.         valid = (*inst_table[data].rtn)
  803.                     ((unsigned char)data, 
  804.                     inst_table[data].text,
  805.                     inst_table[data].special );
  806.         pass = 3;
  807.     } else {
  808.         valid = (*inst_table[data].rtn)
  809.                     ((unsigned char)data, 
  810.                     inst_table[data].text,
  811.                     inst_table[data].special );
  812.     }
  813.  
  814.     inst_offset -= 1;
  815.  
  816.     if ( method == 0 || valid == 0 ) {
  817.         buff_cur = buff_save;
  818.     }
  819.  
  820.     return( valid );
  821. }
  822.  
  823. int seg_over( byte, text, class )
  824.     unsigned char   byte;
  825.     char            *text;
  826.     int             class;
  827. {
  828.     int             valid;
  829.     int             save_seg;
  830.  
  831.     save_seg = over_seg;
  832.  
  833.     if ( byte >= 0x64 ) {
  834.         over_seg = 4 + byte - 0x64;
  835.     } else {
  836.         over_seg = (byte & 0x18) >> 3;
  837.     }
  838.  
  839.     valid = check_forward( instr, 1 );
  840.     if ( valid ) {
  841.         return( valid+1 );
  842.     } else {
  843.         over_seg = save_seg;
  844.         return( 0 );
  845.     }
  846.  
  847.     text;               /* Prevent unused variable warnings */
  848.     class;              /* Prevent unused variable warnings */
  849. }
  850.  
  851. int opsize_over( byte, text, class )
  852.     unsigned char   byte;
  853.     char            *text;
  854.     int             class;
  855. {
  856.     int             valid;
  857.     int             save_large;
  858.     int             save_bytes;
  859.  
  860.     save_large = size_large;
  861.     save_bytes = size_bytes;
  862.  
  863.     size_large = !size_large;       /* Toggle size */
  864.     if ( size_bytes == 2 ) {
  865.         size_bytes = 4;
  866.     } else {
  867.         size_bytes = 2;
  868.     }
  869.     over_opsize = TRUE;
  870.  
  871.     valid = check_forward( instr, 1 );
  872.     if ( valid ) {
  873.         return( valid+1 );
  874.     } else {
  875.         size_large = save_large;
  876.         size_bytes = save_bytes;
  877.         return( 0 );
  878.     }
  879.  
  880.     byte;               /* Prevent unused variable warnings */
  881.     text;               /* Prevent unused variable warnings */
  882.     class;              /* Prevent unused variable warnings */
  883. }
  884.  
  885. int adrsize_over( byte, text, class )
  886.     unsigned char   byte;
  887.     char            *text;
  888.     int             class;
  889. {
  890.     int             valid;
  891.     int             save_large;
  892.     int             save_bytes;
  893.  
  894.     save_large = addr_large;
  895.     save_bytes = addr_bytes;
  896.  
  897.     addr_large = !addr_large;           /* Toggle address */
  898.     if ( addr_bytes == 2 ) {
  899.         addr_bytes = 4;
  900.     } else {
  901.         addr_bytes = 2;
  902.     }
  903.     over_adrsize = TRUE;
  904.  
  905.     valid = check_forward( instr, 1 );
  906.     if ( valid ) {
  907.         return( valid+1 );
  908.     } else {
  909.         addr_large = save_large;
  910.         addr_bytes = save_bytes;
  911.         return( 0 );
  912.     }
  913.  
  914.     byte;               /* Prevent unused variable warnings */
  915.     text;               /* Prevent unused variable warnings */
  916.     class;              /* Prevent unused variable warnings */
  917. }
  918.  
  919. int wait( byte, text, class )
  920.     unsigned char   byte;
  921.     char            *text;
  922.     int             class;
  923. {
  924.     int             valid;
  925.  
  926.     fp_opcode[0] = '\0';
  927.  
  928.     valid = check_forward( instr, 0 );
  929.     if ( !valid ) {
  930.         instr_opcode(text);
  931.         return(1);
  932.     } else {
  933.         if ( strlen(fp_opcode) == 0 ) {
  934.             instr_opcode( text );
  935.             return( 1 );
  936.         } else {
  937.             fp_wait = TRUE;         /* Will be reset by "esc" routine */
  938.             hex_finish = FALSE;
  939.             return( 1 );
  940.         }
  941.     }
  942.  
  943.     byte;               /* Prevent unused variable warnings */
  944.     class;              /* Prevent unused variable warnings */
  945. }
  946.  
  947. int prefix( byte, text, class )
  948.     unsigned char   byte;
  949.     char            *text;
  950.     int             class;
  951. {
  952.     int             valid;
  953.  
  954.     valid = check_forward( instr, 0 );
  955.  
  956.     if ( valid ) {
  957.         instr_opcode( text );
  958.         tab_offset = 1;
  959.         hex_finish = FALSE;
  960.         return( 1 );
  961.     } else {
  962.         return( 0 );
  963.     }
  964.  
  965.     byte;               /* Prevent unused variable warnings */
  966.     class;              /* Prevent unused variable warnings */
  967. }
  968.  
  969. int extra( byte, text, class )
  970.     unsigned char   byte;
  971.     char            *text;
  972.     int             class;
  973. {
  974.     int             result;
  975.  
  976.     result = check_forward( ex_instr, 1 );
  977.  
  978.     if ( result == 0 ) {
  979.         return( 0 );
  980.     } else {
  981.         return( result+1 );
  982.     }
  983.  
  984.     byte;               /* Prevent unused variable warnings */
  985.     text;
  986.     class;
  987. }
  988.  
  989. int disp8( byte, text, class )
  990.     unsigned char   byte;
  991.     char            *text;
  992.     int             class;
  993. {
  994.     int             dcheck;
  995.     char            line[60];
  996.     char            *short_text;
  997.     unsigned long   offset;
  998.     unsigned long   dest;
  999.     PUB_T           *pub_rec;
  1000.  
  1001.     if ( over_seg != -1 ) {             /* No segment overide allowed */
  1002.         return( 0 );
  1003.     }
  1004.  
  1005.     dcheck = data_check(1);
  1006.  
  1007.     if ( dcheck != NORMAL && dcheck != BAD ) {
  1008.         return( 0 );
  1009.     }
  1010.  
  1011.     if ( check_getc( &offset ) ) {
  1012.         return( 0 );
  1013.     }
  1014.  
  1015.     if ( offset == 0xFFFFFFFF ) {       /* This would generate a label in  */
  1016.         return( 0 );                    /* the middle of the jmp statement */
  1017.     }                                   /* thereby preventing it anyway    */
  1018.  
  1019.     /*
  1020.     ** Special 'SHORT' for small jumps 
  1021.     */
  1022.     short_text = "";
  1023.     if ( compatibility != 2 ) {
  1024.         if ( byte == 0xEB || segment_mode == 386 ) {
  1025.             short_text = "short ";
  1026.         }
  1027.     }
  1028.  
  1029.     dest = inst_offset + (signed char)offset + 2;
  1030.  
  1031.     pub_rec = check_public( 1, segment, dest, 'L' );
  1032.  
  1033.     if ( pub_rec ) {
  1034.         pub_rec->type = NEAR;
  1035.         offset = dest - pub_rec->offset;
  1036.         if ( offset > 0 ) {
  1037.             sprintf( line, "%s%s + 0%04lXh", 
  1038.                                 short_text, pub_rec->name, offset );
  1039.         } else {
  1040.             sprintf( line, "%s%s", short_text, pub_rec->name );
  1041.         }
  1042.     } else {
  1043.         if ( compatibility == 2 ) {
  1044.             sprintf( text, " %s.0%04lXh", short_text, offset );
  1045.         } else {
  1046.             sprintf( text, "%s[%s:0%04lXh]", short_text, cseg_name, offset );
  1047.         }
  1048.     }
  1049.  
  1050.     instr_opcode( text );
  1051.     instr_operand( line );
  1052.     return( 2 );
  1053.  
  1054.     byte;               /* Prevent unused variable warnings */
  1055.     class;
  1056. }
  1057.  
  1058. int disp16( byte, text, class )
  1059.     unsigned char   byte;
  1060.     char            *text;
  1061.     int             class;
  1062. {
  1063.     unsigned long   offset;
  1064.     unsigned long   dest;
  1065.     int             dummy;
  1066.     int             bad_size;
  1067.     char            line[60];
  1068.     char            *short_text;
  1069.     PUB_T           *pub_rec;
  1070.     int             data_size;
  1071.  
  1072.     data_size = addr_bytes;
  1073.  
  1074.     if ( over_seg != -1 ) {             /* No segment overide allowed */
  1075.         return( 0 );
  1076.     }
  1077.  
  1078.     switch( data_check( 1 ) ) {
  1079.         case BAD:
  1080.             return( 0 );
  1081.         case LABEL:
  1082.             return( 0 );
  1083.         case FIXUP:
  1084.             if ( fix_rec->word_sized && fix_rec->extended == addr_large
  1085.                                      && fix_rec->relate == 0 ) {
  1086.                 get_fix( line, 1, FALSE, size_bytes, NEAR, TRUE, &dummy, CS );
  1087.                 adjust_assumes();
  1088.                 instr_opcode( text );
  1089.                 instr_operand( line );
  1090.                 return( 1 + data_size );
  1091.             } else {
  1092.                 return( 0 );
  1093.             }
  1094.         case NORMAL:
  1095.             if ( check_getv( &offset, addr_large ) ) {
  1096.                 return( 0 );
  1097.             }
  1098.             /* note: the next if actually checks for 1 byte too far in
  1099.             ** the negative direction. but this is ok, because it would be
  1100.             ** replaced by a short jmp
  1101.             */
  1102.             if ( offset < 0x80 || offset >= 0xFFFFFF7F ) {
  1103.                 bad_size = TRUE;
  1104.                 short_text = "short ";
  1105.             } else {
  1106.                 short_text = "";
  1107.                 bad_size = FALSE;
  1108.             }
  1109.  
  1110.             dest = inst_offset + offset + addr_bytes + 1;
  1111.             pub_rec = check_public( 1, segment, dest, 'L' );
  1112.  
  1113.             if ( pub_rec ) {
  1114.                 offset = dest - pub_rec->offset;
  1115.                 if ( offset > 0L ) {
  1116.                     if ( addr_large ) {
  1117.                         sprintf( line, "%s%s + 0%08lXh", short_text,
  1118.                                  pub_rec->name, offset );
  1119.                     } else {
  1120.                         sprintf( line, "%s%s + 0%04lXh", short_text,
  1121.                                  pub_rec->name, offset );
  1122.                     }
  1123.                 } else {
  1124.                     sprintf( line, "%s%s", short_text, pub_rec->name );
  1125.                 }
  1126.             } else {
  1127.                 if ( compatibility == 2 ) {
  1128.                     if ( addr_large ) {
  1129.                         sprintf( line, "%s .0%08lXh", short_text, offset );
  1130.                     } else {
  1131.                         sprintf( line, "%s .0%04lXh", short_text, offset );
  1132.                     }
  1133.                 } else {
  1134.                     if ( addr_large ) {
  1135.                         sprintf( line, "%s[%s:0%08lXh]", short_text,
  1136.                                  cseg_name, offset );
  1137.                     } else {
  1138.                         sprintf( line, "%s[%s:0%04lXh]", short_text,
  1139.                                  cseg_name, offset );
  1140.                     }
  1141.                 }
  1142.             }
  1143.  
  1144.             instr_opcode( text );
  1145.             instr_operand( line );
  1146.             if ( bad_size ) {
  1147.                 if ( pass == 3 ) {
  1148.                     out_comment( "Large jump translated into short" );
  1149.                 }
  1150.                 instr_opcode( "nop" );
  1151.                 if ( pass == 3 ) {
  1152.                     out_comment( "Nop inserted to retain proper length" );
  1153.                 }
  1154.             }
  1155.             return( 1 + data_size );
  1156.     }
  1157.  
  1158.     byte;               /* Prevent unused variable warnings */
  1159.     class;              /* Prevent unused variable warnings */
  1160. }
  1161.  
  1162. int two_bcd( byte, text, class )
  1163.     unsigned char   byte;
  1164.     char            *text;
  1165.     int             class;
  1166. {
  1167.     unsigned long   offset;
  1168.  
  1169.     if ( check_getc( &offset ) ) {
  1170.         return( 0 );
  1171.     }
  1172.  
  1173.     if ( offset == 0x0AL ) {
  1174.         instr_opcode( text );
  1175.         return(2);
  1176.     } else {
  1177.         return( 0 );
  1178.     }
  1179.  
  1180.     byte;               /* Prevent unused variable warnings */
  1181.     class;              /* Prevent unused variable warnings */
  1182. }
  1183.  
  1184. int mod0( ref_mode, sib_offset,sib_text, text, r_m, type, size_known )
  1185.     int             ref_mode;
  1186.     int             sib_offset;
  1187.     char            *sib_text;
  1188.     char            *text;
  1189.     unsigned char   r_m;
  1190.     int             type;
  1191.     int             *size_known;
  1192. {
  1193.     unsigned long   offset;
  1194.     int             result;
  1195.     PUB_T           *pub_rec;
  1196.     STRUC_T         *pub_struct;
  1197.     int             ref_seg;
  1198.     char            this_member[NAMESIZE+1+1];  /* 1 for ., 1 for \0 */
  1199.     char            temp[16];
  1200.  
  1201.     this_member[0] = '\0';
  1202.  
  1203.     if ( (r_m == 6 && !addr_large) || (r_m == 5 && addr_large) ) {
  1204.         if ( over_seg != -1 ) {
  1205.             ref_seg = 17+over_seg;
  1206.         } else {
  1207.             ref_seg = DS;
  1208.         }
  1209.         switch( data_check( 2+sib_offset ) ) {
  1210.             case BAD:
  1211.                 result = -1;
  1212.                 return( result );
  1213.                 break;
  1214.             case LABEL:
  1215.                 result = -1;
  1216.                 return( result );
  1217.                 break;
  1218.             case FIXUP:
  1219.                 if ( fix_rec->word_sized && fix_rec->extended == addr_large ) {
  1220.                     get_fix( text, 0, FALSE, size_bytes, 
  1221.                                             type, TRUE, size_known, ref_seg );
  1222.                     if ( strlen(sib_text) ) {
  1223.                         strcat( text, "[" );
  1224.                         strcat( text, sib_text );
  1225.                         strcat( text, "]" );
  1226.                     }
  1227.                     result = addr_bytes+sib_offset;
  1228.                 } else {
  1229.                     result = -1;
  1230.                 }
  1231.                 return( result );
  1232.                 break;
  1233.             case NORMAL:
  1234.                 if ( check_getv( &offset, size_large ) ) {
  1235.                     result = -1;
  1236.                     return( result );
  1237.                 }
  1238.                 if ( add_labels ) {
  1239.                     pub_rec = check_public( 0, 0, offset, 'S' );
  1240.                 } else {
  1241.                     pub_rec = NULL;
  1242.                 }
  1243.                 if ( pub_rec ) {
  1244.                     offset -= pub_rec->offset;
  1245.                     pub_struct = pub_rec->structure;
  1246.                     if ( pub_struct ) {
  1247.                         find_member( this_member, pub_struct, &offset );
  1248.                     }
  1249.                     if ( offset != 0 ) {
  1250.                         out_hexize( offset, temp, size_bytes );
  1251.                         sprintf( text, "%s%s + %s",
  1252.                                  pub_rec->name, this_member, temp );
  1253.                     } else {
  1254.                         sprintf( text, "%s%s", pub_rec->name, this_member );
  1255.                     }
  1256.                 } else {
  1257.                     out_hexize( offset, temp, size_bytes );
  1258.                     if ( compatibility == 2 ) {
  1259.                         sprintf( text, " .%s", temp );
  1260.                     } else {
  1261.                         if ( over_seg == -1 ) {
  1262.                             sprintf( text, "ds:[%s", temp );
  1263.                         } else {
  1264.                             sprintf( text, "[%s", temp );
  1265.                         }
  1266.                         if ( strlen( sib_text ) ) {
  1267.                             strcat( text, "+" );
  1268.                             strcat( text, sib_text );
  1269.                         }
  1270.                         strcat( text, "]" );
  1271.                     }
  1272.                 }
  1273.                 result = addr_bytes+sib_offset;
  1274.                 *size_known = FALSE;
  1275.                 return( result );
  1276.                 break;
  1277.         }
  1278.     }
  1279.     if ( addr_large ) {
  1280.         strcpy( text, addr_386m[r_m] );
  1281.     } else {
  1282.         strcpy( text, addr_mode[r_m] );
  1283.     }
  1284.     if ( strlen( sib_text ) ) {
  1285.         strcat( text, "+" );
  1286.         strcat( text, sib_text );
  1287.     }
  1288.     strcat( text, "]" );
  1289.     result = sib_offset;
  1290.     *size_known = TRUE;
  1291.     return( result );
  1292. }
  1293.  
  1294. int mod1( ref_mode, sib_offset, sib_text, text, r_m )
  1295.     int             ref_mode;
  1296.     int             sib_offset;
  1297.     char            *sib_text;
  1298.     char            *text;
  1299.     unsigned char   r_m;
  1300. {
  1301.     char            temp[50];
  1302.     unsigned long   offset;
  1303.     int             result;
  1304.     unsigned char   zero_rm;
  1305.  
  1306.     if ( check_getc( &offset ) ) {
  1307.         result = -1;
  1308.     } else {
  1309.         if ( addr_large ) {
  1310.             /*
  1311.             ** Assembler should have optimized
  1312.             */
  1313.             zero_rm = 5;
  1314.             strcpy( text, addr_386m[r_m] );
  1315.         } else {
  1316.             /*
  1317.             ** Assembler should have optimized
  1318.             */
  1319.             zero_rm = 6;
  1320.             strcpy( text, addr_mode[r_m] );
  1321.         }
  1322.         if ( strlen(sib_text) ) {
  1323.             strcat( text, "+" );
  1324.             strcat( text, sib_text );
  1325.         }
  1326.         if ( offset >= 0x80 ) {
  1327.             sprintf( temp, "-0%02lXh", 0x0100L-offset );
  1328.         } else {
  1329.             if ( offset == 0L ) {
  1330.                 if ( r_m == zero_rm ) {
  1331.                     temp[0] = '\0';
  1332.                 } else {
  1333.                     return( -1 );
  1334.                 }
  1335.             } else {
  1336.                 sprintf( temp, "+0%02lXh", offset );
  1337.             }
  1338.         }
  1339.         if ( compatibility == 2 ) {
  1340.             strcat( text, "]" );
  1341.             strcat( text, temp );
  1342.         } else {
  1343.             strcat( text, temp );
  1344.             strcat( text, "]" );
  1345.         }
  1346.         result = 1 + sib_offset;
  1347.     }
  1348.     return( result );
  1349. }
  1350.  
  1351. int mod2( ref_mode, sib_offset, sib_text, text, r_m, type, size_known )
  1352.     int             ref_mode;
  1353.     int             sib_offset;
  1354.     char            *sib_text;
  1355.     char            *text;
  1356.     unsigned char   r_m;
  1357.     int             type;
  1358.     int             *size_known;
  1359. {
  1360.     unsigned long   offset;
  1361.     int             result;
  1362.     char            temp[50];
  1363.     char            *sign;
  1364.     int             ref_seg;
  1365.  
  1366.     if ( r_m == 2 || r_m == 3 ) {
  1367.         ref_seg = SS;               /* SS relative addressing modes */
  1368.     } else {
  1369.         ref_seg = DS;
  1370.     }
  1371.     if ( over_seg != -1 ) {
  1372.         ref_seg = 17+over_seg;
  1373.     }
  1374.  
  1375.     switch( data_check(2+sib_offset) ) {
  1376.         case BAD:
  1377.             result = -1;
  1378.             break;
  1379.         case LABEL:
  1380.             result = -1;
  1381.             break;
  1382.         case FIXUP:
  1383.             if ( fix_rec->word_sized && fix_rec->extended == addr_large ) {
  1384.                 get_fix( temp, 0, FALSE, addr_bytes,
  1385.                                             type, TRUE, size_known, ref_seg );
  1386.                 if ( compatibility == 2 ) {
  1387.                     strcpy( text, temp );
  1388.                     strcat( text, addr_mode[r_m] );
  1389.                 } else {
  1390.                     if ( addr_large ) {
  1391.                         strcpy( text, addr_386m[r_m] );
  1392.                     } else {
  1393.                         strcpy( text, addr_mode[r_m] );
  1394.                     }
  1395.                     if ( strlen(sib_text) ) {
  1396.                         strcat( text, "+" );
  1397.                         strcat( text, sib_text );
  1398.                     }
  1399.                     strcat( text, "+" );
  1400.                     strcat( text, temp );
  1401.                 }
  1402.                 strcat( text, "]" );
  1403.                 result = addr_bytes+sib_offset;
  1404.             } else {
  1405.                 result = -1;
  1406.             }
  1407.             break;
  1408.         case NORMAL:
  1409.             if ( check_getv( &offset, addr_large ) ) {
  1410.                 result = -1;
  1411.             } else {
  1412.                 if ( offset == 0x00000000L ) { 
  1413.                     return( -1 );       /* Assembler should have optimized */
  1414.                 }
  1415.                 if ( addr_large ) {
  1416.                     strcpy( text, addr_386m[r_m] );
  1417.                 } else {
  1418.                     strcpy( text, addr_mode[r_m] );
  1419.                 }
  1420.                 if ( strlen(sib_text) ) {
  1421.                     strcat( text, "+" );
  1422.                     strcat( text, sib_text );
  1423.                 }
  1424.                 if ( offset > 0x80000000L ) {
  1425.                     offset = -offset;
  1426.                     sign = "-";
  1427.                 } else {
  1428.                     sign = "+";
  1429.                 }
  1430.                 out_hexize( offset, temp, addr_bytes );
  1431.                 if ( compatibility == 2 ) {
  1432.                     strcat( text, "]" );
  1433.                     strcat( text, sign );
  1434.                     strcat( text, temp );
  1435.                 } else {
  1436.                     strcat( text, sign );
  1437.                     strcat( text, temp );
  1438.                     strcat( text, "]" );
  1439.                 }
  1440.                 result = addr_bytes+sib_offset;
  1441.                 *size_known = TRUE;
  1442.             }
  1443.             break;
  1444.     }
  1445.     return( result );
  1446. }
  1447.  
  1448. int mod3( ref_mode, text, r_m, type, type_known )
  1449.     int             ref_mode;
  1450.     char            *text;
  1451.     unsigned char   r_m;
  1452.     int             type;
  1453.     int             *type_known;
  1454. {
  1455.     switch( type ) {
  1456.         case BYTE_PTR:  strcpy( text, regs[0][r_m] );   break;
  1457.         case WORD_PTR:  strcpy( text, regs[1][r_m] );   break;
  1458.         case DWORD_PTR: strcpy( text, regs[2][r_m] );   break;
  1459.         default:        strcpy( text, regs[3][r_m] );   break;
  1460.     }
  1461.     *type_known = TRUE;
  1462.     return( 0 );
  1463. }
  1464.  
  1465. int do_sib( text, base )
  1466.     char            *text;
  1467.     unsigned char   *base;
  1468. {
  1469.     unsigned long   sib_byte;
  1470.     int             ss;
  1471.     int             idx;
  1472.  
  1473.     switch( data_check(2) ) {
  1474.         case LABEL:
  1475.             return( -1 );
  1476.             break;
  1477.         case FIXUP:
  1478.             return( -1 );
  1479.             break;
  1480.         case BAD:
  1481.         case NORMAL:
  1482.             if ( check_getc( &sib_byte ) ) {
  1483.                 return( -1 );
  1484.             }
  1485.             ss    = (int)(sib_byte & 0xC0L) >> 6;
  1486.             idx   = (int)(sib_byte & 0x38L) >> 3;
  1487.             *base = (unsigned char)(sib_byte & 0x07L);
  1488.             if ( idx == 0x04 ) {            /* For special [ESP] */
  1489.                 if ( ss != 0 ) {
  1490.                     return( -1 );
  1491.                 } else {
  1492.                     strcpy( text, "" );
  1493.                 }
  1494.             } else {
  1495.                 strcat( text, regs[2][idx] );
  1496.                 strcat( text, sib_scale[ss] );
  1497.             }
  1498.             return( 1 );
  1499.             break;
  1500.     }
  1501. }
  1502.  
  1503. int do_mod_rm( line, mod, r_m, type, size_needed, ref_mode )
  1504.     char            *line;
  1505.     unsigned char   mod;
  1506.     unsigned char   r_m;
  1507.     int             type;
  1508.     int             size_needed;
  1509.     int             ref_mode;
  1510. {
  1511.     int             size_known;
  1512.     int             sib_offset;
  1513.     char            sib_text[50];
  1514.     char            temp2[50];
  1515.     int             result;
  1516.     
  1517.     size_known = FALSE;
  1518.  
  1519.     strcpy( sib_text, "" );
  1520.     sib_offset = 0;
  1521.  
  1522.     if ( addr_large ) {
  1523.         if ( r_m == 4 && mod != 3 ) {
  1524.             /* Get result and new r_m */
  1525.             sib_offset = do_sib( sib_text, &r_m );
  1526.             if ( sib_offset == -1 ) {
  1527.                 return( -1 );
  1528.             }
  1529.         }
  1530.     }
  1531.     switch( mod ) {
  1532.         case 0: result = mod0( ref_mode, sib_offset, sib_text, temp2,
  1533.                                             r_m, type, &size_known );
  1534.                 break;
  1535.         case 1: result = mod1( ref_mode, sib_offset, sib_text, temp2, r_m );
  1536.                 size_known = TRUE;
  1537.                 break;
  1538.         case 2: result = mod2( ref_mode, sib_offset, sib_text, temp2,
  1539.                                             r_m, type, &size_known );
  1540.                 break;
  1541.         case 3: result = mod3( ref_mode, temp2, r_m, type, &size_known );
  1542.                 size_needed = FALSE;
  1543.                 break;
  1544.     }
  1545.  
  1546.     if ( result != -1 ) {
  1547.         if ( compatibility == 2 ) {
  1548.             if ( over_seg != -1 ) {         /* Any previous segment overide? */
  1549.                 strcat( line, sregsc[over_seg] );
  1550.                 strcat( line, " " );
  1551.             }
  1552.             if ( !size_known || size_needed ) {
  1553.                 strcat( line, type_to_text(type) );
  1554.             }
  1555.         } else {
  1556.             /*
  1557.             ** If the size is already known, then we don't need 'xxxx' ptr text
  1558.             */
  1559.             if ( !size_known || size_needed ) {
  1560.                 strcat( line, type_to_text(type) );
  1561.             }
  1562.             if ( over_seg != -1 ) {         /* Any previous segment overide? */
  1563.                 strcat( line, sregsc[over_seg] );
  1564.             }
  1565.         }
  1566.         strcat( line, temp2 );
  1567.     }
  1568.     return( result );
  1569. }
  1570.  
  1571. int byte_immed( text, additional, sign )
  1572.     char            *text;
  1573.     int             additional;
  1574.     int             sign;
  1575. {
  1576.     int             dcheck;
  1577.     unsigned long   offset;
  1578.  
  1579.     dcheck = data_check( additional+2 );
  1580.  
  1581.     switch( dcheck ) {
  1582.         case LABEL:     return( 1 );
  1583.         case FIXUP:     return( 1 );
  1584.         case BAD:
  1585.         case NORMAL:
  1586.             if ( check_getc( &offset ) ) {
  1587.                 return( 1 );
  1588.             }
  1589.             if ( sign ) {
  1590.                 if ( offset <= 0x7F ) {
  1591.                     sprintf( text, "+0%02lXh", offset );
  1592.                 } else {
  1593.                     sprintf( text, "-0%02lXh", 0x0100L-offset );
  1594.                 }
  1595.             } else {
  1596.                 out_hexize( offset, text, 1 );
  1597.             }
  1598.             break;
  1599.     }
  1600.     return( 0 );
  1601. }
  1602.  
  1603. int word_immed( text, additional )
  1604.     char            *text;
  1605.     int             additional;
  1606. {
  1607.     int             dcheck;
  1608.     int             dummy;
  1609.     unsigned long   offset;
  1610.  
  1611.     dcheck = data_check( additional+2 );
  1612.  
  1613.     switch( dcheck ) {
  1614.         case LABEL:
  1615.             return( 1 );
  1616.         case FIXUP:
  1617.             if ( fix_rec->word_sized && fix_rec->extended == addr_large ) {
  1618.                 get_fix( text, 2, TRUE, size_bytes, NEAR, FALSE, &dummy, DS );
  1619.             } else {
  1620.                 return( 1 );
  1621.             }
  1622.             break;
  1623.         case BAD:
  1624.             return( 1 );
  1625.             break;
  1626.         case NORMAL:
  1627.             if ( check_getv( &offset, size_large ) ) {
  1628.                 return( 1 );
  1629.             }
  1630.             if ( size_large ) {
  1631.                 out_hexize( offset, text, 4 );
  1632.             } else {
  1633.                 out_hexize( offset, text, 2 );
  1634.             }
  1635.             break;
  1636.     }
  1637.     return( 0 );
  1638. }
  1639.  
  1640.  
  1641. int mod_reg( byte, text, class )
  1642.     unsigned char   byte;
  1643.     char            *text;
  1644.     int             class;
  1645. {
  1646.     char            *opcode;
  1647.     int             dir;
  1648.     int             size;
  1649.     int             reg_size;
  1650.     int             size_needed;
  1651.     int             type;
  1652.     int             method;
  1653.     int             group;
  1654.     unsigned long   mod_reg;
  1655.     unsigned char   mod;
  1656.     unsigned char   r_m;
  1657.     unsigned char   reg;
  1658.     int             additional;
  1659.     char            mem_text[50];
  1660.     char            reg_text[50];
  1661.     char            third_text[50];
  1662.     char            operands[80];
  1663.     int             ref_mode;
  1664.  
  1665.     if ( get_checkc( &mod_reg ) ) {
  1666.         return( 0 );
  1667.     }
  1668.  
  1669.     mod = (unsigned char)(((int)mod_reg & 0xC0) >> 6);
  1670.     reg = (unsigned char)(((int)mod_reg & 0x38) >> 3);
  1671.     r_m = (unsigned char)(((int)mod_reg & 0x07) >> 0);
  1672.  
  1673.     dir         = modrm_class[class].dir;
  1674.     size        = modrm_class[class].size;
  1675.     method      = modrm_class[class].method;
  1676.     group       = modrm_class[class].group;
  1677.     size_needed = modrm_class[class].size_needed;
  1678.     type        = modrm_class[class].type;
  1679.  
  1680.     ref_mode = 0;
  1681.  
  1682.     if ( group == 6 ) {
  1683.         if ( mod == 3 ) {
  1684.             if ( reg == 0 || reg == 1 || reg == 2 || reg == 3 ) {
  1685.                 addr_large = FALSE;         /* 286 only instructions */
  1686.                 size_large = FALSE;
  1687.             }
  1688.         }
  1689.         type = WORD_PTR;
  1690.         size_needed = TRUE;
  1691.     }
  1692.  
  1693.     reg_size = size;                /* 386 Segments effect register names */
  1694.     if ( reg_size == 1 && size_large ) {
  1695.         reg_size = 2;
  1696.     }
  1697.     if ( type == UNKNOWN ) {
  1698.         type = reg_size_to_type( reg_size );
  1699.     }
  1700.  
  1701.     if ( group == 0 ) {
  1702.         opcode = text;
  1703.     } else {
  1704.         opcode = op_grp[group-1][reg];
  1705.     }
  1706.     if ( strlen(opcode) == 0 ) {
  1707.         return( 0 );
  1708.     }
  1709.  
  1710.     if ( class == 26 ) {
  1711.         reg_size = 1;
  1712.     }
  1713.  
  1714.     if ( byte == 0x62 || byte == 0x63 ) {
  1715.         if ( byte == 0x63 ) {
  1716.             type = WORD_PTR;
  1717.         }
  1718.         size_needed = TRUE;     /* LAR, LSL, BOUND, ARPL need size */
  1719.     }
  1720.     if ( byte == 0xC4 || byte == 0xC5
  1721.            || byte == 0xB2 || byte == 0xB4 || byte == 0xB5 ) {
  1722.         size_needed = TRUE;
  1723.     }
  1724.  
  1725.     if ( group == 3 ) {         /* Group 3 has a test instruction which    */
  1726.         if ( reg == 0 ) {       /* needs an immediate value (byte or word) */
  1727.             method = 5 + size;  /* the rest of group 3 needs nothing       */
  1728.             dir = 0;
  1729.             size_needed = TRUE;
  1730.         } else {
  1731.             method = 0;
  1732.             if ( reg == 2 || reg == 3 ) {
  1733.                 size_needed = FALSE;
  1734.             } else {
  1735.                 size_needed = TRUE;
  1736.             }
  1737.         }
  1738.     }
  1739.  
  1740.     if ( group == 5 ) {                 /* Group 5 has call far and jump far */
  1741.         if ( reg == 3 || reg == 5 ) {   /* instructions which are dwords     */
  1742.                                         /* the rest of group 5 is words      */
  1743.             if ( size_large ) {
  1744.                 type = FWORD_PTR;
  1745.             } else {
  1746.                 type = DWORD_PTR;
  1747.             }
  1748.             size_needed = TRUE;
  1749.         } else {
  1750.             if ( reg == 0 || reg == 1 ) {
  1751.                 size_needed = TRUE;
  1752.             }
  1753.         }
  1754.     }
  1755.  
  1756.     if ( group == 7 ) {                 /* Group 7 has mostly FWORD sized    */
  1757.         if ( reg == 4 || reg == 6 ) {   /* EAs, but these two are WORD sized */
  1758.             type = WORD_PTR;
  1759.         }
  1760.     }
  1761.  
  1762.     if ( dir == 0 && mod == 3 && (class == 0 || class == 1) ) {
  1763.         /*
  1764.         ** Ambiguous!   eg. OBJ 20F8 = and al,bh => MASM 22C7
  1765.         ** This is because MASM prefers the first operand to be
  1766.         ** a register and the other operand to be a mem/reg.
  1767.         */
  1768.         return(0);
  1769.     }
  1770.  
  1771.     mem_text[0] = '\0';
  1772.     additional = do_mod_rm( mem_text, mod, r_m, type, size_needed, ref_mode );
  1773.     if ( additional == -1 ) {
  1774.         return( 0 );
  1775.     }
  1776.  
  1777.     switch( method ) {
  1778.         case 0:         /* No additional information (one operand only) */
  1779.             break;
  1780.         case 1:         /* Other operand is a register */
  1781.                         /* LES,LDS,BOUND,LSS,LFS,LGS, ARPL instructions
  1782.                         /* revert to Word */
  1783.             if ( byte == 0xC4 || byte == 0xC5 || byte == 0x62 || byte == 0x63
  1784.                    || byte == 0xB2 || byte == 0xB4 || byte == 0xB5 ) {
  1785.                 reg_size = 1;
  1786.             }
  1787.  
  1788.             strcpy( reg_text, regs[reg_size][reg] );
  1789.             break;
  1790.         case 2:         /* Other operand is a segment register */
  1791.             if ( reg > 5 ) {    /* 0=ES,1=CS,2=SS,3=DS,4=FS,5=GS */
  1792.                 return( 0 );
  1793.             }
  1794.             strcpy( reg_text, sregs[reg] );
  1795.             break;
  1796.         case 3:         /* Other operand is 1 */
  1797.             strcpy( reg_text, "1" );
  1798.             break;
  1799.         case 4:         /* Other operand is register CL */
  1800.             strcpy( reg_text, "cl" );
  1801.             break;
  1802.         case 5:         /* Immediate byte value */
  1803.             if ( byte_immed(reg_text, additional,FALSE) ) {
  1804.                 return( 0 );
  1805.             }
  1806.             additional++;
  1807.             break;
  1808.         case 6:         /* Immediate word value (could be fixupp) */
  1809.             if ( word_immed(reg_text, additional) ) {
  1810.                 return( 0 );
  1811.             }
  1812.             if ( size_large ) {
  1813.                 additional += 4;
  1814.             } else {
  1815.                 additional += 2;
  1816.             }
  1817.             break;
  1818.         case 7:         /* Immediate signed byte value */
  1819.             if ( byte_immed(reg_text,additional,TRUE) ) {
  1820.                 return( 0 );
  1821.             }
  1822.             additional++;
  1823.             break;
  1824.         case 8:         /* IMUL (3 operands [reg,mem,immed word]) */
  1825.             strcpy( reg_text, regs[reg_size][reg] );
  1826.             if ( word_immed(third_text, additional) ) {
  1827.                 return(0);
  1828.             }
  1829.             additional += 2;
  1830.             break;
  1831.         case 9:         /* IMUL (3 operands [reg,mem,immed signed byte]) */
  1832.             strcpy( reg_text, regs[reg_size][reg] );
  1833.             if ( byte_immed(third_text, additional,TRUE) ) {
  1834.                 return(0);
  1835.             }
  1836.             additional += 1;
  1837.             break;
  1838.         case 10:        /* Control Register (CR0...) */
  1839.             strcpy( reg_text, cr_regs[reg] );
  1840.             break;
  1841.         case 11:        /* Debug Register (DR0...) */
  1842.             strcpy( reg_text, dr_regs[reg] );
  1843.             break;
  1844.         case 12:
  1845.             strcpy( reg_text, tr_regs[reg] );
  1846.             break;
  1847.         case 13:
  1848.             strcpy( reg_text, regs[reg_size][reg] );
  1849.             strcpy( third_text, "cl" );
  1850.             break;
  1851.     }
  1852.  
  1853.     if ( dir & 0x01 ) {
  1854.         sprintf( operands, dir_fmt[dir], reg_text, mem_text, third_text );
  1855.     } else {
  1856.         sprintf( operands, dir_fmt[dir], mem_text, reg_text, third_text );
  1857.     }
  1858.  
  1859.     adjust_assumes();
  1860.     instr_opcode( opcode );
  1861.     instr_operand( operands );
  1862.  
  1863.     return( 2+additional );
  1864. }
  1865.  
  1866. int esc( byte, text, class )
  1867.     unsigned char   byte;
  1868.     char            *text;
  1869.     int             class;
  1870. {
  1871.     int             size;
  1872.     int             dir;
  1873.     int             type;
  1874.     unsigned long   mod_reg;
  1875.     unsigned char   mod;
  1876.     unsigned char   r_m;
  1877.     unsigned char   lll;        /* Described as LLL in 80386 Prog Ref Man. */
  1878.     unsigned char   ttt;        /* Described as TTT in 80386 Prog Ref Man. */
  1879.     unsigned char   esc_byte;
  1880.     unsigned char   mf;
  1881.     int             additional;
  1882.     int             size_needed;
  1883.     char            line[50];
  1884.     char            temp[50];
  1885.     int             ref_mode;
  1886.  
  1887.     size = (byte & 0x01);
  1888.     dir  = (byte & 0x02) >> 1;
  1889.     ref_mode = 0;
  1890.  
  1891.     if ( get_checkc( &mod_reg ) ) {
  1892.         return( 0 );
  1893.     }
  1894.     mod = (unsigned char)(((int)mod_reg & 0xC0) >> 6);
  1895.     lll = (unsigned char)(((int)mod_reg & 0x38) >> 3);
  1896.     r_m = (unsigned char)(((int)mod_reg & 0x07) >> 0);
  1897.  
  1898.     ttt = (unsigned char)(byte & 0x07);
  1899.     esc_byte = (unsigned char)(ttt << 3) + lll;
  1900.  
  1901.     if ( mod == 0x03 ) {
  1902.         esc_special( temp, line, esc_byte, r_m );
  1903.         additional = 0;
  1904.     } else {
  1905.         mf = (unsigned char)((esc_byte & 0x30) >> 4);
  1906.  
  1907.         size_needed = TRUE;
  1908.  
  1909.         switch( mf ) {
  1910.             case 0:     type = DWORD_PTR;   break;
  1911.             case 1:     type = DWORD_PTR;   break;
  1912.             case 2:     type = QWORD_PTR;   break;
  1913.             case 3:     type = WORD_PTR;    break;
  1914.         }
  1915.  
  1916.         /*
  1917.         ** There are always exceptions to the rule (Thank you, Intel)
  1918.         */
  1919.         if (    esc_byte == 0x1D || esc_byte == 0x1F 
  1920.              || esc_byte == 0x3C || esc_byte == 0x3E ) {
  1921.             type = TBYTE_PTR;
  1922.         }
  1923.         if ( esc_byte == 0x2F ) {
  1924.             type = WORD_PTR;
  1925.         }
  1926.         if ( esc_byte == 0x3D || esc_byte == 0x3F ) {
  1927.             type = DWORD_PTR;
  1928.         }
  1929.  
  1930.         if (    (esc_byte >= 0x0C && esc_byte <= 0x0F)
  1931.              || (esc_byte >= 0x2C && esc_byte <= 0x2E) ) {
  1932.             size_needed = FALSE;
  1933.         }
  1934.         sprintf( line, "" );
  1935.         additional = do_mod_rm( line, mod, r_m, type, size_needed, ref_mode );
  1936.         if ( additional == -1 ) {           /* Error in 'do_mod_rm' */
  1937.             return( 0 );
  1938.         }
  1939.         strcpy( temp, esc_inst[esc_byte] );
  1940.     }
  1941.     if ( strlen( temp ) ) {
  1942.         if ( temp[1] == 'n' && fp_wait ) {
  1943.             fp_opcode[0] = temp[0];             /* Remove the 'n' */
  1944.             strcpy( &fp_opcode[1], &temp[2] );
  1945.         } else {
  1946.             strcpy( fp_opcode, temp );
  1947.         }
  1948.         instr_opcode( fp_opcode );
  1949.         instr_operand( line );
  1950.     } else {
  1951.         sprintf( line, "0%02Xh,%s", esc_byte, regs[1][r_m] );
  1952.         instr_opcode( "esc" );
  1953.         instr_operand( line );
  1954.     }
  1955.  
  1956.     fp_wait = FALSE;                /* Reset always */
  1957.     return( 2+additional );
  1958.  
  1959.     text;               /* Prevent unused variable warnings */
  1960.     class;              /* Prevent unused variable warnings */
  1961. }
  1962.