home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / nasm097s.zip / ASSEMBLE.C next >
C/C++ Source or Header  |  1997-11-07  |  38KB  |  1,174 lines

  1. /* assemble.c   code generation for the Netwide Assembler
  2.  *
  3.  * The Netwide Assembler is copyright (C) 1996 Simon Tatham and
  4.  * Julian Hall. All rights reserved. The software is
  5.  * redistributable under the licence given in the file "Licence"
  6.  * distributed in the NASM archive.
  7.  *
  8.  * the actual codes (C syntax, i.e. octal):
  9.  * \0            - terminates the code. (Unless it's a literal of course.)
  10.  * \1, \2, \3    - that many literal bytes follow in the code stream
  11.  * \4, \6        - the POP/PUSH (respectively) codes for CS, DS, ES, SS
  12.  *                 (POP is never used for CS) depending on operand 0
  13.  * \5, \7        - the second byte of POP/PUSH codes for FS, GS, depending
  14.  *                 on operand 0
  15.  * \10, \11, \12 - a literal byte follows in the code stream, to be added
  16.  *                 to the register value of operand 0, 1 or 2
  17.  * \17           - encodes the literal byte 0. (Some compilers don't take
  18.  *                 kindly to a zero byte in the _middle_ of a compile time
  19.  *                 string constant, so I had to put this hack in.)
  20.  * \14, \15, \16 - a signed byte immediate operand, from operand 0, 1 or 2
  21.  * \20, \21, \22 - a byte immediate operand, from operand 0, 1 or 2
  22.  * \24, \25, \26 - an unsigned byte immediate operand, from operand 0, 1 or 2
  23.  * \30, \31, \32 - a word immediate operand, from operand 0, 1 or 2
  24.  * \34, \35, \36 - select between \3[012] and \4[012] depending on 16/32 bit
  25.  *                 assembly mode or the address-size override on the operand
  26.  * \37           - a word constant, from the _segment_ part of operand 0
  27.  * \40, \41, \42 - a long immediate operand, from operand 0, 1 or 2
  28.  * \50, \51, \52 - a byte relative operand, from operand 0, 1 or 2
  29.  * \60, \61, \62 - a word relative operand, from operand 0, 1 or 2
  30.  * \64, \65, \66 - select between \6[012] and \7[012] depending on 16/32 bit
  31.  *                 assembly mode or the address-size override on the operand
  32.  * \70, \71, \72 - a long relative operand, from operand 0, 1 or 2
  33.  * \1ab          - a ModRM, calculated on EA in operand a, with the spare
  34.  *                 field the register value of operand b.
  35.  * \2ab          - a ModRM, calculated on EA in operand a, with the spare
  36.  *                 field equal to digit b.
  37.  * \30x          - might be an 0x67 byte, depending on the address size of
  38.  *                 the memory reference in operand x.
  39.  * \310          - indicates fixed 16-bit address size, i.e. optional 0x67.
  40.  * \311          - indicates fixed 32-bit address size, i.e. optional 0x67.
  41.  * \320          - indicates fixed 16-bit operand size, i.e. optional 0x66.
  42.  * \321          - indicates fixed 32-bit operand size, i.e. optional 0x66.
  43.  * \322          - indicates that this instruction is only valid when the
  44.  *                 operand size is the default (instruction to disassembler,
  45.  *                 generates no code in the assembler)
  46.  * \330          - a literal byte follows in the code stream, to be added
  47.  *                 to the condition code value of the instruction.
  48.  * \340          - reserve <operand 0> bytes of uninitialised storage.
  49.  *                 Operand 0 had better be a segmentless constant.
  50.  */
  51.  
  52. #include <stdio.h>
  53. #include <string.h>
  54.  
  55. #include "nasm.h"
  56. #include "nasmlib.h"
  57. #include "assemble.h"
  58. #include "insns.h"
  59.  
  60. extern struct itemplate *nasm_instructions[];
  61.  
  62. typedef struct {
  63.     int sib_present;               /* is a SIB byte necessary? */
  64.     int bytes;                   /* # of bytes of offset needed */
  65.     int size;                   /* lazy - this is sib+bytes+1 */
  66.     unsigned char modrm, sib;           /* the bytes themselves */
  67. } ea;
  68.  
  69. static efunc errfunc;
  70. static struct ofmt *outfmt;
  71. static ListGen *list;
  72.  
  73. static long calcsize (long, long, int, insn *, char *);
  74. static void gencode (long, long, int, insn *, char *, long);
  75. static int regval (operand *o);
  76. static int matches (struct itemplate *, insn *);
  77. static ea *process_ea (operand *, ea *, int, int, int);
  78. static int chsize (operand *, int);
  79.  
  80. /*
  81.  * This routine wrappers the real output format's output routine,
  82.  * in order to pass a copy of the data off to the listing file
  83.  * generator at the same time.
  84.  */
  85. static void out (long offset, long segto, void *data, unsigned long type,
  86.          long segment, long wrt) {
  87.     if ((type & OUT_TYPMASK) == OUT_ADDRESS) {
  88.     if (segment != NO_SEG || wrt != NO_SEG) {
  89.         /*
  90.          * This address is relocated. We must write it as
  91.          * OUT_ADDRESS, so there's no work to be done here.
  92.          */
  93.         list->output (offset, data, type);
  94.     } else {
  95.         unsigned char p[4], *q = p;
  96.         /*
  97.          * This is a non-relocated address, and we're going to
  98.          * convert it into RAWDATA format.
  99.          */
  100.         if ((type & OUT_SIZMASK) == 4) {
  101.         WRITELONG (q, * (long *) data);
  102.         list->output (offset, p, OUT_RAWDATA+4);
  103.         } else {
  104.         WRITESHORT (q, * (long *) data);
  105.         list->output (offset, p, OUT_RAWDATA+2);
  106.         }
  107.     }
  108.     } else if ((type & OUT_TYPMASK) == OUT_RAWDATA) {
  109.     list->output (offset, data, type);
  110.     } else if ((type & OUT_TYPMASK) == OUT_RESERVE) {
  111.     list->output (offset, NULL, type);
  112.     } else if ((type & OUT_TYPMASK) == OUT_REL2ADR ||
  113.            (type & OUT_TYPMASK) == OUT_REL4ADR) {
  114.     list->output (offset, data, type);
  115.     }
  116.  
  117.     outfmt->output (segto, data, type, segment, wrt);
  118. }
  119.  
  120. long assemble (long segment, long offset, int bits,
  121.            insn *instruction, struct ofmt *output, efunc error,
  122.            ListGen *listgen) {
  123.     int j, size_prob;
  124.     long insn_end, itimes;
  125.     long start = offset;
  126.     struct itemplate *temp;
  127.  
  128.     errfunc = error;               /* to pass to other functions */
  129.     outfmt = output;               /* likewise */
  130.     list = listgen;               /* and again */
  131.  
  132.     if (instruction->opcode == -1)
  133.         return 0;
  134.  
  135.     if (instruction->opcode == I_DB ||
  136.     instruction->opcode == I_DW ||
  137.     instruction->opcode == I_DD ||
  138.     instruction->opcode == I_DQ ||
  139.     instruction->opcode == I_DT) {
  140.     extop *e;
  141.     long wsize = 0;               /* placate gcc */
  142.     long t = instruction->times;
  143.  
  144.     switch (instruction->opcode) {
  145.       case I_DB: wsize = 1; break;
  146.       case I_DW: wsize = 2; break;
  147.       case I_DD: wsize = 4; break;
  148.       case I_DQ: wsize = 8; break;
  149.       case I_DT: wsize = 10; break;
  150.     }
  151.  
  152.     while (t--) {
  153.         for (e = instruction->eops; e; e = e->next) {
  154.         if (e->type == EOT_DB_NUMBER) {
  155.             if (wsize == 1) {
  156.             if (e->segment != NO_SEG)
  157.                 errfunc (ERR_NONFATAL,
  158.                      "one-byte relocation attempted");
  159.             else {
  160.                 unsigned char c = e->offset;
  161.                 out (offset, segment, &c, OUT_RAWDATA+1,
  162.                  NO_SEG, NO_SEG);
  163.             }
  164.             } else if (wsize > 5) {
  165.             errfunc (ERR_NONFATAL, "integer supplied to a D%c"
  166.                  " instruction", wsize==8 ? 'Q' : 'T');
  167.             } else
  168.             out (offset, segment, &e->offset,
  169.                  OUT_ADDRESS+wsize, e->segment,
  170.                  e->wrt);
  171.             offset += wsize;
  172.         } else if (e->type == EOT_DB_STRING) {
  173.             int align;
  174.  
  175.             align = (-e->stringlen) % wsize;
  176.             if (align < 0)
  177.             align += wsize;
  178.             out (offset, segment, e->stringval,
  179.              OUT_RAWDATA+e->stringlen, NO_SEG, NO_SEG);
  180.             if (align)
  181.             out (offset, segment, "\0\0\0\0",
  182.                  OUT_RAWDATA+align, NO_SEG, NO_SEG);
  183.             offset += e->stringlen + align;
  184.         }
  185.         }
  186.         if (t > 0 && t == instruction->times-1) {
  187.         /*
  188.          * Dummy call to list->output to give the offset to the
  189.          * listing module.
  190.          */
  191.         list->output (offset, NULL, OUT_RAWDATA);
  192.         list->uplevel (LIST_TIMES);
  193.         }
  194.     }
  195.     if (instruction->times > 1)
  196.         list->downlevel (LIST_TIMES);
  197.     return offset - start;
  198.     }
  199.  
  200.     if (instruction->opcode == I_INCBIN) {
  201.     static char fname[FILENAME_MAX];
  202.     FILE *fp;
  203.     long len;
  204.  
  205.     len = FILENAME_MAX-1;
  206.     if (len > instruction->eops->stringlen)
  207.         len = instruction->eops->stringlen;
  208.     strncpy (fname, instruction->eops->stringval, len);
  209.     fname[len] = '\0';
  210.     if (!(fp = fopen(fname, "rb")))
  211.         error (ERR_NONFATAL, "`incbin': unable to open file `%s'", fname);
  212.     else if (fseek(fp, 0L, SEEK_END) < 0)
  213.         error (ERR_NONFATAL, "`incbin': unable to seek on file `%s'",
  214.            fname);
  215.     else {
  216.         static char buf[2048];
  217.         long t = instruction->times;
  218.         long l;
  219.  
  220.         len = ftell (fp);
  221.         if (instruction->eops->next) {
  222.         len -= instruction->eops->next->offset;
  223.         if (instruction->eops->next->next &&
  224.             len > instruction->eops->next->next->offset)
  225.             len = instruction->eops->next->next->offset;
  226.         }
  227.         /*
  228.          * Dummy call to list->output to give the offset to the
  229.          * listing module.
  230.          */
  231.         list->output (offset, NULL, OUT_RAWDATA);
  232.         list->uplevel(LIST_INCBIN);
  233.         while (t--) {
  234.         fseek (fp, 
  235.                (instruction->eops->next ?
  236.             instruction->eops->next->offset : 0),
  237.                SEEK_SET);        
  238.         l = len;
  239.         while (l > 0) {
  240.             long m = fread (buf, 1, (l>sizeof(buf)?sizeof(buf):l),
  241.                     fp);
  242.             if (!m) {
  243.             /*
  244.              * This shouldn't happen unless the file
  245.              * actually changes while we are reading
  246.              * it.
  247.              */
  248.             error (ERR_NONFATAL, "`incbin': unexpected EOF while"
  249.                    " reading file `%s'", fname);
  250.             return 0;      /* it doesn't much matter... */
  251.             }
  252.             out (offset, segment, buf, OUT_RAWDATA+m,
  253.              NO_SEG, NO_SEG);
  254.             l -= m;
  255.         }
  256.         }
  257.         list->downlevel(LIST_INCBIN);
  258.         if (instruction->times > 1) {
  259.         /*
  260.          * Dummy call to list->output to give the offset to the
  261.          * listing module.
  262.          */
  263.         list->output (offset, NULL, OUT_RAWDATA);
  264.         list->uplevel(LIST_TIMES);
  265.         list->downlevel(LIST_TIMES);
  266.         }
  267.         fclose (fp);
  268.         return instruction->times * len;
  269.     }
  270.     return 0;               /* if we're here, there's an error */
  271.     }
  272.  
  273.     size_prob = FALSE;
  274.     temp = nasm_instructions[instruction->opcode];
  275.     while (temp->opcode != -1) {
  276.     int m = matches (temp, instruction);
  277.     if (m == 100) {               /* matches! */
  278.         char *codes = temp->code;
  279.         long insn_size = calcsize(segment, offset, bits,
  280.                       instruction, codes);
  281.         itimes = instruction->times;
  282.         if (insn_size < 0)           /* shouldn't be, on pass two */
  283.             error (ERR_PANIC, "errors made it through from pass one");
  284.         else while (itimes--) {
  285.         insn_end = offset + insn_size;
  286.         for (j=0; j<instruction->nprefix; j++) {
  287.             unsigned char c;
  288.             switch (instruction->prefixes[j]) {
  289.               case P_LOCK:
  290.             c = 0xF0; break;
  291.               case P_REPNE: case P_REPNZ:
  292.             c = 0xF2; break;
  293.               case P_REPE: case P_REPZ: case P_REP:
  294.             c = 0xF3; break;
  295.               case R_CS: c = 0x2E; break;
  296.               case R_DS: c = 0x3E; break;
  297.               case R_ES: c = 0x26; break;
  298.               case R_FS: c = 0x64; break;
  299.               case R_GS: c = 0x65; break;
  300.               case R_SS: c = 0x36; break;
  301.               case P_A16:
  302.             if (bits == 16)
  303.                 c = 0;     /* no prefix */
  304.             else
  305.                 c = 0x67;
  306.             break;
  307.               case P_A32:
  308.             if (bits == 32)
  309.                 c = 0;     /* no prefix */
  310.             else
  311.                 c = 0x67;
  312.             break;
  313.               case P_O16:
  314.             if (bits == 16)
  315.                 c = 0;     /* no prefix */
  316.             else
  317.                 c = 0x66;
  318.             break;
  319.               case P_O32:
  320.             if (bits == 32)
  321.                 c = 0;     /* no prefix */
  322.             else
  323.                 c = 0x66;
  324.             break;
  325.               default:
  326.             error (ERR_PANIC,
  327.                    "invalid instruction prefix");
  328.             }
  329.             if (c != 0)
  330.             out (offset, segment, &c, OUT_RAWDATA+1,
  331.                  NO_SEG, NO_SEG);
  332.             offset++;
  333.         }
  334.         gencode (segment, offset, bits, instruction, codes, insn_end);
  335.         offset += insn_size;
  336.         if (itimes > 0 && itimes == instruction->times-1) {
  337.             /*
  338.              * Dummy call to list->output to give the offset to the
  339.              * listing module.
  340.              */
  341.             list->output (offset, NULL, OUT_RAWDATA);
  342.             list->uplevel (LIST_TIMES);
  343.         }
  344.         }
  345.         if (instruction->times > 1)
  346.         list->downlevel (LIST_TIMES);
  347.         return offset - start;
  348.     } else if (m > 0) {
  349.         size_prob = m;
  350.     }
  351.     temp++;
  352.     }
  353.     if (temp->opcode == -1) {           /* didn't match any instruction */
  354.     if (size_prob == 1)           /* would have matched, but for size */
  355.         error (ERR_NONFATAL, "operation size not specified");
  356.     else if (size_prob == 2)
  357.         error (ERR_NONFATAL, "mismatch in operand sizes");
  358.     else
  359.         error (ERR_NONFATAL,
  360.            "invalid combination of opcode and operands");
  361.     }
  362.     return 0;
  363. }
  364.  
  365. long insn_size (long segment, long offset, int bits,
  366.         insn *instruction, efunc error) {
  367.     struct itemplate *temp;
  368.  
  369.     errfunc = error;               /* to pass to other functions */
  370.  
  371.     if (instruction->opcode == -1)
  372.         return 0;
  373.  
  374.     if (instruction->opcode == I_DB ||
  375.     instruction->opcode == I_DW ||
  376.     instruction->opcode == I_DD ||
  377.     instruction->opcode == I_DQ ||
  378.     instruction->opcode == I_DT) {
  379.     extop *e;
  380.     long isize, osize, wsize = 0;  /* placate gcc */
  381.  
  382.     isize = 0;
  383.     switch (instruction->opcode) {
  384.       case I_DB: wsize = 1; break;
  385.       case I_DW: wsize = 2; break;
  386.       case I_DD: wsize = 4; break;
  387.       case I_DQ: wsize = 8; break;
  388.       case I_DT: wsize = 10; break;
  389.     }
  390.  
  391.     for (e = instruction->eops; e; e = e->next) {
  392.         long align;
  393.  
  394.         osize = 0;
  395.         if (e->type == EOT_DB_NUMBER)
  396.         osize = 1;
  397.         else if (e->type == EOT_DB_STRING)
  398.         osize = e->stringlen;
  399.  
  400.         align = (-osize) % wsize;
  401.         if (align < 0)
  402.         align += wsize;
  403.         isize += osize + align;
  404.     }
  405.     return isize * instruction->times;
  406.     }
  407.  
  408.     if (instruction->opcode == I_INCBIN) {
  409.     char fname[FILENAME_MAX];
  410.     FILE *fp;
  411.     long len;
  412.  
  413.     len = FILENAME_MAX-1;
  414.     if (len > instruction->eops->stringlen)
  415.         len = instruction->eops->stringlen;
  416.     strncpy (fname, instruction->eops->stringval, len);
  417.     fname[len] = '\0';
  418.     if (!(fp = fopen(fname, "rb")))
  419.         error (ERR_NONFATAL, "`incbin': unable to open file `%s'", fname);
  420.     else if (fseek(fp, 0L, SEEK_END) < 0)
  421.         error (ERR_NONFATAL, "`incbin': unable to seek on file `%s'",
  422.            fname);
  423.     else {
  424.         len = ftell (fp);
  425.         fclose (fp);
  426.         if (instruction->eops->next) {
  427.         len -= instruction->eops->next->offset;
  428.         if (instruction->eops->next->next &&
  429.             len > instruction->eops->next->next->offset)
  430.             len = instruction->eops->next->next->offset;
  431.         }
  432.         return instruction->times * len;
  433.     }
  434.     return 0;               /* if we're here, there's an error */
  435.     }
  436.  
  437.     temp = nasm_instructions[instruction->opcode];
  438.     while (temp->opcode != -1) {
  439.     if (matches(temp, instruction) == 100) {
  440.         /* we've matched an instruction. */
  441.         long isize;
  442.         char *codes = temp->code;
  443.         int j;
  444.  
  445.         isize = calcsize(segment, offset, bits, instruction, codes);
  446.         if (isize < 0)
  447.             return -1;
  448.         for (j = 0; j < instruction->nprefix; j++) {
  449.         if ((instruction->prefixes[j] != P_A16 &&
  450.              instruction->prefixes[j] != P_O16 && bits==16) ||
  451.             (instruction->prefixes[j] != P_A32 &&
  452.              instruction->prefixes[j] != P_O32 && bits==32))
  453.             isize++;
  454.         }
  455.         return isize * instruction->times;
  456.     }
  457.     temp++;
  458.     }
  459.     return -1;                   /* didn't match any instruction */
  460. }
  461.  
  462. static long calcsize (long segment, long offset, int bits,
  463.               insn *ins, char *codes) {
  464.     long length = 0;
  465.     unsigned char c;
  466.  
  467.     while (*codes) switch (c = *codes++) {
  468.       case 01: case 02: case 03:
  469.     codes += c, length += c; break;
  470.       case 04: case 05: case 06: case 07:
  471.     length++; break;
  472.       case 010: case 011: case 012:
  473.     codes++, length++; break;
  474.       case 017:
  475.     length++; break;
  476.       case 014: case 015: case 016:
  477.     length++; break;
  478.       case 020: case 021: case 022:
  479.     length++; break;
  480.       case 024: case 025: case 026:
  481.     length++; break;
  482.       case 030: case 031: case 032:
  483.     length += 2; break;
  484.       case 034: case 035: case 036:
  485.     length += ((ins->oprs[c-034].addr_size ?
  486.             ins->oprs[c-034].addr_size : bits) == 16 ? 2 : 4); break;
  487.       case 037:
  488.     length += 2; break;
  489.       case 040: case 041: case 042:
  490.     length += 4; break;
  491.       case 050: case 051: case 052:
  492.     length++; break;
  493.       case 060: case 061: case 062:
  494.     length += 2; break;
  495.       case 064: case 065: case 066:
  496.     length += ((ins->oprs[c-064].addr_size ?
  497.             ins->oprs[c-064].addr_size : bits) == 16 ? 2 : 4); break;
  498.       case 070: case 071: case 072:
  499.     length += 4; break;
  500.       case 0300: case 0301: case 0302:
  501.     length += chsize (&ins->oprs[c-0300], bits);
  502.     break;
  503.       case 0310:
  504.     length += (bits==32);
  505.     break;
  506.       case 0311:
  507.     length += (bits==16);
  508.     break;
  509.       case 0312:
  510.     break;
  511.       case 0320:
  512.     length += (bits==32);
  513.     break;
  514.       case 0321:
  515.     length += (bits==16);
  516.     break;
  517.       case 0322:
  518.     break;
  519.       case 0330:
  520.     codes++, length++; break;
  521.       case 0340: case 0341: case 0342:
  522.     if (ins->oprs[0].segment != NO_SEG)
  523.         errfunc (ERR_NONFATAL, "attempt to reserve non-constant"
  524.              " quantity of BSS space");
  525.     else
  526.         length += ins->oprs[0].offset << (c-0340);
  527.     break;
  528.       default:                   /* can't do it by 'case' statements */
  529.     if (c>=0100 && c<=0277) {      /* it's an EA */
  530.         ea ea_data;
  531.         if (!process_ea (&ins->oprs[(c>>3)&7], &ea_data, bits, 0,
  532.                  ins->forw_ref)) {
  533.             errfunc (ERR_NONFATAL, "invalid effective address");
  534.         return -1;
  535.         } else
  536.             length += ea_data.size;
  537.     } else
  538.         errfunc (ERR_PANIC, "internal instruction table corrupt"
  539.              ": instruction code 0x%02X given", c);
  540.     }
  541.     return length;
  542. }
  543.  
  544. static void gencode (long segment, long offset, int bits,
  545.              insn *ins, char *codes, long insn_end) {
  546.     static char condval[] = { /* conditional opcodes */
  547.     0x7, 0x3, 0x2, 0x6, 0x2, 0x4, 0xF, 0xD, 0xC, 0xE, 0x6, 0x2,
  548.     0x3, 0x7, 0x3, 0x5, 0xE, 0xC, 0xD, 0xF, 0x1, 0xB, 0x9, 0x5,
  549.     0x0, 0xA, 0xA, 0xB, 0x8, 0x4
  550.     };
  551.     unsigned char c, bytes[4];
  552.     long data, size;
  553.  
  554.     while (*codes) switch (c = *codes++) {
  555.       case 01: case 02: case 03:
  556.     out (offset, segment, codes, OUT_RAWDATA+c, NO_SEG, NO_SEG);
  557.     codes += c;
  558.     offset += c;
  559.     break;
  560.       case 04: case 06:
  561.     switch (ins->oprs[0].basereg) {
  562.       case R_CS: bytes[0] = 0x0E + (c == 0x04 ? 1 : 0); break;
  563.       case R_DS: bytes[0] = 0x1E + (c == 0x04 ? 1 : 0); break;
  564.       case R_ES: bytes[0] = 0x06 + (c == 0x04 ? 1 : 0); break;
  565.       case R_SS: bytes[0] = 0x16 + (c == 0x04 ? 1 : 0); break;
  566.       default:
  567.         errfunc (ERR_PANIC, "bizarre 8086 segment register received");
  568.     }
  569.     out (offset, segment, bytes, OUT_RAWDATA+1, NO_SEG, NO_SEG);
  570.     offset++;
  571.     break;
  572.       case 05: case 07:
  573.     switch (ins->oprs[0].basereg) {
  574.       case R_FS: bytes[0] = 0xA0 + (c == 0x05 ? 1 : 0); break;
  575.       case R_GS: bytes[0] = 0xA8 + (c == 0x05 ? 1 : 0); break;
  576.       default:
  577.         errfunc (ERR_PANIC, "bizarre 386 segment register received");
  578.     }
  579.     out (offset, segment, bytes, OUT_RAWDATA+1, NO_SEG, NO_SEG);
  580.     offset++;
  581.     break;
  582.       case 010: case 011: case 012:
  583.     bytes[0] = *codes++ + regval(&ins->oprs[c-010]);
  584.     out (offset, segment, bytes, OUT_RAWDATA+1, NO_SEG, NO_SEG);
  585.     offset += 1;
  586.     break;
  587.       case 017:
  588.     bytes[0] = 0;
  589.     out (offset, segment, bytes, OUT_RAWDATA+1, NO_SEG, NO_SEG);
  590.     offset += 1;
  591.     break;
  592.       case 014: case 015: case 016:
  593.     if (ins->oprs[c-014].offset < -128 || ins->oprs[c-014].offset > 127)
  594.         errfunc (ERR_WARNING, "signed byte value exceeds bounds");
  595.     if (ins->oprs[c-014].segment != NO_SEG) {
  596.         data = ins->oprs[c-014].offset;
  597.         out (offset, segment, &data, OUT_ADDRESS+1,
  598.          ins->oprs[c-014].segment, ins->oprs[c-014].wrt);
  599.     } else {
  600.         bytes[0] = ins->oprs[c-014].offset;
  601.         out (offset, segment, bytes, OUT_RAWDATA+1, NO_SEG, NO_SEG);
  602.     }
  603.     offset += 1;
  604.     break;
  605.       case 020: case 021: case 022:
  606.     if (ins->oprs[c-020].offset < -256 || ins->oprs[c-020].offset > 255)
  607.         errfunc (ERR_WARNING, "byte value exceeds bounds");
  608.     if (ins->oprs[c-020].segment != NO_SEG) {
  609.         data = ins->oprs[c-020].offset;
  610.         out (offset, segment, &data, OUT_ADDRESS+1,
  611.          ins->oprs[c-020].segment, ins->oprs[c-020].wrt);
  612.     } else {
  613.         bytes[0] = ins->oprs[c-020].offset;
  614.         out (offset, segment, bytes, OUT_RAWDATA+1, NO_SEG, NO_SEG);
  615.     }
  616.     offset += 1;
  617.     break;
  618.       case 024: case 025: case 026:
  619.     if (ins->oprs[c-024].offset < 0 || ins->oprs[c-024].offset > 255)
  620.         errfunc (ERR_WARNING, "unsigned byte value exceeds bounds");
  621.     if (ins->oprs[c-024].segment != NO_SEG) {
  622.         data = ins->oprs[c-024].offset;
  623.         out (offset, segment, &data, OUT_ADDRESS+1,
  624.          ins->oprs[c-024].segment, ins->oprs[c-024].wrt);
  625.     } else {
  626.         bytes[0] = ins->oprs[c-024].offset;
  627.         out (offset, segment, bytes, OUT_RAWDATA+1, NO_SEG, NO_SEG);
  628.     }
  629.     offset += 1;
  630.     break;
  631.       case 030: case 031: case 032:
  632.     if (ins->oprs[c-030].segment == NO_SEG &&
  633.         ins->oprs[c-030].wrt == NO_SEG &&
  634.         (ins->oprs[c-030].offset < -65536L ||
  635.         ins->oprs[c-030].offset > 65535L))
  636.         errfunc (ERR_WARNING, "word value exceeds bounds");
  637.     data = ins->oprs[c-030].offset;
  638.     out (offset, segment, &data, OUT_ADDRESS+2,
  639.             ins->oprs[c-030].segment, ins->oprs[c-030].wrt);
  640.     offset += 2;
  641.     break;
  642.       case 034: case 035: case 036:
  643.     data = ins->oprs[c-034].offset;
  644.     size = ((ins->oprs[c-034].addr_size ?
  645.          ins->oprs[c-034].addr_size : bits) == 16 ? 2 : 4);
  646.     if (size==16 && (data < -65536L || data > 65535L))
  647.         errfunc (ERR_WARNING, "word value exceeds bounds");
  648.     out (offset, segment, &data, OUT_ADDRESS+size,
  649.          ins->oprs[c-034].segment, ins->oprs[c-034].wrt);
  650.     offset += size;
  651.     break;
  652.       case 037:
  653.     if (ins->oprs[0].segment == NO_SEG)
  654.         errfunc (ERR_NONFATAL, "value referenced by FAR is not"
  655.              " relocatable");
  656.     data = 0L;
  657.     out (offset, segment, &data, OUT_ADDRESS+2,
  658.          outfmt->segbase(1+ins->oprs[0].segment),
  659.             ins->oprs[0].wrt);
  660.     offset += 2;
  661.     break;
  662.       case 040: case 041: case 042:
  663.     data = ins->oprs[c-040].offset;
  664.     out (offset, segment, &data, OUT_ADDRESS+4,
  665.          ins->oprs[c-040].segment, ins->oprs[c-040].wrt);
  666.     offset += 4;
  667.     break;
  668.       case 050: case 051: case 052:
  669.     if (ins->oprs[c-050].segment != segment)
  670.         errfunc (ERR_NONFATAL, "short relative jump outside segment");
  671.     data = ins->oprs[c-050].offset - insn_end;
  672.     if (data > 127 || data < -128)
  673.         errfunc (ERR_NONFATAL, "short jump is out of range");
  674.     bytes[0] = data;
  675.     out (offset, segment, bytes, OUT_RAWDATA+1, NO_SEG, NO_SEG);
  676.     offset += 1;
  677.     break;
  678.       case 060: case 061: case 062:
  679.     if (ins->oprs[c-060].segment != segment) {
  680.         data = ins->oprs[c-060].offset;
  681.         out (offset, segment, &data, OUT_REL2ADR+insn_end-offset,
  682.          ins->oprs[c-060].segment, ins->oprs[c-060].wrt);
  683.     } else {
  684.         data = ins->oprs[c-060].offset - insn_end;
  685.         out (offset, segment, &data,
  686.          OUT_ADDRESS+2, NO_SEG, NO_SEG);
  687.     }
  688.     offset += 2;
  689.     break;
  690.       case 064: case 065: case 066:
  691.     size = ((ins->oprs[c-064].addr_size ?
  692.          ins->oprs[c-064].addr_size : bits) == 16 ? 2 : 4);
  693.     if (ins->oprs[c-064].segment != segment) {
  694.         data = ins->oprs[c-064].offset;
  695.         size = (bits == 16 ? OUT_REL2ADR : OUT_REL4ADR);
  696.         out (offset, segment, &data, size+insn_end-offset,
  697.          ins->oprs[c-064].segment, ins->oprs[c-064].wrt);
  698.         size = (bits == 16 ? 2 : 4);
  699.     } else {
  700.         data = ins->oprs[c-064].offset - insn_end;
  701.         out (offset, segment, &data,
  702.          OUT_ADDRESS+size, NO_SEG, NO_SEG);
  703.     }
  704.     offset += size;
  705.     break;
  706.       case 070: case 071: case 072:
  707.     if (ins->oprs[c-070].segment != segment) {
  708.         data = ins->oprs[c-070].offset;
  709.         out (offset, segment, &data, OUT_REL4ADR+insn_end-offset,
  710.          ins->oprs[c-070].segment, ins->oprs[c-070].wrt);
  711.     } else {
  712.         data = ins->oprs[c-070].offset - insn_end;
  713.         out (offset, segment, &data,
  714.          OUT_ADDRESS+4, NO_SEG, NO_SEG);
  715.     }
  716.     offset += 4;
  717.     break;
  718.       case 0300: case 0301: case 0302:
  719.     if (chsize (&ins->oprs[c-0300], bits)) {
  720.         *bytes = 0x67;
  721.         out (offset, segment, bytes,
  722.          OUT_RAWDATA+1, NO_SEG, NO_SEG);
  723.         offset += 1;
  724.     } else
  725.         offset += 0;
  726.     break;
  727.       case 0310:
  728.     if (bits==32) {
  729.         *bytes = 0x67;
  730.         out (offset, segment, bytes,
  731.          OUT_RAWDATA+1, NO_SEG, NO_SEG);
  732.         offset += 1;
  733.     } else
  734.         offset += 0;
  735.     break;
  736.       case 0311:
  737.     if (bits==16) {
  738.         *bytes = 0x67;
  739.         out (offset, segment, bytes,
  740.          OUT_RAWDATA+1, NO_SEG, NO_SEG);
  741.         offset += 1;
  742.     } else
  743.         offset += 0;
  744.     break;
  745.       case 0312:
  746.     break;
  747.       case 0320:
  748.     if (bits==32) {
  749.         *bytes = 0x66;
  750.         out (offset, segment, bytes,
  751.          OUT_RAWDATA+1, NO_SEG, NO_SEG);
  752.         offset += 1;
  753.     } else
  754.         offset += 0;
  755.     break;
  756.       case 0321:
  757.     if (bits==16) {
  758.         *bytes = 0x66;
  759.         out (offset, segment, bytes,
  760.          OUT_RAWDATA+1, NO_SEG, NO_SEG);
  761.         offset += 1;
  762.     } else
  763.         offset += 0;
  764.     break;
  765.       case 0322:
  766.     break;
  767.       case 0330:
  768.     *bytes = *codes++ + condval[ins->condition];
  769.     out (offset, segment, bytes,
  770.          OUT_RAWDATA+1, NO_SEG, NO_SEG);
  771.     offset += 1;
  772.     break;
  773.       case 0340: case 0341: case 0342:
  774.     if (ins->oprs[0].segment != NO_SEG)
  775.         errfunc (ERR_PANIC, "non-constant BSS size in pass two");
  776.     else {
  777.         long size = ins->oprs[0].offset << (c-0340);
  778.         if (size > 0)
  779.         out (offset, segment, NULL,
  780.              OUT_RESERVE+size, NO_SEG, NO_SEG);
  781.         offset += size;
  782.     }
  783.     break;
  784.       default:                   /* can't do it by 'case' statements */
  785.     if (c>=0100 && c<=0277) {      /* it's an EA */
  786.         ea ea_data;
  787.         int rfield;
  788.         unsigned char *p;
  789.         long s;
  790.  
  791.         if (c<=0177)           /* pick rfield from operand b */
  792.         rfield = regval (&ins->oprs[c&7]);
  793.         else                /* rfield is constant */
  794.             rfield = c & 7;
  795.         if (!process_ea (&ins->oprs[(c>>3)&7], &ea_data, bits, rfield,
  796.                  ins->forw_ref))
  797.             errfunc (ERR_NONFATAL, "invalid effective address");
  798.  
  799.         p = bytes;
  800.         *p++ = ea_data.modrm;
  801.         if (ea_data.sib_present)
  802.             *p++ = ea_data.sib;
  803.         /*
  804.          * the cast in the next line is to placate MS C...
  805.          */
  806.         out (offset, segment, bytes, OUT_RAWDATA+(long)(p-bytes),
  807.          NO_SEG, NO_SEG);
  808.         s = p-bytes;
  809.  
  810.         switch (ea_data.bytes) {
  811.           case 0:
  812.         break;
  813.           case 1:
  814.         if (ins->oprs[(c>>3)&7].segment != NO_SEG) {
  815.             data = ins->oprs[(c>>3)&7].offset;
  816.             out (offset, segment, &data, OUT_ADDRESS+1,
  817.              ins->oprs[(c>>3)&7].segment,
  818.              ins->oprs[(c>>3)&7].wrt);
  819.         } else {
  820.             *bytes = ins->oprs[(c>>3)&7].offset;
  821.             out (offset, segment, bytes, OUT_RAWDATA+1,
  822.              NO_SEG, NO_SEG);
  823.         }
  824.         s++;
  825.         break;
  826.           case 2:
  827.           case 4:
  828.         data = ins->oprs[(c>>3)&7].offset;
  829.         out (offset, segment, &data,
  830.              OUT_ADDRESS+ea_data.bytes,
  831.              ins->oprs[(c>>3)&7].segment, ins->oprs[(c>>3)&7].wrt);
  832.         s += ea_data.bytes;
  833.         break;
  834.         }
  835.         offset += s;
  836.     } else
  837.         errfunc (ERR_PANIC, "internal instruction table corrupt"
  838.              ": instruction code 0x%02X given", c);
  839.     }
  840. }
  841.  
  842. static int regval (operand *o) {
  843.     switch (o->basereg) {
  844.       case R_EAX: case R_AX: case R_AL: case R_ES: case R_CR0: case R_DR0:
  845.       case R_ST0: case R_MM0:
  846.     return 0;
  847.       case R_ECX: case R_CX: case R_CL: case R_CS: case R_DR1: case R_ST1:
  848.       case R_MM1:
  849.     return 1;
  850.       case R_EDX: case R_DX: case R_DL: case R_SS: case R_CR2: case R_DR2:
  851.       case R_ST2: case R_MM2:
  852.     return 2;
  853.       case R_EBX: case R_BX: case R_BL: case R_DS: case R_CR3: case R_DR3:
  854.       case R_TR3: case R_ST3: case R_MM3:
  855.     return 3;
  856.       case R_ESP: case R_SP: case R_AH: case R_FS: case R_CR4: case R_TR4:
  857.       case R_ST4: case R_MM4:
  858.     return 4;
  859.       case R_EBP: case R_BP: case R_CH: case R_GS: case R_TR5: case R_ST5:
  860.       case R_MM5:
  861.     return 5;
  862.       case R_ESI: case R_SI: case R_DH: case R_DR6: case R_TR6: case R_ST6:
  863.       case R_MM6:
  864.     return 6;
  865.       case R_EDI: case R_DI: case R_BH: case R_DR7: case R_TR7: case R_ST7:
  866.       case R_MM7:
  867.     return 7;
  868.       default:                   /* panic */
  869.     errfunc (ERR_PANIC, "invalid register operand given to regval()");
  870.     return 0;
  871.     }
  872. }
  873.  
  874. static int matches (struct itemplate *itemp, insn *instruction) {
  875.     int i, size, oprs, ret;
  876.  
  877.     ret = 100;
  878.  
  879.     /*
  880.      * Check the opcode
  881.      */
  882.     if (itemp->opcode != instruction->opcode) return 0;
  883.  
  884.     /*
  885.      * Count the operands
  886.      */
  887.     if (itemp->operands != instruction->operands) return 0;
  888.  
  889.     /*
  890.      * Check that no spurious colons or TOs are present
  891.      */
  892.     for (i=0; i<itemp->operands; i++)
  893.     if (instruction->oprs[i].type & ~itemp->opd[i] & (COLON|TO))
  894.         return 0;
  895.  
  896.     /*
  897.      * Check that the operand flags all match up
  898.      */
  899.     for (i=0; i<itemp->operands; i++)
  900.     if (itemp->opd[i] & ~instruction->oprs[i].type ||
  901.         ((itemp->opd[i] & SIZE_MASK) &&
  902.          ((itemp->opd[i] ^ instruction->oprs[i].type) & SIZE_MASK))) {
  903.         if ((itemp->opd[i] & ~instruction->oprs[i].type & NON_SIZE) ||
  904.         (instruction->oprs[i].type & SIZE_MASK))
  905.         return 0;
  906.         else
  907.         ret = 1;
  908.     }
  909.  
  910.     /*
  911.      * Check operand sizes
  912.      */
  913.     if (itemp->flags & IF_SB) {
  914.     size = BITS8;
  915.     oprs = itemp->operands;
  916.     } else if (itemp->flags & IF_SW) {
  917.     size = BITS16;
  918.     oprs = itemp->operands;
  919.     } else if (itemp->flags & IF_SD) {
  920.     size = BITS32;
  921.     oprs = itemp->operands;
  922.     } else if (itemp->flags & (IF_SM | IF_SM2)) {
  923.     oprs = (itemp->flags & IF_SM2 ? 2 : itemp->operands);
  924.     size = 0;               /* placate gcc */
  925.     for (i=0; i<oprs; i++)
  926.         if ( (size = itemp->opd[i] & SIZE_MASK) != 0)
  927.         break;
  928.     } else {
  929.     size = 0;
  930.     oprs = itemp->operands;
  931.     }
  932.  
  933.     for (i=0; i<itemp->operands; i++)
  934.     if (!(itemp->opd[i] & SIZE_MASK) &&
  935.         (instruction->oprs[i].type & SIZE_MASK & ~size))
  936.         ret = 2;
  937.  
  938.     return ret;
  939. }
  940.  
  941. static ea *process_ea (operand *input, ea *output, int addrbits, int rfield,
  942.                int forw_ref) {
  943.     if (!(REGISTER & ~input->type)) {  /* it's a single register */
  944.     static int regs[] = {
  945.         R_MM0, R_EAX, R_AX, R_AL, R_MM1, R_ECX, R_CX, R_CL,
  946.         R_MM2, R_EDX, R_DX, R_DL, R_MM3, R_EBX, R_BX, R_BL,
  947.         R_MM4, R_ESP, R_SP, R_AH, R_MM5, R_EBP, R_BP, R_CH,
  948.         R_MM6, R_ESI, R_SI, R_DH, R_MM7, R_EDI, R_DI, R_BH
  949.     };
  950.     int i;
  951.  
  952.     for (i=0; i<elements(regs); i++)
  953.         if (input->basereg == regs[i]) break;
  954.     if (i<elements(regs)) {
  955.         output->sib_present = FALSE;/* no SIB necessary */
  956.         output->bytes = 0;           /* no offset necessary either */
  957.         output->modrm = 0xC0 | (rfield << 3) | (i/4);
  958.     } else
  959.         return NULL;
  960.     } else {                   /* it's a memory reference */
  961.     if (input->basereg==-1 && (input->indexreg==-1 || input->scale==0)) {
  962.         /* it's a pure offset */
  963.         if (input->addr_size)
  964.         addrbits = input->addr_size;
  965.         output->sib_present = FALSE;
  966.         output->bytes = (addrbits==32 ? 4 : 2);
  967.         output->modrm = (addrbits==32 ? 5 : 6) | (rfield << 3);
  968.     } else {               /* it's an indirection */
  969.         int i=input->indexreg, b=input->basereg, s=input->scale;
  970.         long o=input->offset, seg=input->segment;
  971.         int hb=input->hintbase, ht=input->hinttype;
  972.         int t;
  973.  
  974.         if (s==0) i = -1;           /* make this easy, at least */
  975.  
  976.         if (i==R_EAX || i==R_EBX || i==R_ECX || i==R_EDX
  977.         || i==R_EBP || i==R_ESP || i==R_ESI || i==R_EDI
  978.         || b==R_EAX || b==R_EBX || b==R_ECX || b==R_EDX
  979.         || b==R_EBP || b==R_ESP || b==R_ESI || b==R_EDI) {
  980.         /* it must be a 32-bit memory reference. Firstly we have
  981.          * to check that all registers involved are type Exx. */
  982.         if (i!=-1 && i!=R_EAX && i!=R_EBX && i!=R_ECX && i!=R_EDX
  983.             && i!=R_EBP && i!=R_ESP && i!=R_ESI && i!=R_EDI)
  984.             return NULL;
  985.         if (b!=-1 && b!=R_EAX && b!=R_EBX && b!=R_ECX && b!=R_EDX
  986.             && b!=R_EBP && b!=R_ESP && b!=R_ESI && b!=R_EDI)
  987.             return NULL;
  988.  
  989.         /* While we're here, ensure the user didn't specify WORD. */
  990.         if (input->addr_size == 16)
  991.             return NULL;
  992.  
  993.         /* now reorganise base/index */
  994.         if (s == 1 && b != i && b != -1 && i != -1 &&
  995.             ((hb==b&&ht==EAH_NOTBASE) || (hb==i&&ht==EAH_MAKEBASE)))
  996.             t = b, b = i, i = t;   /* swap if hints say so */
  997.         if (b==i)           /* convert EAX+2*EAX to 3*EAX */
  998.             b = -1, s++;
  999.         if (b==-1 && s==1 && !(hb == i && ht == EAH_NOTBASE))
  1000.             b = i, i = -1;     /* make single reg base, unless hint */
  1001.         if (((s==2 && i!=R_ESP && !(input->eaflags & EAF_TIMESTWO)) ||
  1002.              s==3 || s==5 || s==9) && b==-1)
  1003.             b = i, s--;       /* convert 3*EAX to EAX+2*EAX */
  1004.         if (s==1 && i==R_ESP)  /* swap ESP into base if scale is 1 */
  1005.             i = b, b = R_ESP;
  1006.         if (i==R_ESP || (s!=1 && s!=2 && s!=4 && s!=8 && i!=-1))
  1007.             return NULL;      /* wrong, for various reasons */
  1008.  
  1009.         if (i==-1 && b!=R_ESP) {/* no SIB needed */
  1010.             int mod, rm;
  1011.             switch(b) {
  1012.               case R_EAX: rm = 0; break;
  1013.               case R_ECX: rm = 1; break;
  1014.               case R_EDX: rm = 2; break;
  1015.               case R_EBX: rm = 3; break;
  1016.               case R_EBP: rm = 5; break;
  1017.               case R_ESI: rm = 6; break;
  1018.               case R_EDI: rm = 7; break;
  1019.               case -1: rm = 5; break;
  1020.               default:           /* should never happen */
  1021.             return NULL;
  1022.             }
  1023.             if (b==-1 || (b!=R_EBP && o==0 &&
  1024.                   seg==NO_SEG && !forw_ref &&
  1025.                   !(input->eaflags &
  1026.                     (EAF_BYTEOFFS|EAF_WORDOFFS))))
  1027.                 mod = 0;
  1028.             else if (input->eaflags & EAF_BYTEOFFS ||
  1029.                  (o>=-128 && o<=127 && seg==NO_SEG && !forw_ref &&
  1030.                   !(input->eaflags & EAF_WORDOFFS))) {
  1031.                 mod = 1;
  1032.             } else
  1033.                 mod = 2;
  1034.  
  1035.             output->sib_present = FALSE;
  1036.             output->bytes = (b==-1 || mod==2 ? 4 : mod);
  1037.             output->modrm = (mod<<6) | (rfield<<3) | rm;
  1038.         } else {           /* we need a SIB */
  1039.             int mod, scale, index, base;
  1040.  
  1041.             switch (b) {
  1042.               case R_EAX: base = 0; break;
  1043.               case R_ECX: base = 1; break;
  1044.               case R_EDX: base = 2; break;
  1045.               case R_EBX: base = 3; break;
  1046.               case R_ESP: base = 4; break;
  1047.               case R_EBP: case -1: base = 5; break;
  1048.               case R_ESI: base = 6; break;
  1049.               case R_EDI: base = 7; break;
  1050.               default:           /* then what the smeg is it? */
  1051.             return NULL;  /* panic */
  1052.             }
  1053.  
  1054.             switch (i) {
  1055.               case R_EAX: index = 0; break;
  1056.               case R_ECX: index = 1; break;
  1057.               case R_EDX: index = 2; break;
  1058.               case R_EBX: index = 3; break;
  1059.               case -1: index = 4; break;
  1060.               case R_EBP: index = 5; break;
  1061.               case R_ESI: index = 6; break;
  1062.               case R_EDI: index = 7; break;
  1063.               default:           /* then what the smeg is it? */
  1064.             return NULL;  /* panic */
  1065.             }
  1066.  
  1067.             if (i==-1) s = 1;
  1068.             switch (s) {
  1069.               case 1: scale = 0; break;
  1070.               case 2: scale = 1; break;
  1071.               case 4: scale = 2; break;
  1072.               case 8: scale = 3; break;
  1073.               default:           /* then what the smeg is it? */
  1074.             return NULL;  /* panic */
  1075.             }
  1076.  
  1077.             if (b==-1 || (b!=R_EBP && o==0 &&
  1078.                   seg==NO_SEG && !forw_ref &&
  1079.                   !(input->eaflags &
  1080.                     (EAF_BYTEOFFS|EAF_WORDOFFS))))
  1081.                 mod = 0;
  1082.             else if (input->eaflags & EAF_BYTEOFFS ||
  1083.                  (o>=-128 && o<=127 && seg==NO_SEG && !forw_ref &&
  1084.                   !(input->eaflags & EAF_WORDOFFS)))
  1085.                 mod = 1;
  1086.             else
  1087.                 mod = 2;
  1088.  
  1089.             output->sib_present = TRUE;
  1090.             output->bytes = (b==-1 || mod==2 ? 4 : mod);
  1091.             output->modrm = (mod<<6) | (rfield<<3) | 4;
  1092.             output->sib = (scale<<6) | (index<<3) | base;
  1093.         }
  1094.         } else {               /* it's 16-bit */
  1095.         int mod, rm;
  1096.  
  1097.         /* check all registers are BX, BP, SI or DI */
  1098.         if ((b!=-1 && b!=R_BP && b!=R_BX && b!=R_SI && b!=R_DI) ||
  1099.             (i!=-1 && i!=R_BP && i!=R_BX && i!=R_SI && i!=R_DI))
  1100.             return NULL;
  1101.  
  1102.         /* ensure the user didn't specify DWORD */
  1103.         if (input->addr_size == 32)
  1104.             return NULL;
  1105.  
  1106.         if (s!=1 && i!=-1) return NULL;/* no can do, in 16-bit EA */
  1107.         if (b==-1 && i!=-1) b ^= i ^= b ^= i;   /* swap them round */
  1108.         if ((b==R_SI || b==R_DI) && i!=-1)
  1109.             b ^= i ^= b ^= i; /* have BX/BP as base, SI/DI index */
  1110.         if (b==i) return NULL;/* shouldn't ever happen, in theory */
  1111.         if (i!=-1 && b!=-1 &&
  1112.             (i==R_BP || i==R_BX || b==R_SI || b==R_DI))
  1113.             return NULL;      /* invalid combinations */
  1114.         if (b==-1)           /* pure offset: handled above */
  1115.             return NULL;      /* so if it gets to here, panic! */
  1116.  
  1117.         rm = -1;
  1118.         if (i!=-1)
  1119.             switch (i*256 + b) {
  1120.               case R_SI*256+R_BX: rm=0; break;
  1121.               case R_DI*256+R_BX: rm=1; break;
  1122.               case R_SI*256+R_BP: rm=2; break;
  1123.               case R_DI*256+R_BP: rm=3; break;
  1124.             }
  1125.         else
  1126.             switch (b) {
  1127.               case R_SI: rm=4; break;
  1128.               case R_DI: rm=5; break;
  1129.               case R_BP: rm=6; break;
  1130.               case R_BX: rm=7; break;
  1131.             }
  1132.         if (rm==-1)           /* can't happen, in theory */
  1133.             return NULL;      /* so panic if it does */
  1134.  
  1135.         if (o==0 && seg==NO_SEG && !forw_ref && rm!=6 &&
  1136.             !(input->eaflags & (EAF_BYTEOFFS|EAF_WORDOFFS)))
  1137.             mod = 0;
  1138.         else if (input->eaflags & EAF_BYTEOFFS ||
  1139.              (o>=-128 && o<=127 && seg==NO_SEG && !forw_ref &&
  1140.               !(input->eaflags & EAF_WORDOFFS)))
  1141.             mod = 1;
  1142.         else
  1143.             mod = 2;
  1144.  
  1145.         output->sib_present = FALSE;  /* no SIB - it's 16-bit */
  1146.         output->bytes = mod;  /* bytes of offset needed */
  1147.         output->modrm = (mod<<6) | (rfield<<3) | rm;
  1148.         }
  1149.     }
  1150.     }
  1151.     output->size = 1 + output->sib_present + output->bytes;
  1152.     return output;
  1153. }
  1154.  
  1155. static int chsize (operand *input, int addrbits) {
  1156.     if (!(MEMORY & ~input->type)) {
  1157.     int i=input->indexreg, b=input->basereg;
  1158.  
  1159.     if (input->scale==0) i = -1;
  1160.  
  1161.     if (i == -1 && b == -1) /* pure offset */
  1162.         return (input->addr_size != 0 && input->addr_size != addrbits);
  1163.  
  1164.     if (i==R_EAX || i==R_EBX || i==R_ECX || i==R_EDX
  1165.         || i==R_EBP || i==R_ESP || i==R_ESI || i==R_EDI
  1166.         || b==R_EAX || b==R_EBX || b==R_ECX || b==R_EDX
  1167.         || b==R_EBP || b==R_ESP || b==R_ESI || b==R_EDI)
  1168.         return (addrbits==16);
  1169.     else
  1170.         return (addrbits==32);
  1171.     } else
  1172.         return 0;
  1173. }
  1174.