NASM 0.96
[platform/upstream/nasm.git] / assemble.c
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 }