Avoid releasing intermediate files in the doc bundle
[nasm.git] / assemble.c
blobb87b10408ed24309b58b36e82a506a8617eaa70c
1 /* assemble.c code generation for the Netwide Assembler
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.
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 operand-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 * \130,\131,\132 - an immediate word or signed byte for operand 0, 1, or 2
36 * \133,\134,\135 - or 2 (s-field) into next opcode byte if operand 0, 1, or 2
37 * is a signed byte rather than a word.
38 * \140,\141,\142 - an immediate dword or signed byte for operand 0, 1, or 2
39 * \143,\144,\145 - or 2 (s-field) into next opcode byte if operand 0, 1, or 2
40 * is a signed byte rather than a dword.
41 * \2ab - a ModRM, calculated on EA in operand a, with the spare
42 * field equal to digit b.
43 * \30x - might be an 0x67 byte, depending on the address size of
44 * the memory reference in operand x.
45 * \310 - indicates fixed 16-bit address size, i.e. optional 0x67.
46 * \311 - indicates fixed 32-bit address size, i.e. optional 0x67.
47 * \312 - (disassembler only) marker on LOOP, LOOPxx instructions.
48 * \320 - indicates fixed 16-bit operand size, i.e. optional 0x66.
49 * \321 - indicates fixed 32-bit operand size, i.e. optional 0x66.
50 * \322 - indicates that this instruction is only valid when the
51 * operand size is the default (instruction to disassembler,
52 * generates no code in the assembler)
53 * \330 - a literal byte follows in the code stream, to be added
54 * to the condition code value of the instruction.
55 * \331 - instruction not valid with REP prefix. Hint for
56 * disassembler only; for SSE instructions.
57 * \332 - disassemble a rep (0xF3 byte) prefix as repe not rep.
58 * \333 - REP prefix (0xF3 byte); for SSE instructions. Not encoded
59 * as a literal byte in order to aid the disassembler.
60 * \340 - reserve <operand 0> bytes of uninitialised storage.
61 * Operand 0 had better be a segmentless constant.
62 * \370,\371,\372 - match only if operand 0 meets byte jump criteria.
63 * 370 is used for Jcc, 371 is used for JMP.
64 * \373 - assemble 0x03 if bits==16, 0x05 if bits==32;
65 * used for conditional jump over longer jump
68 #include <stdio.h>
69 #include <string.h>
71 #include "nasm.h"
72 #include "nasmlib.h"
73 #include "assemble.h"
74 #include "insns.h"
76 extern struct itemplate *nasm_instructions[];
78 typedef struct {
79 int sib_present; /* is a SIB byte necessary? */
80 int bytes; /* # of bytes of offset needed */
81 int size; /* lazy - this is sib+bytes+1 */
82 unsigned char modrm, sib; /* the bytes themselves */
83 } ea;
85 static unsigned long cpu; /* cpu level received from nasm.c */
86 static efunc errfunc;
87 static struct ofmt *outfmt;
88 static ListGen *list;
90 static long calcsize (long, long, int, insn *, char *);
91 static void gencode (long, long, int, insn *, char *, long);
92 static int regval (operand *o);
93 static int matches (struct itemplate *, insn *);
94 static ea * process_ea (operand *, ea *, int, int, int);
95 static int chsize (operand *, int);
98 * This routine wrappers the real output format's output routine,
99 * in order to pass a copy of the data off to the listing file
100 * generator at the same time.
102 static void out (long offset, long segto, void *data, unsigned long type,
103 long segment, long wrt)
105 long lineno;
106 char *lnfname = NULL;
108 if ((type & OUT_TYPMASK) == OUT_ADDRESS) {
109 if (segment != NO_SEG || wrt != NO_SEG) {
111 * This address is relocated. We must write it as
112 * OUT_ADDRESS, so there's no work to be done here.
114 list->output (offset, data, type);
116 else {
117 unsigned char p[4], *q = p;
119 * This is a non-relocated address, and we're going to
120 * convert it into RAWDATA format.
122 if ((type & OUT_SIZMASK) == 4) {
123 WRITELONG (q, * (long *) data);
124 list->output (offset, p, OUT_RAWDATA+4);
126 else {
127 WRITESHORT (q, * (long *) data);
128 list->output (offset, p, OUT_RAWDATA+2);
132 else if ((type & OUT_TYPMASK) == OUT_RAWDATA) {
133 list->output (offset, data, type);
135 else if ((type & OUT_TYPMASK) == OUT_RESERVE) {
136 list->output (offset, NULL, type);
138 else if ((type & OUT_TYPMASK) == OUT_REL2ADR ||
139 (type & OUT_TYPMASK) == OUT_REL4ADR) {
140 list->output (offset, data, type);
143 if (src_get(&lineno,&lnfname))
145 outfmt->current_dfmt->linenum(lnfname,lineno,segto);
146 if (lnfname) nasm_free(lnfname);
149 outfmt->output (segto, data, type, segment, wrt);
152 static int jmp_match (long segment, long offset, int bits,
153 insn *ins, char *code)
154 { long isize;
155 unsigned char c = code[0];
158 if (c != 0370 && c != 0371) return 0;
159 if (ins->oprs[0].opflags & OPFLAG_FORWARD) {
160 if ((optimizing<0 || (ins->oprs[0].type & STRICT))
161 && c==0370) return 1;
162 else return (pass0==0); /* match a forward reference */
164 isize = calcsize (segment, offset, bits, ins, code);
165 if (ins->oprs[0].segment != segment) return 0;
166 isize = ins->oprs[0].offset - offset - isize; /* isize is now the delta */
167 if (isize >= -128L && isize <= 127L) return 1; /* it is byte size */
169 return 0;
173 long assemble (long segment, long offset, int bits, unsigned long cp,
174 insn *instruction, struct ofmt *output, efunc error,
175 ListGen *listgen)
177 struct itemplate *temp;
178 int j;
179 int size_prob;
180 long insn_end;
181 long itimes;
182 long start = offset;
183 long wsize = 0; /* size for DB etc. */
185 errfunc = error; /* to pass to other functions */
186 cpu = cp;
187 outfmt = output; /* likewise */
188 list = listgen; /* and again */
190 switch (instruction->opcode)
192 case -1: return 0;
193 case I_DB: wsize = 1; break;
194 case I_DW: wsize = 2; break;
195 case I_DD: wsize = 4; break;
196 case I_DQ: wsize = 8; break;
197 case I_DT: wsize = 10; break;
200 if (wsize) {
201 extop * e;
202 long t = instruction->times;
203 if (t < 0)
204 errfunc(ERR_PANIC, "instruction->times < 0 (%ld) in assemble()",t);
206 while (t--) /* repeat TIMES times */
208 for (e = instruction->eops; e; e = e->next)
210 if (e->type == EOT_DB_NUMBER)
212 if (wsize == 1) {
213 if (e->segment != NO_SEG)
214 errfunc (ERR_NONFATAL,
215 "one-byte relocation attempted");
216 else {
217 unsigned char out_byte = e->offset;
218 out (offset, segment, &out_byte, OUT_RAWDATA+1,
219 NO_SEG, NO_SEG);
222 else if (wsize > 5) {
223 errfunc (ERR_NONFATAL, "integer supplied to a D%c"
224 " instruction", wsize==8 ? 'Q' : 'T');
226 else
227 out (offset, segment, &e->offset,
228 OUT_ADDRESS+wsize, e->segment,
229 e->wrt);
230 offset += wsize;
232 else if (e->type == EOT_DB_STRING)
234 int align;
236 out (offset, segment, e->stringval,
237 OUT_RAWDATA+e->stringlen, NO_SEG, NO_SEG);
238 align = e->stringlen % wsize;
240 if (align) {
241 align = wsize - align;
242 out (offset, segment, "\0\0\0\0\0\0\0\0",
243 OUT_RAWDATA+align, NO_SEG, NO_SEG);
245 offset += e->stringlen + align;
248 if (t > 0 && t == instruction->times-1)
251 * Dummy call to list->output to give the offset to the
252 * listing module.
254 list->output (offset, NULL, OUT_RAWDATA);
255 list->uplevel (LIST_TIMES);
258 if (instruction->times > 1)
259 list->downlevel (LIST_TIMES);
260 return offset - start;
263 if (instruction->opcode == I_INCBIN)
265 static char fname[FILENAME_MAX];
266 FILE * fp;
267 long len;
269 len = FILENAME_MAX-1;
270 if (len > instruction->eops->stringlen)
271 len = instruction->eops->stringlen;
272 strncpy (fname, instruction->eops->stringval, len);
273 fname[len] = '\0';
275 if ( (fp = fopen(fname, "rb")) == NULL)
276 error (ERR_NONFATAL, "`incbin': unable to open file `%s'", fname);
277 else if (fseek(fp, 0L, SEEK_END) < 0)
278 error (ERR_NONFATAL, "`incbin': unable to seek on file `%s'",
279 fname);
280 else
282 static char buf[2048];
283 long t = instruction->times;
284 long base = 0;
286 len = ftell (fp);
287 if (instruction->eops->next) {
288 base = instruction->eops->next->offset;
289 len -= base;
290 if (instruction->eops->next->next &&
291 len > instruction->eops->next->next->offset)
292 len = instruction->eops->next->next->offset;
295 * Dummy call to list->output to give the offset to the
296 * listing module.
298 list->output (offset, NULL, OUT_RAWDATA);
299 list->uplevel(LIST_INCBIN);
300 while (t--)
302 long l;
304 fseek (fp, base, SEEK_SET);
305 l = len;
306 while (l > 0) {
307 long m = fread (buf, 1, (l>sizeof(buf)?sizeof(buf):l),
308 fp);
309 if (!m) {
311 * This shouldn't happen unless the file
312 * actually changes while we are reading
313 * it.
315 error (ERR_NONFATAL, "`incbin': unexpected EOF while"
316 " reading file `%s'", fname);
317 t=0; /* Try to exit cleanly */
318 break;
320 out (offset, segment, buf, OUT_RAWDATA+m,
321 NO_SEG, NO_SEG);
322 l -= m;
325 list->downlevel(LIST_INCBIN);
326 if (instruction->times > 1) {
328 * Dummy call to list->output to give the offset to the
329 * listing module.
331 list->output (offset, NULL, OUT_RAWDATA);
332 list->uplevel(LIST_TIMES);
333 list->downlevel(LIST_TIMES);
335 fclose (fp);
336 return instruction->times * len;
338 return 0; /* if we're here, there's an error */
341 size_prob = FALSE;
342 temp = nasm_instructions[instruction->opcode];
343 while (temp->opcode != -1) {
344 int m = matches (temp, instruction);
345 if (m == 99)
346 m += jmp_match(segment, offset, bits, instruction, temp->code);
348 if (m == 100) /* matches! */
350 char *codes = temp->code;
351 long insn_size = calcsize(segment, offset, bits,
352 instruction, codes);
353 itimes = instruction->times;
354 if (insn_size < 0) /* shouldn't be, on pass two */
355 error (ERR_PANIC, "errors made it through from pass one");
356 else while (itimes--) {
357 insn_end = offset + insn_size;
358 for (j=0; j<instruction->nprefix; j++) {
359 unsigned char c=0;
360 switch (instruction->prefixes[j]) {
361 case P_LOCK:
362 c = 0xF0; break;
363 case P_REPNE: case P_REPNZ:
364 c = 0xF2; break;
365 case P_REPE: case P_REPZ: case P_REP:
366 c = 0xF3; break;
367 case R_CS: c = 0x2E; break;
368 case R_DS: c = 0x3E; break;
369 case R_ES: c = 0x26; break;
370 case R_FS: c = 0x64; break;
371 case R_GS: c = 0x65; break;
372 case R_SS: c = 0x36; break;
373 case P_A16:
374 if (bits != 16)
375 c = 0x67;
376 break;
377 case P_A32:
378 if (bits != 32)
379 c = 0x67;
380 break;
381 case P_O16:
382 if (bits != 16)
383 c = 0x66;
384 break;
385 case P_O32:
386 if (bits != 32)
387 c = 0x66;
388 break;
389 default:
390 error (ERR_PANIC,
391 "invalid instruction prefix");
393 if (c != 0) {
394 out (offset, segment, &c, OUT_RAWDATA+1,
395 NO_SEG, NO_SEG);
396 offset++;
399 gencode (segment, offset, bits, instruction, codes, insn_end);
400 offset += insn_size;
401 if (itimes > 0 && itimes == instruction->times-1) {
403 * Dummy call to list->output to give the offset to the
404 * listing module.
406 list->output (offset, NULL, OUT_RAWDATA);
407 list->uplevel (LIST_TIMES);
410 if (instruction->times > 1)
411 list->downlevel (LIST_TIMES);
412 return offset - start;
413 } else if (m > 0 && m > size_prob) {
414 size_prob = m;
416 temp++;
419 if (temp->opcode == -1) { /* didn't match any instruction */
420 if (size_prob == 1) /* would have matched, but for size */
421 error (ERR_NONFATAL, "operation size not specified");
422 else if (size_prob == 2)
423 error (ERR_NONFATAL, "mismatch in operand sizes");
424 else if (size_prob == 3)
425 error (ERR_NONFATAL, "no instruction for this cpu level");
426 else
427 error (ERR_NONFATAL,
428 "invalid combination of opcode and operands");
430 return 0;
433 long insn_size (long segment, long offset, int bits, unsigned long cp,
434 insn *instruction, efunc error)
436 struct itemplate *temp;
438 errfunc = error; /* to pass to other functions */
439 cpu = cp;
441 if (instruction->opcode == -1)
442 return 0;
444 if (instruction->opcode == I_DB ||
445 instruction->opcode == I_DW ||
446 instruction->opcode == I_DD ||
447 instruction->opcode == I_DQ ||
448 instruction->opcode == I_DT)
450 extop *e;
451 long isize, osize, wsize = 0; /* placate gcc */
453 isize = 0;
454 switch (instruction->opcode)
456 case I_DB: wsize = 1; break;
457 case I_DW: wsize = 2; break;
458 case I_DD: wsize = 4; break;
459 case I_DQ: wsize = 8; break;
460 case I_DT: wsize = 10; break;
463 for (e = instruction->eops; e; e = e->next)
465 long align;
467 osize = 0;
468 if (e->type == EOT_DB_NUMBER)
469 osize = 1;
470 else if (e->type == EOT_DB_STRING)
471 osize = e->stringlen;
473 align = (-osize) % wsize;
474 if (align < 0)
475 align += wsize;
476 isize += osize + align;
478 return isize * instruction->times;
481 if (instruction->opcode == I_INCBIN)
483 char fname[FILENAME_MAX];
484 FILE * fp;
485 long len;
487 len = FILENAME_MAX-1;
488 if (len > instruction->eops->stringlen)
489 len = instruction->eops->stringlen;
490 strncpy (fname, instruction->eops->stringval, len);
491 fname[len] = '\0';
492 if ( (fp = fopen(fname, "rb")) == NULL )
493 error (ERR_NONFATAL, "`incbin': unable to open file `%s'", fname);
494 else if (fseek(fp, 0L, SEEK_END) < 0)
495 error (ERR_NONFATAL, "`incbin': unable to seek on file `%s'",
496 fname);
497 else
499 len = ftell (fp);
500 fclose (fp);
501 if (instruction->eops->next)
503 len -= instruction->eops->next->offset;
504 if (instruction->eops->next->next &&
505 len > instruction->eops->next->next->offset)
507 len = instruction->eops->next->next->offset;
510 return instruction->times * len;
512 return 0; /* if we're here, there's an error */
515 temp = nasm_instructions[instruction->opcode];
516 while (temp->opcode != -1) {
517 int m = matches(temp, instruction);
518 if (m == 99)
519 m += jmp_match(segment, offset, bits, instruction, temp->code);
521 if (m == 100) {
522 /* we've matched an instruction. */
523 long isize;
524 char * codes = temp->code;
525 int j;
527 isize = calcsize(segment, offset, bits, instruction, codes);
528 if (isize < 0)
529 return -1;
530 for (j = 0; j < instruction->nprefix; j++)
532 if ((instruction->prefixes[j] != P_A16 &&
533 instruction->prefixes[j] != P_O16 && bits==16) ||
534 (instruction->prefixes[j] != P_A32 &&
535 instruction->prefixes[j] != P_O32 && bits==32))
537 isize++;
540 return isize * instruction->times;
542 temp++;
544 return -1; /* didn't match any instruction */
548 /* check that opn[op] is a signed byte of size 16 or 32,
549 and return the signed value*/
550 static int is_sbyte (insn *ins, int op, int size)
552 signed long v;
553 int ret;
555 ret = !(ins->forw_ref && ins->oprs[op].opflags ) && /* dead in the water on forward reference or External */
556 optimizing>=0 &&
557 !(ins->oprs[op].type & STRICT) &&
558 ins->oprs[op].wrt==NO_SEG && ins->oprs[op].segment==NO_SEG;
560 v = ins->oprs[op].offset;
561 if (size==16) v = (signed short)v; /* sign extend if 16 bits */
563 return ret && v>=-128L && v<=127L;
566 static long calcsize (long segment, long offset, int bits,
567 insn *ins, char *codes)
569 long length = 0;
570 unsigned char c;
572 (void) segment; /* Don't warn that this parameter is unused */
573 (void) offset; /* Don't warn that this parameter is unused */
575 while (*codes) switch (c = *codes++) {
576 case 01: case 02: case 03:
577 codes += c, length += c; break;
578 case 04: case 05: case 06: case 07:
579 length++; break;
580 case 010: case 011: case 012:
581 codes++, length++; break;
582 case 017:
583 length++; break;
584 case 014: case 015: case 016:
585 length++; break;
586 case 020: case 021: case 022:
587 length++; break;
588 case 024: case 025: case 026:
589 length++; break;
590 case 030: case 031: case 032:
591 length += 2; break;
592 case 034: case 035: case 036:
593 length += ((ins->oprs[c-034].addr_size ?
594 ins->oprs[c-034].addr_size : bits) == 16 ? 2 : 4); break;
595 case 037:
596 length += 2; break;
597 case 040: case 041: case 042:
598 length += 4; break;
599 case 050: case 051: case 052:
600 length++; break;
601 case 060: case 061: case 062:
602 length += 2; break;
603 case 064: case 065: case 066:
604 if ( ins->oprs[c-064].type & (BITS16|BITS32) )
605 length += (ins->oprs[c-064].type & BITS16) ? 2 : 4;
606 else
607 length += (bits == 16) ? 2 : 4;
608 break;
609 case 070: case 071: case 072:
610 length += 4; break;
611 case 0130: case 0131: case 0132:
612 length += is_sbyte(ins, c-0130, 16) ? 1 : 2; break;
613 case 0133: case 0134: case 0135:
614 codes+=2; length++; break;
615 case 0140: case 0141: case 0142:
616 length += is_sbyte(ins, c-0140, 32) ? 1 : 4; break;
617 case 0143: case 0144: case 0145:
618 codes+=2; length++; break;
619 case 0300: case 0301: case 0302:
620 length += chsize (&ins->oprs[c-0300], bits);
621 break;
622 case 0310:
623 length += (bits==32);
624 break;
625 case 0311:
626 length += (bits==16);
627 break;
628 case 0312:
629 break;
630 case 0320:
631 length += (bits==32);
632 break;
633 case 0321:
634 length += (bits==16);
635 break;
636 case 0322:
637 break;
638 case 0330:
639 codes++, length++; break;
640 case 0331:
641 case 0332:
642 break;
643 case 0333:
644 length++; break;
645 case 0340: case 0341: case 0342:
646 if (ins->oprs[0].segment != NO_SEG)
647 errfunc (ERR_NONFATAL, "attempt to reserve non-constant"
648 " quantity of BSS space");
649 else
650 length += ins->oprs[0].offset << (c-0340);
651 break;
652 case 0370: case 0371: case 0372:
653 break;
654 case 0373:
655 length++; break;
656 default: /* can't do it by 'case' statements */
657 if (c>=0100 && c<=0277) { /* it's an EA */
658 ea ea_data;
659 if (!process_ea (&ins->oprs[(c>>3)&7], &ea_data, bits, 0,
660 ins->forw_ref)) {
661 errfunc (ERR_NONFATAL, "invalid effective address");
662 return -1;
663 } else
664 length += ea_data.size;
665 } else
666 errfunc (ERR_PANIC, "internal instruction table corrupt"
667 ": instruction code 0x%02X given", c);
669 return length;
672 static void gencode (long segment, long offset, int bits,
673 insn *ins, char *codes, long insn_end)
675 static char condval[] = { /* conditional opcodes */
676 0x7, 0x3, 0x2, 0x6, 0x2, 0x4, 0xF, 0xD, 0xC, 0xE, 0x6, 0x2,
677 0x3, 0x7, 0x3, 0x5, 0xE, 0xC, 0xD, 0xF, 0x1, 0xB, 0x9, 0x5,
678 0x0, 0xA, 0xA, 0xB, 0x8, 0x4
680 unsigned char c;
681 unsigned char bytes[4];
682 long data, size;
684 while (*codes)
685 switch (c = *codes++)
687 case 01: case 02: case 03:
688 out (offset, segment, codes, OUT_RAWDATA+c, NO_SEG, NO_SEG);
689 codes += c;
690 offset += c;
691 break;
693 case 04: case 06:
694 switch (ins->oprs[0].basereg)
696 case R_CS:
697 bytes[0] = 0x0E + (c == 0x04 ? 1 : 0); break;
698 case R_DS:
699 bytes[0] = 0x1E + (c == 0x04 ? 1 : 0); break;
700 case R_ES:
701 bytes[0] = 0x06 + (c == 0x04 ? 1 : 0); break;
702 case R_SS:
703 bytes[0] = 0x16 + (c == 0x04 ? 1 : 0); break;
704 default:
705 errfunc (ERR_PANIC, "bizarre 8086 segment register received");
707 out (offset, segment, bytes, OUT_RAWDATA+1, NO_SEG, NO_SEG);
708 offset++;
709 break;
711 case 05: case 07:
712 switch (ins->oprs[0].basereg) {
713 case R_FS: bytes[0] = 0xA0 + (c == 0x05 ? 1 : 0); break;
714 case R_GS: bytes[0] = 0xA8 + (c == 0x05 ? 1 : 0); break;
715 default:
716 errfunc (ERR_PANIC, "bizarre 386 segment register received");
718 out (offset, segment, bytes, OUT_RAWDATA+1, NO_SEG, NO_SEG);
719 offset++;
720 break;
722 case 010: case 011: case 012:
723 bytes[0] = *codes++ + regval(&ins->oprs[c-010]);
724 out (offset, segment, bytes, OUT_RAWDATA+1, NO_SEG, NO_SEG);
725 offset += 1;
726 break;
728 case 017:
729 bytes[0] = 0;
730 out (offset, segment, bytes, OUT_RAWDATA+1, NO_SEG, NO_SEG);
731 offset += 1;
732 break;
734 case 014: case 015: case 016:
735 if (ins->oprs[c-014].offset < -128
736 || ins->oprs[c-014].offset > 127)
738 errfunc (ERR_WARNING, "signed byte value exceeds bounds");
741 if (ins->oprs[c-014].segment != NO_SEG)
743 data = ins->oprs[c-014].offset;
744 out (offset, segment, &data, OUT_ADDRESS+1,
745 ins->oprs[c-014].segment, ins->oprs[c-014].wrt);
747 else {
748 bytes[0] = ins->oprs[c-014].offset;
749 out (offset, segment, bytes, OUT_RAWDATA+1, NO_SEG, NO_SEG);
751 offset += 1;
752 break;
754 case 020: case 021: case 022:
755 if (ins->oprs[c-020].offset < -256
756 || ins->oprs[c-020].offset > 255)
758 errfunc (ERR_WARNING, "byte value exceeds bounds");
760 if (ins->oprs[c-020].segment != NO_SEG) {
761 data = ins->oprs[c-020].offset;
762 out (offset, segment, &data, OUT_ADDRESS+1,
763 ins->oprs[c-020].segment, ins->oprs[c-020].wrt);
765 else {
766 bytes[0] = ins->oprs[c-020].offset;
767 out (offset, segment, bytes, OUT_RAWDATA+1, NO_SEG, NO_SEG);
769 offset += 1;
770 break;
772 case 024: case 025: case 026:
773 if (ins->oprs[c-024].offset < 0 || ins->oprs[c-024].offset > 255)
774 errfunc (ERR_WARNING, "unsigned byte value exceeds bounds");
775 if (ins->oprs[c-024].segment != NO_SEG) {
776 data = ins->oprs[c-024].offset;
777 out (offset, segment, &data, OUT_ADDRESS+1,
778 ins->oprs[c-024].segment, ins->oprs[c-024].wrt);
780 else {
781 bytes[0] = ins->oprs[c-024].offset;
782 out (offset, segment, bytes, OUT_RAWDATA+1, NO_SEG, NO_SEG);
784 offset += 1;
785 break;
787 case 030: case 031: case 032:
788 if (ins->oprs[c-030].segment == NO_SEG &&
789 ins->oprs[c-030].wrt == NO_SEG &&
790 (ins->oprs[c-030].offset < -65536L ||
791 ins->oprs[c-030].offset > 65535L))
793 errfunc (ERR_WARNING, "word value exceeds bounds");
795 data = ins->oprs[c-030].offset;
796 out (offset, segment, &data, OUT_ADDRESS+2,
797 ins->oprs[c-030].segment, ins->oprs[c-030].wrt);
798 offset += 2;
799 break;
801 case 034: case 035: case 036:
802 data = ins->oprs[c-034].offset;
803 size = ((ins->oprs[c-034].addr_size ?
804 ins->oprs[c-034].addr_size : bits) == 16 ? 2 : 4);
805 if (size==2 && (data < -65536L || data > 65535L))
806 errfunc (ERR_WARNING, "word value exceeds bounds");
807 out (offset, segment, &data, OUT_ADDRESS+size,
808 ins->oprs[c-034].segment, ins->oprs[c-034].wrt);
809 offset += size;
810 break;
812 case 037:
813 if (ins->oprs[0].segment == NO_SEG)
814 errfunc (ERR_NONFATAL, "value referenced by FAR is not"
815 " relocatable");
816 data = 0L;
817 out (offset, segment, &data, OUT_ADDRESS+2,
818 outfmt->segbase(1+ins->oprs[0].segment),
819 ins->oprs[0].wrt);
820 offset += 2;
821 break;
823 case 040: case 041: case 042:
824 data = ins->oprs[c-040].offset;
825 out (offset, segment, &data, OUT_ADDRESS+4,
826 ins->oprs[c-040].segment, ins->oprs[c-040].wrt);
827 offset += 4;
828 break;
830 case 050: case 051: case 052:
831 if (ins->oprs[c-050].segment != segment)
832 errfunc (ERR_NONFATAL, "short relative jump outside segment");
833 data = ins->oprs[c-050].offset - insn_end;
834 if (data > 127 || data < -128)
835 errfunc (ERR_NONFATAL, "short jump is out of range");
836 bytes[0] = data;
837 out (offset, segment, bytes, OUT_RAWDATA+1, NO_SEG, NO_SEG);
838 offset += 1;
839 break;
841 case 060: case 061: case 062:
842 if (ins->oprs[c-060].segment != segment) {
843 data = ins->oprs[c-060].offset;
844 out (offset, segment, &data, OUT_REL2ADR+insn_end-offset,
845 ins->oprs[c-060].segment, ins->oprs[c-060].wrt);
846 } else {
847 data = ins->oprs[c-060].offset - insn_end;
848 out (offset, segment, &data,
849 OUT_ADDRESS+2, NO_SEG, NO_SEG);
851 offset += 2;
852 break;
854 case 064: case 065: case 066:
855 if ( ins->oprs[c-064].type & (BITS16|BITS32) )
856 size = (ins->oprs[c-064].type & BITS16) ? 2 : 4;
857 else
858 size = (bits == 16) ? 2 : 4;
859 if (ins->oprs[c-064].segment != segment) {
860 long reltype = (size == 2 ? OUT_REL2ADR : OUT_REL4ADR);
861 data = ins->oprs[c-064].offset;
862 out (offset, segment, &data, reltype+insn_end-offset,
863 ins->oprs[c-064].segment, ins->oprs[c-064].wrt);
864 } else {
865 data = ins->oprs[c-064].offset - insn_end;
866 out (offset, segment, &data,
867 OUT_ADDRESS+size, NO_SEG, NO_SEG);
869 offset += size;
870 break;
872 case 070: case 071: case 072:
873 if (ins->oprs[c-070].segment != segment) {
874 data = ins->oprs[c-070].offset;
875 out (offset, segment, &data, OUT_REL4ADR+insn_end-offset,
876 ins->oprs[c-070].segment, ins->oprs[c-070].wrt);
877 } else {
878 data = ins->oprs[c-070].offset - insn_end;
879 out (offset, segment, &data,
880 OUT_ADDRESS+4, NO_SEG, NO_SEG);
882 offset += 4;
883 break;
885 case 0130: case 0131: case 0132:
886 data = ins->oprs[c-0130].offset;
887 if (is_sbyte(ins, c-0130, 16)) {
888 out (offset, segment, &data, OUT_RAWDATA+1, NO_SEG, NO_SEG);
889 offset++;
890 } else {
891 if (ins->oprs[c-0130].segment == NO_SEG &&
892 ins->oprs[c-0130].wrt == NO_SEG &&
893 (data < -65536L || data > 65535L)) {
894 errfunc (ERR_WARNING, "word value exceeds bounds");
896 out (offset, segment, &data, OUT_ADDRESS+2,
897 ins->oprs[c-0130].segment, ins->oprs[c-0130].wrt);
898 offset += 2;
900 break;
902 case 0133: case 0134: case 0135:
903 codes++;
904 bytes[0] = *codes++;
905 if (is_sbyte(ins, c-0133, 16)) bytes[0] |= 2; /* s-bit */
906 out (offset, segment, bytes, OUT_RAWDATA+1, NO_SEG, NO_SEG);
907 offset++;
908 break;
910 case 0140: case 0141: case 0142:
911 data = ins->oprs[c-0140].offset;
912 if (is_sbyte(ins, c-0140, 32)) {
913 out (offset, segment, &data, OUT_RAWDATA+1, NO_SEG, NO_SEG);
914 offset++;
915 } else {
916 out (offset, segment, &data, OUT_ADDRESS+4,
917 ins->oprs[c-0140].segment, ins->oprs[c-0140].wrt);
918 offset += 4;
920 break;
922 case 0143: case 0144: case 0145:
923 codes++;
924 bytes[0] = *codes++;
925 if (is_sbyte(ins, c-0143, 32)) bytes[0] |= 2; /* s-bit */
926 out (offset, segment, bytes, OUT_RAWDATA+1, NO_SEG, NO_SEG);
927 offset++;
928 break;
930 case 0300: case 0301: case 0302:
931 if (chsize (&ins->oprs[c-0300], bits)) {
932 *bytes = 0x67;
933 out (offset, segment, bytes,
934 OUT_RAWDATA+1, NO_SEG, NO_SEG);
935 offset += 1;
936 } else
937 offset += 0;
938 break;
940 case 0310:
941 if (bits==32) {
942 *bytes = 0x67;
943 out (offset, segment, bytes,
944 OUT_RAWDATA+1, NO_SEG, NO_SEG);
945 offset += 1;
946 } else
947 offset += 0;
948 break;
950 case 0311:
951 if (bits==16) {
952 *bytes = 0x67;
953 out (offset, segment, bytes,
954 OUT_RAWDATA+1, NO_SEG, NO_SEG);
955 offset += 1;
956 } else
957 offset += 0;
958 break;
960 case 0312:
961 break;
963 case 0320:
964 if (bits==32) {
965 *bytes = 0x66;
966 out (offset, segment, bytes,
967 OUT_RAWDATA+1, NO_SEG, NO_SEG);
968 offset += 1;
969 } else
970 offset += 0;
971 break;
973 case 0321:
974 if (bits==16) {
975 *bytes = 0x66;
976 out (offset, segment, bytes,
977 OUT_RAWDATA+1, NO_SEG, NO_SEG);
978 offset += 1;
979 } else
980 offset += 0;
981 break;
983 case 0322:
984 break;
986 case 0330:
987 *bytes = *codes++ ^ condval[ins->condition];
988 out (offset, segment, bytes,
989 OUT_RAWDATA+1, NO_SEG, NO_SEG);
990 offset += 1;
991 break;
993 case 0331:
994 case 0332:
995 break;
997 case 0333:
998 *bytes = 0xF3;
999 out (offset, segment, bytes,
1000 OUT_RAWDATA+1, NO_SEG, NO_SEG);
1001 offset += 1;
1002 break;
1004 case 0340: case 0341: case 0342:
1005 if (ins->oprs[0].segment != NO_SEG)
1006 errfunc (ERR_PANIC, "non-constant BSS size in pass two");
1007 else {
1008 long size = ins->oprs[0].offset << (c-0340);
1009 if (size > 0)
1010 out (offset, segment, NULL,
1011 OUT_RESERVE+size, NO_SEG, NO_SEG);
1012 offset += size;
1014 break;
1016 case 0370: case 0371: case 0372:
1017 break;
1019 case 0373:
1020 *bytes = bits==16 ? 3 : 5;
1021 out (offset, segment, bytes,
1022 OUT_RAWDATA+1, NO_SEG, NO_SEG);
1023 offset += 1;
1024 break;
1026 default: /* can't do it by 'case' statements */
1027 if (c>=0100 && c<=0277) { /* it's an EA */
1028 ea ea_data;
1029 int rfield;
1030 unsigned char *p;
1031 long s;
1033 if (c<=0177) /* pick rfield from operand b */
1034 rfield = regval (&ins->oprs[c&7]);
1035 else /* rfield is constant */
1036 rfield = c & 7;
1038 if (!process_ea (&ins->oprs[(c>>3)&7], &ea_data, bits, rfield,
1039 ins->forw_ref))
1041 errfunc (ERR_NONFATAL, "invalid effective address");
1044 p = bytes;
1045 *p++ = ea_data.modrm;
1046 if (ea_data.sib_present)
1047 *p++ = ea_data.sib;
1049 s = p-bytes;
1050 out (offset, segment, bytes, OUT_RAWDATA + s,
1051 NO_SEG, NO_SEG);
1053 switch (ea_data.bytes) {
1054 case 0:
1055 break;
1056 case 1:
1057 if (ins->oprs[(c>>3)&7].segment != NO_SEG) {
1058 data = ins->oprs[(c>>3)&7].offset;
1059 out (offset, segment, &data, OUT_ADDRESS+1,
1060 ins->oprs[(c>>3)&7].segment,
1061 ins->oprs[(c>>3)&7].wrt);
1062 } else {
1063 *bytes = ins->oprs[(c>>3)&7].offset;
1064 out (offset, segment, bytes, OUT_RAWDATA+1,
1065 NO_SEG, NO_SEG);
1067 s++;
1068 break;
1069 case 2:
1070 case 4:
1071 data = ins->oprs[(c>>3)&7].offset;
1072 out (offset, segment, &data,
1073 OUT_ADDRESS+ea_data.bytes,
1074 ins->oprs[(c>>3)&7].segment, ins->oprs[(c>>3)&7].wrt);
1075 s += ea_data.bytes;
1076 break;
1078 offset += s;
1079 } else
1080 errfunc (ERR_PANIC, "internal instruction table corrupt"
1081 ": instruction code 0x%02X given", c);
1085 static int regval (operand *o)
1087 switch (o->basereg) {
1088 case R_EAX: case R_AX: case R_AL: case R_ES: case R_CR0: case R_DR0:
1089 case R_ST0: case R_MM0: case R_XMM0:
1090 return 0;
1091 case R_ECX: case R_CX: case R_CL: case R_CS: case R_DR1: case R_ST1:
1092 case R_MM1: case R_XMM1:
1093 return 1;
1094 case R_EDX: case R_DX: case R_DL: case R_SS: case R_CR2: case R_DR2:
1095 case R_ST2: case R_MM2: case R_XMM2:
1096 return 2;
1097 case R_EBX: case R_BX: case R_BL: case R_DS: case R_CR3: case R_DR3:
1098 case R_TR3: case R_ST3: case R_MM3: case R_XMM3:
1099 return 3;
1100 case R_ESP: case R_SP: case R_AH: case R_FS: case R_CR4: case R_TR4:
1101 case R_ST4: case R_MM4: case R_XMM4:
1102 return 4;
1103 case R_EBP: case R_BP: case R_CH: case R_GS: case R_TR5: case R_ST5:
1104 case R_MM5: case R_XMM5:
1105 return 5;
1106 case R_ESI: case R_SI: case R_DH: case R_DR6: case R_TR6: case R_ST6:
1107 case R_MM6: case R_XMM6:
1108 return 6;
1109 case R_EDI: case R_DI: case R_BH: case R_DR7: case R_TR7: case R_ST7:
1110 case R_MM7: case R_XMM7:
1111 return 7;
1112 default: /* panic */
1113 errfunc (ERR_PANIC, "invalid register operand given to regval()");
1114 return 0;
1118 static int matches (struct itemplate *itemp, insn *instruction)
1120 int i, size[3], asize, oprs, ret;
1122 ret = 100;
1125 * Check the opcode
1127 if (itemp->opcode != instruction->opcode) return 0;
1130 * Count the operands
1132 if (itemp->operands != instruction->operands) return 0;
1135 * Check that no spurious colons or TOs are present
1137 for (i=0; i<itemp->operands; i++)
1138 if (instruction->oprs[i].type & ~itemp->opd[i] & (COLON|TO))
1139 return 0;
1142 * Check that the operand flags all match up
1144 for (i=0; i<itemp->operands; i++)
1145 if (itemp->opd[i] & ~instruction->oprs[i].type ||
1146 ((itemp->opd[i] & SIZE_MASK) &&
1147 ((itemp->opd[i] ^ instruction->oprs[i].type) & SIZE_MASK)))
1149 if ((itemp->opd[i] & ~instruction->oprs[i].type & NON_SIZE) ||
1150 (instruction->oprs[i].type & SIZE_MASK))
1151 return 0;
1152 else
1153 /* ret = 1; */
1154 return 1;
1158 * Check operand sizes
1160 if (itemp->flags & IF_ARMASK) {
1161 size[0] = size[1] = size[2] = 0;
1163 switch (itemp->flags & IF_ARMASK) {
1164 case IF_AR0: i = 0; break;
1165 case IF_AR1: i = 1; break;
1166 case IF_AR2: i = 2; break;
1167 default: break; /* Shouldn't happen */
1169 if (itemp->flags & IF_SB) {
1170 size[i] = BITS8;
1171 } else if (itemp->flags & IF_SW) {
1172 size[i] = BITS16;
1173 } else if (itemp->flags & IF_SD) {
1174 size[i] = BITS32;
1176 } else {
1177 asize = 0;
1178 if (itemp->flags & IF_SB) {
1179 asize = BITS8;
1180 oprs = itemp->operands;
1181 } else if (itemp->flags & IF_SW) {
1182 asize = BITS16;
1183 oprs = itemp->operands;
1184 } else if (itemp->flags & IF_SD) {
1185 asize = BITS32;
1186 oprs = itemp->operands;
1188 size[0] = size[1] = size[2] = asize;
1191 if (itemp->flags & (IF_SM | IF_SM2)) {
1192 oprs = (itemp->flags & IF_SM2 ? 2 : itemp->operands);
1193 asize = 0;
1194 for (i=0; i<oprs; i++) {
1195 if ( (asize = itemp->opd[i] & SIZE_MASK) != 0) {
1196 int j;
1197 for (j=0; j<oprs; j++)
1198 size[j] = asize;
1199 break;
1202 } else {
1203 oprs = itemp->operands;
1206 for (i=0; i<itemp->operands; i++)
1207 if (!(itemp->opd[i] & SIZE_MASK) &&
1208 (instruction->oprs[i].type & SIZE_MASK & ~size[i]))
1209 /* ret = 2; */
1210 return 2;
1213 * Check template is okay at the set cpu level
1215 if ((itemp->flags & IF_PLEVEL) > cpu) return 3;
1218 * Check if special handling needed for Jumps
1220 if ((unsigned char)(itemp->code[0]) >= 0370) return 99;
1222 return ret;
1225 static ea *process_ea (operand *input, ea *output, int addrbits, int rfield,
1226 int forw_ref)
1228 if (!(REGISTER & ~input->type)) { /* it's a single register */
1229 static int regs[] = {
1230 R_AL, R_CL, R_DL, R_BL, R_AH, R_CH, R_DH, R_BH,
1231 R_AX, R_CX, R_DX, R_BX, R_SP, R_BP, R_SI, R_DI,
1232 R_EAX, R_ECX, R_EDX, R_EBX, R_ESP, R_EBP, R_ESI, R_EDI,
1233 R_MM0, R_MM1, R_MM2, R_MM3, R_MM4, R_MM5, R_MM6, R_MM7,
1234 R_XMM0, R_XMM1, R_XMM2, R_XMM3, R_XMM4, R_XMM5, R_XMM6, R_XMM7
1236 int i;
1238 for (i=0; i<elements(regs); i++)
1239 if (input->basereg == regs[i]) break;
1240 if (i<elements(regs)) {
1241 output->sib_present = FALSE;/* no SIB necessary */
1242 output->bytes = 0; /* no offset necessary either */
1243 output->modrm = 0xC0 | (rfield << 3) | (i & 7);
1245 else
1246 return NULL;
1247 } else { /* it's a memory reference */
1248 if (input->basereg==-1 && (input->indexreg==-1 || input->scale==0)) {
1249 /* it's a pure offset */
1250 if (input->addr_size)
1251 addrbits = input->addr_size;
1252 output->sib_present = FALSE;
1253 output->bytes = (addrbits==32 ? 4 : 2);
1254 output->modrm = (addrbits==32 ? 5 : 6) | (rfield << 3);
1256 else { /* it's an indirection */
1257 int i=input->indexreg, b=input->basereg, s=input->scale;
1258 long o=input->offset, seg=input->segment;
1259 int hb=input->hintbase, ht=input->hinttype;
1260 int t;
1262 if (s==0) i = -1; /* make this easy, at least */
1264 if (i==R_EAX || i==R_EBX || i==R_ECX || i==R_EDX
1265 || i==R_EBP || i==R_ESP || i==R_ESI || i==R_EDI
1266 || b==R_EAX || b==R_EBX || b==R_ECX || b==R_EDX
1267 || b==R_EBP || b==R_ESP || b==R_ESI || b==R_EDI) {
1268 /* it must be a 32-bit memory reference. Firstly we have
1269 * to check that all registers involved are type Exx. */
1270 if (i!=-1 && i!=R_EAX && i!=R_EBX && i!=R_ECX && i!=R_EDX
1271 && i!=R_EBP && i!=R_ESP && i!=R_ESI && i!=R_EDI)
1272 return NULL;
1273 if (b!=-1 && b!=R_EAX && b!=R_EBX && b!=R_ECX && b!=R_EDX
1274 && b!=R_EBP && b!=R_ESP && b!=R_ESI && b!=R_EDI)
1275 return NULL;
1277 /* While we're here, ensure the user didn't specify WORD. */
1278 if (input->addr_size == 16)
1279 return NULL;
1281 /* now reorganise base/index */
1282 if (s == 1 && b != i && b != -1 && i != -1 &&
1283 ((hb==b&&ht==EAH_NOTBASE) || (hb==i&&ht==EAH_MAKEBASE)))
1284 t = b, b = i, i = t; /* swap if hints say so */
1285 if (b==i) /* convert EAX+2*EAX to 3*EAX */
1286 b = -1, s++;
1287 if (b==-1 && s==1 && !(hb == i && ht == EAH_NOTBASE))
1288 b = i, i = -1; /* make single reg base, unless hint */
1289 if (((s==2 && i!=R_ESP && !(input->eaflags & EAF_TIMESTWO)) ||
1290 s==3 || s==5 || s==9) && b==-1)
1291 b = i, s--; /* convert 3*EAX to EAX+2*EAX */
1292 if (s==1 && i==R_ESP) /* swap ESP into base if scale is 1 */
1293 i = b, b = R_ESP;
1294 if (i==R_ESP || (s!=1 && s!=2 && s!=4 && s!=8 && i!=-1))
1295 return NULL; /* wrong, for various reasons */
1297 if (i==-1 && b!=R_ESP) {/* no SIB needed */
1298 int mod, rm;
1299 switch(b) {
1300 case R_EAX: rm = 0; break;
1301 case R_ECX: rm = 1; break;
1302 case R_EDX: rm = 2; break;
1303 case R_EBX: rm = 3; break;
1304 case R_EBP: rm = 5; break;
1305 case R_ESI: rm = 6; break;
1306 case R_EDI: rm = 7; break;
1307 case -1: rm = 5; break;
1308 default: /* should never happen */
1309 return NULL;
1311 if (b==-1 || (b!=R_EBP && o==0 &&
1312 seg==NO_SEG && !forw_ref &&
1313 !(input->eaflags &
1314 (EAF_BYTEOFFS|EAF_WORDOFFS))))
1315 mod = 0;
1316 else if (input->eaflags & EAF_BYTEOFFS ||
1317 (o>=-128 && o<=127 && seg==NO_SEG && !forw_ref &&
1318 !(input->eaflags & EAF_WORDOFFS))) {
1319 mod = 1;
1321 else
1322 mod = 2;
1324 output->sib_present = FALSE;
1325 output->bytes = (b==-1 || mod==2 ? 4 : mod);
1326 output->modrm = (mod<<6) | (rfield<<3) | rm;
1328 else { /* we need a SIB */
1329 int mod, scale, index, base;
1331 switch (b) {
1332 case R_EAX: base = 0; break;
1333 case R_ECX: base = 1; break;
1334 case R_EDX: base = 2; break;
1335 case R_EBX: base = 3; break;
1336 case R_ESP: base = 4; break;
1337 case R_EBP: case -1: base = 5; break;
1338 case R_ESI: base = 6; break;
1339 case R_EDI: base = 7; break;
1340 default: /* then what the smeg is it? */
1341 return NULL; /* panic */
1344 switch (i) {
1345 case R_EAX: index = 0; break;
1346 case R_ECX: index = 1; break;
1347 case R_EDX: index = 2; break;
1348 case R_EBX: index = 3; break;
1349 case -1: index = 4; break;
1350 case R_EBP: index = 5; break;
1351 case R_ESI: index = 6; break;
1352 case R_EDI: index = 7; break;
1353 default: /* then what the smeg is it? */
1354 return NULL; /* panic */
1357 if (i==-1) s = 1;
1358 switch (s) {
1359 case 1: scale = 0; break;
1360 case 2: scale = 1; break;
1361 case 4: scale = 2; break;
1362 case 8: scale = 3; break;
1363 default: /* then what the smeg is it? */
1364 return NULL; /* panic */
1367 if (b==-1 || (b!=R_EBP && o==0 &&
1368 seg==NO_SEG && !forw_ref &&
1369 !(input->eaflags &
1370 (EAF_BYTEOFFS|EAF_WORDOFFS))))
1371 mod = 0;
1372 else if (input->eaflags & EAF_BYTEOFFS ||
1373 (o>=-128 && o<=127 && seg==NO_SEG && !forw_ref &&
1374 !(input->eaflags & EAF_WORDOFFS)))
1375 mod = 1;
1376 else
1377 mod = 2;
1379 output->sib_present = TRUE;
1380 output->bytes = (b==-1 || mod==2 ? 4 : mod);
1381 output->modrm = (mod<<6) | (rfield<<3) | 4;
1382 output->sib = (scale<<6) | (index<<3) | base;
1385 else { /* it's 16-bit */
1386 int mod, rm;
1388 /* check all registers are BX, BP, SI or DI */
1389 if ((b!=-1 && b!=R_BP && b!=R_BX && b!=R_SI && b!=R_DI) ||
1390 (i!=-1 && i!=R_BP && i!=R_BX && i!=R_SI && i!=R_DI))
1391 return NULL;
1393 /* ensure the user didn't specify DWORD */
1394 if (input->addr_size == 32)
1395 return NULL;
1397 if (s!=1 && i!=-1) return NULL;/* no can do, in 16-bit EA */
1398 if (b==-1 && i!=-1) { int tmp = b; b = i; i = tmp; } /* swap */
1399 if ((b==R_SI || b==R_DI) && i!=-1)
1400 { int tmp = b; b = i; i = tmp; }
1401 /* have BX/BP as base, SI/DI index */
1402 if (b==i) return NULL;/* shouldn't ever happen, in theory */
1403 if (i!=-1 && b!=-1 &&
1404 (i==R_BP || i==R_BX || b==R_SI || b==R_DI))
1405 return NULL; /* invalid combinations */
1406 if (b==-1) /* pure offset: handled above */
1407 return NULL; /* so if it gets to here, panic! */
1409 rm = -1;
1410 if (i!=-1)
1411 switch (i*256 + b) {
1412 case R_SI*256+R_BX: rm=0; break;
1413 case R_DI*256+R_BX: rm=1; break;
1414 case R_SI*256+R_BP: rm=2; break;
1415 case R_DI*256+R_BP: rm=3; break;
1417 else
1418 switch (b) {
1419 case R_SI: rm=4; break;
1420 case R_DI: rm=5; break;
1421 case R_BP: rm=6; break;
1422 case R_BX: rm=7; break;
1424 if (rm==-1) /* can't happen, in theory */
1425 return NULL; /* so panic if it does */
1427 if (o==0 && seg==NO_SEG && !forw_ref && rm!=6 &&
1428 !(input->eaflags & (EAF_BYTEOFFS|EAF_WORDOFFS)))
1429 mod = 0;
1430 else if (input->eaflags & EAF_BYTEOFFS ||
1431 (o>=-128 && o<=127 && seg==NO_SEG && !forw_ref &&
1432 !(input->eaflags & EAF_WORDOFFS)))
1433 mod = 1;
1434 else
1435 mod = 2;
1437 output->sib_present = FALSE; /* no SIB - it's 16-bit */
1438 output->bytes = mod; /* bytes of offset needed */
1439 output->modrm = (mod<<6) | (rfield<<3) | rm;
1443 output->size = 1 + output->sib_present + output->bytes;
1444 return output;
1447 static int chsize (operand *input, int addrbits)
1449 if (!(MEMORY & ~input->type)) {
1450 int i=input->indexreg, b=input->basereg;
1452 if (input->scale==0) i = -1;
1454 if (i == -1 && b == -1) /* pure offset */
1455 return (input->addr_size != 0 && input->addr_size != addrbits);
1457 if (i==R_EAX || i==R_EBX || i==R_ECX || i==R_EDX
1458 || i==R_EBP || i==R_ESP || i==R_ESI || i==R_EDI
1459 || b==R_EAX || b==R_EBX || b==R_ECX || b==R_EDX
1460 || b==R_EBP || b==R_ESP || b==R_ESI || b==R_EDI)
1461 return (addrbits==16);
1462 else
1463 return (addrbits==32);
1465 else
1466 return 0;