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