fix comment in test/lnxhello.asm
[nasm.git] / assemble.c
blob6da584a556fc4fe8f20a3c417f15b2565e621227
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"
78 extern struct itemplate *nasm_instructions[];
80 typedef struct {
81 int sib_present; /* is a SIB byte necessary? */
82 int bytes; /* # of bytes of offset needed */
83 int size; /* lazy - this is sib+bytes+1 */
84 unsigned char modrm, sib; /* the bytes themselves */
85 } ea;
87 static unsigned long cpu; /* cpu level received from nasm.c */
88 static efunc errfunc;
89 static struct ofmt *outfmt;
90 static ListGen *list;
92 static long calcsize (long, long, int, insn *, const char *);
93 static void gencode (long, long, int, insn *, const char *, long);
94 static int regval (operand *o);
95 static int matches (struct itemplate *, insn *);
96 static ea * process_ea (operand *, ea *, int, int, int);
97 static int chsize (operand *, int);
100 * This routine wrappers the real output format's output routine,
101 * in order to pass a copy of the data off to the listing file
102 * generator at the same time.
104 static void out (long offset, long segto, const void *data, unsigned long type,
105 long segment, long wrt)
107 long lineno;
108 char *lnfname = NULL;
110 if ((type & OUT_TYPMASK) == OUT_ADDRESS) {
111 if (segment != NO_SEG || wrt != NO_SEG) {
113 * This address is relocated. We must write it as
114 * OUT_ADDRESS, so there's no work to be done here.
116 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);
128 else {
129 WRITESHORT (q, * (long *) data);
130 list->output (offset, p, OUT_RAWDATA+2);
134 else if ((type & OUT_TYPMASK) == OUT_RAWDATA) {
135 list->output (offset, data, type);
137 else if ((type & OUT_TYPMASK) == OUT_RESERVE) {
138 list->output (offset, NULL, type);
140 else if ((type & OUT_TYPMASK) == OUT_REL2ADR ||
141 (type & OUT_TYPMASK) == OUT_REL4ADR) {
142 list->output (offset, data, type);
145 if (src_get(&lineno,&lnfname))
147 outfmt->current_dfmt->linenum(lnfname,lineno,segto);
148 if (lnfname) nasm_free(lnfname);
151 outfmt->output (segto, data, type, segment, wrt);
154 static int jmp_match (long segment, long offset, int bits,
155 insn *ins, const char *code)
156 { long isize;
157 unsigned char c = code[0];
160 if (c != 0370 && c != 0371) return 0;
161 if (ins->oprs[0].opflags & OPFLAG_FORWARD) {
162 if ((optimizing<0 || (ins->oprs[0].type & STRICT))
163 && c==0370) return 1;
164 else return (pass0==0); /* match a forward reference */
166 isize = calcsize (segment, offset, bits, ins, code);
167 if (ins->oprs[0].segment != segment) return 0;
168 isize = ins->oprs[0].offset - offset - isize; /* isize is now the delta */
169 if (isize >= -128L && isize <= 127L) return 1; /* it is byte size */
171 return 0;
175 long assemble (long segment, long offset, int bits, unsigned long cp,
176 insn *instruction, struct ofmt *output, efunc error,
177 ListGen *listgen)
179 struct itemplate *temp;
180 int j;
181 int size_prob;
182 long insn_end;
183 long itimes;
184 long start = offset;
185 long wsize = 0; /* size for DB etc. */
187 errfunc = error; /* to pass to other functions */
188 cpu = cp;
189 outfmt = output; /* likewise */
190 list = listgen; /* and again */
192 switch (instruction->opcode)
194 case -1: return 0;
195 case I_DB: wsize = 1; break;
196 case I_DW: wsize = 2; break;
197 case I_DD: wsize = 4; break;
198 case I_DQ: wsize = 8; break;
199 case I_DT: wsize = 10; break;
202 if (wsize) {
203 extop * e;
204 long t = instruction->times;
205 if (t < 0)
206 errfunc(ERR_PANIC, "instruction->times < 0 (%ld) in assemble()",t);
208 while (t--) /* repeat TIMES times */
210 for (e = instruction->eops; e; e = e->next)
212 if (e->type == EOT_DB_NUMBER)
214 if (wsize == 1) {
215 if (e->segment != NO_SEG)
216 errfunc (ERR_NONFATAL,
217 "one-byte relocation attempted");
218 else {
219 unsigned char out_byte = e->offset;
220 out (offset, segment, &out_byte, OUT_RAWDATA+1,
221 NO_SEG, NO_SEG);
224 else if (wsize > 5) {
225 errfunc (ERR_NONFATAL, "integer supplied to a D%c"
226 " instruction", wsize==8 ? 'Q' : 'T');
228 else
229 out (offset, segment, &e->offset,
230 OUT_ADDRESS+wsize, e->segment,
231 e->wrt);
232 offset += wsize;
234 else if (e->type == EOT_DB_STRING)
236 int align;
238 out (offset, segment, e->stringval,
239 OUT_RAWDATA+e->stringlen, NO_SEG, NO_SEG);
240 align = e->stringlen % wsize;
242 if (align) {
243 align = wsize - align;
244 out (offset, segment, "\0\0\0\0\0\0\0\0",
245 OUT_RAWDATA+align, NO_SEG, NO_SEG);
247 offset += e->stringlen + align;
250 if (t > 0 && t == instruction->times-1)
253 * Dummy call to list->output to give the offset to the
254 * listing module.
256 list->output (offset, NULL, OUT_RAWDATA);
257 list->uplevel (LIST_TIMES);
260 if (instruction->times > 1)
261 list->downlevel (LIST_TIMES);
262 return offset - start;
265 if (instruction->opcode == I_INCBIN)
267 static char fname[FILENAME_MAX];
268 FILE * fp;
269 long len;
271 len = FILENAME_MAX-1;
272 if (len > instruction->eops->stringlen)
273 len = instruction->eops->stringlen;
274 strncpy (fname, instruction->eops->stringval, len);
275 fname[len] = '\0';
277 if ( (fp = fopen(fname, "rb")) == NULL)
278 error (ERR_NONFATAL, "`incbin': unable to open file `%s'", fname);
279 else if (fseek(fp, 0L, SEEK_END) < 0)
280 error (ERR_NONFATAL, "`incbin': unable to seek on file `%s'",
281 fname);
282 else
284 static char buf[2048];
285 long t = instruction->times;
286 long base = 0;
288 len = ftell (fp);
289 if (instruction->eops->next) {
290 base = instruction->eops->next->offset;
291 len -= base;
292 if (instruction->eops->next->next &&
293 len > instruction->eops->next->next->offset)
294 len = instruction->eops->next->next->offset;
297 * Dummy call to list->output to give the offset to the
298 * listing module.
300 list->output (offset, NULL, OUT_RAWDATA);
301 list->uplevel(LIST_INCBIN);
302 while (t--)
304 long l;
306 fseek (fp, base, SEEK_SET);
307 l = len;
308 while (l > 0) {
309 long m = fread (buf, 1, (l>sizeof(buf)?sizeof(buf):l),
310 fp);
311 if (!m) {
313 * This shouldn't happen unless the file
314 * actually changes while we are reading
315 * it.
317 error (ERR_NONFATAL, "`incbin': unexpected EOF while"
318 " reading file `%s'", fname);
319 t=0; /* Try to exit cleanly */
320 break;
322 out (offset, segment, buf, OUT_RAWDATA+m,
323 NO_SEG, NO_SEG);
324 l -= m;
327 list->downlevel(LIST_INCBIN);
328 if (instruction->times > 1) {
330 * Dummy call to list->output to give the offset to the
331 * listing module.
333 list->output (offset, NULL, OUT_RAWDATA);
334 list->uplevel(LIST_TIMES);
335 list->downlevel(LIST_TIMES);
337 fclose (fp);
338 return instruction->times * len;
340 return 0; /* if we're here, there's an error */
343 size_prob = FALSE;
344 temp = nasm_instructions[instruction->opcode];
345 while (temp->opcode != -1) {
346 int m = matches (temp, instruction);
347 if (m == 99)
348 m += jmp_match(segment, offset, bits, instruction, temp->code);
350 if (m == 100) /* matches! */
352 const char *codes = temp->code;
353 long insn_size = calcsize(segment, offset, bits,
354 instruction, codes);
355 itimes = instruction->times;
356 if (insn_size < 0) /* shouldn't be, on pass two */
357 error (ERR_PANIC, "errors made it through from pass one");
358 else while (itimes--) {
359 for (j=0; j<instruction->nprefix; j++) {
360 unsigned char c=0;
361 switch (instruction->prefixes[j]) {
362 case P_LOCK:
363 c = 0xF0; break;
364 case P_REPNE: case P_REPNZ:
365 c = 0xF2; break;
366 case P_REPE: case P_REPZ: case P_REP:
367 c = 0xF3; break;
368 case R_CS: c = 0x2E; break;
369 case R_DS: c = 0x3E; break;
370 case R_ES: c = 0x26; break;
371 case R_FS: c = 0x64; break;
372 case R_GS: c = 0x65; break;
373 case R_SS: c = 0x36; break;
374 case R_SEGR6:
375 case R_SEGR7:
376 error (ERR_NONFATAL, "segr6 and segr7 cannot be used as prefixes");
377 break;
378 case P_A16:
379 if (bits != 16)
380 c = 0x67;
381 break;
382 case P_A32:
383 if (bits != 32)
384 c = 0x67;
385 break;
386 case P_O16:
387 if (bits != 16)
388 c = 0x66;
389 break;
390 case P_O32:
391 if (bits != 32)
392 c = 0x66;
393 break;
394 default:
395 error (ERR_PANIC,
396 "invalid instruction prefix");
398 if (c != 0) {
399 out (offset, segment, &c, OUT_RAWDATA+1,
400 NO_SEG, NO_SEG);
401 offset++;
404 insn_end = offset + insn_size;
405 gencode (segment, offset, bits, instruction, codes, insn_end);
406 offset += insn_size;
407 if (itimes > 0 && itimes == instruction->times-1) {
409 * Dummy call to list->output to give the offset to the
410 * listing module.
412 list->output (offset, NULL, OUT_RAWDATA);
413 list->uplevel (LIST_TIMES);
416 if (instruction->times > 1)
417 list->downlevel (LIST_TIMES);
418 return offset - start;
419 } else if (m > 0 && m > size_prob) {
420 size_prob = m;
422 temp++;
425 if (temp->opcode == -1) { /* didn't match any instruction */
426 if (size_prob == 1) /* would have matched, but for size */
427 error (ERR_NONFATAL, "operation size not specified");
428 else if (size_prob == 2)
429 error (ERR_NONFATAL, "mismatch in operand sizes");
430 else if (size_prob == 3)
431 error (ERR_NONFATAL, "no instruction for this cpu level");
432 else
433 error (ERR_NONFATAL,
434 "invalid combination of opcode and operands");
436 return 0;
439 long insn_size (long segment, long offset, int bits, unsigned long cp,
440 insn *instruction, efunc error)
442 struct itemplate *temp;
444 errfunc = error; /* to pass to other functions */
445 cpu = cp;
447 if (instruction->opcode == -1)
448 return 0;
450 if (instruction->opcode == I_DB ||
451 instruction->opcode == I_DW ||
452 instruction->opcode == I_DD ||
453 instruction->opcode == I_DQ ||
454 instruction->opcode == I_DT)
456 extop *e;
457 long isize, osize, wsize = 0; /* placate gcc */
459 isize = 0;
460 switch (instruction->opcode)
462 case I_DB: wsize = 1; break;
463 case I_DW: wsize = 2; break;
464 case I_DD: wsize = 4; break;
465 case I_DQ: wsize = 8; break;
466 case I_DT: wsize = 10; break;
469 for (e = instruction->eops; e; e = e->next)
471 long align;
473 osize = 0;
474 if (e->type == EOT_DB_NUMBER)
475 osize = 1;
476 else if (e->type == EOT_DB_STRING)
477 osize = e->stringlen;
479 align = (-osize) % wsize;
480 if (align < 0)
481 align += wsize;
482 isize += osize + align;
484 return isize * instruction->times;
487 if (instruction->opcode == I_INCBIN)
489 char fname[FILENAME_MAX];
490 FILE * fp;
491 long len;
493 len = FILENAME_MAX-1;
494 if (len > instruction->eops->stringlen)
495 len = instruction->eops->stringlen;
496 strncpy (fname, instruction->eops->stringval, len);
497 fname[len] = '\0';
498 if ( (fp = fopen(fname, "rb")) == NULL )
499 error (ERR_NONFATAL, "`incbin': unable to open file `%s'", fname);
500 else if (fseek(fp, 0L, SEEK_END) < 0)
501 error (ERR_NONFATAL, "`incbin': unable to seek on file `%s'",
502 fname);
503 else
505 len = ftell (fp);
506 fclose (fp);
507 if (instruction->eops->next)
509 len -= instruction->eops->next->offset;
510 if (instruction->eops->next->next &&
511 len > instruction->eops->next->next->offset)
513 len = instruction->eops->next->next->offset;
516 return instruction->times * len;
518 return 0; /* if we're here, there's an error */
521 temp = nasm_instructions[instruction->opcode];
522 while (temp->opcode != -1) {
523 int m = matches(temp, instruction);
524 if (m == 99)
525 m += jmp_match(segment, offset, bits, instruction, temp->code);
527 if (m == 100) {
528 /* we've matched an instruction. */
529 long isize;
530 const char * codes = temp->code;
531 int j;
533 isize = calcsize(segment, offset, bits, instruction, codes);
534 if (isize < 0)
535 return -1;
536 for (j = 0; j < instruction->nprefix; j++)
538 if ((instruction->prefixes[j] != P_A16 &&
539 instruction->prefixes[j] != P_O16 && bits==16) ||
540 (instruction->prefixes[j] != P_A32 &&
541 instruction->prefixes[j] != P_O32 && bits==32))
543 isize++;
546 return isize * instruction->times;
548 temp++;
550 return -1; /* didn't match any instruction */
554 /* check that opn[op] is a signed byte of size 16 or 32,
555 and return the signed value*/
556 static int is_sbyte (insn *ins, int op, int size)
558 signed long v;
559 int ret;
561 ret = !(ins->forw_ref && ins->oprs[op].opflags ) && /* dead in the water on forward reference or External */
562 optimizing>=0 &&
563 !(ins->oprs[op].type & STRICT) &&
564 ins->oprs[op].wrt==NO_SEG && ins->oprs[op].segment==NO_SEG;
566 v = ins->oprs[op].offset;
567 if (size==16) v = (signed short)v; /* sign extend if 16 bits */
569 return ret && v>=-128L && v<=127L;
572 static long calcsize (long segment, long offset, int bits,
573 insn *ins, const char *codes)
575 long length = 0;
576 unsigned char c;
578 (void) segment; /* Don't warn that this parameter is unused */
579 (void) offset; /* Don't warn that this parameter is unused */
581 while (*codes) switch (c = *codes++) {
582 case 01: case 02: case 03:
583 codes += c, length += c; break;
584 case 04: case 05: case 06: case 07:
585 length++; break;
586 case 010: case 011: case 012:
587 codes++, length++; break;
588 case 017:
589 length++; break;
590 case 014: case 015: case 016:
591 length++; break;
592 case 020: case 021: case 022:
593 length++; break;
594 case 024: case 025: case 026:
595 length++; break;
596 case 030: case 031: case 032:
597 length += 2; break;
598 case 034: case 035: case 036:
599 if ( ins->oprs[c-034].type & (BITS16|BITS32) )
600 length += (ins->oprs[c-034].type & BITS16) ? 2 : 4;
601 else
602 length += (bits == 16) ? 2 : 4;
603 break;
604 case 037:
605 length += 2; break;
606 case 040: case 041: case 042:
607 length += 4; break;
608 case 044: case 045: case 046:
609 length += ((ins->oprs[c-044].addr_size ?
610 ins->oprs[c-044].addr_size : bits) == 16 ? 2 : 4); break;
611 case 050: case 051: case 052:
612 length++; break;
613 case 060: case 061: case 062:
614 length += 2; break;
615 case 064: case 065: case 066:
616 if ( ins->oprs[c-064].type & (BITS16|BITS32) )
617 length += (ins->oprs[c-064].type & BITS16) ? 2 : 4;
618 else
619 length += (bits == 16) ? 2 : 4;
620 break;
621 case 070: case 071: case 072:
622 length += 4; break;
623 case 0130: case 0131: case 0132:
624 length += is_sbyte(ins, c-0130, 16) ? 1 : 2; break;
625 case 0133: case 0134: case 0135:
626 codes+=2; length++; break;
627 case 0140: case 0141: case 0142:
628 length += is_sbyte(ins, c-0140, 32) ? 1 : 4; break;
629 case 0143: case 0144: case 0145:
630 codes+=2; length++; break;
631 case 0300: case 0301: case 0302:
632 length += chsize (&ins->oprs[c-0300], bits);
633 break;
634 case 0310:
635 length += (bits==32);
636 break;
637 case 0311:
638 length += (bits==16);
639 break;
640 case 0312:
641 break;
642 case 0320:
643 length += (bits==32);
644 break;
645 case 0321:
646 length += (bits==16);
647 break;
648 case 0322:
649 break;
650 case 0330:
651 codes++, length++; break;
652 case 0331:
653 case 0332:
654 break;
655 case 0333:
656 length++; break;
657 case 0340: case 0341: case 0342:
658 if (ins->oprs[0].segment != NO_SEG)
659 errfunc (ERR_NONFATAL, "attempt to reserve non-constant"
660 " quantity of BSS space");
661 else
662 length += ins->oprs[0].offset << (c-0340);
663 break;
664 case 0370: case 0371: case 0372:
665 break;
666 case 0373:
667 length++; break;
668 default: /* can't do it by 'case' statements */
669 if (c>=0100 && c<=0277) { /* it's an EA */
670 ea ea_data;
671 if (!process_ea (&ins->oprs[(c>>3)&7], &ea_data, bits, 0,
672 ins->forw_ref)) {
673 errfunc (ERR_NONFATAL, "invalid effective address");
674 return -1;
675 } else
676 length += ea_data.size;
677 } else
678 errfunc (ERR_PANIC, "internal instruction table corrupt"
679 ": instruction code 0x%02X given", c);
681 return length;
684 static void gencode (long segment, long offset, int bits,
685 insn *ins, const char *codes, long insn_end)
687 static char condval[] = { /* conditional opcodes */
688 0x7, 0x3, 0x2, 0x6, 0x2, 0x4, 0xF, 0xD, 0xC, 0xE, 0x6, 0x2,
689 0x3, 0x7, 0x3, 0x5, 0xE, 0xC, 0xD, 0xF, 0x1, 0xB, 0x9, 0x5,
690 0x0, 0xA, 0xA, 0xB, 0x8, 0x4
692 unsigned char c;
693 unsigned char bytes[4];
694 long data, size;
696 while (*codes)
697 switch (c = *codes++)
699 case 01: case 02: case 03:
700 out (offset, segment, codes, OUT_RAWDATA+c, NO_SEG, NO_SEG);
701 codes += c;
702 offset += c;
703 break;
705 case 04: case 06:
706 switch (ins->oprs[0].basereg)
708 case R_CS:
709 bytes[0] = 0x0E + (c == 0x04 ? 1 : 0); break;
710 case R_DS:
711 bytes[0] = 0x1E + (c == 0x04 ? 1 : 0); break;
712 case R_ES:
713 bytes[0] = 0x06 + (c == 0x04 ? 1 : 0); break;
714 case R_SS:
715 bytes[0] = 0x16 + (c == 0x04 ? 1 : 0); break;
716 default:
717 errfunc (ERR_PANIC, "bizarre 8086 segment register received");
719 out (offset, segment, bytes, OUT_RAWDATA+1, NO_SEG, NO_SEG);
720 offset++;
721 break;
723 case 05: case 07:
724 switch (ins->oprs[0].basereg) {
725 case R_FS: bytes[0] = 0xA0 + (c == 0x05 ? 1 : 0); break;
726 case R_GS: bytes[0] = 0xA8 + (c == 0x05 ? 1 : 0); break;
727 default:
728 errfunc (ERR_PANIC, "bizarre 386 segment register received");
730 out (offset, segment, bytes, OUT_RAWDATA+1, NO_SEG, NO_SEG);
731 offset++;
732 break;
734 case 010: case 011: case 012:
735 bytes[0] = *codes++ + regval(&ins->oprs[c-010]);
736 out (offset, segment, bytes, OUT_RAWDATA+1, NO_SEG, NO_SEG);
737 offset += 1;
738 break;
740 case 017:
741 bytes[0] = 0;
742 out (offset, segment, bytes, OUT_RAWDATA+1, NO_SEG, NO_SEG);
743 offset += 1;
744 break;
746 case 014: case 015: case 016:
747 if (ins->oprs[c-014].offset < -128
748 || ins->oprs[c-014].offset > 127)
750 errfunc (ERR_WARNING, "signed byte value exceeds bounds");
753 if (ins->oprs[c-014].segment != NO_SEG)
755 data = ins->oprs[c-014].offset;
756 out (offset, segment, &data, OUT_ADDRESS+1,
757 ins->oprs[c-014].segment, ins->oprs[c-014].wrt);
759 else {
760 bytes[0] = ins->oprs[c-014].offset;
761 out (offset, segment, bytes, OUT_RAWDATA+1, NO_SEG, NO_SEG);
763 offset += 1;
764 break;
766 case 020: case 021: case 022:
767 if (ins->oprs[c-020].offset < -256
768 || ins->oprs[c-020].offset > 255)
770 errfunc (ERR_WARNING, "byte value exceeds bounds");
772 if (ins->oprs[c-020].segment != NO_SEG) {
773 data = ins->oprs[c-020].offset;
774 out (offset, segment, &data, OUT_ADDRESS+1,
775 ins->oprs[c-020].segment, ins->oprs[c-020].wrt);
777 else {
778 bytes[0] = ins->oprs[c-020].offset;
779 out (offset, segment, bytes, OUT_RAWDATA+1, NO_SEG, NO_SEG);
781 offset += 1;
782 break;
784 case 024: case 025: case 026:
785 if (ins->oprs[c-024].offset < 0 || ins->oprs[c-024].offset > 255)
786 errfunc (ERR_WARNING, "unsigned byte value exceeds bounds");
787 if (ins->oprs[c-024].segment != NO_SEG) {
788 data = ins->oprs[c-024].offset;
789 out (offset, segment, &data, OUT_ADDRESS+1,
790 ins->oprs[c-024].segment, ins->oprs[c-024].wrt);
792 else {
793 bytes[0] = ins->oprs[c-024].offset;
794 out (offset, segment, bytes, OUT_RAWDATA+1, NO_SEG, NO_SEG);
796 offset += 1;
797 break;
799 case 030: case 031: case 032:
800 if (ins->oprs[c-030].segment == NO_SEG &&
801 ins->oprs[c-030].wrt == NO_SEG &&
802 (ins->oprs[c-030].offset < -65536L ||
803 ins->oprs[c-030].offset > 65535L))
805 errfunc (ERR_WARNING, "word value exceeds bounds");
807 data = ins->oprs[c-030].offset;
808 out (offset, segment, &data, OUT_ADDRESS+2,
809 ins->oprs[c-030].segment, ins->oprs[c-030].wrt);
810 offset += 2;
811 break;
813 case 034: case 035: case 036:
814 if ( ins->oprs[c-034].type & (BITS16|BITS32) )
815 size = (ins->oprs[c-034].type & BITS16) ? 2 : 4;
816 else
817 size = (bits == 16) ? 2 : 4;
818 data = ins->oprs[c-034].offset;
819 if (size==2 && (data < -65536L || data > 65535L))
820 errfunc (ERR_WARNING, "word value exceeds bounds");
821 out (offset, segment, &data, OUT_ADDRESS+size,
822 ins->oprs[c-034].segment, ins->oprs[c-034].wrt);
823 offset += size;
824 break;
826 case 037:
827 if (ins->oprs[0].segment == NO_SEG)
828 errfunc (ERR_NONFATAL, "value referenced by FAR is not"
829 " relocatable");
830 data = 0L;
831 out (offset, segment, &data, OUT_ADDRESS+2,
832 outfmt->segbase(1+ins->oprs[0].segment),
833 ins->oprs[0].wrt);
834 offset += 2;
835 break;
837 case 040: case 041: case 042:
838 data = ins->oprs[c-040].offset;
839 out (offset, segment, &data, OUT_ADDRESS+4,
840 ins->oprs[c-040].segment, ins->oprs[c-040].wrt);
841 offset += 4;
842 break;
844 case 044: case 045: case 046:
845 data = ins->oprs[c-044].offset;
846 size = ((ins->oprs[c-044].addr_size ?
847 ins->oprs[c-044].addr_size : bits) == 16 ? 2 : 4);
848 if (size==2 && (data < -65536L || data > 65535L))
849 errfunc (ERR_WARNING, "word value exceeds bounds");
850 out (offset, segment, &data, OUT_ADDRESS+size,
851 ins->oprs[c-044].segment, ins->oprs[c-044].wrt);
852 offset += size;
853 break;
855 case 050: case 051: case 052:
856 if (ins->oprs[c-050].segment != segment)
857 errfunc (ERR_NONFATAL, "short relative jump outside segment");
858 data = ins->oprs[c-050].offset - insn_end;
859 if (data > 127 || data < -128)
860 errfunc (ERR_NONFATAL, "short jump is out of range");
861 bytes[0] = data;
862 out (offset, segment, bytes, OUT_RAWDATA+1, NO_SEG, NO_SEG);
863 offset += 1;
864 break;
866 case 060: case 061: case 062:
867 if (ins->oprs[c-060].segment != segment) {
868 data = ins->oprs[c-060].offset;
869 out (offset, segment, &data, OUT_REL2ADR+insn_end-offset,
870 ins->oprs[c-060].segment, ins->oprs[c-060].wrt);
871 } else {
872 data = ins->oprs[c-060].offset - insn_end;
873 out (offset, segment, &data,
874 OUT_ADDRESS+2, NO_SEG, NO_SEG);
876 offset += 2;
877 break;
879 case 064: case 065: case 066:
880 if ( ins->oprs[c-064].type & (BITS16|BITS32) )
881 size = (ins->oprs[c-064].type & BITS16) ? 2 : 4;
882 else
883 size = (bits == 16) ? 2 : 4;
884 if (ins->oprs[c-064].segment != segment) {
885 long reltype = (size == 2 ? OUT_REL2ADR : OUT_REL4ADR);
886 data = ins->oprs[c-064].offset;
887 out (offset, segment, &data, reltype+insn_end-offset,
888 ins->oprs[c-064].segment, ins->oprs[c-064].wrt);
889 } else {
890 data = ins->oprs[c-064].offset - insn_end;
891 out (offset, segment, &data,
892 OUT_ADDRESS+size, NO_SEG, NO_SEG);
894 offset += size;
895 break;
897 case 070: case 071: case 072:
898 if (ins->oprs[c-070].segment != segment) {
899 data = ins->oprs[c-070].offset;
900 out (offset, segment, &data, OUT_REL4ADR+insn_end-offset,
901 ins->oprs[c-070].segment, ins->oprs[c-070].wrt);
902 } else {
903 data = ins->oprs[c-070].offset - insn_end;
904 out (offset, segment, &data,
905 OUT_ADDRESS+4, NO_SEG, NO_SEG);
907 offset += 4;
908 break;
910 case 0130: case 0131: case 0132:
911 data = ins->oprs[c-0130].offset;
912 if (is_sbyte(ins, c-0130, 16)) {
913 bytes[0] = data;
914 out (offset, segment, bytes, OUT_RAWDATA+1, NO_SEG, NO_SEG);
915 offset++;
916 } else {
917 if (ins->oprs[c-0130].segment == NO_SEG &&
918 ins->oprs[c-0130].wrt == NO_SEG &&
919 (data < -65536L || data > 65535L)) {
920 errfunc (ERR_WARNING, "word value exceeds bounds");
922 out (offset, segment, &data, OUT_ADDRESS+2,
923 ins->oprs[c-0130].segment, ins->oprs[c-0130].wrt);
924 offset += 2;
926 break;
928 case 0133: case 0134: case 0135:
929 codes++;
930 bytes[0] = *codes++;
931 if (is_sbyte(ins, c-0133, 16)) bytes[0] |= 2; /* s-bit */
932 out (offset, segment, bytes, OUT_RAWDATA+1, NO_SEG, NO_SEG);
933 offset++;
934 break;
936 case 0140: case 0141: case 0142:
937 data = ins->oprs[c-0140].offset;
938 if (is_sbyte(ins, c-0140, 32)) {
939 bytes[0] = data;
940 out (offset, segment, bytes, OUT_RAWDATA+1, NO_SEG, NO_SEG);
941 offset++;
942 } else {
943 out (offset, segment, &data, OUT_ADDRESS+4,
944 ins->oprs[c-0140].segment, ins->oprs[c-0140].wrt);
945 offset += 4;
947 break;
949 case 0143: case 0144: case 0145:
950 codes++;
951 bytes[0] = *codes++;
952 if (is_sbyte(ins, c-0143, 32)) bytes[0] |= 2; /* s-bit */
953 out (offset, segment, bytes, OUT_RAWDATA+1, NO_SEG, NO_SEG);
954 offset++;
955 break;
957 case 0300: case 0301: case 0302:
958 if (chsize (&ins->oprs[c-0300], bits)) {
959 *bytes = 0x67;
960 out (offset, segment, bytes,
961 OUT_RAWDATA+1, NO_SEG, NO_SEG);
962 offset += 1;
963 } else
964 offset += 0;
965 break;
967 case 0310:
968 if (bits==32) {
969 *bytes = 0x67;
970 out (offset, segment, bytes,
971 OUT_RAWDATA+1, NO_SEG, NO_SEG);
972 offset += 1;
973 } else
974 offset += 0;
975 break;
977 case 0311:
978 if (bits==16) {
979 *bytes = 0x67;
980 out (offset, segment, bytes,
981 OUT_RAWDATA+1, NO_SEG, NO_SEG);
982 offset += 1;
983 } else
984 offset += 0;
985 break;
987 case 0312:
988 break;
990 case 0320:
991 if (bits==32) {
992 *bytes = 0x66;
993 out (offset, segment, bytes,
994 OUT_RAWDATA+1, NO_SEG, NO_SEG);
995 offset += 1;
996 } else
997 offset += 0;
998 break;
1000 case 0321:
1001 if (bits==16) {
1002 *bytes = 0x66;
1003 out (offset, segment, bytes,
1004 OUT_RAWDATA+1, NO_SEG, NO_SEG);
1005 offset += 1;
1006 } else
1007 offset += 0;
1008 break;
1010 case 0322:
1011 break;
1013 case 0330:
1014 *bytes = *codes++ ^ condval[ins->condition];
1015 out (offset, segment, bytes,
1016 OUT_RAWDATA+1, NO_SEG, NO_SEG);
1017 offset += 1;
1018 break;
1020 case 0331:
1021 case 0332:
1022 break;
1024 case 0333:
1025 *bytes = 0xF3;
1026 out (offset, segment, bytes,
1027 OUT_RAWDATA+1, NO_SEG, NO_SEG);
1028 offset += 1;
1029 break;
1031 case 0340: case 0341: case 0342:
1032 if (ins->oprs[0].segment != NO_SEG)
1033 errfunc (ERR_PANIC, "non-constant BSS size in pass two");
1034 else {
1035 long size = ins->oprs[0].offset << (c-0340);
1036 if (size > 0)
1037 out (offset, segment, NULL,
1038 OUT_RESERVE+size, NO_SEG, NO_SEG);
1039 offset += size;
1041 break;
1043 case 0370: case 0371: case 0372:
1044 break;
1046 case 0373:
1047 *bytes = bits==16 ? 3 : 5;
1048 out (offset, segment, bytes,
1049 OUT_RAWDATA+1, NO_SEG, NO_SEG);
1050 offset += 1;
1051 break;
1053 default: /* can't do it by 'case' statements */
1054 if (c>=0100 && c<=0277) { /* it's an EA */
1055 ea ea_data;
1056 int rfield;
1057 unsigned char *p;
1058 long s;
1060 if (c<=0177) /* pick rfield from operand b */
1061 rfield = regval (&ins->oprs[c&7]);
1062 else /* rfield is constant */
1063 rfield = c & 7;
1065 if (!process_ea (&ins->oprs[(c>>3)&7], &ea_data, bits, rfield,
1066 ins->forw_ref))
1068 errfunc (ERR_NONFATAL, "invalid effective address");
1071 p = bytes;
1072 *p++ = ea_data.modrm;
1073 if (ea_data.sib_present)
1074 *p++ = ea_data.sib;
1076 s = p-bytes;
1077 out (offset, segment, bytes, OUT_RAWDATA + s,
1078 NO_SEG, NO_SEG);
1080 switch (ea_data.bytes) {
1081 case 0:
1082 break;
1083 case 1:
1084 if (ins->oprs[(c>>3)&7].segment != NO_SEG) {
1085 data = ins->oprs[(c>>3)&7].offset;
1086 out (offset, segment, &data, OUT_ADDRESS+1,
1087 ins->oprs[(c>>3)&7].segment,
1088 ins->oprs[(c>>3)&7].wrt);
1089 } else {
1090 *bytes = ins->oprs[(c>>3)&7].offset;
1091 out (offset, segment, bytes, OUT_RAWDATA+1,
1092 NO_SEG, NO_SEG);
1094 s++;
1095 break;
1096 case 2:
1097 case 4:
1098 data = ins->oprs[(c>>3)&7].offset;
1099 out (offset, segment, &data,
1100 OUT_ADDRESS+ea_data.bytes,
1101 ins->oprs[(c>>3)&7].segment, ins->oprs[(c>>3)&7].wrt);
1102 s += ea_data.bytes;
1103 break;
1105 offset += s;
1106 } else
1107 errfunc (ERR_PANIC, "internal instruction table corrupt"
1108 ": instruction code 0x%02X given", c);
1112 #include "regvals.c"
1114 static int regval (operand *o)
1116 if ( o->basereg < EXPR_REG_START || o->basereg >= REG_ENUM_LIMIT ) {
1117 errfunc (ERR_PANIC, "invalid operand passed to regval()");
1119 return regvals[o->basereg];
1122 static int matches (struct itemplate *itemp, insn *instruction)
1124 int i, size[3], asize, oprs, ret;
1126 ret = 100;
1129 * Check the opcode
1131 if (itemp->opcode != instruction->opcode) return 0;
1134 * Count the operands
1136 if (itemp->operands != instruction->operands) return 0;
1139 * Check that no spurious colons or TOs are present
1141 for (i=0; i<itemp->operands; i++)
1142 if (instruction->oprs[i].type & ~itemp->opd[i] & (COLON|TO))
1143 return 0;
1146 * Check that the operand flags all match up
1148 for (i=0; i<itemp->operands; i++)
1149 if (itemp->opd[i] & ~instruction->oprs[i].type ||
1150 ((itemp->opd[i] & SIZE_MASK) &&
1151 ((itemp->opd[i] ^ instruction->oprs[i].type) & SIZE_MASK)))
1153 if ((itemp->opd[i] & ~instruction->oprs[i].type & NON_SIZE) ||
1154 (instruction->oprs[i].type & SIZE_MASK))
1155 return 0;
1156 else
1157 /* ret = 1; */
1158 return 1;
1162 * Check operand sizes
1164 if (itemp->flags & IF_ARMASK) {
1165 size[0] = size[1] = size[2] = 0;
1167 switch (itemp->flags & IF_ARMASK) {
1168 case IF_AR0: i = 0; break;
1169 case IF_AR1: i = 1; break;
1170 case IF_AR2: i = 2; break;
1171 default: break; /* Shouldn't happen */
1173 if (itemp->flags & IF_SB) {
1174 size[i] = BITS8;
1175 } else if (itemp->flags & IF_SW) {
1176 size[i] = BITS16;
1177 } else if (itemp->flags & IF_SD) {
1178 size[i] = BITS32;
1180 } else {
1181 asize = 0;
1182 if (itemp->flags & IF_SB) {
1183 asize = BITS8;
1184 oprs = itemp->operands;
1185 } else if (itemp->flags & IF_SW) {
1186 asize = BITS16;
1187 oprs = itemp->operands;
1188 } else if (itemp->flags & IF_SD) {
1189 asize = BITS32;
1190 oprs = itemp->operands;
1192 size[0] = size[1] = size[2] = asize;
1195 if (itemp->flags & (IF_SM | IF_SM2)) {
1196 oprs = (itemp->flags & IF_SM2 ? 2 : itemp->operands);
1197 asize = 0;
1198 for (i=0; i<oprs; i++) {
1199 if ( (asize = itemp->opd[i] & SIZE_MASK) != 0) {
1200 int j;
1201 for (j=0; j<oprs; j++)
1202 size[j] = asize;
1203 break;
1206 } else {
1207 oprs = itemp->operands;
1210 for (i=0; i<itemp->operands; i++)
1211 if (!(itemp->opd[i] & SIZE_MASK) &&
1212 (instruction->oprs[i].type & SIZE_MASK & ~size[i]))
1213 /* ret = 2; */
1214 return 2;
1217 * Check template is okay at the set cpu level
1219 if ((itemp->flags & IF_PLEVEL) > cpu) return 3;
1222 * Check if special handling needed for Jumps
1224 if ((unsigned char)(itemp->code[0]) >= 0370) return 99;
1226 return ret;
1229 static ea *process_ea (operand *input, ea *output, int addrbits, int rfield,
1230 int forw_ref)
1232 if (!(REGISTER & ~input->type)) { /* it's a single register */
1233 static int regs[] = {
1234 R_AL, R_CL, R_DL, R_BL, R_AH, R_CH, R_DH, R_BH,
1235 R_AX, R_CX, R_DX, R_BX, R_SP, R_BP, R_SI, R_DI,
1236 R_EAX, R_ECX, R_EDX, R_EBX, R_ESP, R_EBP, R_ESI, R_EDI,
1237 R_MM0, R_MM1, R_MM2, R_MM3, R_MM4, R_MM5, R_MM6, R_MM7,
1238 R_XMM0, R_XMM1, R_XMM2, R_XMM3, R_XMM4, R_XMM5, R_XMM6, R_XMM7
1240 int i;
1242 for (i=0; i<elements(regs); i++)
1243 if (input->basereg == regs[i]) break;
1244 if (i<elements(regs)) {
1245 output->sib_present = FALSE;/* no SIB necessary */
1246 output->bytes = 0; /* no offset necessary either */
1247 output->modrm = 0xC0 | (rfield << 3) | (i & 7);
1249 else
1250 return NULL;
1251 } else { /* it's a memory reference */
1252 if (input->basereg==-1 && (input->indexreg==-1 || input->scale==0)) {
1253 /* it's a pure offset */
1254 if (input->addr_size)
1255 addrbits = input->addr_size;
1256 output->sib_present = FALSE;
1257 output->bytes = (addrbits==32 ? 4 : 2);
1258 output->modrm = (addrbits==32 ? 5 : 6) | (rfield << 3);
1260 else { /* it's an indirection */
1261 int i=input->indexreg, b=input->basereg, s=input->scale;
1262 long o=input->offset, seg=input->segment;
1263 int hb=input->hintbase, ht=input->hinttype;
1264 int t;
1266 if (s==0) i = -1; /* make this easy, at least */
1268 if (i==R_EAX || i==R_EBX || i==R_ECX || i==R_EDX
1269 || i==R_EBP || i==R_ESP || i==R_ESI || i==R_EDI
1270 || b==R_EAX || b==R_EBX || b==R_ECX || b==R_EDX
1271 || b==R_EBP || b==R_ESP || b==R_ESI || b==R_EDI) {
1272 /* it must be a 32-bit memory reference. Firstly we have
1273 * to check that all registers involved are type Exx. */
1274 if (i!=-1 && i!=R_EAX && i!=R_EBX && i!=R_ECX && i!=R_EDX
1275 && i!=R_EBP && i!=R_ESP && i!=R_ESI && i!=R_EDI)
1276 return NULL;
1277 if (b!=-1 && b!=R_EAX && b!=R_EBX && b!=R_ECX && b!=R_EDX
1278 && b!=R_EBP && b!=R_ESP && b!=R_ESI && b!=R_EDI)
1279 return NULL;
1281 /* While we're here, ensure the user didn't specify WORD. */
1282 if (input->addr_size == 16)
1283 return NULL;
1285 /* now reorganise base/index */
1286 if (s == 1 && b != i && b != -1 && i != -1 &&
1287 ((hb==b&&ht==EAH_NOTBASE) || (hb==i&&ht==EAH_MAKEBASE)))
1288 t = b, b = i, i = t; /* swap if hints say so */
1289 if (b==i) /* convert EAX+2*EAX to 3*EAX */
1290 b = -1, s++;
1291 if (b==-1 && s==1 && !(hb == i && ht == EAH_NOTBASE))
1292 b = i, i = -1; /* make single reg base, unless hint */
1293 if (((s==2 && i!=R_ESP && !(input->eaflags & EAF_TIMESTWO)) ||
1294 s==3 || s==5 || s==9) && b==-1)
1295 b = i, s--; /* convert 3*EAX to EAX+2*EAX */
1296 if (i==-1 && b!=R_ESP && (input->eaflags & EAF_TIMESTWO))
1297 i = b, b = -1, s = 1;
1298 /* convert [NOSPLIT EAX] to sib format with 0x0 displacement */
1299 if (s==1 && i==R_ESP) /* swap ESP into base if scale is 1 */
1300 i = b, b = R_ESP;
1301 if (i==R_ESP || (s!=1 && s!=2 && s!=4 && s!=8 && i!=-1))
1302 return NULL; /* wrong, for various reasons */
1304 if (i==-1 && b!=R_ESP) {/* no SIB needed */
1305 int mod, rm;
1306 switch(b) {
1307 case R_EAX: rm = 0; break;
1308 case R_ECX: rm = 1; break;
1309 case R_EDX: rm = 2; break;
1310 case R_EBX: rm = 3; break;
1311 case R_EBP: rm = 5; break;
1312 case R_ESI: rm = 6; break;
1313 case R_EDI: rm = 7; break;
1314 case -1: rm = 5; break;
1315 default: /* should never happen */
1316 return NULL;
1318 if (b==-1 || (b!=R_EBP && o==0 &&
1319 seg==NO_SEG && !forw_ref &&
1320 !(input->eaflags &
1321 (EAF_BYTEOFFS|EAF_WORDOFFS))))
1322 mod = 0;
1323 else if (input->eaflags & EAF_BYTEOFFS ||
1324 (o>=-128 && o<=127 && seg==NO_SEG && !forw_ref &&
1325 !(input->eaflags & EAF_WORDOFFS))) {
1326 mod = 1;
1328 else
1329 mod = 2;
1331 output->sib_present = FALSE;
1332 output->bytes = (b==-1 || mod==2 ? 4 : mod);
1333 output->modrm = (mod<<6) | (rfield<<3) | rm;
1335 else { /* we need a SIB */
1336 int mod, scale, index, base;
1338 switch (b) {
1339 case R_EAX: base = 0; break;
1340 case R_ECX: base = 1; break;
1341 case R_EDX: base = 2; break;
1342 case R_EBX: base = 3; break;
1343 case R_ESP: base = 4; break;
1344 case R_EBP: case -1: base = 5; break;
1345 case R_ESI: base = 6; break;
1346 case R_EDI: base = 7; break;
1347 default: /* then what the smeg is it? */
1348 return NULL; /* panic */
1351 switch (i) {
1352 case R_EAX: index = 0; break;
1353 case R_ECX: index = 1; break;
1354 case R_EDX: index = 2; break;
1355 case R_EBX: index = 3; break;
1356 case -1: index = 4; break;
1357 case R_EBP: index = 5; break;
1358 case R_ESI: index = 6; break;
1359 case R_EDI: index = 7; break;
1360 default: /* then what the smeg is it? */
1361 return NULL; /* panic */
1364 if (i==-1) s = 1;
1365 switch (s) {
1366 case 1: scale = 0; break;
1367 case 2: scale = 1; break;
1368 case 4: scale = 2; break;
1369 case 8: scale = 3; break;
1370 default: /* then what the smeg is it? */
1371 return NULL; /* panic */
1374 if (b==-1 || (b!=R_EBP && o==0 &&
1375 seg==NO_SEG && !forw_ref &&
1376 !(input->eaflags &
1377 (EAF_BYTEOFFS|EAF_WORDOFFS))))
1378 mod = 0;
1379 else if (input->eaflags & EAF_BYTEOFFS ||
1380 (o>=-128 && o<=127 && seg==NO_SEG && !forw_ref &&
1381 !(input->eaflags & EAF_WORDOFFS)))
1382 mod = 1;
1383 else
1384 mod = 2;
1386 output->sib_present = TRUE;
1387 output->bytes = (b==-1 || mod==2 ? 4 : mod);
1388 output->modrm = (mod<<6) | (rfield<<3) | 4;
1389 output->sib = (scale<<6) | (index<<3) | base;
1392 else { /* it's 16-bit */
1393 int mod, rm;
1395 /* check all registers are BX, BP, SI or DI */
1396 if ((b!=-1 && b!=R_BP && b!=R_BX && b!=R_SI && b!=R_DI) ||
1397 (i!=-1 && i!=R_BP && i!=R_BX && i!=R_SI && i!=R_DI))
1398 return NULL;
1400 /* ensure the user didn't specify DWORD */
1401 if (input->addr_size == 32)
1402 return NULL;
1404 if (s!=1 && i!=-1) return NULL;/* no can do, in 16-bit EA */
1405 if (b==-1 && i!=-1) { int tmp = b; b = i; i = tmp; } /* swap */
1406 if ((b==R_SI || b==R_DI) && i!=-1)
1407 { int tmp = b; b = i; i = tmp; }
1408 /* have BX/BP as base, SI/DI index */
1409 if (b==i) return NULL;/* shouldn't ever happen, in theory */
1410 if (i!=-1 && b!=-1 &&
1411 (i==R_BP || i==R_BX || b==R_SI || b==R_DI))
1412 return NULL; /* invalid combinations */
1413 if (b==-1) /* pure offset: handled above */
1414 return NULL; /* so if it gets to here, panic! */
1416 rm = -1;
1417 if (i!=-1)
1418 switch (i*256 + b) {
1419 case R_SI*256+R_BX: rm=0; break;
1420 case R_DI*256+R_BX: rm=1; break;
1421 case R_SI*256+R_BP: rm=2; break;
1422 case R_DI*256+R_BP: rm=3; break;
1424 else
1425 switch (b) {
1426 case R_SI: rm=4; break;
1427 case R_DI: rm=5; break;
1428 case R_BP: rm=6; break;
1429 case R_BX: rm=7; break;
1431 if (rm==-1) /* can't happen, in theory */
1432 return NULL; /* so panic if it does */
1434 if (o==0 && seg==NO_SEG && !forw_ref && rm!=6 &&
1435 !(input->eaflags & (EAF_BYTEOFFS|EAF_WORDOFFS)))
1436 mod = 0;
1437 else if (input->eaflags & EAF_BYTEOFFS ||
1438 (o>=-128 && o<=127 && seg==NO_SEG && !forw_ref &&
1439 !(input->eaflags & EAF_WORDOFFS)))
1440 mod = 1;
1441 else
1442 mod = 2;
1444 output->sib_present = FALSE; /* no SIB - it's 16-bit */
1445 output->bytes = mod; /* bytes of offset needed */
1446 output->modrm = (mod<<6) | (rfield<<3) | rm;
1450 output->size = 1 + output->sib_present + output->bytes;
1451 return output;
1454 static int chsize (operand *input, int addrbits)
1456 if (!(MEMORY & ~input->type)) {
1457 int i=input->indexreg, b=input->basereg;
1459 if (input->scale==0) i = -1;
1461 if (i == -1 && b == -1) /* pure offset */
1462 return (input->addr_size != 0 && input->addr_size != addrbits);
1464 if (i==R_EAX || i==R_EBX || i==R_ECX || i==R_EDX
1465 || i==R_EBP || i==R_ESP || i==R_ESI || i==R_EDI
1466 || b==R_EAX || b==R_EBX || b==R_ECX || b==R_EDX
1467 || b==R_EBP || b==R_ESP || b==R_ESI || b==R_EDI)
1468 return (addrbits==16);
1469 else
1470 return (addrbits==32);
1472 else
1473 return 0;