RAA fix from theowl
[nasm.git] / assemble.c
bloba3e1a9aabcb8059bc8b3e5d9b23b69acdc6d8cda
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 insn_end = offset + insn_size;
360 for (j=0; j<instruction->nprefix; j++) {
361 unsigned char c=0;
362 switch (instruction->prefixes[j]) {
363 case P_LOCK:
364 c = 0xF0; break;
365 case P_REPNE: case P_REPNZ:
366 c = 0xF2; break;
367 case P_REPE: case P_REPZ: case P_REP:
368 c = 0xF3; break;
369 case R_CS: c = 0x2E; break;
370 case R_DS: c = 0x3E; break;
371 case R_ES: c = 0x26; break;
372 case R_FS: c = 0x64; break;
373 case R_GS: c = 0x65; break;
374 case R_SS: c = 0x36; break;
375 case R_SEGR6:
376 case R_SEGR7:
377 error (ERR_NONFATAL, "segr6 and segr7 cannot be used as prefixes");
378 break;
379 case P_A16:
380 if (bits != 16)
381 c = 0x67;
382 break;
383 case P_A32:
384 if (bits != 32)
385 c = 0x67;
386 break;
387 case P_O16:
388 if (bits != 16)
389 c = 0x66;
390 break;
391 case P_O32:
392 if (bits != 32)
393 c = 0x66;
394 break;
395 default:
396 error (ERR_PANIC,
397 "invalid instruction prefix");
399 if (c != 0) {
400 out (offset, segment, &c, OUT_RAWDATA+1,
401 NO_SEG, NO_SEG);
402 offset++;
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 out (offset, segment, &data, OUT_RAWDATA+1, NO_SEG, NO_SEG);
914 offset++;
915 } else {
916 if (ins->oprs[c-0130].segment == NO_SEG &&
917 ins->oprs[c-0130].wrt == NO_SEG &&
918 (data < -65536L || data > 65535L)) {
919 errfunc (ERR_WARNING, "word value exceeds bounds");
921 out (offset, segment, &data, OUT_ADDRESS+2,
922 ins->oprs[c-0130].segment, ins->oprs[c-0130].wrt);
923 offset += 2;
925 break;
927 case 0133: case 0134: case 0135:
928 codes++;
929 bytes[0] = *codes++;
930 if (is_sbyte(ins, c-0133, 16)) bytes[0] |= 2; /* s-bit */
931 out (offset, segment, bytes, OUT_RAWDATA+1, NO_SEG, NO_SEG);
932 offset++;
933 break;
935 case 0140: case 0141: case 0142:
936 data = ins->oprs[c-0140].offset;
937 if (is_sbyte(ins, c-0140, 32)) {
938 out (offset, segment, &data, OUT_RAWDATA+1, NO_SEG, NO_SEG);
939 offset++;
940 } else {
941 out (offset, segment, &data, OUT_ADDRESS+4,
942 ins->oprs[c-0140].segment, ins->oprs[c-0140].wrt);
943 offset += 4;
945 break;
947 case 0143: case 0144: case 0145:
948 codes++;
949 bytes[0] = *codes++;
950 if (is_sbyte(ins, c-0143, 32)) bytes[0] |= 2; /* s-bit */
951 out (offset, segment, bytes, OUT_RAWDATA+1, NO_SEG, NO_SEG);
952 offset++;
953 break;
955 case 0300: case 0301: case 0302:
956 if (chsize (&ins->oprs[c-0300], bits)) {
957 *bytes = 0x67;
958 out (offset, segment, bytes,
959 OUT_RAWDATA+1, NO_SEG, NO_SEG);
960 offset += 1;
961 } else
962 offset += 0;
963 break;
965 case 0310:
966 if (bits==32) {
967 *bytes = 0x67;
968 out (offset, segment, bytes,
969 OUT_RAWDATA+1, NO_SEG, NO_SEG);
970 offset += 1;
971 } else
972 offset += 0;
973 break;
975 case 0311:
976 if (bits==16) {
977 *bytes = 0x67;
978 out (offset, segment, bytes,
979 OUT_RAWDATA+1, NO_SEG, NO_SEG);
980 offset += 1;
981 } else
982 offset += 0;
983 break;
985 case 0312:
986 break;
988 case 0320:
989 if (bits==32) {
990 *bytes = 0x66;
991 out (offset, segment, bytes,
992 OUT_RAWDATA+1, NO_SEG, NO_SEG);
993 offset += 1;
994 } else
995 offset += 0;
996 break;
998 case 0321:
999 if (bits==16) {
1000 *bytes = 0x66;
1001 out (offset, segment, bytes,
1002 OUT_RAWDATA+1, NO_SEG, NO_SEG);
1003 offset += 1;
1004 } else
1005 offset += 0;
1006 break;
1008 case 0322:
1009 break;
1011 case 0330:
1012 *bytes = *codes++ ^ condval[ins->condition];
1013 out (offset, segment, bytes,
1014 OUT_RAWDATA+1, NO_SEG, NO_SEG);
1015 offset += 1;
1016 break;
1018 case 0331:
1019 case 0332:
1020 break;
1022 case 0333:
1023 *bytes = 0xF3;
1024 out (offset, segment, bytes,
1025 OUT_RAWDATA+1, NO_SEG, NO_SEG);
1026 offset += 1;
1027 break;
1029 case 0340: case 0341: case 0342:
1030 if (ins->oprs[0].segment != NO_SEG)
1031 errfunc (ERR_PANIC, "non-constant BSS size in pass two");
1032 else {
1033 long size = ins->oprs[0].offset << (c-0340);
1034 if (size > 0)
1035 out (offset, segment, NULL,
1036 OUT_RESERVE+size, NO_SEG, NO_SEG);
1037 offset += size;
1039 break;
1041 case 0370: case 0371: case 0372:
1042 break;
1044 case 0373:
1045 *bytes = bits==16 ? 3 : 5;
1046 out (offset, segment, bytes,
1047 OUT_RAWDATA+1, NO_SEG, NO_SEG);
1048 offset += 1;
1049 break;
1051 default: /* can't do it by 'case' statements */
1052 if (c>=0100 && c<=0277) { /* it's an EA */
1053 ea ea_data;
1054 int rfield;
1055 unsigned char *p;
1056 long s;
1058 if (c<=0177) /* pick rfield from operand b */
1059 rfield = regval (&ins->oprs[c&7]);
1060 else /* rfield is constant */
1061 rfield = c & 7;
1063 if (!process_ea (&ins->oprs[(c>>3)&7], &ea_data, bits, rfield,
1064 ins->forw_ref))
1066 errfunc (ERR_NONFATAL, "invalid effective address");
1069 p = bytes;
1070 *p++ = ea_data.modrm;
1071 if (ea_data.sib_present)
1072 *p++ = ea_data.sib;
1074 s = p-bytes;
1075 out (offset, segment, bytes, OUT_RAWDATA + s,
1076 NO_SEG, NO_SEG);
1078 switch (ea_data.bytes) {
1079 case 0:
1080 break;
1081 case 1:
1082 if (ins->oprs[(c>>3)&7].segment != NO_SEG) {
1083 data = ins->oprs[(c>>3)&7].offset;
1084 out (offset, segment, &data, OUT_ADDRESS+1,
1085 ins->oprs[(c>>3)&7].segment,
1086 ins->oprs[(c>>3)&7].wrt);
1087 } else {
1088 *bytes = ins->oprs[(c>>3)&7].offset;
1089 out (offset, segment, bytes, OUT_RAWDATA+1,
1090 NO_SEG, NO_SEG);
1092 s++;
1093 break;
1094 case 2:
1095 case 4:
1096 data = ins->oprs[(c>>3)&7].offset;
1097 out (offset, segment, &data,
1098 OUT_ADDRESS+ea_data.bytes,
1099 ins->oprs[(c>>3)&7].segment, ins->oprs[(c>>3)&7].wrt);
1100 s += ea_data.bytes;
1101 break;
1103 offset += s;
1104 } else
1105 errfunc (ERR_PANIC, "internal instruction table corrupt"
1106 ": instruction code 0x%02X given", c);
1110 #include "regvals.c"
1112 static int regval (operand *o)
1114 if ( o->basereg < EXPR_REG_START || o->basereg >= REG_ENUM_LIMIT ) {
1115 errfunc (ERR_PANIC, "invalid operand passed to regval()");
1117 return regvals[o->basereg];
1120 static int matches (struct itemplate *itemp, insn *instruction)
1122 int i, size[3], asize, oprs, ret;
1124 ret = 100;
1127 * Check the opcode
1129 if (itemp->opcode != instruction->opcode) return 0;
1132 * Count the operands
1134 if (itemp->operands != instruction->operands) return 0;
1137 * Check that no spurious colons or TOs are present
1139 for (i=0; i<itemp->operands; i++)
1140 if (instruction->oprs[i].type & ~itemp->opd[i] & (COLON|TO))
1141 return 0;
1144 * Check that the operand flags all match up
1146 for (i=0; i<itemp->operands; i++)
1147 if (itemp->opd[i] & ~instruction->oprs[i].type ||
1148 ((itemp->opd[i] & SIZE_MASK) &&
1149 ((itemp->opd[i] ^ instruction->oprs[i].type) & SIZE_MASK)))
1151 if ((itemp->opd[i] & ~instruction->oprs[i].type & NON_SIZE) ||
1152 (instruction->oprs[i].type & SIZE_MASK))
1153 return 0;
1154 else
1155 /* ret = 1; */
1156 return 1;
1160 * Check operand sizes
1162 if (itemp->flags & IF_ARMASK) {
1163 size[0] = size[1] = size[2] = 0;
1165 switch (itemp->flags & IF_ARMASK) {
1166 case IF_AR0: i = 0; break;
1167 case IF_AR1: i = 1; break;
1168 case IF_AR2: i = 2; break;
1169 default: break; /* Shouldn't happen */
1171 if (itemp->flags & IF_SB) {
1172 size[i] = BITS8;
1173 } else if (itemp->flags & IF_SW) {
1174 size[i] = BITS16;
1175 } else if (itemp->flags & IF_SD) {
1176 size[i] = BITS32;
1178 } else {
1179 asize = 0;
1180 if (itemp->flags & IF_SB) {
1181 asize = BITS8;
1182 oprs = itemp->operands;
1183 } else if (itemp->flags & IF_SW) {
1184 asize = BITS16;
1185 oprs = itemp->operands;
1186 } else if (itemp->flags & IF_SD) {
1187 asize = BITS32;
1188 oprs = itemp->operands;
1190 size[0] = size[1] = size[2] = asize;
1193 if (itemp->flags & (IF_SM | IF_SM2)) {
1194 oprs = (itemp->flags & IF_SM2 ? 2 : itemp->operands);
1195 asize = 0;
1196 for (i=0; i<oprs; i++) {
1197 if ( (asize = itemp->opd[i] & SIZE_MASK) != 0) {
1198 int j;
1199 for (j=0; j<oprs; j++)
1200 size[j] = asize;
1201 break;
1204 } else {
1205 oprs = itemp->operands;
1208 for (i=0; i<itemp->operands; i++)
1209 if (!(itemp->opd[i] & SIZE_MASK) &&
1210 (instruction->oprs[i].type & SIZE_MASK & ~size[i]))
1211 /* ret = 2; */
1212 return 2;
1215 * Check template is okay at the set cpu level
1217 if ((itemp->flags & IF_PLEVEL) > cpu) return 3;
1220 * Check if special handling needed for Jumps
1222 if ((unsigned char)(itemp->code[0]) >= 0370) return 99;
1224 return ret;
1227 static ea *process_ea (operand *input, ea *output, int addrbits, int rfield,
1228 int forw_ref)
1230 if (!(REGISTER & ~input->type)) { /* it's a single register */
1231 static int regs[] = {
1232 R_AL, R_CL, R_DL, R_BL, R_AH, R_CH, R_DH, R_BH,
1233 R_AX, R_CX, R_DX, R_BX, R_SP, R_BP, R_SI, R_DI,
1234 R_EAX, R_ECX, R_EDX, R_EBX, R_ESP, R_EBP, R_ESI, R_EDI,
1235 R_MM0, R_MM1, R_MM2, R_MM3, R_MM4, R_MM5, R_MM6, R_MM7,
1236 R_XMM0, R_XMM1, R_XMM2, R_XMM3, R_XMM4, R_XMM5, R_XMM6, R_XMM7
1238 int i;
1240 for (i=0; i<elements(regs); i++)
1241 if (input->basereg == regs[i]) break;
1242 if (i<elements(regs)) {
1243 output->sib_present = FALSE;/* no SIB necessary */
1244 output->bytes = 0; /* no offset necessary either */
1245 output->modrm = 0xC0 | (rfield << 3) | (i & 7);
1247 else
1248 return NULL;
1249 } else { /* it's a memory reference */
1250 if (input->basereg==-1 && (input->indexreg==-1 || input->scale==0)) {
1251 /* it's a pure offset */
1252 if (input->addr_size)
1253 addrbits = input->addr_size;
1254 output->sib_present = FALSE;
1255 output->bytes = (addrbits==32 ? 4 : 2);
1256 output->modrm = (addrbits==32 ? 5 : 6) | (rfield << 3);
1258 else { /* it's an indirection */
1259 int i=input->indexreg, b=input->basereg, s=input->scale;
1260 long o=input->offset, seg=input->segment;
1261 int hb=input->hintbase, ht=input->hinttype;
1262 int t;
1264 if (s==0) i = -1; /* make this easy, at least */
1266 if (i==R_EAX || i==R_EBX || i==R_ECX || i==R_EDX
1267 || i==R_EBP || i==R_ESP || i==R_ESI || i==R_EDI
1268 || b==R_EAX || b==R_EBX || b==R_ECX || b==R_EDX
1269 || b==R_EBP || b==R_ESP || b==R_ESI || b==R_EDI) {
1270 /* it must be a 32-bit memory reference. Firstly we have
1271 * to check that all registers involved are type Exx. */
1272 if (i!=-1 && i!=R_EAX && i!=R_EBX && i!=R_ECX && i!=R_EDX
1273 && i!=R_EBP && i!=R_ESP && i!=R_ESI && i!=R_EDI)
1274 return NULL;
1275 if (b!=-1 && b!=R_EAX && b!=R_EBX && b!=R_ECX && b!=R_EDX
1276 && b!=R_EBP && b!=R_ESP && b!=R_ESI && b!=R_EDI)
1277 return NULL;
1279 /* While we're here, ensure the user didn't specify WORD. */
1280 if (input->addr_size == 16)
1281 return NULL;
1283 /* now reorganise base/index */
1284 if (s == 1 && b != i && b != -1 && i != -1 &&
1285 ((hb==b&&ht==EAH_NOTBASE) || (hb==i&&ht==EAH_MAKEBASE)))
1286 t = b, b = i, i = t; /* swap if hints say so */
1287 if (b==i) /* convert EAX+2*EAX to 3*EAX */
1288 b = -1, s++;
1289 if (b==-1 && s==1 && !(hb == i && ht == EAH_NOTBASE))
1290 b = i, i = -1; /* make single reg base, unless hint */
1291 if (((s==2 && i!=R_ESP && !(input->eaflags & EAF_TIMESTWO)) ||
1292 s==3 || s==5 || s==9) && b==-1)
1293 b = i, s--; /* convert 3*EAX to EAX+2*EAX */
1294 if (i==-1 && b!=R_ESP && (input->eaflags & EAF_TIMESTWO))
1295 i = b, b = -1, s = 1;
1296 /* convert [NOSPLIT EAX] to sib format with 0x0 displacement */
1297 if (s==1 && i==R_ESP) /* swap ESP into base if scale is 1 */
1298 i = b, b = R_ESP;
1299 if (i==R_ESP || (s!=1 && s!=2 && s!=4 && s!=8 && i!=-1))
1300 return NULL; /* wrong, for various reasons */
1302 if (i==-1 && b!=R_ESP) {/* no SIB needed */
1303 int mod, rm;
1304 switch(b) {
1305 case R_EAX: rm = 0; break;
1306 case R_ECX: rm = 1; break;
1307 case R_EDX: rm = 2; break;
1308 case R_EBX: rm = 3; break;
1309 case R_EBP: rm = 5; break;
1310 case R_ESI: rm = 6; break;
1311 case R_EDI: rm = 7; break;
1312 case -1: rm = 5; break;
1313 default: /* should never happen */
1314 return NULL;
1316 if (b==-1 || (b!=R_EBP && o==0 &&
1317 seg==NO_SEG && !forw_ref &&
1318 !(input->eaflags &
1319 (EAF_BYTEOFFS|EAF_WORDOFFS))))
1320 mod = 0;
1321 else if (input->eaflags & EAF_BYTEOFFS ||
1322 (o>=-128 && o<=127 && seg==NO_SEG && !forw_ref &&
1323 !(input->eaflags & EAF_WORDOFFS))) {
1324 mod = 1;
1326 else
1327 mod = 2;
1329 output->sib_present = FALSE;
1330 output->bytes = (b==-1 || mod==2 ? 4 : mod);
1331 output->modrm = (mod<<6) | (rfield<<3) | rm;
1333 else { /* we need a SIB */
1334 int mod, scale, index, base;
1336 switch (b) {
1337 case R_EAX: base = 0; break;
1338 case R_ECX: base = 1; break;
1339 case R_EDX: base = 2; break;
1340 case R_EBX: base = 3; break;
1341 case R_ESP: base = 4; break;
1342 case R_EBP: case -1: base = 5; break;
1343 case R_ESI: base = 6; break;
1344 case R_EDI: base = 7; break;
1345 default: /* then what the smeg is it? */
1346 return NULL; /* panic */
1349 switch (i) {
1350 case R_EAX: index = 0; break;
1351 case R_ECX: index = 1; break;
1352 case R_EDX: index = 2; break;
1353 case R_EBX: index = 3; break;
1354 case -1: index = 4; break;
1355 case R_EBP: index = 5; break;
1356 case R_ESI: index = 6; break;
1357 case R_EDI: index = 7; break;
1358 default: /* then what the smeg is it? */
1359 return NULL; /* panic */
1362 if (i==-1) s = 1;
1363 switch (s) {
1364 case 1: scale = 0; break;
1365 case 2: scale = 1; break;
1366 case 4: scale = 2; break;
1367 case 8: scale = 3; break;
1368 default: /* then what the smeg is it? */
1369 return NULL; /* panic */
1372 if (b==-1 || (b!=R_EBP && o==0 &&
1373 seg==NO_SEG && !forw_ref &&
1374 !(input->eaflags &
1375 (EAF_BYTEOFFS|EAF_WORDOFFS))))
1376 mod = 0;
1377 else if (input->eaflags & EAF_BYTEOFFS ||
1378 (o>=-128 && o<=127 && seg==NO_SEG && !forw_ref &&
1379 !(input->eaflags & EAF_WORDOFFS)))
1380 mod = 1;
1381 else
1382 mod = 2;
1384 output->sib_present = TRUE;
1385 output->bytes = (b==-1 || mod==2 ? 4 : mod);
1386 output->modrm = (mod<<6) | (rfield<<3) | 4;
1387 output->sib = (scale<<6) | (index<<3) | base;
1390 else { /* it's 16-bit */
1391 int mod, rm;
1393 /* check all registers are BX, BP, SI or DI */
1394 if ((b!=-1 && b!=R_BP && b!=R_BX && b!=R_SI && b!=R_DI) ||
1395 (i!=-1 && i!=R_BP && i!=R_BX && i!=R_SI && i!=R_DI))
1396 return NULL;
1398 /* ensure the user didn't specify DWORD */
1399 if (input->addr_size == 32)
1400 return NULL;
1402 if (s!=1 && i!=-1) return NULL;/* no can do, in 16-bit EA */
1403 if (b==-1 && i!=-1) { int tmp = b; b = i; i = tmp; } /* swap */
1404 if ((b==R_SI || b==R_DI) && i!=-1)
1405 { int tmp = b; b = i; i = tmp; }
1406 /* have BX/BP as base, SI/DI index */
1407 if (b==i) return NULL;/* shouldn't ever happen, in theory */
1408 if (i!=-1 && b!=-1 &&
1409 (i==R_BP || i==R_BX || b==R_SI || b==R_DI))
1410 return NULL; /* invalid combinations */
1411 if (b==-1) /* pure offset: handled above */
1412 return NULL; /* so if it gets to here, panic! */
1414 rm = -1;
1415 if (i!=-1)
1416 switch (i*256 + b) {
1417 case R_SI*256+R_BX: rm=0; break;
1418 case R_DI*256+R_BX: rm=1; break;
1419 case R_SI*256+R_BP: rm=2; break;
1420 case R_DI*256+R_BP: rm=3; break;
1422 else
1423 switch (b) {
1424 case R_SI: rm=4; break;
1425 case R_DI: rm=5; break;
1426 case R_BP: rm=6; break;
1427 case R_BX: rm=7; break;
1429 if (rm==-1) /* can't happen, in theory */
1430 return NULL; /* so panic if it does */
1432 if (o==0 && seg==NO_SEG && !forw_ref && rm!=6 &&
1433 !(input->eaflags & (EAF_BYTEOFFS|EAF_WORDOFFS)))
1434 mod = 0;
1435 else if (input->eaflags & EAF_BYTEOFFS ||
1436 (o>=-128 && o<=127 && seg==NO_SEG && !forw_ref &&
1437 !(input->eaflags & EAF_WORDOFFS)))
1438 mod = 1;
1439 else
1440 mod = 2;
1442 output->sib_present = FALSE; /* no SIB - it's 16-bit */
1443 output->bytes = mod; /* bytes of offset needed */
1444 output->modrm = (mod<<6) | (rfield<<3) | rm;
1448 output->size = 1 + output->sib_present + output->bytes;
1449 return output;
1452 static int chsize (operand *input, int addrbits)
1454 if (!(MEMORY & ~input->type)) {
1455 int i=input->indexreg, b=input->basereg;
1457 if (input->scale==0) i = -1;
1459 if (i == -1 && b == -1) /* pure offset */
1460 return (input->addr_size != 0 && input->addr_size != addrbits);
1462 if (i==R_EAX || i==R_EBX || i==R_ECX || i==R_EDX
1463 || i==R_EBP || i==R_ESP || i==R_ESI || i==R_EDI
1464 || b==R_EAX || b==R_EBX || b==R_ECX || b==R_EDX
1465 || b==R_EBP || b==R_ESP || b==R_ESI || b==R_EDI)
1466 return (addrbits==16);
1467 else
1468 return (addrbits==32);
1470 else
1471 return 0;