Touch up Makefile.b32
[nasm/autotest.git] / assemble.c
blob160e6713d1ef3fd67c51df17f3113205f128f8ab
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 long lineno;
109 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);
146 if (src_get(&lineno,&lnfname))
148 outfmt->current_dfmt->linenum(lnfname,lineno,segto);
149 if (lnfname) nasm_free(lnfname);
152 outfmt->output (segto, data, type, segment, wrt);
155 static int jmp_match (long segment, long offset, int bits,
156 insn *ins, const char *code)
157 { long isize;
158 unsigned char c = code[0];
161 if (c != 0370 && c != 0371) return 0;
162 if (ins->oprs[0].opflags & OPFLAG_FORWARD) {
163 if ((optimizing<0 || (ins->oprs[0].type & STRICT))
164 && c==0370) return 1;
165 else return (pass0==0); /* match a forward reference */
167 isize = calcsize (segment, offset, bits, ins, code);
168 if (ins->oprs[0].segment != segment) return 0;
169 isize = ins->oprs[0].offset - offset - isize; /* isize is now the delta */
170 if (isize >= -128L && isize <= 127L) return 1; /* it is byte size */
172 return 0;
176 long assemble (long segment, long offset, int bits, unsigned long cp,
177 insn *instruction, struct ofmt *output, efunc error,
178 ListGen *listgen)
180 struct itemplate *temp;
181 int j;
182 int size_prob;
183 long insn_end;
184 long itimes;
185 long start = offset;
186 long wsize = 0; /* size for DB etc. */
188 errfunc = error; /* to pass to other functions */
189 cpu = cp;
190 outfmt = output; /* likewise */
191 list = listgen; /* and again */
193 switch (instruction->opcode)
195 case -1: return 0;
196 case I_DB: wsize = 1; break;
197 case I_DW: wsize = 2; break;
198 case I_DD: wsize = 4; break;
199 case I_DQ: wsize = 8; break;
200 case I_DT: wsize = 10; break;
203 if (wsize) {
204 extop * e;
205 long t = instruction->times;
206 if (t < 0)
207 errfunc(ERR_PANIC, "instruction->times < 0 (%ld) in assemble()",t);
209 while (t--) /* repeat TIMES times */
211 for (e = instruction->eops; e; e = e->next)
213 if (e->type == EOT_DB_NUMBER)
215 if (wsize == 1) {
216 if (e->segment != NO_SEG)
217 errfunc (ERR_NONFATAL,
218 "one-byte relocation attempted");
219 else {
220 unsigned char out_byte = e->offset;
221 out (offset, segment, &out_byte, OUT_RAWDATA+1,
222 NO_SEG, NO_SEG);
225 else if (wsize > 5) {
226 errfunc (ERR_NONFATAL, "integer supplied to a D%c"
227 " instruction", wsize==8 ? 'Q' : 'T');
229 else
230 out (offset, segment, &e->offset,
231 OUT_ADDRESS+wsize, e->segment,
232 e->wrt);
233 offset += wsize;
235 else if (e->type == EOT_DB_STRING)
237 int align;
239 out (offset, segment, e->stringval,
240 OUT_RAWDATA+e->stringlen, NO_SEG, NO_SEG);
241 align = e->stringlen % wsize;
243 if (align) {
244 align = wsize - align;
245 out (offset, segment, "\0\0\0\0\0\0\0\0",
246 OUT_RAWDATA+align, NO_SEG, NO_SEG);
248 offset += e->stringlen + align;
251 if (t > 0 && t == instruction->times-1)
254 * Dummy call to list->output to give the offset to the
255 * listing module.
257 list->output (offset, NULL, OUT_RAWDATA);
258 list->uplevel (LIST_TIMES);
261 if (instruction->times > 1)
262 list->downlevel (LIST_TIMES);
263 return offset - start;
266 if (instruction->opcode == I_INCBIN)
268 static char fname[FILENAME_MAX];
269 FILE * fp;
270 long len;
271 char *prefix = "", *combine;
272 char** pPrevPath = NULL;
274 len = FILENAME_MAX-1;
275 if (len > instruction->eops->stringlen)
276 len = instruction->eops->stringlen;
277 strncpy (fname, instruction->eops->stringval, len);
278 fname[len] = '\0';
280 while (1) /* added by alexfru: 'incbin' uses include paths */
282 combine = nasm_malloc(strlen(prefix) + len + 1);
283 strcpy(combine, prefix);
284 strcat(combine, fname);
286 if ( (fp = fopen(combine, "rb")) != NULL)
288 nasm_free(combine);
289 break;
292 nasm_free(combine);
293 pPrevPath = pp_get_include_path_ptr (pPrevPath);
294 if (pPrevPath == NULL)
295 break;
296 prefix = *pPrevPath;
299 if (fp == NULL)
300 error (ERR_NONFATAL, "`incbin': unable to open file `%s'", fname);
301 else if (fseek(fp, 0L, SEEK_END) < 0)
302 error (ERR_NONFATAL, "`incbin': unable to seek on file `%s'",
303 fname);
304 else
306 static char buf[2048];
307 long t = instruction->times;
308 long base = 0;
310 len = ftell (fp);
311 if (instruction->eops->next) {
312 base = instruction->eops->next->offset;
313 len -= base;
314 if (instruction->eops->next->next &&
315 len > instruction->eops->next->next->offset)
316 len = instruction->eops->next->next->offset;
319 * Dummy call to list->output to give the offset to the
320 * listing module.
322 list->output (offset, NULL, OUT_RAWDATA);
323 list->uplevel(LIST_INCBIN);
324 while (t--)
326 long l;
328 fseek (fp, base, SEEK_SET);
329 l = len;
330 while (l > 0) {
331 long m = fread (buf, 1, (l>sizeof(buf)?sizeof(buf):l),
332 fp);
333 if (!m) {
335 * This shouldn't happen unless the file
336 * actually changes while we are reading
337 * it.
339 error (ERR_NONFATAL, "`incbin': unexpected EOF while"
340 " reading file `%s'", fname);
341 t=0; /* Try to exit cleanly */
342 break;
344 out (offset, segment, buf, OUT_RAWDATA+m,
345 NO_SEG, NO_SEG);
346 l -= m;
349 list->downlevel(LIST_INCBIN);
350 if (instruction->times > 1) {
352 * Dummy call to list->output to give the offset to the
353 * listing module.
355 list->output (offset, NULL, OUT_RAWDATA);
356 list->uplevel(LIST_TIMES);
357 list->downlevel(LIST_TIMES);
359 fclose (fp);
360 return instruction->times * len;
362 return 0; /* if we're here, there's an error */
365 size_prob = FALSE;
366 temp = nasm_instructions[instruction->opcode];
367 while (temp->opcode != -1) {
368 int m = matches (temp, instruction);
369 if (m == 99)
370 m += jmp_match(segment, offset, bits, instruction, temp->code);
372 if (m == 100) /* matches! */
374 const char *codes = temp->code;
375 long insn_size = calcsize(segment, offset, bits,
376 instruction, codes);
377 itimes = instruction->times;
378 if (insn_size < 0) /* shouldn't be, on pass two */
379 error (ERR_PANIC, "errors made it through from pass one");
380 else while (itimes--) {
381 for (j=0; j<instruction->nprefix; j++) {
382 unsigned char c=0;
383 switch (instruction->prefixes[j]) {
384 case P_LOCK:
385 c = 0xF0; break;
386 case P_REPNE: case P_REPNZ:
387 c = 0xF2; break;
388 case P_REPE: case P_REPZ: case P_REP:
389 c = 0xF3; break;
390 case R_CS: c = 0x2E; break;
391 case R_DS: c = 0x3E; break;
392 case R_ES: c = 0x26; break;
393 case R_FS: c = 0x64; break;
394 case R_GS: c = 0x65; break;
395 case R_SS: c = 0x36; break;
396 case R_SEGR6:
397 case R_SEGR7:
398 error (ERR_NONFATAL, "segr6 and segr7 cannot be used as prefixes");
399 break;
400 case P_A16:
401 if (bits != 16)
402 c = 0x67;
403 break;
404 case P_A32:
405 if (bits != 32)
406 c = 0x67;
407 break;
408 case P_O16:
409 if (bits != 16)
410 c = 0x66;
411 break;
412 case P_O32:
413 if (bits != 32)
414 c = 0x66;
415 break;
416 default:
417 error (ERR_PANIC,
418 "invalid instruction prefix");
420 if (c != 0) {
421 out (offset, segment, &c, OUT_RAWDATA+1,
422 NO_SEG, NO_SEG);
423 offset++;
426 insn_end = offset + insn_size;
427 gencode (segment, offset, bits, instruction, codes, insn_end);
428 offset += insn_size;
429 if (itimes > 0 && itimes == instruction->times-1) {
431 * Dummy call to list->output to give the offset to the
432 * listing module.
434 list->output (offset, NULL, OUT_RAWDATA);
435 list->uplevel (LIST_TIMES);
438 if (instruction->times > 1)
439 list->downlevel (LIST_TIMES);
440 return offset - start;
441 } else if (m > 0 && m > size_prob) {
442 size_prob = m;
444 temp++;
447 if (temp->opcode == -1) { /* didn't match any instruction */
448 if (size_prob == 1) /* would have matched, but for size */
449 error (ERR_NONFATAL, "operation size not specified");
450 else if (size_prob == 2)
451 error (ERR_NONFATAL, "mismatch in operand sizes");
452 else if (size_prob == 3)
453 error (ERR_NONFATAL, "no instruction for this cpu level");
454 else
455 error (ERR_NONFATAL,
456 "invalid combination of opcode and operands");
458 return 0;
461 long insn_size (long segment, long offset, int bits, unsigned long cp,
462 insn *instruction, efunc error)
464 struct itemplate *temp;
466 errfunc = error; /* to pass to other functions */
467 cpu = cp;
469 if (instruction->opcode == -1)
470 return 0;
472 if (instruction->opcode == I_DB ||
473 instruction->opcode == I_DW ||
474 instruction->opcode == I_DD ||
475 instruction->opcode == I_DQ ||
476 instruction->opcode == I_DT)
478 extop *e;
479 long isize, osize, wsize = 0; /* placate gcc */
481 isize = 0;
482 switch (instruction->opcode)
484 case I_DB: wsize = 1; break;
485 case I_DW: wsize = 2; break;
486 case I_DD: wsize = 4; break;
487 case I_DQ: wsize = 8; break;
488 case I_DT: wsize = 10; break;
491 for (e = instruction->eops; e; e = e->next)
493 long align;
495 osize = 0;
496 if (e->type == EOT_DB_NUMBER)
497 osize = 1;
498 else if (e->type == EOT_DB_STRING)
499 osize = e->stringlen;
501 align = (-osize) % wsize;
502 if (align < 0)
503 align += wsize;
504 isize += osize + align;
506 return isize * instruction->times;
509 if (instruction->opcode == I_INCBIN)
511 char fname[FILENAME_MAX];
512 FILE * fp;
513 long len;
514 char *prefix = "", *combine;
515 char** pPrevPath = NULL;
517 len = FILENAME_MAX-1;
518 if (len > instruction->eops->stringlen)
519 len = instruction->eops->stringlen;
520 strncpy (fname, instruction->eops->stringval, len);
521 fname[len] = '\0';
523 while (1) /* added by alexfru: 'incbin' uses include paths */
525 combine = nasm_malloc(strlen(prefix) + len + 1);
526 strcpy(combine, prefix);
527 strcat(combine, fname);
529 if ( (fp = fopen(combine, "rb")) != NULL)
531 nasm_free(combine);
532 break;
535 nasm_free(combine);
536 pPrevPath = pp_get_include_path_ptr (pPrevPath);
537 if (pPrevPath == NULL)
538 break;
539 prefix = *pPrevPath;
542 if (fp == NULL)
543 error (ERR_NONFATAL, "`incbin': unable to open file `%s'", fname);
544 else if (fseek(fp, 0L, SEEK_END) < 0)
545 error (ERR_NONFATAL, "`incbin': unable to seek on file `%s'",
546 fname);
547 else
549 len = ftell (fp);
550 fclose (fp);
551 if (instruction->eops->next)
553 len -= instruction->eops->next->offset;
554 if (instruction->eops->next->next &&
555 len > instruction->eops->next->next->offset)
557 len = instruction->eops->next->next->offset;
560 return instruction->times * len;
562 return 0; /* if we're here, there's an error */
565 temp = nasm_instructions[instruction->opcode];
566 while (temp->opcode != -1) {
567 int m = matches(temp, instruction);
568 if (m == 99)
569 m += jmp_match(segment, offset, bits, instruction, temp->code);
571 if (m == 100) {
572 /* we've matched an instruction. */
573 long isize;
574 const char * codes = temp->code;
575 int j;
577 isize = calcsize(segment, offset, bits, instruction, codes);
578 if (isize < 0)
579 return -1;
580 for (j = 0; j < instruction->nprefix; j++)
582 if ((instruction->prefixes[j] != P_A16 &&
583 instruction->prefixes[j] != P_O16 && bits==16) ||
584 (instruction->prefixes[j] != P_A32 &&
585 instruction->prefixes[j] != P_O32 && bits==32))
587 isize++;
590 return isize * instruction->times;
592 temp++;
594 return -1; /* didn't match any instruction */
598 /* check that opn[op] is a signed byte of size 16 or 32,
599 and return the signed value*/
600 static int is_sbyte (insn *ins, int op, int size)
602 signed long v;
603 int ret;
605 ret = !(ins->forw_ref && ins->oprs[op].opflags ) && /* dead in the water on forward reference or External */
606 optimizing>=0 &&
607 !(ins->oprs[op].type & STRICT) &&
608 ins->oprs[op].wrt==NO_SEG && ins->oprs[op].segment==NO_SEG;
610 v = ins->oprs[op].offset;
611 if (size==16) v = (signed short)v; /* sign extend if 16 bits */
613 return ret && v>=-128L && v<=127L;
616 static long calcsize (long segment, long offset, int bits,
617 insn *ins, const char *codes)
619 long length = 0;
620 unsigned char c;
622 (void) segment; /* Don't warn that this parameter is unused */
623 (void) offset; /* Don't warn that this parameter is unused */
625 while (*codes) switch (c = *codes++) {
626 case 01: case 02: case 03:
627 codes += c, length += c; break;
628 case 04: case 05: case 06: case 07:
629 length++; break;
630 case 010: case 011: case 012:
631 codes++, length++; break;
632 case 017:
633 length++; break;
634 case 014: case 015: case 016:
635 length++; break;
636 case 020: case 021: case 022:
637 length++; break;
638 case 024: case 025: case 026:
639 length++; break;
640 case 030: case 031: case 032:
641 length += 2; break;
642 case 034: case 035: case 036:
643 if ( ins->oprs[c-034].type & (BITS16|BITS32) )
644 length += (ins->oprs[c-034].type & BITS16) ? 2 : 4;
645 else
646 length += (bits == 16) ? 2 : 4;
647 break;
648 case 037:
649 length += 2; break;
650 case 040: case 041: case 042:
651 length += 4; break;
652 case 044: case 045: case 046:
653 length += ((ins->oprs[c-044].addr_size ?
654 ins->oprs[c-044].addr_size : bits) == 16 ? 2 : 4); break;
655 case 050: case 051: case 052:
656 length++; break;
657 case 060: case 061: case 062:
658 length += 2; break;
659 case 064: case 065: case 066:
660 if ( ins->oprs[c-064].type & (BITS16|BITS32) )
661 length += (ins->oprs[c-064].type & BITS16) ? 2 : 4;
662 else
663 length += (bits == 16) ? 2 : 4;
664 break;
665 case 070: case 071: case 072:
666 length += 4; break;
667 case 0130: case 0131: case 0132:
668 length += is_sbyte(ins, c-0130, 16) ? 1 : 2; break;
669 case 0133: case 0134: case 0135:
670 codes+=2; length++; break;
671 case 0140: case 0141: case 0142:
672 length += is_sbyte(ins, c-0140, 32) ? 1 : 4; break;
673 case 0143: case 0144: case 0145:
674 codes+=2; length++; break;
675 case 0300: case 0301: case 0302:
676 length += chsize (&ins->oprs[c-0300], bits);
677 break;
678 case 0310:
679 length += (bits==32);
680 break;
681 case 0311:
682 length += (bits==16);
683 break;
684 case 0312:
685 break;
686 case 0320:
687 length += (bits==32);
688 break;
689 case 0321:
690 length += (bits==16);
691 break;
692 case 0322:
693 break;
694 case 0330:
695 codes++, length++; break;
696 case 0331:
697 case 0332:
698 break;
699 case 0333:
700 length++; break;
701 case 0340: case 0341: case 0342:
702 if (ins->oprs[0].segment != NO_SEG)
703 errfunc (ERR_NONFATAL, "attempt to reserve non-constant"
704 " quantity of BSS space");
705 else
706 length += ins->oprs[0].offset << (c-0340);
707 break;
708 case 0370: case 0371: case 0372:
709 break;
710 case 0373:
711 length++; break;
712 default: /* can't do it by 'case' statements */
713 if (c>=0100 && c<=0277) { /* it's an EA */
714 ea ea_data;
715 if (!process_ea (&ins->oprs[(c>>3)&7], &ea_data, bits, 0,
716 ins->forw_ref)) {
717 errfunc (ERR_NONFATAL, "invalid effective address");
718 return -1;
719 } else
720 length += ea_data.size;
721 } else
722 errfunc (ERR_PANIC, "internal instruction table corrupt"
723 ": instruction code 0x%02X given", c);
725 return length;
728 static void gencode (long segment, long offset, int bits,
729 insn *ins, const char *codes, long insn_end)
731 static char condval[] = { /* conditional opcodes */
732 0x7, 0x3, 0x2, 0x6, 0x2, 0x4, 0xF, 0xD, 0xC, 0xE, 0x6, 0x2,
733 0x3, 0x7, 0x3, 0x5, 0xE, 0xC, 0xD, 0xF, 0x1, 0xB, 0x9, 0x5,
734 0x0, 0xA, 0xA, 0xB, 0x8, 0x4
736 unsigned char c;
737 unsigned char bytes[4];
738 long data, size;
740 while (*codes)
741 switch (c = *codes++)
743 case 01: case 02: case 03:
744 out (offset, segment, codes, OUT_RAWDATA+c, NO_SEG, NO_SEG);
745 codes += c;
746 offset += c;
747 break;
749 case 04: case 06:
750 switch (ins->oprs[0].basereg)
752 case R_CS:
753 bytes[0] = 0x0E + (c == 0x04 ? 1 : 0); break;
754 case R_DS:
755 bytes[0] = 0x1E + (c == 0x04 ? 1 : 0); break;
756 case R_ES:
757 bytes[0] = 0x06 + (c == 0x04 ? 1 : 0); break;
758 case R_SS:
759 bytes[0] = 0x16 + (c == 0x04 ? 1 : 0); break;
760 default:
761 errfunc (ERR_PANIC, "bizarre 8086 segment register received");
763 out (offset, segment, bytes, OUT_RAWDATA+1, NO_SEG, NO_SEG);
764 offset++;
765 break;
767 case 05: case 07:
768 switch (ins->oprs[0].basereg) {
769 case R_FS: bytes[0] = 0xA0 + (c == 0x05 ? 1 : 0); break;
770 case R_GS: bytes[0] = 0xA8 + (c == 0x05 ? 1 : 0); break;
771 default:
772 errfunc (ERR_PANIC, "bizarre 386 segment register received");
774 out (offset, segment, bytes, OUT_RAWDATA+1, NO_SEG, NO_SEG);
775 offset++;
776 break;
778 case 010: case 011: case 012:
779 bytes[0] = *codes++ + regval(&ins->oprs[c-010]);
780 out (offset, segment, bytes, OUT_RAWDATA+1, NO_SEG, NO_SEG);
781 offset += 1;
782 break;
784 case 017:
785 bytes[0] = 0;
786 out (offset, segment, bytes, OUT_RAWDATA+1, NO_SEG, NO_SEG);
787 offset += 1;
788 break;
790 case 014: case 015: case 016:
791 if (ins->oprs[c-014].offset < -128
792 || ins->oprs[c-014].offset > 127)
794 errfunc (ERR_WARNING, "signed byte value exceeds bounds");
797 if (ins->oprs[c-014].segment != NO_SEG)
799 data = ins->oprs[c-014].offset;
800 out (offset, segment, &data, OUT_ADDRESS+1,
801 ins->oprs[c-014].segment, ins->oprs[c-014].wrt);
803 else {
804 bytes[0] = ins->oprs[c-014].offset;
805 out (offset, segment, bytes, OUT_RAWDATA+1, NO_SEG, NO_SEG);
807 offset += 1;
808 break;
810 case 020: case 021: case 022:
811 if (ins->oprs[c-020].offset < -256
812 || ins->oprs[c-020].offset > 255)
814 errfunc (ERR_WARNING, "byte value exceeds bounds");
816 if (ins->oprs[c-020].segment != NO_SEG) {
817 data = ins->oprs[c-020].offset;
818 out (offset, segment, &data, OUT_ADDRESS+1,
819 ins->oprs[c-020].segment, ins->oprs[c-020].wrt);
821 else {
822 bytes[0] = ins->oprs[c-020].offset;
823 out (offset, segment, bytes, OUT_RAWDATA+1, NO_SEG, NO_SEG);
825 offset += 1;
826 break;
828 case 024: case 025: case 026:
829 if (ins->oprs[c-024].offset < 0 || ins->oprs[c-024].offset > 255)
830 errfunc (ERR_WARNING, "unsigned byte value exceeds bounds");
831 if (ins->oprs[c-024].segment != NO_SEG) {
832 data = ins->oprs[c-024].offset;
833 out (offset, segment, &data, OUT_ADDRESS+1,
834 ins->oprs[c-024].segment, ins->oprs[c-024].wrt);
836 else {
837 bytes[0] = ins->oprs[c-024].offset;
838 out (offset, segment, bytes, OUT_RAWDATA+1, NO_SEG, NO_SEG);
840 offset += 1;
841 break;
843 case 030: case 031: case 032:
844 if (ins->oprs[c-030].segment == NO_SEG &&
845 ins->oprs[c-030].wrt == NO_SEG &&
846 (ins->oprs[c-030].offset < -65536L ||
847 ins->oprs[c-030].offset > 65535L))
849 errfunc (ERR_WARNING, "word value exceeds bounds");
851 data = ins->oprs[c-030].offset;
852 out (offset, segment, &data, OUT_ADDRESS+2,
853 ins->oprs[c-030].segment, ins->oprs[c-030].wrt);
854 offset += 2;
855 break;
857 case 034: case 035: case 036:
858 if ( ins->oprs[c-034].type & (BITS16|BITS32) )
859 size = (ins->oprs[c-034].type & BITS16) ? 2 : 4;
860 else
861 size = (bits == 16) ? 2 : 4;
862 data = ins->oprs[c-034].offset;
863 if (size==2 && (data < -65536L || data > 65535L))
864 errfunc (ERR_WARNING, "word value exceeds bounds");
865 out (offset, segment, &data, OUT_ADDRESS+size,
866 ins->oprs[c-034].segment, ins->oprs[c-034].wrt);
867 offset += size;
868 break;
870 case 037:
871 if (ins->oprs[0].segment == NO_SEG)
872 errfunc (ERR_NONFATAL, "value referenced by FAR is not"
873 " relocatable");
874 data = 0L;
875 out (offset, segment, &data, OUT_ADDRESS+2,
876 outfmt->segbase(1+ins->oprs[0].segment),
877 ins->oprs[0].wrt);
878 offset += 2;
879 break;
881 case 040: case 041: case 042:
882 data = ins->oprs[c-040].offset;
883 out (offset, segment, &data, OUT_ADDRESS+4,
884 ins->oprs[c-040].segment, ins->oprs[c-040].wrt);
885 offset += 4;
886 break;
888 case 044: case 045: case 046:
889 data = ins->oprs[c-044].offset;
890 size = ((ins->oprs[c-044].addr_size ?
891 ins->oprs[c-044].addr_size : bits) == 16 ? 2 : 4);
892 if (size==2 && (data < -65536L || data > 65535L))
893 errfunc (ERR_WARNING, "word value exceeds bounds");
894 out (offset, segment, &data, OUT_ADDRESS+size,
895 ins->oprs[c-044].segment, ins->oprs[c-044].wrt);
896 offset += size;
897 break;
899 case 050: case 051: case 052:
900 if (ins->oprs[c-050].segment != segment)
901 errfunc (ERR_NONFATAL, "short relative jump outside segment");
902 data = ins->oprs[c-050].offset - insn_end;
903 if (data > 127 || data < -128)
904 errfunc (ERR_NONFATAL, "short jump is out of range");
905 bytes[0] = data;
906 out (offset, segment, bytes, OUT_RAWDATA+1, NO_SEG, NO_SEG);
907 offset += 1;
908 break;
910 case 060: case 061: case 062:
911 if (ins->oprs[c-060].segment != segment) {
912 data = ins->oprs[c-060].offset;
913 out (offset, segment, &data, OUT_REL2ADR+insn_end-offset,
914 ins->oprs[c-060].segment, ins->oprs[c-060].wrt);
915 } else {
916 data = ins->oprs[c-060].offset - insn_end;
917 out (offset, segment, &data,
918 OUT_ADDRESS+2, NO_SEG, NO_SEG);
920 offset += 2;
921 break;
923 case 064: case 065: case 066:
924 if ( ins->oprs[c-064].type & (BITS16|BITS32) )
925 size = (ins->oprs[c-064].type & BITS16) ? 2 : 4;
926 else
927 size = (bits == 16) ? 2 : 4;
928 if (ins->oprs[c-064].segment != segment) {
929 long reltype = (size == 2 ? OUT_REL2ADR : OUT_REL4ADR);
930 data = ins->oprs[c-064].offset;
931 out (offset, segment, &data, reltype+insn_end-offset,
932 ins->oprs[c-064].segment, ins->oprs[c-064].wrt);
933 } else {
934 data = ins->oprs[c-064].offset - insn_end;
935 out (offset, segment, &data,
936 OUT_ADDRESS+size, NO_SEG, NO_SEG);
938 offset += size;
939 break;
941 case 070: case 071: case 072:
942 if (ins->oprs[c-070].segment != segment) {
943 data = ins->oprs[c-070].offset;
944 out (offset, segment, &data, OUT_REL4ADR+insn_end-offset,
945 ins->oprs[c-070].segment, ins->oprs[c-070].wrt);
946 } else {
947 data = ins->oprs[c-070].offset - insn_end;
948 out (offset, segment, &data,
949 OUT_ADDRESS+4, NO_SEG, NO_SEG);
951 offset += 4;
952 break;
954 case 0130: case 0131: case 0132:
955 data = ins->oprs[c-0130].offset;
956 if (is_sbyte(ins, c-0130, 16)) {
957 bytes[0] = data;
958 out (offset, segment, bytes, OUT_RAWDATA+1, NO_SEG, NO_SEG);
959 offset++;
960 } else {
961 if (ins->oprs[c-0130].segment == NO_SEG &&
962 ins->oprs[c-0130].wrt == NO_SEG &&
963 (data < -65536L || data > 65535L)) {
964 errfunc (ERR_WARNING, "word value exceeds bounds");
966 out (offset, segment, &data, OUT_ADDRESS+2,
967 ins->oprs[c-0130].segment, ins->oprs[c-0130].wrt);
968 offset += 2;
970 break;
972 case 0133: case 0134: case 0135:
973 codes++;
974 bytes[0] = *codes++;
975 if (is_sbyte(ins, c-0133, 16)) bytes[0] |= 2; /* s-bit */
976 out (offset, segment, bytes, OUT_RAWDATA+1, NO_SEG, NO_SEG);
977 offset++;
978 break;
980 case 0140: case 0141: case 0142:
981 data = ins->oprs[c-0140].offset;
982 if (is_sbyte(ins, c-0140, 32)) {
983 bytes[0] = data;
984 out (offset, segment, bytes, OUT_RAWDATA+1, NO_SEG, NO_SEG);
985 offset++;
986 } else {
987 out (offset, segment, &data, OUT_ADDRESS+4,
988 ins->oprs[c-0140].segment, ins->oprs[c-0140].wrt);
989 offset += 4;
991 break;
993 case 0143: case 0144: case 0145:
994 codes++;
995 bytes[0] = *codes++;
996 if (is_sbyte(ins, c-0143, 32)) bytes[0] |= 2; /* s-bit */
997 out (offset, segment, bytes, OUT_RAWDATA+1, NO_SEG, NO_SEG);
998 offset++;
999 break;
1001 case 0300: case 0301: case 0302:
1002 if (chsize (&ins->oprs[c-0300], bits)) {
1003 *bytes = 0x67;
1004 out (offset, segment, bytes,
1005 OUT_RAWDATA+1, NO_SEG, NO_SEG);
1006 offset += 1;
1007 } else
1008 offset += 0;
1009 break;
1011 case 0310:
1012 if (bits==32) {
1013 *bytes = 0x67;
1014 out (offset, segment, bytes,
1015 OUT_RAWDATA+1, NO_SEG, NO_SEG);
1016 offset += 1;
1017 } else
1018 offset += 0;
1019 break;
1021 case 0311:
1022 if (bits==16) {
1023 *bytes = 0x67;
1024 out (offset, segment, bytes,
1025 OUT_RAWDATA+1, NO_SEG, NO_SEG);
1026 offset += 1;
1027 } else
1028 offset += 0;
1029 break;
1031 case 0312:
1032 break;
1034 case 0320:
1035 if (bits==32) {
1036 *bytes = 0x66;
1037 out (offset, segment, bytes,
1038 OUT_RAWDATA+1, NO_SEG, NO_SEG);
1039 offset += 1;
1040 } else
1041 offset += 0;
1042 break;
1044 case 0321:
1045 if (bits==16) {
1046 *bytes = 0x66;
1047 out (offset, segment, bytes,
1048 OUT_RAWDATA+1, NO_SEG, NO_SEG);
1049 offset += 1;
1050 } else
1051 offset += 0;
1052 break;
1054 case 0322:
1055 break;
1057 case 0330:
1058 *bytes = *codes++ ^ condval[ins->condition];
1059 out (offset, segment, bytes,
1060 OUT_RAWDATA+1, NO_SEG, NO_SEG);
1061 offset += 1;
1062 break;
1064 case 0331:
1065 case 0332:
1066 break;
1068 case 0333:
1069 *bytes = 0xF3;
1070 out (offset, segment, bytes,
1071 OUT_RAWDATA+1, NO_SEG, NO_SEG);
1072 offset += 1;
1073 break;
1075 case 0340: case 0341: case 0342:
1076 if (ins->oprs[0].segment != NO_SEG)
1077 errfunc (ERR_PANIC, "non-constant BSS size in pass two");
1078 else {
1079 long size = ins->oprs[0].offset << (c-0340);
1080 if (size > 0)
1081 out (offset, segment, NULL,
1082 OUT_RESERVE+size, NO_SEG, NO_SEG);
1083 offset += size;
1085 break;
1087 case 0370: case 0371: case 0372:
1088 break;
1090 case 0373:
1091 *bytes = bits==16 ? 3 : 5;
1092 out (offset, segment, bytes,
1093 OUT_RAWDATA+1, NO_SEG, NO_SEG);
1094 offset += 1;
1095 break;
1097 default: /* can't do it by 'case' statements */
1098 if (c>=0100 && c<=0277) { /* it's an EA */
1099 ea ea_data;
1100 int rfield;
1101 unsigned char *p;
1102 long s;
1104 if (c<=0177) /* pick rfield from operand b */
1105 rfield = regval (&ins->oprs[c&7]);
1106 else /* rfield is constant */
1107 rfield = c & 7;
1109 if (!process_ea (&ins->oprs[(c>>3)&7], &ea_data, bits, rfield,
1110 ins->forw_ref))
1112 errfunc (ERR_NONFATAL, "invalid effective address");
1115 p = bytes;
1116 *p++ = ea_data.modrm;
1117 if (ea_data.sib_present)
1118 *p++ = ea_data.sib;
1120 s = p-bytes;
1121 out (offset, segment, bytes, OUT_RAWDATA + s,
1122 NO_SEG, NO_SEG);
1124 switch (ea_data.bytes) {
1125 case 0:
1126 break;
1127 case 1:
1128 if (ins->oprs[(c>>3)&7].segment != NO_SEG) {
1129 data = ins->oprs[(c>>3)&7].offset;
1130 out (offset, segment, &data, OUT_ADDRESS+1,
1131 ins->oprs[(c>>3)&7].segment,
1132 ins->oprs[(c>>3)&7].wrt);
1133 } else {
1134 *bytes = ins->oprs[(c>>3)&7].offset;
1135 out (offset, segment, bytes, OUT_RAWDATA+1,
1136 NO_SEG, NO_SEG);
1138 s++;
1139 break;
1140 case 2:
1141 case 4:
1142 data = ins->oprs[(c>>3)&7].offset;
1143 out (offset, segment, &data,
1144 OUT_ADDRESS+ea_data.bytes,
1145 ins->oprs[(c>>3)&7].segment, ins->oprs[(c>>3)&7].wrt);
1146 s += ea_data.bytes;
1147 break;
1149 offset += s;
1150 } else
1151 errfunc (ERR_PANIC, "internal instruction table corrupt"
1152 ": instruction code 0x%02X given", c);
1156 #include "regvals.c"
1158 static int regval (operand *o)
1160 if ( o->basereg < EXPR_REG_START || o->basereg >= REG_ENUM_LIMIT ) {
1161 errfunc (ERR_PANIC, "invalid operand passed to regval()");
1163 return regvals[o->basereg];
1166 static int matches (struct itemplate *itemp, insn *instruction)
1168 int i, size[3], asize, oprs, ret;
1170 ret = 100;
1173 * Check the opcode
1175 if (itemp->opcode != instruction->opcode) return 0;
1178 * Count the operands
1180 if (itemp->operands != instruction->operands) return 0;
1183 * Check that no spurious colons or TOs are present
1185 for (i=0; i<itemp->operands; i++)
1186 if (instruction->oprs[i].type & ~itemp->opd[i] & (COLON|TO))
1187 return 0;
1190 * Check that the operand flags all match up
1192 for (i=0; i<itemp->operands; i++)
1193 if (itemp->opd[i] & ~instruction->oprs[i].type ||
1194 ((itemp->opd[i] & SIZE_MASK) &&
1195 ((itemp->opd[i] ^ instruction->oprs[i].type) & SIZE_MASK)))
1197 if ((itemp->opd[i] & ~instruction->oprs[i].type & NON_SIZE) ||
1198 (instruction->oprs[i].type & SIZE_MASK))
1199 return 0;
1200 else
1201 /* ret = 1; */
1202 return 1;
1206 * Check operand sizes
1208 if (itemp->flags & IF_ARMASK) {
1209 size[0] = size[1] = size[2] = 0;
1211 switch (itemp->flags & IF_ARMASK) {
1212 case IF_AR0: i = 0; break;
1213 case IF_AR1: i = 1; break;
1214 case IF_AR2: i = 2; break;
1215 default: break; /* Shouldn't happen */
1217 if (itemp->flags & IF_SB) {
1218 size[i] = BITS8;
1219 } else if (itemp->flags & IF_SW) {
1220 size[i] = BITS16;
1221 } else if (itemp->flags & IF_SD) {
1222 size[i] = BITS32;
1224 } else {
1225 asize = 0;
1226 if (itemp->flags & IF_SB) {
1227 asize = BITS8;
1228 oprs = itemp->operands;
1229 } else if (itemp->flags & IF_SW) {
1230 asize = BITS16;
1231 oprs = itemp->operands;
1232 } else if (itemp->flags & IF_SD) {
1233 asize = BITS32;
1234 oprs = itemp->operands;
1236 size[0] = size[1] = size[2] = asize;
1239 if (itemp->flags & (IF_SM | IF_SM2)) {
1240 oprs = (itemp->flags & IF_SM2 ? 2 : itemp->operands);
1241 asize = 0;
1242 for (i=0; i<oprs; i++) {
1243 if ( (asize = itemp->opd[i] & SIZE_MASK) != 0) {
1244 int j;
1245 for (j=0; j<oprs; j++)
1246 size[j] = asize;
1247 break;
1250 } else {
1251 oprs = itemp->operands;
1254 for (i=0; i<itemp->operands; i++)
1255 if (!(itemp->opd[i] & SIZE_MASK) &&
1256 (instruction->oprs[i].type & SIZE_MASK & ~size[i]))
1257 /* ret = 2; */
1258 return 2;
1261 * Check template is okay at the set cpu level
1263 if ((itemp->flags & IF_PLEVEL) > cpu) return 3;
1266 * Check if special handling needed for Jumps
1268 if ((unsigned char)(itemp->code[0]) >= 0370) return 99;
1270 return ret;
1273 static ea *process_ea (operand *input, ea *output, int addrbits, int rfield,
1274 int forw_ref)
1276 if (!(REGISTER & ~input->type)) { /* it's a single register */
1277 static int regs[] = {
1278 R_AL, R_CL, R_DL, R_BL, R_AH, R_CH, R_DH, R_BH,
1279 R_AX, R_CX, R_DX, R_BX, R_SP, R_BP, R_SI, R_DI,
1280 R_EAX, R_ECX, R_EDX, R_EBX, R_ESP, R_EBP, R_ESI, R_EDI,
1281 R_MM0, R_MM1, R_MM2, R_MM3, R_MM4, R_MM5, R_MM6, R_MM7,
1282 R_XMM0, R_XMM1, R_XMM2, R_XMM3, R_XMM4, R_XMM5, R_XMM6, R_XMM7
1284 int i;
1286 for (i=0; i<elements(regs); i++)
1287 if (input->basereg == regs[i]) break;
1288 if (i<elements(regs)) {
1289 output->sib_present = FALSE;/* no SIB necessary */
1290 output->bytes = 0; /* no offset necessary either */
1291 output->modrm = 0xC0 | (rfield << 3) | (i & 7);
1293 else
1294 return NULL;
1295 } else { /* it's a memory reference */
1296 if (input->basereg==-1 && (input->indexreg==-1 || input->scale==0)) {
1297 /* it's a pure offset */
1298 if (input->addr_size)
1299 addrbits = input->addr_size;
1300 output->sib_present = FALSE;
1301 output->bytes = (addrbits==32 ? 4 : 2);
1302 output->modrm = (addrbits==32 ? 5 : 6) | (rfield << 3);
1304 else { /* it's an indirection */
1305 int i=input->indexreg, b=input->basereg, s=input->scale;
1306 long o=input->offset, seg=input->segment;
1307 int hb=input->hintbase, ht=input->hinttype;
1308 int t;
1310 if (s==0) i = -1; /* make this easy, at least */
1312 if (i==R_EAX || i==R_EBX || i==R_ECX || i==R_EDX
1313 || i==R_EBP || i==R_ESP || i==R_ESI || i==R_EDI
1314 || b==R_EAX || b==R_EBX || b==R_ECX || b==R_EDX
1315 || b==R_EBP || b==R_ESP || b==R_ESI || b==R_EDI) {
1316 /* it must be a 32-bit memory reference. Firstly we have
1317 * to check that all registers involved are type Exx. */
1318 if (i!=-1 && i!=R_EAX && i!=R_EBX && i!=R_ECX && i!=R_EDX
1319 && i!=R_EBP && i!=R_ESP && i!=R_ESI && i!=R_EDI)
1320 return NULL;
1321 if (b!=-1 && b!=R_EAX && b!=R_EBX && b!=R_ECX && b!=R_EDX
1322 && b!=R_EBP && b!=R_ESP && b!=R_ESI && b!=R_EDI)
1323 return NULL;
1325 /* While we're here, ensure the user didn't specify WORD. */
1326 if (input->addr_size == 16)
1327 return NULL;
1329 /* now reorganise base/index */
1330 if (s == 1 && b != i && b != -1 && i != -1 &&
1331 ((hb==b&&ht==EAH_NOTBASE) || (hb==i&&ht==EAH_MAKEBASE)))
1332 t = b, b = i, i = t; /* swap if hints say so */
1333 if (b==i) /* convert EAX+2*EAX to 3*EAX */
1334 b = -1, s++;
1335 if (b==-1 && s==1 && !(hb == i && ht == EAH_NOTBASE))
1336 b = i, i = -1; /* make single reg base, unless hint */
1337 if (((s==2 && i!=R_ESP && !(input->eaflags & EAF_TIMESTWO)) ||
1338 s==3 || s==5 || s==9) && b==-1)
1339 b = i, s--; /* convert 3*EAX to EAX+2*EAX */
1340 if (i==-1 && b!=R_ESP && (input->eaflags & EAF_TIMESTWO))
1341 i = b, b = -1, s = 1;
1342 /* convert [NOSPLIT EAX] to sib format with 0x0 displacement */
1343 if (s==1 && i==R_ESP) /* swap ESP into base if scale is 1 */
1344 i = b, b = R_ESP;
1345 if (i==R_ESP || (s!=1 && s!=2 && s!=4 && s!=8 && i!=-1))
1346 return NULL; /* wrong, for various reasons */
1348 if (i==-1 && b!=R_ESP) {/* no SIB needed */
1349 int mod, rm;
1350 switch(b) {
1351 case R_EAX: rm = 0; break;
1352 case R_ECX: rm = 1; break;
1353 case R_EDX: rm = 2; break;
1354 case R_EBX: rm = 3; break;
1355 case R_EBP: rm = 5; break;
1356 case R_ESI: rm = 6; break;
1357 case R_EDI: rm = 7; break;
1358 case -1: rm = 5; break;
1359 default: /* should never happen */
1360 return NULL;
1362 if (b==-1 || (b!=R_EBP && o==0 &&
1363 seg==NO_SEG && !forw_ref &&
1364 !(input->eaflags &
1365 (EAF_BYTEOFFS|EAF_WORDOFFS))))
1366 mod = 0;
1367 else if (input->eaflags & EAF_BYTEOFFS ||
1368 (o>=-128 && o<=127 && seg==NO_SEG && !forw_ref &&
1369 !(input->eaflags & EAF_WORDOFFS))) {
1370 mod = 1;
1372 else
1373 mod = 2;
1375 output->sib_present = FALSE;
1376 output->bytes = (b==-1 || mod==2 ? 4 : mod);
1377 output->modrm = (mod<<6) | (rfield<<3) | rm;
1379 else { /* we need a SIB */
1380 int mod, scale, index, base;
1382 switch (b) {
1383 case R_EAX: base = 0; break;
1384 case R_ECX: base = 1; break;
1385 case R_EDX: base = 2; break;
1386 case R_EBX: base = 3; break;
1387 case R_ESP: base = 4; break;
1388 case R_EBP: case -1: base = 5; break;
1389 case R_ESI: base = 6; break;
1390 case R_EDI: base = 7; break;
1391 default: /* then what the smeg is it? */
1392 return NULL; /* panic */
1395 switch (i) {
1396 case R_EAX: index = 0; break;
1397 case R_ECX: index = 1; break;
1398 case R_EDX: index = 2; break;
1399 case R_EBX: index = 3; break;
1400 case -1: index = 4; break;
1401 case R_EBP: index = 5; break;
1402 case R_ESI: index = 6; break;
1403 case R_EDI: index = 7; break;
1404 default: /* then what the smeg is it? */
1405 return NULL; /* panic */
1408 if (i==-1) s = 1;
1409 switch (s) {
1410 case 1: scale = 0; break;
1411 case 2: scale = 1; break;
1412 case 4: scale = 2; break;
1413 case 8: scale = 3; break;
1414 default: /* then what the smeg is it? */
1415 return NULL; /* panic */
1418 if (b==-1 || (b!=R_EBP && o==0 &&
1419 seg==NO_SEG && !forw_ref &&
1420 !(input->eaflags &
1421 (EAF_BYTEOFFS|EAF_WORDOFFS))))
1422 mod = 0;
1423 else if (input->eaflags & EAF_BYTEOFFS ||
1424 (o>=-128 && o<=127 && seg==NO_SEG && !forw_ref &&
1425 !(input->eaflags & EAF_WORDOFFS)))
1426 mod = 1;
1427 else
1428 mod = 2;
1430 output->sib_present = TRUE;
1431 output->bytes = (b==-1 || mod==2 ? 4 : mod);
1432 output->modrm = (mod<<6) | (rfield<<3) | 4;
1433 output->sib = (scale<<6) | (index<<3) | base;
1436 else { /* it's 16-bit */
1437 int mod, rm;
1439 /* check all registers are BX, BP, SI or DI */
1440 if ((b!=-1 && b!=R_BP && b!=R_BX && b!=R_SI && b!=R_DI) ||
1441 (i!=-1 && i!=R_BP && i!=R_BX && i!=R_SI && i!=R_DI))
1442 return NULL;
1444 /* ensure the user didn't specify DWORD */
1445 if (input->addr_size == 32)
1446 return NULL;
1448 if (s!=1 && i!=-1) return NULL;/* no can do, in 16-bit EA */
1449 if (b==-1 && i!=-1) { int tmp = b; b = i; i = tmp; } /* swap */
1450 if ((b==R_SI || b==R_DI) && i!=-1)
1451 { int tmp = b; b = i; i = tmp; }
1452 /* have BX/BP as base, SI/DI index */
1453 if (b==i) return NULL;/* shouldn't ever happen, in theory */
1454 if (i!=-1 && b!=-1 &&
1455 (i==R_BP || i==R_BX || b==R_SI || b==R_DI))
1456 return NULL; /* invalid combinations */
1457 if (b==-1) /* pure offset: handled above */
1458 return NULL; /* so if it gets to here, panic! */
1460 rm = -1;
1461 if (i!=-1)
1462 switch (i*256 + b) {
1463 case R_SI*256+R_BX: rm=0; break;
1464 case R_DI*256+R_BX: rm=1; break;
1465 case R_SI*256+R_BP: rm=2; break;
1466 case R_DI*256+R_BP: rm=3; break;
1468 else
1469 switch (b) {
1470 case R_SI: rm=4; break;
1471 case R_DI: rm=5; break;
1472 case R_BP: rm=6; break;
1473 case R_BX: rm=7; break;
1475 if (rm==-1) /* can't happen, in theory */
1476 return NULL; /* so panic if it does */
1478 if (o==0 && seg==NO_SEG && !forw_ref && rm!=6 &&
1479 !(input->eaflags & (EAF_BYTEOFFS|EAF_WORDOFFS)))
1480 mod = 0;
1481 else if (input->eaflags & EAF_BYTEOFFS ||
1482 (o>=-128 && o<=127 && seg==NO_SEG && !forw_ref &&
1483 !(input->eaflags & EAF_WORDOFFS)))
1484 mod = 1;
1485 else
1486 mod = 2;
1488 output->sib_present = FALSE; /* no SIB - it's 16-bit */
1489 output->bytes = mod; /* bytes of offset needed */
1490 output->modrm = (mod<<6) | (rfield<<3) | rm;
1494 output->size = 1 + output->sib_present + output->bytes;
1495 return output;
1498 static int chsize (operand *input, int addrbits)
1500 if (!(MEMORY & ~input->type)) {
1501 int i=input->indexreg, b=input->basereg;
1503 if (input->scale==0) i = -1;
1505 if (i == -1 && b == -1) /* pure offset */
1506 return (input->addr_size != 0 && input->addr_size != addrbits);
1508 if (i==R_EAX || i==R_EBX || i==R_ECX || i==R_EDX
1509 || i==R_EBP || i==R_ESP || i==R_ESI || i==R_EDI
1510 || b==R_EAX || b==R_EBX || b==R_ECX || b==R_EDX
1511 || b==R_EBP || b==R_ESP || b==R_ESI || b==R_EDI)
1512 return (addrbits==16);
1513 else
1514 return (addrbits==32);
1516 else
1517 return 0;