Document change to -g internals
[nasm/avx512.git] / assemble.c
blob8a6bd0d26e075a19016fc6787e2877323e3a943c
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 operand-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 * \44, \45, \46 - select between \3[012] and \4[012] depending on 16/32 bit
29 * assembly mode or the address-size override on the operand
30 * \50, \51, \52 - a byte relative operand, from operand 0, 1 or 2
31 * \60, \61, \62 - a word relative operand, from operand 0, 1 or 2
32 * \64, \65, \66 - select between \6[012] and \7[012] depending on 16/32 bit
33 * assembly mode or the operand-size override on the operand
34 * \70, \71, \72 - a long relative operand, from operand 0, 1 or 2
35 * \1ab - a ModRM, calculated on EA in operand a, with the spare
36 * field the register value of operand b.
37 * \130,\131,\132 - an immediate word or signed byte for operand 0, 1, or 2
38 * \133,\134,\135 - or 2 (s-field) into next opcode byte if operand 0, 1, or 2
39 * is a signed byte rather than a word.
40 * \140,\141,\142 - an immediate dword or signed byte for operand 0, 1, or 2
41 * \143,\144,\145 - or 2 (s-field) into next opcode byte if operand 0, 1, or 2
42 * is a signed byte rather than a dword.
43 * \2ab - a ModRM, calculated on EA in operand a, with the spare
44 * field equal to digit b.
45 * \30x - might be an 0x67 byte, depending on the address size of
46 * the memory reference in operand x.
47 * \310 - indicates fixed 16-bit address size, i.e. optional 0x67.
48 * \311 - indicates fixed 32-bit address size, i.e. optional 0x67.
49 * \312 - (disassembler only) marker on LOOP, LOOPxx instructions.
50 * \320 - indicates fixed 16-bit operand size, i.e. optional 0x66.
51 * \321 - indicates fixed 32-bit operand size, i.e. optional 0x66.
52 * \322 - indicates that this instruction is only valid when the
53 * operand size is the default (instruction to disassembler,
54 * generates no code in the assembler)
55 * \330 - a literal byte follows in the code stream, to be added
56 * to the condition code value of the instruction.
57 * \331 - instruction not valid with REP prefix. Hint for
58 * disassembler only; for SSE instructions.
59 * \332 - disassemble a rep (0xF3 byte) prefix as repe not rep.
60 * \333 - REP prefix (0xF3 byte); for SSE instructions. Not encoded
61 * as a literal byte in order to aid the disassembler.
62 * \340 - reserve <operand 0> bytes of uninitialised storage.
63 * Operand 0 had better be a segmentless constant.
64 * \370,\371,\372 - match only if operand 0 meets byte jump criteria.
65 * 370 is used for Jcc, 371 is used for JMP.
66 * \373 - assemble 0x03 if bits==16, 0x05 if bits==32;
67 * used for conditional jump over longer jump
70 #include <stdio.h>
71 #include <string.h>
73 #include "nasm.h"
74 #include "nasmlib.h"
75 #include "assemble.h"
76 #include "insns.h"
77 #include "preproc.h"
79 extern struct itemplate *nasm_instructions[];
81 typedef struct {
82 int sib_present; /* is a SIB byte necessary? */
83 int bytes; /* # of bytes of offset needed */
84 int size; /* lazy - this is sib+bytes+1 */
85 unsigned char modrm, sib; /* the bytes themselves */
86 } ea;
88 static unsigned long cpu; /* cpu level received from nasm.c */
89 static efunc errfunc;
90 static struct ofmt *outfmt;
91 static ListGen *list;
93 static long calcsize (long, long, int, insn *, const char *);
94 static void gencode (long, long, int, insn *, const char *, long);
95 static int regval (operand *o);
96 static int matches (struct itemplate *, insn *);
97 static ea * process_ea (operand *, ea *, int, int, int);
98 static int chsize (operand *, int);
101 * This routine wrappers the real output format's output routine,
102 * in order to pass a copy of the data off to the listing file
103 * generator at the same time.
105 static void out (long offset, long segto, const void *data, unsigned long type,
106 long segment, long wrt)
108 static long lineno = 0; /* static!!! */
109 static char *lnfname = NULL;
111 if ((type & OUT_TYPMASK) == OUT_ADDRESS) {
112 if (segment != NO_SEG || wrt != NO_SEG) {
114 * This address is relocated. We must write it as
115 * OUT_ADDRESS, so there's no work to be done here.
117 list->output (offset, data, type);
119 else {
120 unsigned char p[4], *q = p;
122 * This is a non-relocated address, and we're going to
123 * convert it into RAWDATA format.
125 if ((type & OUT_SIZMASK) == 4) {
126 WRITELONG (q, * (long *) data);
127 list->output (offset, p, OUT_RAWDATA+4);
129 else {
130 WRITESHORT (q, * (long *) data);
131 list->output (offset, p, OUT_RAWDATA+2);
135 else if ((type & OUT_TYPMASK) == OUT_RAWDATA) {
136 list->output (offset, data, type);
138 else if ((type & OUT_TYPMASK) == OUT_RESERVE) {
139 list->output (offset, NULL, type);
141 else if ((type & OUT_TYPMASK) == OUT_REL2ADR ||
142 (type & OUT_TYPMASK) == OUT_REL4ADR) {
143 list->output (offset, data, type);
147 * this call to src_get determines when we call the
148 * debug-format-specific "linenum" function
149 * it updates lineno and lnfname to the current values
150 * returning 0 if "same as last time", -2 if lnfname
151 * changed, and the amount by which lineno changed,
152 * if it did. thus, these variables must be static
155 if (src_get(&lineno,&lnfname))
157 outfmt->current_dfmt->linenum(lnfname,lineno,segto);
160 outfmt->output (segto, data, type, segment, wrt);
163 static int jmp_match (long segment, long offset, int bits,
164 insn *ins, const char *code)
165 { long isize;
166 unsigned char c = code[0];
169 if (c != 0370 && c != 0371) return 0;
170 if (ins->oprs[0].opflags & OPFLAG_FORWARD) {
171 if ((optimizing<0 || (ins->oprs[0].type & STRICT))
172 && c==0370) return 1;
173 else return (pass0==0); /* match a forward reference */
175 isize = calcsize (segment, offset, bits, ins, code);
176 if (ins->oprs[0].segment != segment) return 0;
177 isize = ins->oprs[0].offset - offset - isize; /* isize is now the delta */
178 if (isize >= -128L && isize <= 127L) return 1; /* it is byte size */
180 return 0;
184 long assemble (long segment, long offset, int bits, unsigned long cp,
185 insn *instruction, struct ofmt *output, efunc error,
186 ListGen *listgen)
188 struct itemplate *temp;
189 int j;
190 int size_prob;
191 long insn_end;
192 long itimes;
193 long start = offset;
194 long wsize = 0; /* size for DB etc. */
196 errfunc = error; /* to pass to other functions */
197 cpu = cp;
198 outfmt = output; /* likewise */
199 list = listgen; /* and again */
201 switch (instruction->opcode)
203 case -1: return 0;
204 case I_DB: wsize = 1; break;
205 case I_DW: wsize = 2; break;
206 case I_DD: wsize = 4; break;
207 case I_DQ: wsize = 8; break;
208 case I_DT: wsize = 10; break;
211 if (wsize) {
212 extop * e;
213 long t = instruction->times;
214 if (t < 0)
215 errfunc(ERR_PANIC, "instruction->times < 0 (%ld) in assemble()",t);
217 while (t--) /* repeat TIMES times */
219 for (e = instruction->eops; e; e = e->next)
221 if (e->type == EOT_DB_NUMBER)
223 if (wsize == 1) {
224 if (e->segment != NO_SEG)
225 errfunc (ERR_NONFATAL,
226 "one-byte relocation attempted");
227 else {
228 unsigned char out_byte = e->offset;
229 out (offset, segment, &out_byte, OUT_RAWDATA+1,
230 NO_SEG, NO_SEG);
233 else if (wsize > 5) {
234 errfunc (ERR_NONFATAL, "integer supplied to a D%c"
235 " instruction", wsize==8 ? 'Q' : 'T');
237 else
238 out (offset, segment, &e->offset,
239 OUT_ADDRESS+wsize, e->segment,
240 e->wrt);
241 offset += wsize;
243 else if (e->type == EOT_DB_STRING)
245 int align;
247 out (offset, segment, e->stringval,
248 OUT_RAWDATA+e->stringlen, NO_SEG, NO_SEG);
249 align = e->stringlen % wsize;
251 if (align) {
252 align = wsize - align;
253 out (offset, segment, "\0\0\0\0\0\0\0\0",
254 OUT_RAWDATA+align, NO_SEG, NO_SEG);
256 offset += e->stringlen + align;
259 if (t > 0 && t == instruction->times-1)
262 * Dummy call to list->output to give the offset to the
263 * listing module.
265 list->output (offset, NULL, OUT_RAWDATA);
266 list->uplevel (LIST_TIMES);
269 if (instruction->times > 1)
270 list->downlevel (LIST_TIMES);
271 return offset - start;
274 if (instruction->opcode == I_INCBIN)
276 static char fname[FILENAME_MAX];
277 FILE * fp;
278 long len;
279 char *prefix = "", *combine;
280 char** pPrevPath = NULL;
282 len = FILENAME_MAX-1;
283 if (len > instruction->eops->stringlen)
284 len = instruction->eops->stringlen;
285 strncpy (fname, instruction->eops->stringval, len);
286 fname[len] = '\0';
288 while (1) /* added by alexfru: 'incbin' uses include paths */
290 combine = nasm_malloc(strlen(prefix) + len + 1);
291 strcpy(combine, prefix);
292 strcat(combine, fname);
294 if ( (fp = fopen(combine, "rb")) != NULL)
296 nasm_free(combine);
297 break;
300 nasm_free(combine);
301 pPrevPath = pp_get_include_path_ptr (pPrevPath);
302 if (pPrevPath == NULL)
303 break;
304 prefix = *pPrevPath;
307 if (fp == NULL)
308 error (ERR_NONFATAL, "`incbin': unable to open file `%s'", fname);
309 else if (fseek(fp, 0L, SEEK_END) < 0)
310 error (ERR_NONFATAL, "`incbin': unable to seek on file `%s'",
311 fname);
312 else
314 static char buf[2048];
315 long t = instruction->times;
316 long base = 0;
318 len = ftell (fp);
319 if (instruction->eops->next) {
320 base = instruction->eops->next->offset;
321 len -= base;
322 if (instruction->eops->next->next &&
323 len > instruction->eops->next->next->offset)
324 len = instruction->eops->next->next->offset;
327 * Dummy call to list->output to give the offset to the
328 * listing module.
330 list->output (offset, NULL, OUT_RAWDATA);
331 list->uplevel(LIST_INCBIN);
332 while (t--)
334 long l;
336 fseek (fp, base, SEEK_SET);
337 l = len;
338 while (l > 0) {
339 long m = fread (buf, 1, (l>sizeof(buf)?sizeof(buf):l),
340 fp);
341 if (!m) {
343 * This shouldn't happen unless the file
344 * actually changes while we are reading
345 * it.
347 error (ERR_NONFATAL, "`incbin': unexpected EOF while"
348 " reading file `%s'", fname);
349 t=0; /* Try to exit cleanly */
350 break;
352 out (offset, segment, buf, OUT_RAWDATA+m,
353 NO_SEG, NO_SEG);
354 l -= m;
357 list->downlevel(LIST_INCBIN);
358 if (instruction->times > 1) {
360 * Dummy call to list->output to give the offset to the
361 * listing module.
363 list->output (offset, NULL, OUT_RAWDATA);
364 list->uplevel(LIST_TIMES);
365 list->downlevel(LIST_TIMES);
367 fclose (fp);
368 return instruction->times * len;
370 return 0; /* if we're here, there's an error */
373 size_prob = FALSE;
374 temp = nasm_instructions[instruction->opcode];
375 while (temp->opcode != -1) {
376 int m = matches (temp, instruction);
377 if (m == 99)
378 m += jmp_match(segment, offset, bits, instruction, temp->code);
380 if (m == 100) /* matches! */
382 const char *codes = temp->code;
383 long insn_size = calcsize(segment, offset, bits,
384 instruction, codes);
385 itimes = instruction->times;
386 if (insn_size < 0) /* shouldn't be, on pass two */
387 error (ERR_PANIC, "errors made it through from pass one");
388 else while (itimes--) {
389 for (j=0; j<instruction->nprefix; j++) {
390 unsigned char c=0;
391 switch (instruction->prefixes[j]) {
392 case P_LOCK:
393 c = 0xF0; break;
394 case P_REPNE: case P_REPNZ:
395 c = 0xF2; break;
396 case P_REPE: case P_REPZ: case P_REP:
397 c = 0xF3; break;
398 case R_CS: c = 0x2E; break;
399 case R_DS: c = 0x3E; break;
400 case R_ES: c = 0x26; break;
401 case R_FS: c = 0x64; break;
402 case R_GS: c = 0x65; break;
403 case R_SS: c = 0x36; break;
404 case R_SEGR6:
405 case R_SEGR7:
406 error (ERR_NONFATAL, "segr6 and segr7 cannot be used as prefixes");
407 break;
408 case P_A16:
409 if (bits != 16)
410 c = 0x67;
411 break;
412 case P_A32:
413 if (bits != 32)
414 c = 0x67;
415 break;
416 case P_O16:
417 if (bits != 16)
418 c = 0x66;
419 break;
420 case P_O32:
421 if (bits != 32)
422 c = 0x66;
423 break;
424 default:
425 error (ERR_PANIC,
426 "invalid instruction prefix");
428 if (c != 0) {
429 out (offset, segment, &c, OUT_RAWDATA+1,
430 NO_SEG, NO_SEG);
431 offset++;
434 insn_end = offset + insn_size;
435 gencode (segment, offset, bits, instruction, codes, insn_end);
436 offset += insn_size;
437 if (itimes > 0 && itimes == instruction->times-1) {
439 * Dummy call to list->output to give the offset to the
440 * listing module.
442 list->output (offset, NULL, OUT_RAWDATA);
443 list->uplevel (LIST_TIMES);
446 if (instruction->times > 1)
447 list->downlevel (LIST_TIMES);
448 return offset - start;
449 } else if (m > 0 && m > size_prob) {
450 size_prob = m;
452 temp++;
455 if (temp->opcode == -1) { /* didn't match any instruction */
456 if (size_prob == 1) /* would have matched, but for size */
457 error (ERR_NONFATAL, "operation size not specified");
458 else if (size_prob == 2)
459 error (ERR_NONFATAL, "mismatch in operand sizes");
460 else if (size_prob == 3)
461 error (ERR_NONFATAL, "no instruction for this cpu level");
462 else
463 error (ERR_NONFATAL,
464 "invalid combination of opcode and operands");
466 return 0;
469 long insn_size (long segment, long offset, int bits, unsigned long cp,
470 insn *instruction, efunc error)
472 struct itemplate *temp;
474 errfunc = error; /* to pass to other functions */
475 cpu = cp;
477 if (instruction->opcode == -1)
478 return 0;
480 if (instruction->opcode == I_DB ||
481 instruction->opcode == I_DW ||
482 instruction->opcode == I_DD ||
483 instruction->opcode == I_DQ ||
484 instruction->opcode == I_DT)
486 extop *e;
487 long isize, osize, wsize = 0; /* placate gcc */
489 isize = 0;
490 switch (instruction->opcode)
492 case I_DB: wsize = 1; break;
493 case I_DW: wsize = 2; break;
494 case I_DD: wsize = 4; break;
495 case I_DQ: wsize = 8; break;
496 case I_DT: wsize = 10; break;
499 for (e = instruction->eops; e; e = e->next)
501 long align;
503 osize = 0;
504 if (e->type == EOT_DB_NUMBER)
505 osize = 1;
506 else if (e->type == EOT_DB_STRING)
507 osize = e->stringlen;
509 align = (-osize) % wsize;
510 if (align < 0)
511 align += wsize;
512 isize += osize + align;
514 return isize * instruction->times;
517 if (instruction->opcode == I_INCBIN)
519 char fname[FILENAME_MAX];
520 FILE * fp;
521 long len;
522 char *prefix = "", *combine;
523 char** pPrevPath = NULL;
525 len = FILENAME_MAX-1;
526 if (len > instruction->eops->stringlen)
527 len = instruction->eops->stringlen;
528 strncpy (fname, instruction->eops->stringval, len);
529 fname[len] = '\0';
531 while (1) /* added by alexfru: 'incbin' uses include paths */
533 combine = nasm_malloc(strlen(prefix) + len + 1);
534 strcpy(combine, prefix);
535 strcat(combine, fname);
537 if ( (fp = fopen(combine, "rb")) != NULL)
539 nasm_free(combine);
540 break;
543 nasm_free(combine);
544 pPrevPath = pp_get_include_path_ptr (pPrevPath);
545 if (pPrevPath == NULL)
546 break;
547 prefix = *pPrevPath;
550 if (fp == NULL)
551 error (ERR_NONFATAL, "`incbin': unable to open file `%s'", fname);
552 else if (fseek(fp, 0L, SEEK_END) < 0)
553 error (ERR_NONFATAL, "`incbin': unable to seek on file `%s'",
554 fname);
555 else
557 len = ftell (fp);
558 fclose (fp);
559 if (instruction->eops->next)
561 len -= instruction->eops->next->offset;
562 if (instruction->eops->next->next &&
563 len > instruction->eops->next->next->offset)
565 len = instruction->eops->next->next->offset;
568 return instruction->times * len;
570 return 0; /* if we're here, there's an error */
573 temp = nasm_instructions[instruction->opcode];
574 while (temp->opcode != -1) {
575 int m = matches(temp, instruction);
576 if (m == 99)
577 m += jmp_match(segment, offset, bits, instruction, temp->code);
579 if (m == 100) {
580 /* we've matched an instruction. */
581 long isize;
582 const char * codes = temp->code;
583 int j;
585 isize = calcsize(segment, offset, bits, instruction, codes);
586 if (isize < 0)
587 return -1;
588 for (j = 0; j < instruction->nprefix; j++)
590 if ((instruction->prefixes[j] != P_A16 &&
591 instruction->prefixes[j] != P_O16 && bits==16) ||
592 (instruction->prefixes[j] != P_A32 &&
593 instruction->prefixes[j] != P_O32 && bits==32))
595 isize++;
598 return isize * instruction->times;
600 temp++;
602 return -1; /* didn't match any instruction */
606 /* check that opn[op] is a signed byte of size 16 or 32,
607 and return the signed value*/
608 static int is_sbyte (insn *ins, int op, int size)
610 signed long v;
611 int ret;
613 ret = !(ins->forw_ref && ins->oprs[op].opflags ) && /* dead in the water on forward reference or External */
614 optimizing>=0 &&
615 !(ins->oprs[op].type & STRICT) &&
616 ins->oprs[op].wrt==NO_SEG && ins->oprs[op].segment==NO_SEG;
618 v = ins->oprs[op].offset;
619 if (size==16) v = (signed short)v; /* sign extend if 16 bits */
621 return ret && v>=-128L && v<=127L;
624 static long calcsize (long segment, long offset, int bits,
625 insn *ins, const char *codes)
627 long length = 0;
628 unsigned char c;
630 (void) segment; /* Don't warn that this parameter is unused */
631 (void) offset; /* Don't warn that this parameter is unused */
633 while (*codes) switch (c = *codes++) {
634 case 01: case 02: case 03:
635 codes += c, length += c; break;
636 case 04: case 05: case 06: case 07:
637 length++; break;
638 case 010: case 011: case 012:
639 codes++, length++; break;
640 case 017:
641 length++; break;
642 case 014: case 015: case 016:
643 length++; break;
644 case 020: case 021: case 022:
645 length++; break;
646 case 024: case 025: case 026:
647 length++; break;
648 case 030: case 031: case 032:
649 length += 2; break;
650 case 034: case 035: case 036:
651 if ( ins->oprs[c-034].type & (BITS16|BITS32) )
652 length += (ins->oprs[c-034].type & BITS16) ? 2 : 4;
653 else
654 length += (bits == 16) ? 2 : 4;
655 break;
656 case 037:
657 length += 2; break;
658 case 040: case 041: case 042:
659 length += 4; break;
660 case 044: case 045: case 046:
661 length += ((ins->oprs[c-044].addr_size ?
662 ins->oprs[c-044].addr_size : bits) == 16 ? 2 : 4); break;
663 case 050: case 051: case 052:
664 length++; break;
665 case 060: case 061: case 062:
666 length += 2; break;
667 case 064: case 065: case 066:
668 if ( ins->oprs[c-064].type & (BITS16|BITS32) )
669 length += (ins->oprs[c-064].type & BITS16) ? 2 : 4;
670 else
671 length += (bits == 16) ? 2 : 4;
672 break;
673 case 070: case 071: case 072:
674 length += 4; break;
675 case 0130: case 0131: case 0132:
676 length += is_sbyte(ins, c-0130, 16) ? 1 : 2; break;
677 case 0133: case 0134: case 0135:
678 codes+=2; length++; break;
679 case 0140: case 0141: case 0142:
680 length += is_sbyte(ins, c-0140, 32) ? 1 : 4; break;
681 case 0143: case 0144: case 0145:
682 codes+=2; length++; break;
683 case 0300: case 0301: case 0302:
684 length += chsize (&ins->oprs[c-0300], bits);
685 break;
686 case 0310:
687 length += (bits==32);
688 break;
689 case 0311:
690 length += (bits==16);
691 break;
692 case 0312:
693 break;
694 case 0320:
695 length += (bits==32);
696 break;
697 case 0321:
698 length += (bits==16);
699 break;
700 case 0322:
701 break;
702 case 0330:
703 codes++, length++; break;
704 case 0331:
705 case 0332:
706 break;
707 case 0333:
708 length++; break;
709 case 0340: case 0341: case 0342:
710 if (ins->oprs[0].segment != NO_SEG)
711 errfunc (ERR_NONFATAL, "attempt to reserve non-constant"
712 " quantity of BSS space");
713 else
714 length += ins->oprs[0].offset << (c-0340);
715 break;
716 case 0370: case 0371: case 0372:
717 break;
718 case 0373:
719 length++; break;
720 default: /* can't do it by 'case' statements */
721 if (c>=0100 && c<=0277) { /* it's an EA */
722 ea ea_data;
723 if (!process_ea (&ins->oprs[(c>>3)&7], &ea_data, bits, 0,
724 ins->forw_ref)) {
725 errfunc (ERR_NONFATAL, "invalid effective address");
726 return -1;
727 } else
728 length += ea_data.size;
729 } else
730 errfunc (ERR_PANIC, "internal instruction table corrupt"
731 ": instruction code 0x%02X given", c);
733 return length;
736 static void gencode (long segment, long offset, int bits,
737 insn *ins, const char *codes, long insn_end)
739 static char condval[] = { /* conditional opcodes */
740 0x7, 0x3, 0x2, 0x6, 0x2, 0x4, 0xF, 0xD, 0xC, 0xE, 0x6, 0x2,
741 0x3, 0x7, 0x3, 0x5, 0xE, 0xC, 0xD, 0xF, 0x1, 0xB, 0x9, 0x5,
742 0x0, 0xA, 0xA, 0xB, 0x8, 0x4
744 unsigned char c;
745 unsigned char bytes[4];
746 long data, size;
748 while (*codes)
749 switch (c = *codes++)
751 case 01: case 02: case 03:
752 out (offset, segment, codes, OUT_RAWDATA+c, NO_SEG, NO_SEG);
753 codes += c;
754 offset += c;
755 break;
757 case 04: case 06:
758 switch (ins->oprs[0].basereg)
760 case R_CS:
761 bytes[0] = 0x0E + (c == 0x04 ? 1 : 0); break;
762 case R_DS:
763 bytes[0] = 0x1E + (c == 0x04 ? 1 : 0); break;
764 case R_ES:
765 bytes[0] = 0x06 + (c == 0x04 ? 1 : 0); break;
766 case R_SS:
767 bytes[0] = 0x16 + (c == 0x04 ? 1 : 0); break;
768 default:
769 errfunc (ERR_PANIC, "bizarre 8086 segment register received");
771 out (offset, segment, bytes, OUT_RAWDATA+1, NO_SEG, NO_SEG);
772 offset++;
773 break;
775 case 05: case 07:
776 switch (ins->oprs[0].basereg) {
777 case R_FS: bytes[0] = 0xA0 + (c == 0x05 ? 1 : 0); break;
778 case R_GS: bytes[0] = 0xA8 + (c == 0x05 ? 1 : 0); break;
779 default:
780 errfunc (ERR_PANIC, "bizarre 386 segment register received");
782 out (offset, segment, bytes, OUT_RAWDATA+1, NO_SEG, NO_SEG);
783 offset++;
784 break;
786 case 010: case 011: case 012:
787 bytes[0] = *codes++ + regval(&ins->oprs[c-010]);
788 out (offset, segment, bytes, OUT_RAWDATA+1, NO_SEG, NO_SEG);
789 offset += 1;
790 break;
792 case 017:
793 bytes[0] = 0;
794 out (offset, segment, bytes, OUT_RAWDATA+1, NO_SEG, NO_SEG);
795 offset += 1;
796 break;
798 case 014: case 015: case 016:
799 if (ins->oprs[c-014].offset < -128
800 || ins->oprs[c-014].offset > 127)
802 errfunc (ERR_WARNING, "signed byte value exceeds bounds");
805 if (ins->oprs[c-014].segment != NO_SEG)
807 data = ins->oprs[c-014].offset;
808 out (offset, segment, &data, OUT_ADDRESS+1,
809 ins->oprs[c-014].segment, ins->oprs[c-014].wrt);
811 else {
812 bytes[0] = ins->oprs[c-014].offset;
813 out (offset, segment, bytes, OUT_RAWDATA+1, NO_SEG, NO_SEG);
815 offset += 1;
816 break;
818 case 020: case 021: case 022:
819 if (ins->oprs[c-020].offset < -256
820 || ins->oprs[c-020].offset > 255)
822 errfunc (ERR_WARNING, "byte value exceeds bounds");
824 if (ins->oprs[c-020].segment != NO_SEG) {
825 data = ins->oprs[c-020].offset;
826 out (offset, segment, &data, OUT_ADDRESS+1,
827 ins->oprs[c-020].segment, ins->oprs[c-020].wrt);
829 else {
830 bytes[0] = ins->oprs[c-020].offset;
831 out (offset, segment, bytes, OUT_RAWDATA+1, NO_SEG, NO_SEG);
833 offset += 1;
834 break;
836 case 024: case 025: case 026:
837 if (ins->oprs[c-024].offset < 0 || ins->oprs[c-024].offset > 255)
838 errfunc (ERR_WARNING, "unsigned byte value exceeds bounds");
839 if (ins->oprs[c-024].segment != NO_SEG) {
840 data = ins->oprs[c-024].offset;
841 out (offset, segment, &data, OUT_ADDRESS+1,
842 ins->oprs[c-024].segment, ins->oprs[c-024].wrt);
844 else {
845 bytes[0] = ins->oprs[c-024].offset;
846 out (offset, segment, bytes, OUT_RAWDATA+1, NO_SEG, NO_SEG);
848 offset += 1;
849 break;
851 case 030: case 031: case 032:
852 if (ins->oprs[c-030].segment == NO_SEG &&
853 ins->oprs[c-030].wrt == NO_SEG &&
854 (ins->oprs[c-030].offset < -65536L ||
855 ins->oprs[c-030].offset > 65535L))
857 errfunc (ERR_WARNING, "word value exceeds bounds");
859 data = ins->oprs[c-030].offset;
860 out (offset, segment, &data, OUT_ADDRESS+2,
861 ins->oprs[c-030].segment, ins->oprs[c-030].wrt);
862 offset += 2;
863 break;
865 case 034: case 035: case 036:
866 if ( ins->oprs[c-034].type & (BITS16|BITS32) )
867 size = (ins->oprs[c-034].type & BITS16) ? 2 : 4;
868 else
869 size = (bits == 16) ? 2 : 4;
870 data = ins->oprs[c-034].offset;
871 if (size==2 && (data < -65536L || data > 65535L))
872 errfunc (ERR_WARNING, "word value exceeds bounds");
873 out (offset, segment, &data, OUT_ADDRESS+size,
874 ins->oprs[c-034].segment, ins->oprs[c-034].wrt);
875 offset += size;
876 break;
878 case 037:
879 if (ins->oprs[0].segment == NO_SEG)
880 errfunc (ERR_NONFATAL, "value referenced by FAR is not"
881 " relocatable");
882 data = 0L;
883 out (offset, segment, &data, OUT_ADDRESS+2,
884 outfmt->segbase(1+ins->oprs[0].segment),
885 ins->oprs[0].wrt);
886 offset += 2;
887 break;
889 case 040: case 041: case 042:
890 data = ins->oprs[c-040].offset;
891 out (offset, segment, &data, OUT_ADDRESS+4,
892 ins->oprs[c-040].segment, ins->oprs[c-040].wrt);
893 offset += 4;
894 break;
896 case 044: case 045: case 046:
897 data = ins->oprs[c-044].offset;
898 size = ((ins->oprs[c-044].addr_size ?
899 ins->oprs[c-044].addr_size : bits) == 16 ? 2 : 4);
900 if (size==2 && (data < -65536L || data > 65535L))
901 errfunc (ERR_WARNING, "word value exceeds bounds");
902 out (offset, segment, &data, OUT_ADDRESS+size,
903 ins->oprs[c-044].segment, ins->oprs[c-044].wrt);
904 offset += size;
905 break;
907 case 050: case 051: case 052:
908 if (ins->oprs[c-050].segment != segment)
909 errfunc (ERR_NONFATAL, "short relative jump outside segment");
910 data = ins->oprs[c-050].offset - insn_end;
911 if (data > 127 || data < -128)
912 errfunc (ERR_NONFATAL, "short jump is out of range");
913 bytes[0] = data;
914 out (offset, segment, bytes, OUT_RAWDATA+1, NO_SEG, NO_SEG);
915 offset += 1;
916 break;
918 case 060: case 061: case 062:
919 if (ins->oprs[c-060].segment != segment) {
920 data = ins->oprs[c-060].offset;
921 out (offset, segment, &data, OUT_REL2ADR+insn_end-offset,
922 ins->oprs[c-060].segment, ins->oprs[c-060].wrt);
923 } else {
924 data = ins->oprs[c-060].offset - insn_end;
925 out (offset, segment, &data,
926 OUT_ADDRESS+2, NO_SEG, NO_SEG);
928 offset += 2;
929 break;
931 case 064: case 065: case 066:
932 if ( ins->oprs[c-064].type & (BITS16|BITS32) )
933 size = (ins->oprs[c-064].type & BITS16) ? 2 : 4;
934 else
935 size = (bits == 16) ? 2 : 4;
936 if (ins->oprs[c-064].segment != segment) {
937 long reltype = (size == 2 ? OUT_REL2ADR : OUT_REL4ADR);
938 data = ins->oprs[c-064].offset;
939 out (offset, segment, &data, reltype+insn_end-offset,
940 ins->oprs[c-064].segment, ins->oprs[c-064].wrt);
941 } else {
942 data = ins->oprs[c-064].offset - insn_end;
943 out (offset, segment, &data,
944 OUT_ADDRESS+size, NO_SEG, NO_SEG);
946 offset += size;
947 break;
949 case 070: case 071: case 072:
950 if (ins->oprs[c-070].segment != segment) {
951 data = ins->oprs[c-070].offset;
952 out (offset, segment, &data, OUT_REL4ADR+insn_end-offset,
953 ins->oprs[c-070].segment, ins->oprs[c-070].wrt);
954 } else {
955 data = ins->oprs[c-070].offset - insn_end;
956 out (offset, segment, &data,
957 OUT_ADDRESS+4, NO_SEG, NO_SEG);
959 offset += 4;
960 break;
962 case 0130: case 0131: case 0132:
963 data = ins->oprs[c-0130].offset;
964 if (is_sbyte(ins, c-0130, 16)) {
965 bytes[0] = data;
966 out (offset, segment, bytes, OUT_RAWDATA+1, NO_SEG, NO_SEG);
967 offset++;
968 } else {
969 if (ins->oprs[c-0130].segment == NO_SEG &&
970 ins->oprs[c-0130].wrt == NO_SEG &&
971 (data < -65536L || data > 65535L)) {
972 errfunc (ERR_WARNING, "word value exceeds bounds");
974 out (offset, segment, &data, OUT_ADDRESS+2,
975 ins->oprs[c-0130].segment, ins->oprs[c-0130].wrt);
976 offset += 2;
978 break;
980 case 0133: case 0134: case 0135:
981 codes++;
982 bytes[0] = *codes++;
983 if (is_sbyte(ins, c-0133, 16)) bytes[0] |= 2; /* s-bit */
984 out (offset, segment, bytes, OUT_RAWDATA+1, NO_SEG, NO_SEG);
985 offset++;
986 break;
988 case 0140: case 0141: case 0142:
989 data = ins->oprs[c-0140].offset;
990 if (is_sbyte(ins, c-0140, 32)) {
991 bytes[0] = data;
992 out (offset, segment, bytes, OUT_RAWDATA+1, NO_SEG, NO_SEG);
993 offset++;
994 } else {
995 out (offset, segment, &data, OUT_ADDRESS+4,
996 ins->oprs[c-0140].segment, ins->oprs[c-0140].wrt);
997 offset += 4;
999 break;
1001 case 0143: case 0144: case 0145:
1002 codes++;
1003 bytes[0] = *codes++;
1004 if (is_sbyte(ins, c-0143, 32)) bytes[0] |= 2; /* s-bit */
1005 out (offset, segment, bytes, OUT_RAWDATA+1, NO_SEG, NO_SEG);
1006 offset++;
1007 break;
1009 case 0300: case 0301: case 0302:
1010 if (chsize (&ins->oprs[c-0300], bits)) {
1011 *bytes = 0x67;
1012 out (offset, segment, bytes,
1013 OUT_RAWDATA+1, NO_SEG, NO_SEG);
1014 offset += 1;
1015 } else
1016 offset += 0;
1017 break;
1019 case 0310:
1020 if (bits==32) {
1021 *bytes = 0x67;
1022 out (offset, segment, bytes,
1023 OUT_RAWDATA+1, NO_SEG, NO_SEG);
1024 offset += 1;
1025 } else
1026 offset += 0;
1027 break;
1029 case 0311:
1030 if (bits==16) {
1031 *bytes = 0x67;
1032 out (offset, segment, bytes,
1033 OUT_RAWDATA+1, NO_SEG, NO_SEG);
1034 offset += 1;
1035 } else
1036 offset += 0;
1037 break;
1039 case 0312:
1040 break;
1042 case 0320:
1043 if (bits==32) {
1044 *bytes = 0x66;
1045 out (offset, segment, bytes,
1046 OUT_RAWDATA+1, NO_SEG, NO_SEG);
1047 offset += 1;
1048 } else
1049 offset += 0;
1050 break;
1052 case 0321:
1053 if (bits==16) {
1054 *bytes = 0x66;
1055 out (offset, segment, bytes,
1056 OUT_RAWDATA+1, NO_SEG, NO_SEG);
1057 offset += 1;
1058 } else
1059 offset += 0;
1060 break;
1062 case 0322:
1063 break;
1065 case 0330:
1066 *bytes = *codes++ ^ condval[ins->condition];
1067 out (offset, segment, bytes,
1068 OUT_RAWDATA+1, NO_SEG, NO_SEG);
1069 offset += 1;
1070 break;
1072 case 0331:
1073 case 0332:
1074 break;
1076 case 0333:
1077 *bytes = 0xF3;
1078 out (offset, segment, bytes,
1079 OUT_RAWDATA+1, NO_SEG, NO_SEG);
1080 offset += 1;
1081 break;
1083 case 0340: case 0341: case 0342:
1084 if (ins->oprs[0].segment != NO_SEG)
1085 errfunc (ERR_PANIC, "non-constant BSS size in pass two");
1086 else {
1087 long size = ins->oprs[0].offset << (c-0340);
1088 if (size > 0)
1089 out (offset, segment, NULL,
1090 OUT_RESERVE+size, NO_SEG, NO_SEG);
1091 offset += size;
1093 break;
1095 case 0370: case 0371: case 0372:
1096 break;
1098 case 0373:
1099 *bytes = bits==16 ? 3 : 5;
1100 out (offset, segment, bytes,
1101 OUT_RAWDATA+1, NO_SEG, NO_SEG);
1102 offset += 1;
1103 break;
1105 default: /* can't do it by 'case' statements */
1106 if (c>=0100 && c<=0277) { /* it's an EA */
1107 ea ea_data;
1108 int rfield;
1109 unsigned char *p;
1110 long s;
1112 if (c<=0177) /* pick rfield from operand b */
1113 rfield = regval (&ins->oprs[c&7]);
1114 else /* rfield is constant */
1115 rfield = c & 7;
1117 if (!process_ea (&ins->oprs[(c>>3)&7], &ea_data, bits, rfield,
1118 ins->forw_ref))
1120 errfunc (ERR_NONFATAL, "invalid effective address");
1123 p = bytes;
1124 *p++ = ea_data.modrm;
1125 if (ea_data.sib_present)
1126 *p++ = ea_data.sib;
1128 s = p-bytes;
1129 out (offset, segment, bytes, OUT_RAWDATA + s,
1130 NO_SEG, NO_SEG);
1132 switch (ea_data.bytes) {
1133 case 0:
1134 break;
1135 case 1:
1136 if (ins->oprs[(c>>3)&7].segment != NO_SEG) {
1137 data = ins->oprs[(c>>3)&7].offset;
1138 out (offset, segment, &data, OUT_ADDRESS+1,
1139 ins->oprs[(c>>3)&7].segment,
1140 ins->oprs[(c>>3)&7].wrt);
1141 } else {
1142 *bytes = ins->oprs[(c>>3)&7].offset;
1143 out (offset, segment, bytes, OUT_RAWDATA+1,
1144 NO_SEG, NO_SEG);
1146 s++;
1147 break;
1148 case 2:
1149 case 4:
1150 data = ins->oprs[(c>>3)&7].offset;
1151 out (offset, segment, &data,
1152 OUT_ADDRESS+ea_data.bytes,
1153 ins->oprs[(c>>3)&7].segment, ins->oprs[(c>>3)&7].wrt);
1154 s += ea_data.bytes;
1155 break;
1157 offset += s;
1158 } else
1159 errfunc (ERR_PANIC, "internal instruction table corrupt"
1160 ": instruction code 0x%02X given", c);
1164 #include "regvals.c"
1166 static int regval (operand *o)
1168 if ( o->basereg < EXPR_REG_START || o->basereg >= REG_ENUM_LIMIT ) {
1169 errfunc (ERR_PANIC, "invalid operand passed to regval()");
1171 return regvals[o->basereg];
1174 static int matches (struct itemplate *itemp, insn *instruction)
1176 int i, size[3], asize, oprs, ret;
1178 ret = 100;
1181 * Check the opcode
1183 if (itemp->opcode != instruction->opcode) return 0;
1186 * Count the operands
1188 if (itemp->operands != instruction->operands) return 0;
1191 * Check that no spurious colons or TOs are present
1193 for (i=0; i<itemp->operands; i++)
1194 if (instruction->oprs[i].type & ~itemp->opd[i] & (COLON|TO))
1195 return 0;
1198 * Check that the operand flags all match up
1200 for (i=0; i<itemp->operands; i++)
1201 if (itemp->opd[i] & ~instruction->oprs[i].type ||
1202 ((itemp->opd[i] & SIZE_MASK) &&
1203 ((itemp->opd[i] ^ instruction->oprs[i].type) & SIZE_MASK)))
1205 if ((itemp->opd[i] & ~instruction->oprs[i].type & NON_SIZE) ||
1206 (instruction->oprs[i].type & SIZE_MASK))
1207 return 0;
1208 else
1209 /* ret = 1; */
1210 return 1;
1214 * Check operand sizes
1216 if (itemp->flags & IF_ARMASK) {
1217 size[0] = size[1] = size[2] = 0;
1219 switch (itemp->flags & IF_ARMASK) {
1220 case IF_AR0: i = 0; break;
1221 case IF_AR1: i = 1; break;
1222 case IF_AR2: i = 2; break;
1223 default: break; /* Shouldn't happen */
1225 if (itemp->flags & IF_SB) {
1226 size[i] = BITS8;
1227 } else if (itemp->flags & IF_SW) {
1228 size[i] = BITS16;
1229 } else if (itemp->flags & IF_SD) {
1230 size[i] = BITS32;
1232 } else {
1233 asize = 0;
1234 if (itemp->flags & IF_SB) {
1235 asize = BITS8;
1236 oprs = itemp->operands;
1237 } else if (itemp->flags & IF_SW) {
1238 asize = BITS16;
1239 oprs = itemp->operands;
1240 } else if (itemp->flags & IF_SD) {
1241 asize = BITS32;
1242 oprs = itemp->operands;
1244 size[0] = size[1] = size[2] = asize;
1247 if (itemp->flags & (IF_SM | IF_SM2)) {
1248 oprs = (itemp->flags & IF_SM2 ? 2 : itemp->operands);
1249 asize = 0;
1250 for (i=0; i<oprs; i++) {
1251 if ( (asize = itemp->opd[i] & SIZE_MASK) != 0) {
1252 int j;
1253 for (j=0; j<oprs; j++)
1254 size[j] = asize;
1255 break;
1258 } else {
1259 oprs = itemp->operands;
1262 for (i=0; i<itemp->operands; i++)
1263 if (!(itemp->opd[i] & SIZE_MASK) &&
1264 (instruction->oprs[i].type & SIZE_MASK & ~size[i]))
1265 /* ret = 2; */
1266 return 2;
1269 * Check template is okay at the set cpu level
1271 if ((itemp->flags & IF_PLEVEL) > cpu) return 3;
1274 * Check if special handling needed for Jumps
1276 if ((unsigned char)(itemp->code[0]) >= 0370) return 99;
1278 return ret;
1281 static ea *process_ea (operand *input, ea *output, int addrbits, int rfield,
1282 int forw_ref)
1284 if (!(REGISTER & ~input->type)) { /* it's a single register */
1285 static int regs[] = {
1286 R_AL, R_CL, R_DL, R_BL, R_AH, R_CH, R_DH, R_BH,
1287 R_AX, R_CX, R_DX, R_BX, R_SP, R_BP, R_SI, R_DI,
1288 R_EAX, R_ECX, R_EDX, R_EBX, R_ESP, R_EBP, R_ESI, R_EDI,
1289 R_MM0, R_MM1, R_MM2, R_MM3, R_MM4, R_MM5, R_MM6, R_MM7,
1290 R_XMM0, R_XMM1, R_XMM2, R_XMM3, R_XMM4, R_XMM5, R_XMM6, R_XMM7
1292 int i;
1294 for (i=0; i<elements(regs); i++)
1295 if (input->basereg == regs[i]) break;
1296 if (i<elements(regs)) {
1297 output->sib_present = FALSE;/* no SIB necessary */
1298 output->bytes = 0; /* no offset necessary either */
1299 output->modrm = 0xC0 | (rfield << 3) | (i & 7);
1301 else
1302 return NULL;
1303 } else { /* it's a memory reference */
1304 if (input->basereg==-1 && (input->indexreg==-1 || input->scale==0)) {
1305 /* it's a pure offset */
1306 if (input->addr_size)
1307 addrbits = input->addr_size;
1308 output->sib_present = FALSE;
1309 output->bytes = (addrbits==32 ? 4 : 2);
1310 output->modrm = (addrbits==32 ? 5 : 6) | (rfield << 3);
1312 else { /* it's an indirection */
1313 int i=input->indexreg, b=input->basereg, s=input->scale;
1314 long o=input->offset, seg=input->segment;
1315 int hb=input->hintbase, ht=input->hinttype;
1316 int t;
1318 if (s==0) i = -1; /* make this easy, at least */
1320 if (i==R_EAX || i==R_EBX || i==R_ECX || i==R_EDX
1321 || i==R_EBP || i==R_ESP || i==R_ESI || i==R_EDI
1322 || b==R_EAX || b==R_EBX || b==R_ECX || b==R_EDX
1323 || b==R_EBP || b==R_ESP || b==R_ESI || b==R_EDI) {
1324 /* it must be a 32-bit memory reference. Firstly we have
1325 * to check that all registers involved are type Exx. */
1326 if (i!=-1 && i!=R_EAX && i!=R_EBX && i!=R_ECX && i!=R_EDX
1327 && i!=R_EBP && i!=R_ESP && i!=R_ESI && i!=R_EDI)
1328 return NULL;
1329 if (b!=-1 && b!=R_EAX && b!=R_EBX && b!=R_ECX && b!=R_EDX
1330 && b!=R_EBP && b!=R_ESP && b!=R_ESI && b!=R_EDI)
1331 return NULL;
1333 /* While we're here, ensure the user didn't specify WORD. */
1334 if (input->addr_size == 16)
1335 return NULL;
1337 /* now reorganise base/index */
1338 if (s == 1 && b != i && b != -1 && i != -1 &&
1339 ((hb==b&&ht==EAH_NOTBASE) || (hb==i&&ht==EAH_MAKEBASE)))
1340 t = b, b = i, i = t; /* swap if hints say so */
1341 if (b==i) /* convert EAX+2*EAX to 3*EAX */
1342 b = -1, s++;
1343 if (b==-1 && s==1 && !(hb == i && ht == EAH_NOTBASE))
1344 b = i, i = -1; /* make single reg base, unless hint */
1345 if (((s==2 && i!=R_ESP && !(input->eaflags & EAF_TIMESTWO)) ||
1346 s==3 || s==5 || s==9) && b==-1)
1347 b = i, s--; /* convert 3*EAX to EAX+2*EAX */
1348 if (i==-1 && b!=R_ESP && (input->eaflags & EAF_TIMESTWO))
1349 i = b, b = -1, s = 1;
1350 /* convert [NOSPLIT EAX] to sib format with 0x0 displacement */
1351 if (s==1 && i==R_ESP) /* swap ESP into base if scale is 1 */
1352 i = b, b = R_ESP;
1353 if (i==R_ESP || (s!=1 && s!=2 && s!=4 && s!=8 && i!=-1))
1354 return NULL; /* wrong, for various reasons */
1356 if (i==-1 && b!=R_ESP) {/* no SIB needed */
1357 int mod, rm;
1358 switch(b) {
1359 case R_EAX: rm = 0; break;
1360 case R_ECX: rm = 1; break;
1361 case R_EDX: rm = 2; break;
1362 case R_EBX: rm = 3; break;
1363 case R_EBP: rm = 5; break;
1364 case R_ESI: rm = 6; break;
1365 case R_EDI: rm = 7; break;
1366 case -1: rm = 5; break;
1367 default: /* should never happen */
1368 return NULL;
1370 if (b==-1 || (b!=R_EBP && o==0 &&
1371 seg==NO_SEG && !forw_ref &&
1372 !(input->eaflags &
1373 (EAF_BYTEOFFS|EAF_WORDOFFS))))
1374 mod = 0;
1375 else if (input->eaflags & EAF_BYTEOFFS ||
1376 (o>=-128 && o<=127 && seg==NO_SEG && !forw_ref &&
1377 !(input->eaflags & EAF_WORDOFFS))) {
1378 mod = 1;
1380 else
1381 mod = 2;
1383 output->sib_present = FALSE;
1384 output->bytes = (b==-1 || mod==2 ? 4 : mod);
1385 output->modrm = (mod<<6) | (rfield<<3) | rm;
1387 else { /* we need a SIB */
1388 int mod, scale, index, base;
1390 switch (b) {
1391 case R_EAX: base = 0; break;
1392 case R_ECX: base = 1; break;
1393 case R_EDX: base = 2; break;
1394 case R_EBX: base = 3; break;
1395 case R_ESP: base = 4; break;
1396 case R_EBP: case -1: base = 5; break;
1397 case R_ESI: base = 6; break;
1398 case R_EDI: base = 7; break;
1399 default: /* then what the smeg is it? */
1400 return NULL; /* panic */
1403 switch (i) {
1404 case R_EAX: index = 0; break;
1405 case R_ECX: index = 1; break;
1406 case R_EDX: index = 2; break;
1407 case R_EBX: index = 3; break;
1408 case -1: index = 4; break;
1409 case R_EBP: index = 5; break;
1410 case R_ESI: index = 6; break;
1411 case R_EDI: index = 7; break;
1412 default: /* then what the smeg is it? */
1413 return NULL; /* panic */
1416 if (i==-1) s = 1;
1417 switch (s) {
1418 case 1: scale = 0; break;
1419 case 2: scale = 1; break;
1420 case 4: scale = 2; break;
1421 case 8: scale = 3; break;
1422 default: /* then what the smeg is it? */
1423 return NULL; /* panic */
1426 if (b==-1 || (b!=R_EBP && o==0 &&
1427 seg==NO_SEG && !forw_ref &&
1428 !(input->eaflags &
1429 (EAF_BYTEOFFS|EAF_WORDOFFS))))
1430 mod = 0;
1431 else if (input->eaflags & EAF_BYTEOFFS ||
1432 (o>=-128 && o<=127 && seg==NO_SEG && !forw_ref &&
1433 !(input->eaflags & EAF_WORDOFFS)))
1434 mod = 1;
1435 else
1436 mod = 2;
1438 output->sib_present = TRUE;
1439 output->bytes = (b==-1 || mod==2 ? 4 : mod);
1440 output->modrm = (mod<<6) | (rfield<<3) | 4;
1441 output->sib = (scale<<6) | (index<<3) | base;
1444 else { /* it's 16-bit */
1445 int mod, rm;
1447 /* check all registers are BX, BP, SI or DI */
1448 if ((b!=-1 && b!=R_BP && b!=R_BX && b!=R_SI && b!=R_DI) ||
1449 (i!=-1 && i!=R_BP && i!=R_BX && i!=R_SI && i!=R_DI))
1450 return NULL;
1452 /* ensure the user didn't specify DWORD */
1453 if (input->addr_size == 32)
1454 return NULL;
1456 if (s!=1 && i!=-1) return NULL;/* no can do, in 16-bit EA */
1457 if (b==-1 && i!=-1) { int tmp = b; b = i; i = tmp; } /* swap */
1458 if ((b==R_SI || b==R_DI) && i!=-1)
1459 { int tmp = b; b = i; i = tmp; }
1460 /* have BX/BP as base, SI/DI index */
1461 if (b==i) return NULL;/* shouldn't ever happen, in theory */
1462 if (i!=-1 && b!=-1 &&
1463 (i==R_BP || i==R_BX || b==R_SI || b==R_DI))
1464 return NULL; /* invalid combinations */
1465 if (b==-1) /* pure offset: handled above */
1466 return NULL; /* so if it gets to here, panic! */
1468 rm = -1;
1469 if (i!=-1)
1470 switch (i*256 + b) {
1471 case R_SI*256+R_BX: rm=0; break;
1472 case R_DI*256+R_BX: rm=1; break;
1473 case R_SI*256+R_BP: rm=2; break;
1474 case R_DI*256+R_BP: rm=3; break;
1476 else
1477 switch (b) {
1478 case R_SI: rm=4; break;
1479 case R_DI: rm=5; break;
1480 case R_BP: rm=6; break;
1481 case R_BX: rm=7; break;
1483 if (rm==-1) /* can't happen, in theory */
1484 return NULL; /* so panic if it does */
1486 if (o==0 && seg==NO_SEG && !forw_ref && rm!=6 &&
1487 !(input->eaflags & (EAF_BYTEOFFS|EAF_WORDOFFS)))
1488 mod = 0;
1489 else if (input->eaflags & EAF_BYTEOFFS ||
1490 (o>=-128 && o<=127 && seg==NO_SEG && !forw_ref &&
1491 !(input->eaflags & EAF_WORDOFFS)))
1492 mod = 1;
1493 else
1494 mod = 2;
1496 output->sib_present = FALSE; /* no SIB - it's 16-bit */
1497 output->bytes = mod; /* bytes of offset needed */
1498 output->modrm = (mod<<6) | (rfield<<3) | rm;
1502 output->size = 1 + output->sib_present + output->bytes;
1503 return output;
1506 static int chsize (operand *input, int addrbits)
1508 if (!(MEMORY & ~input->type)) {
1509 int i=input->indexreg, b=input->basereg;
1511 if (input->scale==0) i = -1;
1513 if (i == -1 && b == -1) /* pure offset */
1514 return (input->addr_size != 0 && input->addr_size != addrbits);
1516 if (i==R_EAX || i==R_EBX || i==R_ECX || i==R_EDX
1517 || i==R_EBP || i==R_ESP || i==R_ESI || i==R_EDI
1518 || b==R_EAX || b==R_EBX || b==R_ECX || b==R_EDX
1519 || b==R_EBP || b==R_ESP || b==R_ESI || b==R_EDI)
1520 return (addrbits==16);
1521 else
1522 return (addrbits==32);
1524 else
1525 return 0;