NASM 0.98.08
[nasm/avx512.git] / assemble.c
blob98bb507494582ca880cd31940a4a2b68cb7640d0
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 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 * \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, 1, 2 meets byte jump criteria.
63 * \373 - assemble 0x03 if bits==16, 0x05 if bits==32;
64 * used for conditional jump over longer jump
67 #include <stdio.h>
68 #include <string.h>
70 #include "nasm.h"
71 #include "nasmlib.h"
72 #include "assemble.h"
73 #include "insns.h"
75 extern struct itemplate *nasm_instructions[];
77 typedef struct {
78 int sib_present; /* is a SIB byte necessary? */
79 int bytes; /* # of bytes of offset needed */
80 int size; /* lazy - this is sib+bytes+1 */
81 unsigned char modrm, sib; /* the bytes themselves */
82 } ea;
84 static unsigned long cpu; /* cpu level received from nasm.c */
85 static efunc errfunc;
86 static struct ofmt *outfmt;
87 static ListGen *list;
89 static long calcsize (long, long, int, insn *, char *);
90 static void gencode (long, long, int, insn *, char *, long);
91 static int regval (operand *o);
92 static int matches (struct itemplate *, insn *);
93 static ea * process_ea (operand *, ea *, int, int, int);
94 static int chsize (operand *, int);
97 * This routine wrappers the real output format's output routine,
98 * in order to pass a copy of the data off to the listing file
99 * generator at the same time.
101 static void out (long offset, long segto, void *data, unsigned long type,
102 long segment, long wrt)
104 static long lineno;
105 static char *lnfname;
107 if ((type & OUT_TYPMASK) == OUT_ADDRESS) {
108 if (segment != NO_SEG || wrt != NO_SEG) {
110 * This address is relocated. We must write it as
111 * OUT_ADDRESS, so there's no work to be done here.
113 list->output (offset, data, type);
115 else {
116 unsigned char p[4], *q = p;
118 * This is a non-relocated address, and we're going to
119 * convert it into RAWDATA format.
121 if ((type & OUT_SIZMASK) == 4) {
122 WRITELONG (q, * (long *) data);
123 list->output (offset, p, OUT_RAWDATA+4);
125 else {
126 WRITESHORT (q, * (long *) data);
127 list->output (offset, p, OUT_RAWDATA+2);
131 else if ((type & OUT_TYPMASK) == OUT_RAWDATA) {
132 list->output (offset, data, type);
134 else if ((type & OUT_TYPMASK) == OUT_RESERVE) {
135 list->output (offset, NULL, type);
137 else if ((type & OUT_TYPMASK) == OUT_REL2ADR ||
138 (type & OUT_TYPMASK) == OUT_REL4ADR) {
139 list->output (offset, data, type);
142 if (src_get(&lineno,&lnfname))
143 outfmt->current_dfmt->linenum(lnfname,lineno,segto);
145 outfmt->output (segto, data, type, segment, wrt);
148 static int jmp_match (long segment, long offset, int bits,
149 insn *ins, char *code)
150 { long isize;
151 unsigned char c = code[0];
154 if (c != 0370) return 0;
155 if (ins->oprs[0].opflags & OPFLAG_FORWARD) return (! pass0); /*1;*/ /* match a forward reference */
157 isize = calcsize (segment, offset, bits, ins, code);
158 if (ins->oprs[0].segment != segment) return 0;
159 isize = ins->oprs[0].offset - offset - isize; /* isize is now the delta */
160 if (isize >= -128L && isize <= 127L) return 1; /* it is byte size */
162 return 0;
166 long assemble (long segment, long offset, int bits, unsigned long cp,
167 insn *instruction, struct ofmt *output, efunc error,
168 ListGen *listgen)
170 struct itemplate *temp;
171 int j;
172 int size_prob;
173 long insn_end;
174 long itimes;
175 long start = offset;
176 long wsize = 0; /* size for DB etc. */
178 errfunc = error; /* to pass to other functions */
179 cpu = cp;
180 outfmt = output; /* likewise */
181 list = listgen; /* and again */
183 switch (instruction->opcode)
185 case -1: return 0;
186 case I_DB: wsize = 1; break;
187 case I_DW: wsize = 2; break;
188 case I_DD: wsize = 4; break;
189 case I_DQ: wsize = 8; break;
190 case I_DT: wsize = 10; break;
193 if (wsize) {
194 extop * e;
195 long t = instruction->times;
196 if (t < 0)
197 errfunc(ERR_PANIC, "instruction->times < 0 (%ld) in assemble()",t);
199 while (t--) /* repeat TIMES times */
201 for (e = instruction->eops; e; e = e->next)
203 if (e->type == EOT_DB_NUMBER)
205 if (wsize == 1) {
206 if (e->segment != NO_SEG)
207 errfunc (ERR_NONFATAL,
208 "one-byte relocation attempted");
209 else {
210 unsigned char out_byte = e->offset;
211 out (offset, segment, &out_byte, OUT_RAWDATA+1,
212 NO_SEG, NO_SEG);
215 else if (wsize > 5) {
216 errfunc (ERR_NONFATAL, "integer supplied to a D%c"
217 " instruction", wsize==8 ? 'Q' : 'T');
219 else
220 out (offset, segment, &e->offset,
221 OUT_ADDRESS+wsize, e->segment,
222 e->wrt);
223 offset += wsize;
225 else if (e->type == EOT_DB_STRING)
227 int align;
229 out (offset, segment, e->stringval,
230 OUT_RAWDATA+e->stringlen, NO_SEG, NO_SEG);
231 align = e->stringlen % wsize;
233 if (align) {
234 align = wsize - align;
235 out (offset, segment, "\0\0\0\0\0\0\0\0",
236 OUT_RAWDATA+align, NO_SEG, NO_SEG);
238 offset += e->stringlen + align;
241 if (t > 0 && t == instruction->times-1)
244 * Dummy call to list->output to give the offset to the
245 * listing module.
247 list->output (offset, NULL, OUT_RAWDATA);
248 list->uplevel (LIST_TIMES);
251 if (instruction->times > 1)
252 list->downlevel (LIST_TIMES);
253 return offset - start;
256 if (instruction->opcode == I_INCBIN)
258 static char fname[FILENAME_MAX];
259 FILE * fp;
260 long len;
262 len = FILENAME_MAX-1;
263 if (len > instruction->eops->stringlen)
264 len = instruction->eops->stringlen;
265 strncpy (fname, instruction->eops->stringval, len);
266 fname[len] = '\0';
268 if ( (fp = fopen(fname, "rb")) == NULL)
269 error (ERR_NONFATAL, "`incbin': unable to open file `%s'", fname);
270 else if (fseek(fp, 0L, SEEK_END) < 0)
271 error (ERR_NONFATAL, "`incbin': unable to seek on file `%s'",
272 fname);
273 else
275 static char buf[2048];
276 long t = instruction->times;
277 long base = 0;
279 len = ftell (fp);
280 if (instruction->eops->next) {
281 base = instruction->eops->next->offset;
282 len -= base;
283 if (instruction->eops->next->next &&
284 len > instruction->eops->next->next->offset)
285 len = instruction->eops->next->next->offset;
288 * Dummy call to list->output to give the offset to the
289 * listing module.
291 list->output (offset, NULL, OUT_RAWDATA);
292 list->uplevel(LIST_INCBIN);
293 while (t--)
295 long l;
297 fseek (fp, base, SEEK_SET);
298 l = len;
299 while (l > 0) {
300 long m = fread (buf, 1, (l>sizeof(buf)?sizeof(buf):l),
301 fp);
302 if (!m) {
304 * This shouldn't happen unless the file
305 * actually changes while we are reading
306 * it.
308 error (ERR_NONFATAL, "`incbin': unexpected EOF while"
309 " reading file `%s'", fname);
310 t=0; /* Try to exit cleanly */
311 break;
313 out (offset, segment, buf, OUT_RAWDATA+m,
314 NO_SEG, NO_SEG);
315 l -= m;
318 list->downlevel(LIST_INCBIN);
319 if (instruction->times > 1) {
321 * Dummy call to list->output to give the offset to the
322 * listing module.
324 list->output (offset, NULL, OUT_RAWDATA);
325 list->uplevel(LIST_TIMES);
326 list->downlevel(LIST_TIMES);
328 fclose (fp);
329 return instruction->times * len;
331 return 0; /* if we're here, there's an error */
334 size_prob = FALSE;
335 temp = nasm_instructions[instruction->opcode];
336 while (temp->opcode != -1) {
337 int m = matches (temp, instruction);
338 if (m == 99)
339 m += jmp_match(segment, offset, bits, instruction, temp->code);
341 if (m == 100) /* matches! */
343 char *codes = temp->code;
344 long insn_size = calcsize(segment, offset, bits,
345 instruction, codes);
346 itimes = instruction->times;
347 if (insn_size < 0) /* shouldn't be, on pass two */
348 error (ERR_PANIC, "errors made it through from pass one");
349 else while (itimes--) {
350 insn_end = offset + insn_size;
351 for (j=0; j<instruction->nprefix; j++) {
352 unsigned char c=0;
353 switch (instruction->prefixes[j]) {
354 case P_LOCK:
355 c = 0xF0; break;
356 case P_REPNE: case P_REPNZ:
357 c = 0xF2; break;
358 case P_REPE: case P_REPZ: case P_REP:
359 c = 0xF3; break;
360 case R_CS: c = 0x2E; break;
361 case R_DS: c = 0x3E; break;
362 case R_ES: c = 0x26; break;
363 case R_FS: c = 0x64; break;
364 case R_GS: c = 0x65; break;
365 case R_SS: c = 0x36; break;
366 case P_A16:
367 if (bits != 16)
368 c = 0x67;
369 break;
370 case P_A32:
371 if (bits != 32)
372 c = 0x67;
373 break;
374 case P_O16:
375 if (bits != 16)
376 c = 0x66;
377 break;
378 case P_O32:
379 if (bits != 32)
380 c = 0x66;
381 break;
382 default:
383 error (ERR_PANIC,
384 "invalid instruction prefix");
386 if (c != 0) {
387 out (offset, segment, &c, OUT_RAWDATA+1,
388 NO_SEG, NO_SEG);
389 offset++;
392 gencode (segment, offset, bits, instruction, codes, insn_end);
393 offset += insn_size;
394 if (itimes > 0 && itimes == instruction->times-1) {
396 * Dummy call to list->output to give the offset to the
397 * listing module.
399 list->output (offset, NULL, OUT_RAWDATA);
400 list->uplevel (LIST_TIMES);
403 if (instruction->times > 1)
404 list->downlevel (LIST_TIMES);
405 return offset - start;
406 } else if (m > 0 && m > size_prob) {
407 size_prob = m;
409 temp++;
412 if (temp->opcode == -1) { /* didn't match any instruction */
413 if (size_prob == 1) /* would have matched, but for size */
414 error (ERR_NONFATAL, "operation size not specified");
415 else if (size_prob == 2)
416 error (ERR_NONFATAL, "mismatch in operand sizes");
417 else if (size_prob == 3)
418 error (ERR_NONFATAL, "no instruction for this cpu level");
419 else
420 error (ERR_NONFATAL,
421 "invalid combination of opcode and operands");
423 return 0;
426 long insn_size (long segment, long offset, int bits, unsigned long cp,
427 insn *instruction, efunc error)
429 struct itemplate *temp;
431 errfunc = error; /* to pass to other functions */
432 cpu = cp;
434 if (instruction->opcode == -1)
435 return 0;
437 if (instruction->opcode == I_DB ||
438 instruction->opcode == I_DW ||
439 instruction->opcode == I_DD ||
440 instruction->opcode == I_DQ ||
441 instruction->opcode == I_DT)
443 extop *e;
444 long isize, osize, wsize = 0; /* placate gcc */
446 isize = 0;
447 switch (instruction->opcode)
449 case I_DB: wsize = 1; break;
450 case I_DW: wsize = 2; break;
451 case I_DD: wsize = 4; break;
452 case I_DQ: wsize = 8; break;
453 case I_DT: wsize = 10; break;
456 for (e = instruction->eops; e; e = e->next)
458 long align;
460 osize = 0;
461 if (e->type == EOT_DB_NUMBER)
462 osize = 1;
463 else if (e->type == EOT_DB_STRING)
464 osize = e->stringlen;
466 align = (-osize) % wsize;
467 if (align < 0)
468 align += wsize;
469 isize += osize + align;
471 return isize * instruction->times;
474 if (instruction->opcode == I_INCBIN)
476 char fname[FILENAME_MAX];
477 FILE * fp;
478 long len;
480 len = FILENAME_MAX-1;
481 if (len > instruction->eops->stringlen)
482 len = instruction->eops->stringlen;
483 strncpy (fname, instruction->eops->stringval, len);
484 fname[len] = '\0';
485 if ( (fp = fopen(fname, "rb")) == NULL )
486 error (ERR_NONFATAL, "`incbin': unable to open file `%s'", fname);
487 else if (fseek(fp, 0L, SEEK_END) < 0)
488 error (ERR_NONFATAL, "`incbin': unable to seek on file `%s'",
489 fname);
490 else
492 len = ftell (fp);
493 fclose (fp);
494 if (instruction->eops->next)
496 len -= instruction->eops->next->offset;
497 if (instruction->eops->next->next &&
498 len > instruction->eops->next->next->offset)
500 len = instruction->eops->next->next->offset;
503 return instruction->times * len;
505 return 0; /* if we're here, there's an error */
508 temp = nasm_instructions[instruction->opcode];
509 while (temp->opcode != -1) {
510 int m = matches(temp, instruction);
511 if (m == 99)
512 m += jmp_match(segment, offset, bits, instruction, temp->code);
514 if (m == 100) {
515 /* we've matched an instruction. */
516 long isize;
517 char * codes = temp->code;
518 int j;
520 isize = calcsize(segment, offset, bits, instruction, codes);
521 if (isize < 0)
522 return -1;
523 for (j = 0; j < instruction->nprefix; j++)
525 if ((instruction->prefixes[j] != P_A16 &&
526 instruction->prefixes[j] != P_O16 && bits==16) ||
527 (instruction->prefixes[j] != P_A32 &&
528 instruction->prefixes[j] != P_O32 && bits==32))
530 isize++;
533 return isize * instruction->times;
535 temp++;
537 return -1; /* didn't match any instruction */
541 /* check that opn[op] is a signed byte of size 16 or 32,
542 and return the signed value*/
543 static int is_sbyte (insn *ins, int op, int size)
545 signed long v;
546 int ret;
548 ret = !(ins->forw_ref && ins->oprs[op].opflags ) && /* dead in the water on forward reference or External */
549 ins->oprs[op].wrt==NO_SEG && ins->oprs[op].segment==NO_SEG;
550 v = ins->oprs[op].offset;
551 if (size==16) v = (signed short)v; /* sign extend if 16 bits */
553 return ret && v>=-128L && v<=127L;
556 static long calcsize (long segment, long offset, int bits,
557 insn *ins, char *codes)
559 long length = 0;
560 unsigned char c;
562 (void) segment; /* Don't warn that this parameter is unused */
563 (void) offset; /* Don't warn that this parameter is unused */
565 while (*codes) switch (c = *codes++) {
566 case 01: case 02: case 03:
567 codes += c, length += c; break;
568 case 04: case 05: case 06: case 07:
569 length++; break;
570 case 010: case 011: case 012:
571 codes++, length++; break;
572 case 017:
573 length++; break;
574 case 014: case 015: case 016:
575 length++; break;
576 case 020: case 021: case 022:
577 length++; break;
578 case 024: case 025: case 026:
579 length++; break;
580 case 030: case 031: case 032:
581 length += 2; break;
582 case 034: case 035: case 036:
583 length += ((ins->oprs[c-034].addr_size ?
584 ins->oprs[c-034].addr_size : bits) == 16 ? 2 : 4); break;
585 case 037:
586 length += 2; break;
587 case 040: case 041: case 042:
588 length += 4; break;
589 case 050: case 051: case 052:
590 length++; break;
591 case 060: case 061: case 062:
592 length += 2; break;
593 case 064: case 065: case 066:
594 length += ((ins->oprs[c-064].addr_size ?
595 ins->oprs[c-064].addr_size : bits) == 16 ? 2 : 4); break;
596 case 070: case 071: case 072:
597 length += 4; break;
598 case 0130: case 0131: case 0132:
599 length += is_sbyte(ins, c-0130, 16) ? 1 : 2; break;
600 case 0133: case 0134: case 0135:
601 codes+=2; length++; break;
602 case 0140: case 0141: case 0142:
603 length += is_sbyte(ins, c-0140, 32) ? 1 : 4; break;
604 case 0143: case 0144: case 0145:
605 codes+=2; length++; break;
606 case 0300: case 0301: case 0302:
607 length += chsize (&ins->oprs[c-0300], bits);
608 break;
609 case 0310:
610 length += (bits==32);
611 break;
612 case 0311:
613 length += (bits==16);
614 break;
615 case 0312:
616 break;
617 case 0320:
618 length += (bits==32);
619 break;
620 case 0321:
621 length += (bits==16);
622 break;
623 case 0322:
624 break;
625 case 0330:
626 codes++, length++; break;
627 case 0331:
628 case 0332:
629 break;
630 case 0333:
631 length++; break;
632 case 0340: case 0341: case 0342:
633 if (ins->oprs[0].segment != NO_SEG)
634 errfunc (ERR_NONFATAL, "attempt to reserve non-constant"
635 " quantity of BSS space");
636 else
637 length += ins->oprs[0].offset << (c-0340);
638 break;
639 case 0370: case 0371: case 0372:
640 break;
641 case 0373:
642 length++; break;
643 default: /* can't do it by 'case' statements */
644 if (c>=0100 && c<=0277) { /* it's an EA */
645 ea ea_data;
646 if (!process_ea (&ins->oprs[(c>>3)&7], &ea_data, bits, 0,
647 ins->forw_ref)) {
648 errfunc (ERR_NONFATAL, "invalid effective address");
649 return -1;
650 } else
651 length += ea_data.size;
652 } else
653 errfunc (ERR_PANIC, "internal instruction table corrupt"
654 ": instruction code 0x%02X given", c);
656 return length;
659 static void gencode (long segment, long offset, int bits,
660 insn *ins, char *codes, long insn_end)
662 static char condval[] = { /* conditional opcodes */
663 0x7, 0x3, 0x2, 0x6, 0x2, 0x4, 0xF, 0xD, 0xC, 0xE, 0x6, 0x2,
664 0x3, 0x7, 0x3, 0x5, 0xE, 0xC, 0xD, 0xF, 0x1, 0xB, 0x9, 0x5,
665 0x0, 0xA, 0xA, 0xB, 0x8, 0x4
667 unsigned char c;
668 unsigned char bytes[4];
669 long data, size;
671 while (*codes)
672 switch (c = *codes++)
674 case 01: case 02: case 03:
675 out (offset, segment, codes, OUT_RAWDATA+c, NO_SEG, NO_SEG);
676 codes += c;
677 offset += c;
678 break;
680 case 04: case 06:
681 switch (ins->oprs[0].basereg)
683 case R_CS:
684 bytes[0] = 0x0E + (c == 0x04 ? 1 : 0); break;
685 case R_DS:
686 bytes[0] = 0x1E + (c == 0x04 ? 1 : 0); break;
687 case R_ES:
688 bytes[0] = 0x06 + (c == 0x04 ? 1 : 0); break;
689 case R_SS:
690 bytes[0] = 0x16 + (c == 0x04 ? 1 : 0); break;
691 default:
692 errfunc (ERR_PANIC, "bizarre 8086 segment register received");
694 out (offset, segment, bytes, OUT_RAWDATA+1, NO_SEG, NO_SEG);
695 offset++;
696 break;
698 case 05: case 07:
699 switch (ins->oprs[0].basereg) {
700 case R_FS: bytes[0] = 0xA0 + (c == 0x05 ? 1 : 0); break;
701 case R_GS: bytes[0] = 0xA8 + (c == 0x05 ? 1 : 0); break;
702 default:
703 errfunc (ERR_PANIC, "bizarre 386 segment register received");
705 out (offset, segment, bytes, OUT_RAWDATA+1, NO_SEG, NO_SEG);
706 offset++;
707 break;
709 case 010: case 011: case 012:
710 bytes[0] = *codes++ + regval(&ins->oprs[c-010]);
711 out (offset, segment, bytes, OUT_RAWDATA+1, NO_SEG, NO_SEG);
712 offset += 1;
713 break;
715 case 017:
716 bytes[0] = 0;
717 out (offset, segment, bytes, OUT_RAWDATA+1, NO_SEG, NO_SEG);
718 offset += 1;
719 break;
721 case 014: case 015: case 016:
722 if (ins->oprs[c-014].offset < -128
723 || ins->oprs[c-014].offset > 127)
725 errfunc (ERR_WARNING, "signed byte value exceeds bounds");
728 if (ins->oprs[c-014].segment != NO_SEG)
730 data = ins->oprs[c-014].offset;
731 out (offset, segment, &data, OUT_ADDRESS+1,
732 ins->oprs[c-014].segment, ins->oprs[c-014].wrt);
734 else {
735 bytes[0] = ins->oprs[c-014].offset;
736 out (offset, segment, bytes, OUT_RAWDATA+1, NO_SEG, NO_SEG);
738 offset += 1;
739 break;
741 case 020: case 021: case 022:
742 if (ins->oprs[c-020].offset < -256
743 || ins->oprs[c-020].offset > 255)
745 errfunc (ERR_WARNING, "byte value exceeds bounds");
747 if (ins->oprs[c-020].segment != NO_SEG) {
748 data = ins->oprs[c-020].offset;
749 out (offset, segment, &data, OUT_ADDRESS+1,
750 ins->oprs[c-020].segment, ins->oprs[c-020].wrt);
752 else {
753 bytes[0] = ins->oprs[c-020].offset;
754 out (offset, segment, bytes, OUT_RAWDATA+1, NO_SEG, NO_SEG);
756 offset += 1;
757 break;
759 case 024: case 025: case 026:
760 if (ins->oprs[c-024].offset < 0 || ins->oprs[c-024].offset > 255)
761 errfunc (ERR_WARNING, "unsigned byte value exceeds bounds");
762 if (ins->oprs[c-024].segment != NO_SEG) {
763 data = ins->oprs[c-024].offset;
764 out (offset, segment, &data, OUT_ADDRESS+1,
765 ins->oprs[c-024].segment, ins->oprs[c-024].wrt);
767 else {
768 bytes[0] = ins->oprs[c-024].offset;
769 out (offset, segment, bytes, OUT_RAWDATA+1, NO_SEG, NO_SEG);
771 offset += 1;
772 break;
774 case 030: case 031: case 032:
775 if (ins->oprs[c-030].segment == NO_SEG &&
776 ins->oprs[c-030].wrt == NO_SEG &&
777 (ins->oprs[c-030].offset < -65536L ||
778 ins->oprs[c-030].offset > 65535L))
780 errfunc (ERR_WARNING, "word value exceeds bounds");
782 data = ins->oprs[c-030].offset;
783 out (offset, segment, &data, OUT_ADDRESS+2,
784 ins->oprs[c-030].segment, ins->oprs[c-030].wrt);
785 offset += 2;
786 break;
788 case 034: case 035: case 036:
789 data = ins->oprs[c-034].offset;
790 size = ((ins->oprs[c-034].addr_size ?
791 ins->oprs[c-034].addr_size : bits) == 16 ? 2 : 4);
792 if (size==16 && (data < -65536L || data > 65535L))
793 errfunc (ERR_WARNING, "word value exceeds bounds");
794 out (offset, segment, &data, OUT_ADDRESS+size,
795 ins->oprs[c-034].segment, ins->oprs[c-034].wrt);
796 offset += size;
797 break;
799 case 037:
800 if (ins->oprs[0].segment == NO_SEG)
801 errfunc (ERR_NONFATAL, "value referenced by FAR is not"
802 " relocatable");
803 data = 0L;
804 out (offset, segment, &data, OUT_ADDRESS+2,
805 outfmt->segbase(1+ins->oprs[0].segment),
806 ins->oprs[0].wrt);
807 offset += 2;
808 break;
810 case 040: case 041: case 042:
811 data = ins->oprs[c-040].offset;
812 out (offset, segment, &data, OUT_ADDRESS+4,
813 ins->oprs[c-040].segment, ins->oprs[c-040].wrt);
814 offset += 4;
815 break;
817 case 050: case 051: case 052:
818 if (ins->oprs[c-050].segment != segment)
819 errfunc (ERR_NONFATAL, "short relative jump outside segment");
820 data = ins->oprs[c-050].offset - insn_end;
821 if (data > 127 || data < -128)
822 errfunc (ERR_NONFATAL, "short jump is out of range");
823 bytes[0] = data;
824 out (offset, segment, bytes, OUT_RAWDATA+1, NO_SEG, NO_SEG);
825 offset += 1;
826 break;
828 case 060: case 061: case 062:
829 if (ins->oprs[c-060].segment != segment) {
830 data = ins->oprs[c-060].offset;
831 out (offset, segment, &data, OUT_REL2ADR+insn_end-offset,
832 ins->oprs[c-060].segment, ins->oprs[c-060].wrt);
833 } else {
834 data = ins->oprs[c-060].offset - insn_end;
835 out (offset, segment, &data,
836 OUT_ADDRESS+2, NO_SEG, NO_SEG);
838 offset += 2;
839 break;
841 case 064: case 065: case 066:
842 size = ((ins->oprs[c-064].addr_size ?
843 ins->oprs[c-064].addr_size : bits) == 16 ? 2 : 4);
844 if (ins->oprs[c-064].segment != segment) {
845 data = ins->oprs[c-064].offset;
846 size = (bits == 16 ? OUT_REL2ADR : OUT_REL4ADR);
847 out (offset, segment, &data, size+insn_end-offset,
848 ins->oprs[c-064].segment, ins->oprs[c-064].wrt);
849 size = (bits == 16 ? 2 : 4);
850 } else {
851 data = ins->oprs[c-064].offset - insn_end;
852 out (offset, segment, &data,
853 OUT_ADDRESS+size, NO_SEG, NO_SEG);
855 offset += size;
856 break;
858 case 070: case 071: case 072:
859 if (ins->oprs[c-070].segment != segment) {
860 data = ins->oprs[c-070].offset;
861 out (offset, segment, &data, OUT_REL4ADR+insn_end-offset,
862 ins->oprs[c-070].segment, ins->oprs[c-070].wrt);
863 } else {
864 data = ins->oprs[c-070].offset - insn_end;
865 out (offset, segment, &data,
866 OUT_ADDRESS+4, NO_SEG, NO_SEG);
868 offset += 4;
869 break;
871 case 0130: case 0131: case 0132:
872 data = ins->oprs[c-0130].offset;
873 if (is_sbyte(ins, c-0130, 16)) {
874 out (offset, segment, &data, OUT_RAWDATA+1, NO_SEG, NO_SEG);
875 offset++;
876 } else {
877 if (ins->oprs[c-0130].segment == NO_SEG &&
878 ins->oprs[c-0130].wrt == NO_SEG &&
879 (data < -65536L || data > 65535L)) {
880 errfunc (ERR_WARNING, "word value exceeds bounds");
882 out (offset, segment, &data, OUT_ADDRESS+2,
883 ins->oprs[c-0130].segment, ins->oprs[c-0130].wrt);
884 offset += 2;
886 break;
888 case 0133: case 0134: case 0135:
889 codes++;
890 bytes[0] = *codes++;
891 if (is_sbyte(ins, c-0133, 16)) bytes[0] |= 2; /* s-bit */
892 out (offset, segment, bytes, OUT_RAWDATA+1, NO_SEG, NO_SEG);
893 offset++;
894 break;
896 case 0140: case 0141: case 0142:
897 data = ins->oprs[c-0140].offset;
898 if (is_sbyte(ins, c-0140, 32)) {
899 out (offset, segment, &data, OUT_RAWDATA+1, NO_SEG, NO_SEG);
900 offset++;
901 } else {
902 out (offset, segment, &data, OUT_ADDRESS+4,
903 ins->oprs[c-0140].segment, ins->oprs[c-0140].wrt);
904 offset += 4;
906 break;
908 case 0143: case 0144: case 0145:
909 codes++;
910 bytes[0] = *codes++;
911 if (is_sbyte(ins, c-0143, 32)) bytes[0] |= 2; /* s-bit */
912 out (offset, segment, bytes, OUT_RAWDATA+1, NO_SEG, NO_SEG);
913 offset++;
914 break;
916 case 0300: case 0301: case 0302:
917 if (chsize (&ins->oprs[c-0300], bits)) {
918 *bytes = 0x67;
919 out (offset, segment, bytes,
920 OUT_RAWDATA+1, NO_SEG, NO_SEG);
921 offset += 1;
922 } else
923 offset += 0;
924 break;
926 case 0310:
927 if (bits==32) {
928 *bytes = 0x67;
929 out (offset, segment, bytes,
930 OUT_RAWDATA+1, NO_SEG, NO_SEG);
931 offset += 1;
932 } else
933 offset += 0;
934 break;
936 case 0311:
937 if (bits==16) {
938 *bytes = 0x67;
939 out (offset, segment, bytes,
940 OUT_RAWDATA+1, NO_SEG, NO_SEG);
941 offset += 1;
942 } else
943 offset += 0;
944 break;
946 case 0312:
947 break;
949 case 0320:
950 if (bits==32) {
951 *bytes = 0x66;
952 out (offset, segment, bytes,
953 OUT_RAWDATA+1, NO_SEG, NO_SEG);
954 offset += 1;
955 } else
956 offset += 0;
957 break;
959 case 0321:
960 if (bits==16) {
961 *bytes = 0x66;
962 out (offset, segment, bytes,
963 OUT_RAWDATA+1, NO_SEG, NO_SEG);
964 offset += 1;
965 } else
966 offset += 0;
967 break;
969 case 0322:
970 break;
972 case 0330:
973 *bytes = *codes++ ^ condval[ins->condition];
974 out (offset, segment, bytes,
975 OUT_RAWDATA+1, NO_SEG, NO_SEG);
976 offset += 1;
977 break;
979 case 0331:
980 case 0332:
981 break;
983 case 0333:
984 *bytes = 0xF3;
985 out (offset, segment, bytes,
986 OUT_RAWDATA+1, NO_SEG, NO_SEG);
987 offset += 1;
988 break;
990 case 0340: case 0341: case 0342:
991 if (ins->oprs[0].segment != NO_SEG)
992 errfunc (ERR_PANIC, "non-constant BSS size in pass two");
993 else {
994 long size = ins->oprs[0].offset << (c-0340);
995 if (size > 0)
996 out (offset, segment, NULL,
997 OUT_RESERVE+size, NO_SEG, NO_SEG);
998 offset += size;
1000 break;
1002 case 0370: case 0371: case 0372:
1003 break;
1005 case 0373:
1006 *bytes = bits==16 ? 3 : 5;
1007 out (offset, segment, bytes,
1008 OUT_RAWDATA+1, NO_SEG, NO_SEG);
1009 offset += 1;
1010 break;
1012 default: /* can't do it by 'case' statements */
1013 if (c>=0100 && c<=0277) { /* it's an EA */
1014 ea ea_data;
1015 int rfield;
1016 unsigned char *p;
1017 long s;
1019 if (c<=0177) /* pick rfield from operand b */
1020 rfield = regval (&ins->oprs[c&7]);
1021 else /* rfield is constant */
1022 rfield = c & 7;
1024 if (!process_ea (&ins->oprs[(c>>3)&7], &ea_data, bits, rfield,
1025 ins->forw_ref))
1027 errfunc (ERR_NONFATAL, "invalid effective address");
1030 p = bytes;
1031 *p++ = ea_data.modrm;
1032 if (ea_data.sib_present)
1033 *p++ = ea_data.sib;
1035 s = p-bytes;
1036 out (offset, segment, bytes, OUT_RAWDATA + s,
1037 NO_SEG, NO_SEG);
1039 switch (ea_data.bytes) {
1040 case 0:
1041 break;
1042 case 1:
1043 if (ins->oprs[(c>>3)&7].segment != NO_SEG) {
1044 data = ins->oprs[(c>>3)&7].offset;
1045 out (offset, segment, &data, OUT_ADDRESS+1,
1046 ins->oprs[(c>>3)&7].segment,
1047 ins->oprs[(c>>3)&7].wrt);
1048 } else {
1049 *bytes = ins->oprs[(c>>3)&7].offset;
1050 out (offset, segment, bytes, OUT_RAWDATA+1,
1051 NO_SEG, NO_SEG);
1053 s++;
1054 break;
1055 case 2:
1056 case 4:
1057 data = ins->oprs[(c>>3)&7].offset;
1058 out (offset, segment, &data,
1059 OUT_ADDRESS+ea_data.bytes,
1060 ins->oprs[(c>>3)&7].segment, ins->oprs[(c>>3)&7].wrt);
1061 s += ea_data.bytes;
1062 break;
1064 offset += s;
1065 } else
1066 errfunc (ERR_PANIC, "internal instruction table corrupt"
1067 ": instruction code 0x%02X given", c);
1071 static int regval (operand *o)
1073 switch (o->basereg) {
1074 case R_EAX: case R_AX: case R_AL: case R_ES: case R_CR0: case R_DR0:
1075 case R_ST0: case R_MM0: case R_XMM0:
1076 return 0;
1077 case R_ECX: case R_CX: case R_CL: case R_CS: case R_DR1: case R_ST1:
1078 case R_MM1: case R_XMM1:
1079 return 1;
1080 case R_EDX: case R_DX: case R_DL: case R_SS: case R_CR2: case R_DR2:
1081 case R_ST2: case R_MM2: case R_XMM2:
1082 return 2;
1083 case R_EBX: case R_BX: case R_BL: case R_DS: case R_CR3: case R_DR3:
1084 case R_TR3: case R_ST3: case R_MM3: case R_XMM3:
1085 return 3;
1086 case R_ESP: case R_SP: case R_AH: case R_FS: case R_CR4: case R_TR4:
1087 case R_ST4: case R_MM4: case R_XMM4:
1088 return 4;
1089 case R_EBP: case R_BP: case R_CH: case R_GS: case R_TR5: case R_ST5:
1090 case R_MM5: case R_XMM5:
1091 return 5;
1092 case R_ESI: case R_SI: case R_DH: case R_DR6: case R_TR6: case R_ST6:
1093 case R_MM6: case R_XMM6:
1094 return 6;
1095 case R_EDI: case R_DI: case R_BH: case R_DR7: case R_TR7: case R_ST7:
1096 case R_MM7: case R_XMM7:
1097 return 7;
1098 default: /* panic */
1099 errfunc (ERR_PANIC, "invalid register operand given to regval()");
1100 return 0;
1104 static int matches (struct itemplate *itemp, insn *instruction)
1106 int i, size[3], asize, oprs, ret;
1108 ret = 100;
1111 * Check the opcode
1113 if (itemp->opcode != instruction->opcode) return 0;
1116 * Count the operands
1118 if (itemp->operands != instruction->operands) return 0;
1121 * Check that no spurious colons or TOs are present
1123 for (i=0; i<itemp->operands; i++)
1124 if (instruction->oprs[i].type & ~itemp->opd[i] & (COLON|TO))
1125 return 0;
1128 * Check that the operand flags all match up
1130 for (i=0; i<itemp->operands; i++)
1131 if (itemp->opd[i] & ~instruction->oprs[i].type ||
1132 ((itemp->opd[i] & SIZE_MASK) &&
1133 ((itemp->opd[i] ^ instruction->oprs[i].type) & SIZE_MASK)))
1135 if ((itemp->opd[i] & ~instruction->oprs[i].type & NON_SIZE) ||
1136 (instruction->oprs[i].type & SIZE_MASK))
1137 return 0;
1138 else
1139 /* ret = 1; */
1140 return 1;
1144 * Check operand sizes
1146 if (itemp->flags & IF_ARMASK) {
1147 size[0] = size[1] = size[2] = 0;
1149 switch (itemp->flags & IF_ARMASK) {
1150 case IF_AR0: i = 0; break;
1151 case IF_AR1: i = 1; break;
1152 case IF_AR2: i = 2; break;
1153 default: break; /* Shouldn't happen */
1155 if (itemp->flags & IF_SB) {
1156 size[i] = BITS8;
1157 } else if (itemp->flags & IF_SW) {
1158 size[i] = BITS16;
1159 } else if (itemp->flags & IF_SD) {
1160 size[i] = BITS32;
1162 } else {
1163 asize = 0;
1164 if (itemp->flags & IF_SB) {
1165 asize = BITS8;
1166 oprs = itemp->operands;
1167 } else if (itemp->flags & IF_SW) {
1168 asize = BITS16;
1169 oprs = itemp->operands;
1170 } else if (itemp->flags & IF_SD) {
1171 asize = BITS32;
1172 oprs = itemp->operands;
1174 size[0] = size[1] = size[2] = asize;
1177 if (itemp->flags & (IF_SM | IF_SM2)) {
1178 oprs = (itemp->flags & IF_SM2 ? 2 : itemp->operands);
1179 asize = 0;
1180 for (i=0; i<oprs; i++) {
1181 if ( (asize = itemp->opd[i] & SIZE_MASK) != 0) {
1182 int j;
1183 for (j=0; j<oprs; j++)
1184 size[j] = asize;
1185 break;
1188 } else {
1189 oprs = itemp->operands;
1192 for (i=0; i<itemp->operands; i++)
1193 if (!(itemp->opd[i] & SIZE_MASK) &&
1194 (instruction->oprs[i].type & SIZE_MASK & ~size[i]))
1195 /* ret = 2; */
1196 return 2;
1199 * Check template is okay at the set cpu level
1201 if ((itemp->flags & IF_PLEVEL) > cpu) return 3;
1204 * Check if special handling needed for Jumps
1206 if ((unsigned char)(itemp->code[0]) >= 0370) return 99;
1208 return ret;
1211 static ea *process_ea (operand *input, ea *output, int addrbits, int rfield,
1212 int forw_ref)
1214 if (!(REGISTER & ~input->type)) { /* it's a single register */
1215 static int regs[] = {
1216 R_AL, R_CL, R_DL, R_BL, R_AH, R_CH, R_DH, R_BH,
1217 R_AX, R_CX, R_DX, R_BX, R_SP, R_BP, R_SI, R_DI,
1218 R_EAX, R_ECX, R_EDX, R_EBX, R_ESP, R_EBP, R_ESI, R_EDI,
1219 R_MM0, R_MM1, R_MM2, R_MM3, R_MM4, R_MM5, R_MM6, R_MM7,
1220 R_XMM0, R_XMM1, R_XMM2, R_XMM3, R_XMM4, R_XMM5, R_XMM6, R_XMM7
1222 int i;
1224 for (i=0; i<elements(regs); i++)
1225 if (input->basereg == regs[i]) break;
1226 if (i<elements(regs)) {
1227 output->sib_present = FALSE;/* no SIB necessary */
1228 output->bytes = 0; /* no offset necessary either */
1229 output->modrm = 0xC0 | (rfield << 3) | (i & 7);
1231 else
1232 return NULL;
1233 } else { /* it's a memory reference */
1234 if (input->basereg==-1 && (input->indexreg==-1 || input->scale==0)) {
1235 /* it's a pure offset */
1236 if (input->addr_size)
1237 addrbits = input->addr_size;
1238 output->sib_present = FALSE;
1239 output->bytes = (addrbits==32 ? 4 : 2);
1240 output->modrm = (addrbits==32 ? 5 : 6) | (rfield << 3);
1242 else { /* it's an indirection */
1243 int i=input->indexreg, b=input->basereg, s=input->scale;
1244 long o=input->offset, seg=input->segment;
1245 int hb=input->hintbase, ht=input->hinttype;
1246 int t;
1248 if (s==0) i = -1; /* make this easy, at least */
1250 if (i==R_EAX || i==R_EBX || i==R_ECX || i==R_EDX
1251 || i==R_EBP || i==R_ESP || i==R_ESI || i==R_EDI
1252 || b==R_EAX || b==R_EBX || b==R_ECX || b==R_EDX
1253 || b==R_EBP || b==R_ESP || b==R_ESI || b==R_EDI) {
1254 /* it must be a 32-bit memory reference. Firstly we have
1255 * to check that all registers involved are type Exx. */
1256 if (i!=-1 && i!=R_EAX && i!=R_EBX && i!=R_ECX && i!=R_EDX
1257 && i!=R_EBP && i!=R_ESP && i!=R_ESI && i!=R_EDI)
1258 return NULL;
1259 if (b!=-1 && b!=R_EAX && b!=R_EBX && b!=R_ECX && b!=R_EDX
1260 && b!=R_EBP && b!=R_ESP && b!=R_ESI && b!=R_EDI)
1261 return NULL;
1263 /* While we're here, ensure the user didn't specify WORD. */
1264 if (input->addr_size == 16)
1265 return NULL;
1267 /* now reorganise base/index */
1268 if (s == 1 && b != i && b != -1 && i != -1 &&
1269 ((hb==b&&ht==EAH_NOTBASE) || (hb==i&&ht==EAH_MAKEBASE)))
1270 t = b, b = i, i = t; /* swap if hints say so */
1271 if (b==i) /* convert EAX+2*EAX to 3*EAX */
1272 b = -1, s++;
1273 if (b==-1 && s==1 && !(hb == i && ht == EAH_NOTBASE))
1274 b = i, i = -1; /* make single reg base, unless hint */
1275 if (((s==2 && i!=R_ESP && !(input->eaflags & EAF_TIMESTWO)) ||
1276 s==3 || s==5 || s==9) && b==-1)
1277 b = i, s--; /* convert 3*EAX to EAX+2*EAX */
1278 if (s==1 && i==R_ESP) /* swap ESP into base if scale is 1 */
1279 i = b, b = R_ESP;
1280 if (i==R_ESP || (s!=1 && s!=2 && s!=4 && s!=8 && i!=-1))
1281 return NULL; /* wrong, for various reasons */
1283 if (i==-1 && b!=R_ESP) {/* no SIB needed */
1284 int mod, rm;
1285 switch(b) {
1286 case R_EAX: rm = 0; break;
1287 case R_ECX: rm = 1; break;
1288 case R_EDX: rm = 2; break;
1289 case R_EBX: rm = 3; break;
1290 case R_EBP: rm = 5; break;
1291 case R_ESI: rm = 6; break;
1292 case R_EDI: rm = 7; break;
1293 case -1: rm = 5; break;
1294 default: /* should never happen */
1295 return NULL;
1297 if (b==-1 || (b!=R_EBP && o==0 &&
1298 seg==NO_SEG && !forw_ref &&
1299 !(input->eaflags &
1300 (EAF_BYTEOFFS|EAF_WORDOFFS))))
1301 mod = 0;
1302 else if (input->eaflags & EAF_BYTEOFFS ||
1303 (o>=-128 && o<=127 && seg==NO_SEG && !forw_ref &&
1304 !(input->eaflags & EAF_WORDOFFS))) {
1305 mod = 1;
1307 else
1308 mod = 2;
1310 output->sib_present = FALSE;
1311 output->bytes = (b==-1 || mod==2 ? 4 : mod);
1312 output->modrm = (mod<<6) | (rfield<<3) | rm;
1314 else { /* we need a SIB */
1315 int mod, scale, index, base;
1317 switch (b) {
1318 case R_EAX: base = 0; break;
1319 case R_ECX: base = 1; break;
1320 case R_EDX: base = 2; break;
1321 case R_EBX: base = 3; break;
1322 case R_ESP: base = 4; break;
1323 case R_EBP: case -1: base = 5; break;
1324 case R_ESI: base = 6; break;
1325 case R_EDI: base = 7; break;
1326 default: /* then what the smeg is it? */
1327 return NULL; /* panic */
1330 switch (i) {
1331 case R_EAX: index = 0; break;
1332 case R_ECX: index = 1; break;
1333 case R_EDX: index = 2; break;
1334 case R_EBX: index = 3; break;
1335 case -1: index = 4; break;
1336 case R_EBP: index = 5; break;
1337 case R_ESI: index = 6; break;
1338 case R_EDI: index = 7; break;
1339 default: /* then what the smeg is it? */
1340 return NULL; /* panic */
1343 if (i==-1) s = 1;
1344 switch (s) {
1345 case 1: scale = 0; break;
1346 case 2: scale = 1; break;
1347 case 4: scale = 2; break;
1348 case 8: scale = 3; break;
1349 default: /* then what the smeg is it? */
1350 return NULL; /* panic */
1353 if (b==-1 || (b!=R_EBP && o==0 &&
1354 seg==NO_SEG && !forw_ref &&
1355 !(input->eaflags &
1356 (EAF_BYTEOFFS|EAF_WORDOFFS))))
1357 mod = 0;
1358 else if (input->eaflags & EAF_BYTEOFFS ||
1359 (o>=-128 && o<=127 && seg==NO_SEG && !forw_ref &&
1360 !(input->eaflags & EAF_WORDOFFS)))
1361 mod = 1;
1362 else
1363 mod = 2;
1365 output->sib_present = TRUE;
1366 output->bytes = (b==-1 || mod==2 ? 4 : mod);
1367 output->modrm = (mod<<6) | (rfield<<3) | 4;
1368 output->sib = (scale<<6) | (index<<3) | base;
1371 else { /* it's 16-bit */
1372 int mod, rm;
1374 /* check all registers are BX, BP, SI or DI */
1375 if ((b!=-1 && b!=R_BP && b!=R_BX && b!=R_SI && b!=R_DI) ||
1376 (i!=-1 && i!=R_BP && i!=R_BX && i!=R_SI && i!=R_DI))
1377 return NULL;
1379 /* ensure the user didn't specify DWORD */
1380 if (input->addr_size == 32)
1381 return NULL;
1383 if (s!=1 && i!=-1) return NULL;/* no can do, in 16-bit EA */
1384 if (b==-1 && i!=-1) b ^= i ^= b ^= i; /* swap them round */
1385 if ((b==R_SI || b==R_DI) && i!=-1)
1386 b ^= i ^= b ^= i; /* have BX/BP as base, SI/DI index */
1387 if (b==i) return NULL;/* shouldn't ever happen, in theory */
1388 if (i!=-1 && b!=-1 &&
1389 (i==R_BP || i==R_BX || b==R_SI || b==R_DI))
1390 return NULL; /* invalid combinations */
1391 if (b==-1) /* pure offset: handled above */
1392 return NULL; /* so if it gets to here, panic! */
1394 rm = -1;
1395 if (i!=-1)
1396 switch (i*256 + b) {
1397 case R_SI*256+R_BX: rm=0; break;
1398 case R_DI*256+R_BX: rm=1; break;
1399 case R_SI*256+R_BP: rm=2; break;
1400 case R_DI*256+R_BP: rm=3; break;
1402 else
1403 switch (b) {
1404 case R_SI: rm=4; break;
1405 case R_DI: rm=5; break;
1406 case R_BP: rm=6; break;
1407 case R_BX: rm=7; break;
1409 if (rm==-1) /* can't happen, in theory */
1410 return NULL; /* so panic if it does */
1412 if (o==0 && seg==NO_SEG && !forw_ref && rm!=6 &&
1413 !(input->eaflags & (EAF_BYTEOFFS|EAF_WORDOFFS)))
1414 mod = 0;
1415 else if (input->eaflags & EAF_BYTEOFFS ||
1416 (o>=-128 && o<=127 && seg==NO_SEG && !forw_ref &&
1417 !(input->eaflags & EAF_WORDOFFS)))
1418 mod = 1;
1419 else
1420 mod = 2;
1422 output->sib_present = FALSE; /* no SIB - it's 16-bit */
1423 output->bytes = mod; /* bytes of offset needed */
1424 output->modrm = (mod<<6) | (rfield<<3) | rm;
1428 output->size = 1 + output->sib_present + output->bytes;
1429 return output;
1432 static int chsize (operand *input, int addrbits)
1434 if (!(MEMORY & ~input->type)) {
1435 int i=input->indexreg, b=input->basereg;
1437 if (input->scale==0) i = -1;
1439 if (i == -1 && b == -1) /* pure offset */
1440 return (input->addr_size != 0 && input->addr_size != addrbits);
1442 if (i==R_EAX || i==R_EBX || i==R_ECX || i==R_EDX
1443 || i==R_EBP || i==R_ESP || i==R_ESI || i==R_EDI
1444 || b==R_EAX || b==R_EBX || b==R_ECX || b==R_EDX
1445 || b==R_EBP || b==R_ESP || b==R_ESI || b==R_EDI)
1446 return (addrbits==16);
1447 else
1448 return (addrbits==32);
1450 else
1451 return 0;