Apply Nindent to all .c and .h files
[nasm/avx512.git] / assemble.c
blob3a610411507a5f9f403d921b8c78c88cfe1b8036
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,
106 unsigned long type, 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);
118 } else {
119 unsigned char p[4], *q = p;
121 * This is a non-relocated address, and we're going to
122 * convert it into RAWDATA format.
124 if ((type & OUT_SIZMASK) == 4) {
125 WRITELONG(q, *(long *)data);
126 list->output(offset, p, OUT_RAWDATA + 4);
127 } else {
128 WRITESHORT(q, *(long *)data);
129 list->output(offset, p, OUT_RAWDATA + 2);
132 } else if ((type & OUT_TYPMASK) == OUT_RAWDATA) {
133 list->output(offset, data, type);
134 } else if ((type & OUT_TYPMASK) == OUT_RESERVE) {
135 list->output(offset, NULL, type);
136 } else if ((type & OUT_TYPMASK) == OUT_REL2ADR ||
137 (type & OUT_TYPMASK) == OUT_REL4ADR) {
138 list->output(offset, data, type);
142 * this call to src_get determines when we call the
143 * debug-format-specific "linenum" function
144 * it updates lineno and lnfname to the current values
145 * returning 0 if "same as last time", -2 if lnfname
146 * changed, and the amount by which lineno changed,
147 * if it did. thus, these variables must be static
150 if (src_get(&lineno, &lnfname)) {
151 outfmt->current_dfmt->linenum(lnfname, lineno, segto);
154 outfmt->output(segto, data, type, segment, wrt);
157 static int jmp_match(long segment, long offset, int bits,
158 insn * ins, const char *code)
160 long isize;
161 unsigned char c = code[0];
163 if (c != 0370 && c != 0371)
164 return 0;
165 if (ins->oprs[0].opflags & OPFLAG_FORWARD) {
166 if ((optimizing < 0 || (ins->oprs[0].type & STRICT))
167 && c == 0370)
168 return 1;
169 else
170 return (pass0 == 0); /* match a forward reference */
172 isize = calcsize(segment, offset, bits, ins, code);
173 if (ins->oprs[0].segment != segment)
174 return 0;
175 isize = ins->oprs[0].offset - offset - isize; /* isize is now the delta */
176 if (isize >= -128L && isize <= 127L)
177 return 1; /* it is byte size */
179 return 0;
182 long assemble(long segment, long offset, int bits, unsigned long cp,
183 insn * instruction, struct ofmt *output, efunc error,
184 ListGen * listgen)
186 struct itemplate *temp;
187 int j;
188 int size_prob;
189 long insn_end;
190 long itimes;
191 long start = offset;
192 long wsize = 0; /* size for DB etc. */
194 errfunc = error; /* to pass to other functions */
195 cpu = cp;
196 outfmt = output; /* likewise */
197 list = listgen; /* and again */
199 switch (instruction->opcode) {
200 case -1:
201 return 0;
202 case I_DB:
203 wsize = 1;
204 break;
205 case I_DW:
206 wsize = 2;
207 break;
208 case I_DD:
209 wsize = 4;
210 break;
211 case I_DQ:
212 wsize = 8;
213 break;
214 case I_DT:
215 wsize = 10;
216 break;
219 if (wsize) {
220 extop *e;
221 long t = instruction->times;
222 if (t < 0)
223 errfunc(ERR_PANIC,
224 "instruction->times < 0 (%ld) in assemble()", t);
226 while (t--) { /* repeat TIMES times */
227 for (e = instruction->eops; e; e = e->next) {
228 if (e->type == EOT_DB_NUMBER) {
229 if (wsize == 1) {
230 if (e->segment != NO_SEG)
231 errfunc(ERR_NONFATAL,
232 "one-byte relocation attempted");
233 else {
234 unsigned char out_byte = e->offset;
235 out(offset, segment, &out_byte,
236 OUT_RAWDATA + 1, NO_SEG, NO_SEG);
238 } else if (wsize > 5) {
239 errfunc(ERR_NONFATAL, "integer supplied to a D%c"
240 " instruction", wsize == 8 ? 'Q' : 'T');
241 } else
242 out(offset, segment, &e->offset,
243 OUT_ADDRESS + wsize, e->segment, e->wrt);
244 offset += wsize;
245 } else if (e->type == EOT_DB_STRING) {
246 int align;
248 out(offset, segment, e->stringval,
249 OUT_RAWDATA + e->stringlen, NO_SEG, NO_SEG);
250 align = e->stringlen % wsize;
252 if (align) {
253 align = wsize - align;
254 out(offset, segment, "\0\0\0\0\0\0\0\0",
255 OUT_RAWDATA + align, NO_SEG, NO_SEG);
257 offset += e->stringlen + align;
260 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) {
275 static char fname[FILENAME_MAX];
276 FILE *fp;
277 long len;
278 char *prefix = "", *combine;
279 char **pPrevPath = NULL;
281 len = FILENAME_MAX - 1;
282 if (len > instruction->eops->stringlen)
283 len = instruction->eops->stringlen;
284 strncpy(fname, instruction->eops->stringval, len);
285 fname[len] = '\0';
287 while (1) { /* added by alexfru: 'incbin' uses include paths */
288 combine = nasm_malloc(strlen(prefix) + len + 1);
289 strcpy(combine, prefix);
290 strcat(combine, fname);
292 if ((fp = fopen(combine, "rb")) != NULL) {
293 nasm_free(combine);
294 break;
297 nasm_free(combine);
298 pPrevPath = pp_get_include_path_ptr(pPrevPath);
299 if (pPrevPath == NULL)
300 break;
301 prefix = *pPrevPath;
304 if (fp == NULL)
305 error(ERR_NONFATAL, "`incbin': unable to open file `%s'",
306 fname);
307 else if (fseek(fp, 0L, SEEK_END) < 0)
308 error(ERR_NONFATAL, "`incbin': unable to seek on file `%s'",
309 fname);
310 else {
311 static char buf[2048];
312 long t = instruction->times;
313 long base = 0;
315 len = ftell(fp);
316 if (instruction->eops->next) {
317 base = instruction->eops->next->offset;
318 len -= base;
319 if (instruction->eops->next->next &&
320 len > instruction->eops->next->next->offset)
321 len = instruction->eops->next->next->offset;
324 * Dummy call to list->output to give the offset to the
325 * listing module.
327 list->output(offset, NULL, OUT_RAWDATA);
328 list->uplevel(LIST_INCBIN);
329 while (t--) {
330 long l;
332 fseek(fp, base, SEEK_SET);
333 l = len;
334 while (l > 0) {
335 long m =
336 fread(buf, 1, (l > sizeof(buf) ? sizeof(buf) : l),
337 fp);
338 if (!m) {
340 * This shouldn't happen unless the file
341 * actually changes while we are reading
342 * it.
344 error(ERR_NONFATAL,
345 "`incbin': unexpected EOF while"
346 " reading file `%s'", fname);
347 t = 0; /* Try to exit cleanly */
348 break;
350 out(offset, segment, buf, OUT_RAWDATA + m,
351 NO_SEG, NO_SEG);
352 l -= m;
355 list->downlevel(LIST_INCBIN);
356 if (instruction->times > 1) {
358 * Dummy call to list->output to give the offset to the
359 * listing module.
361 list->output(offset, NULL, OUT_RAWDATA);
362 list->uplevel(LIST_TIMES);
363 list->downlevel(LIST_TIMES);
365 fclose(fp);
366 return instruction->times * len;
368 return 0; /* if we're here, there's an error */
371 size_prob = FALSE;
372 temp = nasm_instructions[instruction->opcode];
373 while (temp->opcode != -1) {
374 int m = matches(temp, instruction);
375 if (m == 99)
376 m += jmp_match(segment, offset, bits, instruction, temp->code);
378 if (m == 100) { /* matches! */
379 const char *codes = temp->code;
380 long insn_size = calcsize(segment, offset, bits,
381 instruction, codes);
382 itimes = instruction->times;
383 if (insn_size < 0) /* shouldn't be, on pass two */
384 error(ERR_PANIC, "errors made it through from pass one");
385 else
386 while (itimes--) {
387 for (j = 0; j < instruction->nprefix; j++) {
388 unsigned char c = 0;
389 switch (instruction->prefixes[j]) {
390 case P_LOCK:
391 c = 0xF0;
392 break;
393 case P_REPNE:
394 case P_REPNZ:
395 c = 0xF2;
396 break;
397 case P_REPE:
398 case P_REPZ:
399 case P_REP:
400 c = 0xF3;
401 break;
402 case R_CS:
403 c = 0x2E;
404 break;
405 case R_DS:
406 c = 0x3E;
407 break;
408 case R_ES:
409 c = 0x26;
410 break;
411 case R_FS:
412 c = 0x64;
413 break;
414 case R_GS:
415 c = 0x65;
416 break;
417 case R_SS:
418 c = 0x36;
419 break;
420 case R_SEGR6:
421 case R_SEGR7:
422 error(ERR_NONFATAL,
423 "segr6 and segr7 cannot be used as prefixes");
424 break;
425 case P_A16:
426 if (bits != 16)
427 c = 0x67;
428 break;
429 case P_A32:
430 if (bits != 32)
431 c = 0x67;
432 break;
433 case P_O16:
434 if (bits != 16)
435 c = 0x66;
436 break;
437 case P_O32:
438 if (bits != 32)
439 c = 0x66;
440 break;
441 default:
442 error(ERR_PANIC, "invalid instruction prefix");
444 if (c != 0) {
445 out(offset, segment, &c, OUT_RAWDATA + 1,
446 NO_SEG, NO_SEG);
447 offset++;
450 insn_end = offset + insn_size;
451 gencode(segment, offset, bits, instruction, codes,
452 insn_end);
453 offset += insn_size;
454 if (itimes > 0 && itimes == instruction->times - 1) {
456 * Dummy call to list->output to give the offset to the
457 * listing module.
459 list->output(offset, NULL, OUT_RAWDATA);
460 list->uplevel(LIST_TIMES);
463 if (instruction->times > 1)
464 list->downlevel(LIST_TIMES);
465 return offset - start;
466 } else if (m > 0 && m > size_prob) {
467 size_prob = m;
469 temp++;
472 if (temp->opcode == -1) { /* didn't match any instruction */
473 if (size_prob == 1) /* would have matched, but for size */
474 error(ERR_NONFATAL, "operation size not specified");
475 else if (size_prob == 2)
476 error(ERR_NONFATAL, "mismatch in operand sizes");
477 else if (size_prob == 3)
478 error(ERR_NONFATAL, "no instruction for this cpu level");
479 else
480 error(ERR_NONFATAL,
481 "invalid combination of opcode and operands");
483 return 0;
486 long insn_size(long segment, long offset, int bits, unsigned long cp,
487 insn * instruction, efunc error)
489 struct itemplate *temp;
491 errfunc = error; /* to pass to other functions */
492 cpu = cp;
494 if (instruction->opcode == -1)
495 return 0;
497 if (instruction->opcode == I_DB ||
498 instruction->opcode == I_DW ||
499 instruction->opcode == I_DD ||
500 instruction->opcode == I_DQ || instruction->opcode == I_DT) {
501 extop *e;
502 long isize, osize, wsize = 0; /* placate gcc */
504 isize = 0;
505 switch (instruction->opcode) {
506 case I_DB:
507 wsize = 1;
508 break;
509 case I_DW:
510 wsize = 2;
511 break;
512 case I_DD:
513 wsize = 4;
514 break;
515 case I_DQ:
516 wsize = 8;
517 break;
518 case I_DT:
519 wsize = 10;
520 break;
523 for (e = instruction->eops; e; e = e->next) {
524 long align;
526 osize = 0;
527 if (e->type == EOT_DB_NUMBER)
528 osize = 1;
529 else if (e->type == EOT_DB_STRING)
530 osize = e->stringlen;
532 align = (-osize) % wsize;
533 if (align < 0)
534 align += wsize;
535 isize += osize + align;
537 return isize * instruction->times;
540 if (instruction->opcode == I_INCBIN) {
541 char fname[FILENAME_MAX];
542 FILE *fp;
543 long len;
544 char *prefix = "", *combine;
545 char **pPrevPath = NULL;
547 len = FILENAME_MAX - 1;
548 if (len > instruction->eops->stringlen)
549 len = instruction->eops->stringlen;
550 strncpy(fname, instruction->eops->stringval, len);
551 fname[len] = '\0';
553 while (1) { /* added by alexfru: 'incbin' uses include paths */
554 combine = nasm_malloc(strlen(prefix) + len + 1);
555 strcpy(combine, prefix);
556 strcat(combine, fname);
558 if ((fp = fopen(combine, "rb")) != NULL) {
559 nasm_free(combine);
560 break;
563 nasm_free(combine);
564 pPrevPath = pp_get_include_path_ptr(pPrevPath);
565 if (pPrevPath == NULL)
566 break;
567 prefix = *pPrevPath;
570 if (fp == NULL)
571 error(ERR_NONFATAL, "`incbin': unable to open file `%s'",
572 fname);
573 else if (fseek(fp, 0L, SEEK_END) < 0)
574 error(ERR_NONFATAL, "`incbin': unable to seek on file `%s'",
575 fname);
576 else {
577 len = ftell(fp);
578 fclose(fp);
579 if (instruction->eops->next) {
580 len -= instruction->eops->next->offset;
581 if (instruction->eops->next->next &&
582 len > instruction->eops->next->next->offset) {
583 len = instruction->eops->next->next->offset;
586 return instruction->times * len;
588 return 0; /* if we're here, there's an error */
591 temp = nasm_instructions[instruction->opcode];
592 while (temp->opcode != -1) {
593 int m = matches(temp, instruction);
594 if (m == 99)
595 m += jmp_match(segment, offset, bits, instruction, temp->code);
597 if (m == 100) {
598 /* we've matched an instruction. */
599 long isize;
600 const char *codes = temp->code;
601 int j;
603 isize = calcsize(segment, offset, bits, instruction, codes);
604 if (isize < 0)
605 return -1;
606 for (j = 0; j < instruction->nprefix; j++) {
607 if ((instruction->prefixes[j] != P_A16 &&
608 instruction->prefixes[j] != P_O16 && bits == 16) ||
609 (instruction->prefixes[j] != P_A32 &&
610 instruction->prefixes[j] != P_O32 && bits == 32)) {
611 isize++;
614 return isize * instruction->times;
616 temp++;
618 return -1; /* didn't match any instruction */
621 /* check that opn[op] is a signed byte of size 16 or 32,
622 and return the signed value*/
623 static int is_sbyte(insn * ins, int op, int size)
625 signed long v;
626 int ret;
628 ret = !(ins->forw_ref && ins->oprs[op].opflags) && /* dead in the water on forward reference or External */
629 optimizing >= 0 &&
630 !(ins->oprs[op].type & STRICT) &&
631 ins->oprs[op].wrt == NO_SEG && ins->oprs[op].segment == NO_SEG;
633 v = ins->oprs[op].offset;
634 if (size == 16)
635 v = (signed short)v; /* sign extend if 16 bits */
637 return ret && v >= -128L && v <= 127L;
640 static long calcsize(long segment, long offset, int bits,
641 insn * ins, const char *codes)
643 long length = 0;
644 unsigned char c;
646 (void)segment; /* Don't warn that this parameter is unused */
647 (void)offset; /* Don't warn that this parameter is unused */
649 while (*codes)
650 switch (c = *codes++) {
651 case 01:
652 case 02:
653 case 03:
654 codes += c, length += c;
655 break;
656 case 04:
657 case 05:
658 case 06:
659 case 07:
660 length++;
661 break;
662 case 010:
663 case 011:
664 case 012:
665 codes++, length++;
666 break;
667 case 017:
668 length++;
669 break;
670 case 014:
671 case 015:
672 case 016:
673 length++;
674 break;
675 case 020:
676 case 021:
677 case 022:
678 length++;
679 break;
680 case 024:
681 case 025:
682 case 026:
683 length++;
684 break;
685 case 030:
686 case 031:
687 case 032:
688 length += 2;
689 break;
690 case 034:
691 case 035:
692 case 036:
693 if (ins->oprs[c - 034].type & (BITS16 | BITS32))
694 length += (ins->oprs[c - 034].type & BITS16) ? 2 : 4;
695 else
696 length += (bits == 16) ? 2 : 4;
697 break;
698 case 037:
699 length += 2;
700 break;
701 case 040:
702 case 041:
703 case 042:
704 length += 4;
705 break;
706 case 044:
707 case 045:
708 case 046:
709 length += ((ins->oprs[c - 044].addr_size ?
710 ins->oprs[c - 044].addr_size : bits) ==
711 16 ? 2 : 4);
712 break;
713 case 050:
714 case 051:
715 case 052:
716 length++;
717 break;
718 case 060:
719 case 061:
720 case 062:
721 length += 2;
722 break;
723 case 064:
724 case 065:
725 case 066:
726 if (ins->oprs[c - 064].type & (BITS16 | BITS32))
727 length += (ins->oprs[c - 064].type & BITS16) ? 2 : 4;
728 else
729 length += (bits == 16) ? 2 : 4;
730 break;
731 case 070:
732 case 071:
733 case 072:
734 length += 4;
735 break;
736 case 0130:
737 case 0131:
738 case 0132:
739 length += is_sbyte(ins, c - 0130, 16) ? 1 : 2;
740 break;
741 case 0133:
742 case 0134:
743 case 0135:
744 codes += 2;
745 length++;
746 break;
747 case 0140:
748 case 0141:
749 case 0142:
750 length += is_sbyte(ins, c - 0140, 32) ? 1 : 4;
751 break;
752 case 0143:
753 case 0144:
754 case 0145:
755 codes += 2;
756 length++;
757 break;
758 case 0300:
759 case 0301:
760 case 0302:
761 length += chsize(&ins->oprs[c - 0300], bits);
762 break;
763 case 0310:
764 length += (bits == 32);
765 break;
766 case 0311:
767 length += (bits == 16);
768 break;
769 case 0312:
770 break;
771 case 0320:
772 length += (bits == 32);
773 break;
774 case 0321:
775 length += (bits == 16);
776 break;
777 case 0322:
778 break;
779 case 0330:
780 codes++, length++;
781 break;
782 case 0331:
783 case 0332:
784 break;
785 case 0333:
786 length++;
787 break;
788 case 0340:
789 case 0341:
790 case 0342:
791 if (ins->oprs[0].segment != NO_SEG)
792 errfunc(ERR_NONFATAL, "attempt to reserve non-constant"
793 " quantity of BSS space");
794 else
795 length += ins->oprs[0].offset << (c - 0340);
796 break;
797 case 0370:
798 case 0371:
799 case 0372:
800 break;
801 case 0373:
802 length++;
803 break;
804 default: /* can't do it by 'case' statements */
805 if (c >= 0100 && c <= 0277) { /* it's an EA */
806 ea ea_data;
807 if (!process_ea
808 (&ins->oprs[(c >> 3) & 7], &ea_data, bits, 0,
809 ins->forw_ref)) {
810 errfunc(ERR_NONFATAL, "invalid effective address");
811 return -1;
812 } else
813 length += ea_data.size;
814 } else
815 errfunc(ERR_PANIC, "internal instruction table corrupt"
816 ": instruction code 0x%02X given", c);
818 return length;
821 static void gencode(long segment, long offset, int bits,
822 insn * ins, const char *codes, long insn_end)
824 static char condval[] = { /* conditional opcodes */
825 0x7, 0x3, 0x2, 0x6, 0x2, 0x4, 0xF, 0xD, 0xC, 0xE, 0x6, 0x2,
826 0x3, 0x7, 0x3, 0x5, 0xE, 0xC, 0xD, 0xF, 0x1, 0xB, 0x9, 0x5,
827 0x0, 0xA, 0xA, 0xB, 0x8, 0x4
829 unsigned char c;
830 unsigned char bytes[4];
831 long data, size;
833 while (*codes)
834 switch (c = *codes++) {
835 case 01:
836 case 02:
837 case 03:
838 out(offset, segment, codes, OUT_RAWDATA + c, NO_SEG, NO_SEG);
839 codes += c;
840 offset += c;
841 break;
843 case 04:
844 case 06:
845 switch (ins->oprs[0].basereg) {
846 case R_CS:
847 bytes[0] = 0x0E + (c == 0x04 ? 1 : 0);
848 break;
849 case R_DS:
850 bytes[0] = 0x1E + (c == 0x04 ? 1 : 0);
851 break;
852 case R_ES:
853 bytes[0] = 0x06 + (c == 0x04 ? 1 : 0);
854 break;
855 case R_SS:
856 bytes[0] = 0x16 + (c == 0x04 ? 1 : 0);
857 break;
858 default:
859 errfunc(ERR_PANIC,
860 "bizarre 8086 segment register received");
862 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
863 offset++;
864 break;
866 case 05:
867 case 07:
868 switch (ins->oprs[0].basereg) {
869 case R_FS:
870 bytes[0] = 0xA0 + (c == 0x05 ? 1 : 0);
871 break;
872 case R_GS:
873 bytes[0] = 0xA8 + (c == 0x05 ? 1 : 0);
874 break;
875 default:
876 errfunc(ERR_PANIC,
877 "bizarre 386 segment register received");
879 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
880 offset++;
881 break;
883 case 010:
884 case 011:
885 case 012:
886 bytes[0] = *codes++ + regval(&ins->oprs[c - 010]);
887 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
888 offset += 1;
889 break;
891 case 017:
892 bytes[0] = 0;
893 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
894 offset += 1;
895 break;
897 case 014:
898 case 015:
899 case 016:
900 if (ins->oprs[c - 014].offset < -128
901 || ins->oprs[c - 014].offset > 127) {
902 errfunc(ERR_WARNING, "signed byte value exceeds bounds");
905 if (ins->oprs[c - 014].segment != NO_SEG) {
906 data = ins->oprs[c - 014].offset;
907 out(offset, segment, &data, OUT_ADDRESS + 1,
908 ins->oprs[c - 014].segment, ins->oprs[c - 014].wrt);
909 } else {
910 bytes[0] = ins->oprs[c - 014].offset;
911 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG,
912 NO_SEG);
914 offset += 1;
915 break;
917 case 020:
918 case 021:
919 case 022:
920 if (ins->oprs[c - 020].offset < -256
921 || ins->oprs[c - 020].offset > 255) {
922 errfunc(ERR_WARNING, "byte value exceeds bounds");
924 if (ins->oprs[c - 020].segment != NO_SEG) {
925 data = ins->oprs[c - 020].offset;
926 out(offset, segment, &data, OUT_ADDRESS + 1,
927 ins->oprs[c - 020].segment, ins->oprs[c - 020].wrt);
928 } else {
929 bytes[0] = ins->oprs[c - 020].offset;
930 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG,
931 NO_SEG);
933 offset += 1;
934 break;
936 case 024:
937 case 025:
938 case 026:
939 if (ins->oprs[c - 024].offset < 0
940 || ins->oprs[c - 024].offset > 255)
941 errfunc(ERR_WARNING, "unsigned byte value exceeds bounds");
942 if (ins->oprs[c - 024].segment != NO_SEG) {
943 data = ins->oprs[c - 024].offset;
944 out(offset, segment, &data, OUT_ADDRESS + 1,
945 ins->oprs[c - 024].segment, ins->oprs[c - 024].wrt);
946 } else {
947 bytes[0] = ins->oprs[c - 024].offset;
948 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG,
949 NO_SEG);
951 offset += 1;
952 break;
954 case 030:
955 case 031:
956 case 032:
957 if (ins->oprs[c - 030].segment == NO_SEG &&
958 ins->oprs[c - 030].wrt == NO_SEG &&
959 (ins->oprs[c - 030].offset < -65536L ||
960 ins->oprs[c - 030].offset > 65535L)) {
961 errfunc(ERR_WARNING, "word value exceeds bounds");
963 data = ins->oprs[c - 030].offset;
964 out(offset, segment, &data, OUT_ADDRESS + 2,
965 ins->oprs[c - 030].segment, ins->oprs[c - 030].wrt);
966 offset += 2;
967 break;
969 case 034:
970 case 035:
971 case 036:
972 if (ins->oprs[c - 034].type & (BITS16 | BITS32))
973 size = (ins->oprs[c - 034].type & BITS16) ? 2 : 4;
974 else
975 size = (bits == 16) ? 2 : 4;
976 data = ins->oprs[c - 034].offset;
977 if (size == 2 && (data < -65536L || data > 65535L))
978 errfunc(ERR_WARNING, "word value exceeds bounds");
979 out(offset, segment, &data, OUT_ADDRESS + size,
980 ins->oprs[c - 034].segment, ins->oprs[c - 034].wrt);
981 offset += size;
982 break;
984 case 037:
985 if (ins->oprs[0].segment == NO_SEG)
986 errfunc(ERR_NONFATAL, "value referenced by FAR is not"
987 " relocatable");
988 data = 0L;
989 out(offset, segment, &data, OUT_ADDRESS + 2,
990 outfmt->segbase(1 + ins->oprs[0].segment),
991 ins->oprs[0].wrt);
992 offset += 2;
993 break;
995 case 040:
996 case 041:
997 case 042:
998 data = ins->oprs[c - 040].offset;
999 out(offset, segment, &data, OUT_ADDRESS + 4,
1000 ins->oprs[c - 040].segment, ins->oprs[c - 040].wrt);
1001 offset += 4;
1002 break;
1004 case 044:
1005 case 045:
1006 case 046:
1007 data = ins->oprs[c - 044].offset;
1008 size = ((ins->oprs[c - 044].addr_size ?
1009 ins->oprs[c - 044].addr_size : bits) == 16 ? 2 : 4);
1010 if (size == 2 && (data < -65536L || data > 65535L))
1011 errfunc(ERR_WARNING, "word value exceeds bounds");
1012 out(offset, segment, &data, OUT_ADDRESS + size,
1013 ins->oprs[c - 044].segment, ins->oprs[c - 044].wrt);
1014 offset += size;
1015 break;
1017 case 050:
1018 case 051:
1019 case 052:
1020 if (ins->oprs[c - 050].segment != segment)
1021 errfunc(ERR_NONFATAL,
1022 "short relative jump outside segment");
1023 data = ins->oprs[c - 050].offset - insn_end;
1024 if (data > 127 || data < -128)
1025 errfunc(ERR_NONFATAL, "short jump is out of range");
1026 bytes[0] = data;
1027 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1028 offset += 1;
1029 break;
1031 case 060:
1032 case 061:
1033 case 062:
1034 if (ins->oprs[c - 060].segment != segment) {
1035 data = ins->oprs[c - 060].offset;
1036 out(offset, segment, &data,
1037 OUT_REL2ADR + insn_end - offset,
1038 ins->oprs[c - 060].segment, ins->oprs[c - 060].wrt);
1039 } else {
1040 data = ins->oprs[c - 060].offset - insn_end;
1041 out(offset, segment, &data,
1042 OUT_ADDRESS + 2, NO_SEG, NO_SEG);
1044 offset += 2;
1045 break;
1047 case 064:
1048 case 065:
1049 case 066:
1050 if (ins->oprs[c - 064].type & (BITS16 | BITS32))
1051 size = (ins->oprs[c - 064].type & BITS16) ? 2 : 4;
1052 else
1053 size = (bits == 16) ? 2 : 4;
1054 if (ins->oprs[c - 064].segment != segment) {
1055 long reltype = (size == 2 ? OUT_REL2ADR : OUT_REL4ADR);
1056 data = ins->oprs[c - 064].offset;
1057 out(offset, segment, &data, reltype + insn_end - offset,
1058 ins->oprs[c - 064].segment, ins->oprs[c - 064].wrt);
1059 } else {
1060 data = ins->oprs[c - 064].offset - insn_end;
1061 out(offset, segment, &data,
1062 OUT_ADDRESS + size, NO_SEG, NO_SEG);
1064 offset += size;
1065 break;
1067 case 070:
1068 case 071:
1069 case 072:
1070 if (ins->oprs[c - 070].segment != segment) {
1071 data = ins->oprs[c - 070].offset;
1072 out(offset, segment, &data,
1073 OUT_REL4ADR + insn_end - offset,
1074 ins->oprs[c - 070].segment, ins->oprs[c - 070].wrt);
1075 } else {
1076 data = ins->oprs[c - 070].offset - insn_end;
1077 out(offset, segment, &data,
1078 OUT_ADDRESS + 4, NO_SEG, NO_SEG);
1080 offset += 4;
1081 break;
1083 case 0130:
1084 case 0131:
1085 case 0132:
1086 data = ins->oprs[c - 0130].offset;
1087 if (is_sbyte(ins, c - 0130, 16)) {
1088 bytes[0] = data;
1089 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG,
1090 NO_SEG);
1091 offset++;
1092 } else {
1093 if (ins->oprs[c - 0130].segment == NO_SEG &&
1094 ins->oprs[c - 0130].wrt == NO_SEG &&
1095 (data < -65536L || data > 65535L)) {
1096 errfunc(ERR_WARNING, "word value exceeds bounds");
1098 out(offset, segment, &data, OUT_ADDRESS + 2,
1099 ins->oprs[c - 0130].segment, ins->oprs[c - 0130].wrt);
1100 offset += 2;
1102 break;
1104 case 0133:
1105 case 0134:
1106 case 0135:
1107 codes++;
1108 bytes[0] = *codes++;
1109 if (is_sbyte(ins, c - 0133, 16))
1110 bytes[0] |= 2; /* s-bit */
1111 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1112 offset++;
1113 break;
1115 case 0140:
1116 case 0141:
1117 case 0142:
1118 data = ins->oprs[c - 0140].offset;
1119 if (is_sbyte(ins, c - 0140, 32)) {
1120 bytes[0] = data;
1121 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG,
1122 NO_SEG);
1123 offset++;
1124 } else {
1125 out(offset, segment, &data, OUT_ADDRESS + 4,
1126 ins->oprs[c - 0140].segment, ins->oprs[c - 0140].wrt);
1127 offset += 4;
1129 break;
1131 case 0143:
1132 case 0144:
1133 case 0145:
1134 codes++;
1135 bytes[0] = *codes++;
1136 if (is_sbyte(ins, c - 0143, 32))
1137 bytes[0] |= 2; /* s-bit */
1138 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1139 offset++;
1140 break;
1142 case 0300:
1143 case 0301:
1144 case 0302:
1145 if (chsize(&ins->oprs[c - 0300], bits)) {
1146 *bytes = 0x67;
1147 out(offset, segment, bytes,
1148 OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1149 offset += 1;
1150 } else
1151 offset += 0;
1152 break;
1154 case 0310:
1155 if (bits == 32) {
1156 *bytes = 0x67;
1157 out(offset, segment, bytes,
1158 OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1159 offset += 1;
1160 } else
1161 offset += 0;
1162 break;
1164 case 0311:
1165 if (bits == 16) {
1166 *bytes = 0x67;
1167 out(offset, segment, bytes,
1168 OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1169 offset += 1;
1170 } else
1171 offset += 0;
1172 break;
1174 case 0312:
1175 break;
1177 case 0320:
1178 if (bits == 32) {
1179 *bytes = 0x66;
1180 out(offset, segment, bytes,
1181 OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1182 offset += 1;
1183 } else
1184 offset += 0;
1185 break;
1187 case 0321:
1188 if (bits == 16) {
1189 *bytes = 0x66;
1190 out(offset, segment, bytes,
1191 OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1192 offset += 1;
1193 } else
1194 offset += 0;
1195 break;
1197 case 0322:
1198 break;
1200 case 0330:
1201 *bytes = *codes++ ^ condval[ins->condition];
1202 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1203 offset += 1;
1204 break;
1206 case 0331:
1207 case 0332:
1208 break;
1210 case 0333:
1211 *bytes = 0xF3;
1212 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1213 offset += 1;
1214 break;
1216 case 0340:
1217 case 0341:
1218 case 0342:
1219 if (ins->oprs[0].segment != NO_SEG)
1220 errfunc(ERR_PANIC, "non-constant BSS size in pass two");
1221 else {
1222 long size = ins->oprs[0].offset << (c - 0340);
1223 if (size > 0)
1224 out(offset, segment, NULL,
1225 OUT_RESERVE + size, NO_SEG, NO_SEG);
1226 offset += size;
1228 break;
1230 case 0370:
1231 case 0371:
1232 case 0372:
1233 break;
1235 case 0373:
1236 *bytes = bits == 16 ? 3 : 5;
1237 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1238 offset += 1;
1239 break;
1241 default: /* can't do it by 'case' statements */
1242 if (c >= 0100 && c <= 0277) { /* it's an EA */
1243 ea ea_data;
1244 int rfield;
1245 unsigned char *p;
1246 long s;
1248 if (c <= 0177) /* pick rfield from operand b */
1249 rfield = regval(&ins->oprs[c & 7]);
1250 else /* rfield is constant */
1251 rfield = c & 7;
1253 if (!process_ea
1254 (&ins->oprs[(c >> 3) & 7], &ea_data, bits, rfield,
1255 ins->forw_ref)) {
1256 errfunc(ERR_NONFATAL, "invalid effective address");
1259 p = bytes;
1260 *p++ = ea_data.modrm;
1261 if (ea_data.sib_present)
1262 *p++ = ea_data.sib;
1264 s = p - bytes;
1265 out(offset, segment, bytes, OUT_RAWDATA + s,
1266 NO_SEG, NO_SEG);
1268 switch (ea_data.bytes) {
1269 case 0:
1270 break;
1271 case 1:
1272 if (ins->oprs[(c >> 3) & 7].segment != NO_SEG) {
1273 data = ins->oprs[(c >> 3) & 7].offset;
1274 out(offset, segment, &data, OUT_ADDRESS + 1,
1275 ins->oprs[(c >> 3) & 7].segment,
1276 ins->oprs[(c >> 3) & 7].wrt);
1277 } else {
1278 *bytes = ins->oprs[(c >> 3) & 7].offset;
1279 out(offset, segment, bytes, OUT_RAWDATA + 1,
1280 NO_SEG, NO_SEG);
1282 s++;
1283 break;
1284 case 2:
1285 case 4:
1286 data = ins->oprs[(c >> 3) & 7].offset;
1287 out(offset, segment, &data,
1288 OUT_ADDRESS + ea_data.bytes,
1289 ins->oprs[(c >> 3) & 7].segment,
1290 ins->oprs[(c >> 3) & 7].wrt);
1291 s += ea_data.bytes;
1292 break;
1294 offset += s;
1295 } else
1296 errfunc(ERR_PANIC, "internal instruction table corrupt"
1297 ": instruction code 0x%02X given", c);
1301 #include "regvals.c"
1303 static int regval(operand * o)
1305 if (o->basereg < EXPR_REG_START || o->basereg >= REG_ENUM_LIMIT) {
1306 errfunc(ERR_PANIC, "invalid operand passed to regval()");
1308 return regvals[o->basereg];
1311 static int matches(struct itemplate *itemp, insn * instruction)
1313 int i, size[3], asize, oprs, ret;
1315 ret = 100;
1318 * Check the opcode
1320 if (itemp->opcode != instruction->opcode)
1321 return 0;
1324 * Count the operands
1326 if (itemp->operands != instruction->operands)
1327 return 0;
1330 * Check that no spurious colons or TOs are present
1332 for (i = 0; i < itemp->operands; i++)
1333 if (instruction->oprs[i].type & ~itemp->opd[i] & (COLON | TO))
1334 return 0;
1337 * Check that the operand flags all match up
1339 for (i = 0; i < itemp->operands; i++)
1340 if (itemp->opd[i] & ~instruction->oprs[i].type ||
1341 ((itemp->opd[i] & SIZE_MASK) &&
1342 ((itemp->opd[i] ^ instruction->oprs[i].type) & SIZE_MASK))) {
1343 if ((itemp->opd[i] & ~instruction->oprs[i].type & NON_SIZE) ||
1344 (instruction->oprs[i].type & SIZE_MASK))
1345 return 0;
1346 else
1347 /* ret = 1; */
1348 return 1;
1352 * Check operand sizes
1354 if (itemp->flags & IF_ARMASK) {
1355 size[0] = size[1] = size[2] = 0;
1357 switch (itemp->flags & IF_ARMASK) {
1358 case IF_AR0:
1359 i = 0;
1360 break;
1361 case IF_AR1:
1362 i = 1;
1363 break;
1364 case IF_AR2:
1365 i = 2;
1366 break;
1367 default:
1368 break; /* Shouldn't happen */
1370 if (itemp->flags & IF_SB) {
1371 size[i] = BITS8;
1372 } else if (itemp->flags & IF_SW) {
1373 size[i] = BITS16;
1374 } else if (itemp->flags & IF_SD) {
1375 size[i] = BITS32;
1377 } else {
1378 asize = 0;
1379 if (itemp->flags & IF_SB) {
1380 asize = BITS8;
1381 oprs = itemp->operands;
1382 } else if (itemp->flags & IF_SW) {
1383 asize = BITS16;
1384 oprs = itemp->operands;
1385 } else if (itemp->flags & IF_SD) {
1386 asize = BITS32;
1387 oprs = itemp->operands;
1389 size[0] = size[1] = size[2] = asize;
1392 if (itemp->flags & (IF_SM | IF_SM2)) {
1393 oprs = (itemp->flags & IF_SM2 ? 2 : itemp->operands);
1394 asize = 0;
1395 for (i = 0; i < oprs; i++) {
1396 if ((asize = itemp->opd[i] & SIZE_MASK) != 0) {
1397 int j;
1398 for (j = 0; j < oprs; j++)
1399 size[j] = asize;
1400 break;
1403 } else {
1404 oprs = itemp->operands;
1407 for (i = 0; i < itemp->operands; i++)
1408 if (!(itemp->opd[i] & SIZE_MASK) &&
1409 (instruction->oprs[i].type & SIZE_MASK & ~size[i]))
1410 /* ret = 2; */
1411 return 2;
1414 * Check template is okay at the set cpu level
1416 if ((itemp->flags & IF_PLEVEL) > cpu)
1417 return 3;
1420 * Check if special handling needed for Jumps
1422 if ((unsigned char)(itemp->code[0]) >= 0370)
1423 return 99;
1425 return ret;
1428 static ea *process_ea(operand * input, ea * output, int addrbits,
1429 int rfield, int forw_ref)
1431 if (!(REGISTER & ~input->type)) { /* it's a single register */
1432 static int regs[] = {
1433 R_AL, R_CL, R_DL, R_BL, R_AH, R_CH, R_DH, R_BH,
1434 R_AX, R_CX, R_DX, R_BX, R_SP, R_BP, R_SI, R_DI,
1435 R_EAX, R_ECX, R_EDX, R_EBX, R_ESP, R_EBP, R_ESI, R_EDI,
1436 R_MM0, R_MM1, R_MM2, R_MM3, R_MM4, R_MM5, R_MM6, R_MM7,
1437 R_XMM0, R_XMM1, R_XMM2, R_XMM3, R_XMM4, R_XMM5, R_XMM6, R_XMM7
1439 int i;
1441 for (i = 0; i < elements(regs); i++)
1442 if (input->basereg == regs[i])
1443 break;
1444 if (i < elements(regs)) {
1445 output->sib_present = FALSE; /* no SIB necessary */
1446 output->bytes = 0; /* no offset necessary either */
1447 output->modrm = 0xC0 | (rfield << 3) | (i & 7);
1448 } else
1449 return NULL;
1450 } else { /* it's a memory reference */
1451 if (input->basereg == -1
1452 && (input->indexreg == -1 || input->scale == 0)) {
1453 /* it's a pure offset */
1454 if (input->addr_size)
1455 addrbits = input->addr_size;
1456 output->sib_present = FALSE;
1457 output->bytes = (addrbits == 32 ? 4 : 2);
1458 output->modrm = (addrbits == 32 ? 5 : 6) | (rfield << 3);
1459 } else { /* it's an indirection */
1460 int i = input->indexreg, b = input->basereg, s = input->scale;
1461 long o = input->offset, seg = input->segment;
1462 int hb = input->hintbase, ht = input->hinttype;
1463 int t;
1465 if (s == 0)
1466 i = -1; /* make this easy, at least */
1468 if (i == R_EAX || i == R_EBX || i == R_ECX || i == R_EDX
1469 || i == R_EBP || i == R_ESP || i == R_ESI || i == R_EDI
1470 || b == R_EAX || b == R_EBX || b == R_ECX || b == R_EDX
1471 || b == R_EBP || b == R_ESP || b == R_ESI || b == R_EDI) {
1472 /* it must be a 32-bit memory reference. Firstly we have
1473 * to check that all registers involved are type Exx. */
1474 if (i != -1 && i != R_EAX && i != R_EBX && i != R_ECX
1475 && i != R_EDX && i != R_EBP && i != R_ESP && i != R_ESI
1476 && i != R_EDI)
1477 return NULL;
1478 if (b != -1 && b != R_EAX && b != R_EBX && b != R_ECX
1479 && b != R_EDX && b != R_EBP && b != R_ESP && b != R_ESI
1480 && b != R_EDI)
1481 return NULL;
1483 /* While we're here, ensure the user didn't specify WORD. */
1484 if (input->addr_size == 16)
1485 return NULL;
1487 /* now reorganise base/index */
1488 if (s == 1 && b != i && b != -1 && i != -1 &&
1489 ((hb == b && ht == EAH_NOTBASE)
1490 || (hb == i && ht == EAH_MAKEBASE)))
1491 t = b, b = i, i = t; /* swap if hints say so */
1492 if (b == i) /* convert EAX+2*EAX to 3*EAX */
1493 b = -1, s++;
1494 if (b == -1 && s == 1 && !(hb == i && ht == EAH_NOTBASE))
1495 b = i, i = -1; /* make single reg base, unless hint */
1496 if (((s == 2 && i != R_ESP
1497 && !(input->eaflags & EAF_TIMESTWO)) || s == 3
1498 || s == 5 || s == 9) && b == -1)
1499 b = i, s--; /* convert 3*EAX to EAX+2*EAX */
1500 if (i == -1 && b != R_ESP
1501 && (input->eaflags & EAF_TIMESTWO))
1502 i = b, b = -1, s = 1;
1503 /* convert [NOSPLIT EAX] to sib format with 0x0 displacement */
1504 if (s == 1 && i == R_ESP) /* swap ESP into base if scale is 1 */
1505 i = b, b = R_ESP;
1506 if (i == R_ESP
1507 || (s != 1 && s != 2 && s != 4 && s != 8 && i != -1))
1508 return NULL; /* wrong, for various reasons */
1510 if (i == -1 && b != R_ESP) { /* no SIB needed */
1511 int mod, rm;
1512 switch (b) {
1513 case R_EAX:
1514 rm = 0;
1515 break;
1516 case R_ECX:
1517 rm = 1;
1518 break;
1519 case R_EDX:
1520 rm = 2;
1521 break;
1522 case R_EBX:
1523 rm = 3;
1524 break;
1525 case R_EBP:
1526 rm = 5;
1527 break;
1528 case R_ESI:
1529 rm = 6;
1530 break;
1531 case R_EDI:
1532 rm = 7;
1533 break;
1534 case -1:
1535 rm = 5;
1536 break;
1537 default: /* should never happen */
1538 return NULL;
1540 if (b == -1 || (b != R_EBP && o == 0 &&
1541 seg == NO_SEG && !forw_ref &&
1542 !(input->eaflags &
1543 (EAF_BYTEOFFS | EAF_WORDOFFS))))
1544 mod = 0;
1545 else if (input->eaflags & EAF_BYTEOFFS ||
1546 (o >= -128 && o <= 127 && seg == NO_SEG
1547 && !forw_ref
1548 && !(input->eaflags & EAF_WORDOFFS))) {
1549 mod = 1;
1550 } else
1551 mod = 2;
1553 output->sib_present = FALSE;
1554 output->bytes = (b == -1 || mod == 2 ? 4 : mod);
1555 output->modrm = (mod << 6) | (rfield << 3) | rm;
1556 } else { /* we need a SIB */
1557 int mod, scale, index, base;
1559 switch (b) {
1560 case R_EAX:
1561 base = 0;
1562 break;
1563 case R_ECX:
1564 base = 1;
1565 break;
1566 case R_EDX:
1567 base = 2;
1568 break;
1569 case R_EBX:
1570 base = 3;
1571 break;
1572 case R_ESP:
1573 base = 4;
1574 break;
1575 case R_EBP:
1576 case -1:
1577 base = 5;
1578 break;
1579 case R_ESI:
1580 base = 6;
1581 break;
1582 case R_EDI:
1583 base = 7;
1584 break;
1585 default: /* then what the smeg is it? */
1586 return NULL; /* panic */
1589 switch (i) {
1590 case R_EAX:
1591 index = 0;
1592 break;
1593 case R_ECX:
1594 index = 1;
1595 break;
1596 case R_EDX:
1597 index = 2;
1598 break;
1599 case R_EBX:
1600 index = 3;
1601 break;
1602 case -1:
1603 index = 4;
1604 break;
1605 case R_EBP:
1606 index = 5;
1607 break;
1608 case R_ESI:
1609 index = 6;
1610 break;
1611 case R_EDI:
1612 index = 7;
1613 break;
1614 default: /* then what the smeg is it? */
1615 return NULL; /* panic */
1618 if (i == -1)
1619 s = 1;
1620 switch (s) {
1621 case 1:
1622 scale = 0;
1623 break;
1624 case 2:
1625 scale = 1;
1626 break;
1627 case 4:
1628 scale = 2;
1629 break;
1630 case 8:
1631 scale = 3;
1632 break;
1633 default: /* then what the smeg is it? */
1634 return NULL; /* panic */
1637 if (b == -1 || (b != R_EBP && o == 0 &&
1638 seg == NO_SEG && !forw_ref &&
1639 !(input->eaflags &
1640 (EAF_BYTEOFFS | EAF_WORDOFFS))))
1641 mod = 0;
1642 else if (input->eaflags & EAF_BYTEOFFS ||
1643 (o >= -128 && o <= 127 && seg == NO_SEG
1644 && !forw_ref
1645 && !(input->eaflags & EAF_WORDOFFS)))
1646 mod = 1;
1647 else
1648 mod = 2;
1650 output->sib_present = TRUE;
1651 output->bytes = (b == -1 || mod == 2 ? 4 : mod);
1652 output->modrm = (mod << 6) | (rfield << 3) | 4;
1653 output->sib = (scale << 6) | (index << 3) | base;
1655 } else { /* it's 16-bit */
1656 int mod, rm;
1658 /* check all registers are BX, BP, SI or DI */
1659 if ((b != -1 && b != R_BP && b != R_BX && b != R_SI
1660 && b != R_DI) || (i != -1 && i != R_BP && i != R_BX
1661 && i != R_SI && i != R_DI))
1662 return NULL;
1664 /* ensure the user didn't specify DWORD */
1665 if (input->addr_size == 32)
1666 return NULL;
1668 if (s != 1 && i != -1)
1669 return NULL; /* no can do, in 16-bit EA */
1670 if (b == -1 && i != -1) {
1671 int tmp = b;
1672 b = i;
1673 i = tmp;
1674 } /* swap */
1675 if ((b == R_SI || b == R_DI) && i != -1) {
1676 int tmp = b;
1677 b = i;
1678 i = tmp;
1680 /* have BX/BP as base, SI/DI index */
1681 if (b == i)
1682 return NULL; /* shouldn't ever happen, in theory */
1683 if (i != -1 && b != -1 &&
1684 (i == R_BP || i == R_BX || b == R_SI || b == R_DI))
1685 return NULL; /* invalid combinations */
1686 if (b == -1) /* pure offset: handled above */
1687 return NULL; /* so if it gets to here, panic! */
1689 rm = -1;
1690 if (i != -1)
1691 switch (i * 256 + b) {
1692 case R_SI * 256 + R_BX:
1693 rm = 0;
1694 break;
1695 case R_DI * 256 + R_BX:
1696 rm = 1;
1697 break;
1698 case R_SI * 256 + R_BP:
1699 rm = 2;
1700 break;
1701 case R_DI * 256 + R_BP:
1702 rm = 3;
1703 break;
1704 } else
1705 switch (b) {
1706 case R_SI:
1707 rm = 4;
1708 break;
1709 case R_DI:
1710 rm = 5;
1711 break;
1712 case R_BP:
1713 rm = 6;
1714 break;
1715 case R_BX:
1716 rm = 7;
1717 break;
1719 if (rm == -1) /* can't happen, in theory */
1720 return NULL; /* so panic if it does */
1722 if (o == 0 && seg == NO_SEG && !forw_ref && rm != 6 &&
1723 !(input->eaflags & (EAF_BYTEOFFS | EAF_WORDOFFS)))
1724 mod = 0;
1725 else if (input->eaflags & EAF_BYTEOFFS ||
1726 (o >= -128 && o <= 127 && seg == NO_SEG
1727 && !forw_ref
1728 && !(input->eaflags & EAF_WORDOFFS)))
1729 mod = 1;
1730 else
1731 mod = 2;
1733 output->sib_present = FALSE; /* no SIB - it's 16-bit */
1734 output->bytes = mod; /* bytes of offset needed */
1735 output->modrm = (mod << 6) | (rfield << 3) | rm;
1739 output->size = 1 + output->sib_present + output->bytes;
1740 return output;
1743 static int chsize(operand * input, int addrbits)
1745 if (!(MEMORY & ~input->type)) {
1746 int i = input->indexreg, b = input->basereg;
1748 if (input->scale == 0)
1749 i = -1;
1751 if (i == -1 && b == -1) /* pure offset */
1752 return (input->addr_size != 0 && input->addr_size != addrbits);
1754 if (i == R_EAX || i == R_EBX || i == R_ECX || i == R_EDX
1755 || i == R_EBP || i == R_ESP || i == R_ESI || i == R_EDI
1756 || b == R_EAX || b == R_EBX || b == R_ECX || b == R_EDX
1757 || b == R_EBP || b == R_ESP || b == R_ESI || b == R_EDI)
1758 return (addrbits == 16);
1759 else
1760 return (addrbits == 32);
1761 } else
1762 return 0;