NASM 0.98.12
[nasm.git] / assemble.c
blobf93457d9ea12e0baee6efe5325d6d022919727df
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 address-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 * \50, \51, \52 - a byte relative operand, from operand 0, 1 or 2
29 * \60, \61, \62 - a word relative operand, from operand 0, 1 or 2
30 * \64, \65, \66 - select between \6[012] and \7[012] depending on 16/32 bit
31 * assembly mode or the address-size override on the operand
32 * \70, \71, \72 - a long relative operand, from operand 0, 1 or 2
33 * \1ab - a ModRM, calculated on EA in operand a, with the spare
34 * field the register value of operand b.
35 * \130,\131,\132 - an immediate word or signed byte for operand 0, 1, or 2
36 * \133,\134,\135 - or 2 (s-field) into next opcode byte if operand 0, 1, or 2
37 * is a signed byte rather than a word.
38 * \140,\141,\142 - an immediate dword or signed byte for operand 0, 1, or 2
39 * \143,\144,\145 - or 2 (s-field) into next opcode byte if operand 0, 1, or 2
40 * is a signed byte rather than a dword.
41 * \2ab - a ModRM, calculated on EA in operand a, with the spare
42 * field equal to digit b.
43 * \30x - might be an 0x67 byte, depending on the address size of
44 * the memory reference in operand x.
45 * \310 - indicates fixed 16-bit address size, i.e. optional 0x67.
46 * \311 - indicates fixed 32-bit address size, i.e. optional 0x67.
47 * \312 - (disassembler only) marker on LOOP, LOOPxx instructions.
48 * \320 - indicates fixed 16-bit operand size, i.e. optional 0x66.
49 * \321 - indicates fixed 32-bit operand size, i.e. optional 0x66.
50 * \322 - indicates that this instruction is only valid when the
51 * operand size is the default (instruction to disassembler,
52 * generates no code in the assembler)
53 * \330 - a literal byte follows in the code stream, to be added
54 * to the condition code value of the instruction.
55 * \331 - instruction not valid with REP prefix. Hint for
56 * disassembler only; for SSE instructions.
57 * \332 - disassemble a rep (0xF3 byte) prefix as repe not rep.
58 * \333 - REP prefix (0xF3 byte); for SSE instructions. Not encoded
59 * as a literal byte in order to aid the disassembler.
60 * \340 - reserve <operand 0> bytes of uninitialised storage.
61 * Operand 0 had better be a segmentless constant.
62 * \370,\371,\372 - match only if operand 0 meets byte jump criteria.
63 * 370 is used for Jcc, 371 is used for JMP.
64 * \373 - assemble 0x03 if bits==16, 0x05 if bits==32;
65 * used for conditional jump over longer jump
68 #include <stdio.h>
69 #include <string.h>
71 #include "nasm.h"
72 #include "nasmlib.h"
73 #include "assemble.h"
74 #include "insns.h"
76 extern struct itemplate *nasm_instructions[];
78 typedef struct {
79 int sib_present; /* is a SIB byte necessary? */
80 int bytes; /* # of bytes of offset needed */
81 int size; /* lazy - this is sib+bytes+1 */
82 unsigned char modrm, sib; /* the bytes themselves */
83 } ea;
85 static unsigned long cpu; /* cpu level received from nasm.c */
86 static efunc errfunc;
87 static struct ofmt *outfmt;
88 static ListGen *list;
90 static long calcsize (long, long, int, insn *, char *);
91 static void gencode (long, long, int, insn *, char *, long);
92 static int regval (operand *o);
93 static int matches (struct itemplate *, insn *);
94 static ea * process_ea (operand *, ea *, int, int, int);
95 static int chsize (operand *, int);
98 * This routine wrappers the real output format's output routine,
99 * in order to pass a copy of the data off to the listing file
100 * generator at the same time.
102 static void out (long offset, long segto, void *data, unsigned long type,
103 long segment, long wrt)
105 static long lineno;
106 static char *lnfname;
108 if ((type & OUT_TYPMASK) == OUT_ADDRESS) {
109 if (segment != NO_SEG || wrt != NO_SEG) {
111 * This address is relocated. We must write it as
112 * OUT_ADDRESS, so there's no work to be done here.
114 list->output (offset, data, type);
116 else {
117 unsigned char p[4], *q = p;
119 * This is a non-relocated address, and we're going to
120 * convert it into RAWDATA format.
122 if ((type & OUT_SIZMASK) == 4) {
123 WRITELONG (q, * (long *) data);
124 list->output (offset, p, OUT_RAWDATA+4);
126 else {
127 WRITESHORT (q, * (long *) data);
128 list->output (offset, p, OUT_RAWDATA+2);
132 else if ((type & OUT_TYPMASK) == OUT_RAWDATA) {
133 list->output (offset, data, type);
135 else if ((type & OUT_TYPMASK) == OUT_RESERVE) {
136 list->output (offset, NULL, type);
138 else if ((type & OUT_TYPMASK) == OUT_REL2ADR ||
139 (type & OUT_TYPMASK) == OUT_REL4ADR) {
140 list->output (offset, data, type);
143 if (src_get(&lineno,&lnfname))
144 outfmt->current_dfmt->linenum(lnfname,lineno,segto);
146 outfmt->output (segto, data, type, segment, wrt);
149 static int jmp_match (long segment, long offset, int bits,
150 insn *ins, char *code)
151 { long isize;
152 unsigned char c = code[0];
155 if (c != 0370 && c != 0371) return 0;
156 if (ins->oprs[0].opflags & OPFLAG_FORWARD) {
157 if (optimizing<0 && c==0370) return 1;
158 else return (pass0==0); /* match a forward reference */
160 isize = calcsize (segment, offset, bits, ins, code);
161 if (ins->oprs[0].segment != segment) return 0;
162 isize = ins->oprs[0].offset - offset - isize; /* isize is now the delta */
163 if (isize >= -128L && isize <= 127L) return 1; /* it is byte size */
165 return 0;
169 long assemble (long segment, long offset, int bits, unsigned long cp,
170 insn *instruction, struct ofmt *output, efunc error,
171 ListGen *listgen)
173 struct itemplate *temp;
174 int j;
175 int size_prob;
176 long insn_end;
177 long itimes;
178 long start = offset;
179 long wsize = 0; /* size for DB etc. */
181 errfunc = error; /* to pass to other functions */
182 cpu = cp;
183 outfmt = output; /* likewise */
184 list = listgen; /* and again */
186 switch (instruction->opcode)
188 case -1: return 0;
189 case I_DB: wsize = 1; break;
190 case I_DW: wsize = 2; break;
191 case I_DD: wsize = 4; break;
192 case I_DQ: wsize = 8; break;
193 case I_DT: wsize = 10; break;
196 if (wsize) {
197 extop * e;
198 long t = instruction->times;
199 if (t < 0)
200 errfunc(ERR_PANIC, "instruction->times < 0 (%ld) in assemble()",t);
202 while (t--) /* repeat TIMES times */
204 for (e = instruction->eops; e; e = e->next)
206 if (e->type == EOT_DB_NUMBER)
208 if (wsize == 1) {
209 if (e->segment != NO_SEG)
210 errfunc (ERR_NONFATAL,
211 "one-byte relocation attempted");
212 else {
213 unsigned char out_byte = e->offset;
214 out (offset, segment, &out_byte, OUT_RAWDATA+1,
215 NO_SEG, NO_SEG);
218 else if (wsize > 5) {
219 errfunc (ERR_NONFATAL, "integer supplied to a D%c"
220 " instruction", wsize==8 ? 'Q' : 'T');
222 else
223 out (offset, segment, &e->offset,
224 OUT_ADDRESS+wsize, e->segment,
225 e->wrt);
226 offset += wsize;
228 else if (e->type == EOT_DB_STRING)
230 int align;
232 out (offset, segment, e->stringval,
233 OUT_RAWDATA+e->stringlen, NO_SEG, NO_SEG);
234 align = e->stringlen % wsize;
236 if (align) {
237 align = wsize - align;
238 out (offset, segment, "\0\0\0\0\0\0\0\0",
239 OUT_RAWDATA+align, NO_SEG, NO_SEG);
241 offset += e->stringlen + align;
244 if (t > 0 && t == instruction->times-1)
247 * Dummy call to list->output to give the offset to the
248 * listing module.
250 list->output (offset, NULL, OUT_RAWDATA);
251 list->uplevel (LIST_TIMES);
254 if (instruction->times > 1)
255 list->downlevel (LIST_TIMES);
256 return offset - start;
259 if (instruction->opcode == I_INCBIN)
261 static char fname[FILENAME_MAX];
262 FILE * fp;
263 long len;
265 len = FILENAME_MAX-1;
266 if (len > instruction->eops->stringlen)
267 len = instruction->eops->stringlen;
268 strncpy (fname, instruction->eops->stringval, len);
269 fname[len] = '\0';
271 if ( (fp = fopen(fname, "rb")) == NULL)
272 error (ERR_NONFATAL, "`incbin': unable to open file `%s'", fname);
273 else if (fseek(fp, 0L, SEEK_END) < 0)
274 error (ERR_NONFATAL, "`incbin': unable to seek on file `%s'",
275 fname);
276 else
278 static char buf[2048];
279 long t = instruction->times;
280 long base = 0;
282 len = ftell (fp);
283 if (instruction->eops->next) {
284 base = instruction->eops->next->offset;
285 len -= base;
286 if (instruction->eops->next->next &&
287 len > instruction->eops->next->next->offset)
288 len = instruction->eops->next->next->offset;
291 * Dummy call to list->output to give the offset to the
292 * listing module.
294 list->output (offset, NULL, OUT_RAWDATA);
295 list->uplevel(LIST_INCBIN);
296 while (t--)
298 long l;
300 fseek (fp, base, SEEK_SET);
301 l = len;
302 while (l > 0) {
303 long m = fread (buf, 1, (l>sizeof(buf)?sizeof(buf):l),
304 fp);
305 if (!m) {
307 * This shouldn't happen unless the file
308 * actually changes while we are reading
309 * it.
311 error (ERR_NONFATAL, "`incbin': unexpected EOF while"
312 " reading file `%s'", fname);
313 t=0; /* Try to exit cleanly */
314 break;
316 out (offset, segment, buf, OUT_RAWDATA+m,
317 NO_SEG, NO_SEG);
318 l -= m;
321 list->downlevel(LIST_INCBIN);
322 if (instruction->times > 1) {
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_TIMES);
329 list->downlevel(LIST_TIMES);
331 fclose (fp);
332 return instruction->times * len;
334 return 0; /* if we're here, there's an error */
337 size_prob = FALSE;
338 temp = nasm_instructions[instruction->opcode];
339 while (temp->opcode != -1) {
340 int m = matches (temp, instruction);
341 if (m == 99)
342 m += jmp_match(segment, offset, bits, instruction, temp->code);
344 if (m == 100) /* matches! */
346 char *codes = temp->code;
347 long insn_size = calcsize(segment, offset, bits,
348 instruction, codes);
349 itimes = instruction->times;
350 if (insn_size < 0) /* shouldn't be, on pass two */
351 error (ERR_PANIC, "errors made it through from pass one");
352 else while (itimes--) {
353 insn_end = offset + insn_size;
354 for (j=0; j<instruction->nprefix; j++) {
355 unsigned char c=0;
356 switch (instruction->prefixes[j]) {
357 case P_LOCK:
358 c = 0xF0; break;
359 case P_REPNE: case P_REPNZ:
360 c = 0xF2; break;
361 case P_REPE: case P_REPZ: case P_REP:
362 c = 0xF3; break;
363 case R_CS: c = 0x2E; break;
364 case R_DS: c = 0x3E; break;
365 case R_ES: c = 0x26; break;
366 case R_FS: c = 0x64; break;
367 case R_GS: c = 0x65; break;
368 case R_SS: c = 0x36; break;
369 case P_A16:
370 if (bits != 16)
371 c = 0x67;
372 break;
373 case P_A32:
374 if (bits != 32)
375 c = 0x67;
376 break;
377 case P_O16:
378 if (bits != 16)
379 c = 0x66;
380 break;
381 case P_O32:
382 if (bits != 32)
383 c = 0x66;
384 break;
385 default:
386 error (ERR_PANIC,
387 "invalid instruction prefix");
389 if (c != 0) {
390 out (offset, segment, &c, OUT_RAWDATA+1,
391 NO_SEG, NO_SEG);
392 offset++;
395 gencode (segment, offset, bits, instruction, codes, insn_end);
396 offset += insn_size;
397 if (itimes > 0 && itimes == instruction->times-1) {
399 * Dummy call to list->output to give the offset to the
400 * listing module.
402 list->output (offset, NULL, OUT_RAWDATA);
403 list->uplevel (LIST_TIMES);
406 if (instruction->times > 1)
407 list->downlevel (LIST_TIMES);
408 return offset - start;
409 } else if (m > 0 && m > size_prob) {
410 size_prob = m;
412 temp++;
415 if (temp->opcode == -1) { /* didn't match any instruction */
416 if (size_prob == 1) /* would have matched, but for size */
417 error (ERR_NONFATAL, "operation size not specified");
418 else if (size_prob == 2)
419 error (ERR_NONFATAL, "mismatch in operand sizes");
420 else if (size_prob == 3)
421 error (ERR_NONFATAL, "no instruction for this cpu level");
422 else
423 error (ERR_NONFATAL,
424 "invalid combination of opcode and operands");
426 return 0;
429 long insn_size (long segment, long offset, int bits, unsigned long cp,
430 insn *instruction, efunc error)
432 struct itemplate *temp;
434 errfunc = error; /* to pass to other functions */
435 cpu = cp;
437 if (instruction->opcode == -1)
438 return 0;
440 if (instruction->opcode == I_DB ||
441 instruction->opcode == I_DW ||
442 instruction->opcode == I_DD ||
443 instruction->opcode == I_DQ ||
444 instruction->opcode == I_DT)
446 extop *e;
447 long isize, osize, wsize = 0; /* placate gcc */
449 isize = 0;
450 switch (instruction->opcode)
452 case I_DB: wsize = 1; break;
453 case I_DW: wsize = 2; break;
454 case I_DD: wsize = 4; break;
455 case I_DQ: wsize = 8; break;
456 case I_DT: wsize = 10; break;
459 for (e = instruction->eops; e; e = e->next)
461 long align;
463 osize = 0;
464 if (e->type == EOT_DB_NUMBER)
465 osize = 1;
466 else if (e->type == EOT_DB_STRING)
467 osize = e->stringlen;
469 align = (-osize) % wsize;
470 if (align < 0)
471 align += wsize;
472 isize += osize + align;
474 return isize * instruction->times;
477 if (instruction->opcode == I_INCBIN)
479 char fname[FILENAME_MAX];
480 FILE * fp;
481 long len;
483 len = FILENAME_MAX-1;
484 if (len > instruction->eops->stringlen)
485 len = instruction->eops->stringlen;
486 strncpy (fname, instruction->eops->stringval, len);
487 fname[len] = '\0';
488 if ( (fp = fopen(fname, "rb")) == NULL )
489 error (ERR_NONFATAL, "`incbin': unable to open file `%s'", fname);
490 else if (fseek(fp, 0L, SEEK_END) < 0)
491 error (ERR_NONFATAL, "`incbin': unable to seek on file `%s'",
492 fname);
493 else
495 len = ftell (fp);
496 fclose (fp);
497 if (instruction->eops->next)
499 len -= instruction->eops->next->offset;
500 if (instruction->eops->next->next &&
501 len > instruction->eops->next->next->offset)
503 len = instruction->eops->next->next->offset;
506 return instruction->times * len;
508 return 0; /* if we're here, there's an error */
511 temp = nasm_instructions[instruction->opcode];
512 while (temp->opcode != -1) {
513 int m = matches(temp, instruction);
514 if (m == 99)
515 m += jmp_match(segment, offset, bits, instruction, temp->code);
517 if (m == 100) {
518 /* we've matched an instruction. */
519 long isize;
520 char * codes = temp->code;
521 int j;
523 isize = calcsize(segment, offset, bits, instruction, codes);
524 if (isize < 0)
525 return -1;
526 for (j = 0; j < instruction->nprefix; j++)
528 if ((instruction->prefixes[j] != P_A16 &&
529 instruction->prefixes[j] != P_O16 && bits==16) ||
530 (instruction->prefixes[j] != P_A32 &&
531 instruction->prefixes[j] != P_O32 && bits==32))
533 isize++;
536 return isize * instruction->times;
538 temp++;
540 return -1; /* didn't match any instruction */
544 /* check that opn[op] is a signed byte of size 16 or 32,
545 and return the signed value*/
546 static int is_sbyte (insn *ins, int op, int size)
548 signed long v;
549 int ret;
551 ret = !(ins->forw_ref && ins->oprs[op].opflags ) && /* dead in the water on forward reference or External */
552 (optimizing>0 || !(ins->oprs[op].type & (BITS16|BITS32))) &&
553 ins->oprs[op].wrt==NO_SEG && ins->oprs[op].segment==NO_SEG;
555 v = ins->oprs[op].offset;
556 if (size==16) v = (signed short)v; /* sign extend if 16 bits */
558 return ret && v>=-128L && v<=127L;
561 static long calcsize (long segment, long offset, int bits,
562 insn *ins, char *codes)
564 long length = 0;
565 unsigned char c;
567 (void) segment; /* Don't warn that this parameter is unused */
568 (void) offset; /* Don't warn that this parameter is unused */
570 while (*codes) switch (c = *codes++) {
571 case 01: case 02: case 03:
572 codes += c, length += c; break;
573 case 04: case 05: case 06: case 07:
574 length++; break;
575 case 010: case 011: case 012:
576 codes++, length++; break;
577 case 017:
578 length++; break;
579 case 014: case 015: case 016:
580 length++; break;
581 case 020: case 021: case 022:
582 length++; break;
583 case 024: case 025: case 026:
584 length++; break;
585 case 030: case 031: case 032:
586 length += 2; break;
587 case 034: case 035: case 036:
588 length += ((ins->oprs[c-034].addr_size ?
589 ins->oprs[c-034].addr_size : bits) == 16 ? 2 : 4); break;
590 case 037:
591 length += 2; break;
592 case 040: case 041: case 042:
593 length += 4; break;
594 case 050: case 051: case 052:
595 length++; break;
596 case 060: case 061: case 062:
597 length += 2; break;
598 case 064: case 065: case 066:
599 length += ((ins->oprs[c-064].addr_size ?
600 ins->oprs[c-064].addr_size : bits) == 16 ? 2 : 4); break;
601 case 070: case 071: case 072:
602 length += 4; break;
603 case 0130: case 0131: case 0132:
604 length += is_sbyte(ins, c-0130, 16) ? 1 : 2; break;
605 case 0133: case 0134: case 0135:
606 codes+=2; length++; break;
607 case 0140: case 0141: case 0142:
608 length += is_sbyte(ins, c-0140, 32) ? 1 : 4; break;
609 case 0143: case 0144: case 0145:
610 codes+=2; length++; break;
611 case 0300: case 0301: case 0302:
612 length += chsize (&ins->oprs[c-0300], bits);
613 break;
614 case 0310:
615 length += (bits==32);
616 break;
617 case 0311:
618 length += (bits==16);
619 break;
620 case 0312:
621 break;
622 case 0320:
623 length += (bits==32);
624 break;
625 case 0321:
626 length += (bits==16);
627 break;
628 case 0322:
629 break;
630 case 0330:
631 codes++, length++; break;
632 case 0331:
633 case 0332:
634 break;
635 case 0333:
636 length++; break;
637 case 0340: case 0341: case 0342:
638 if (ins->oprs[0].segment != NO_SEG)
639 errfunc (ERR_NONFATAL, "attempt to reserve non-constant"
640 " quantity of BSS space");
641 else
642 length += ins->oprs[0].offset << (c-0340);
643 break;
644 case 0370: case 0371: case 0372:
645 break;
646 case 0373:
647 length++; break;
648 default: /* can't do it by 'case' statements */
649 if (c>=0100 && c<=0277) { /* it's an EA */
650 ea ea_data;
651 if (!process_ea (&ins->oprs[(c>>3)&7], &ea_data, bits, 0,
652 ins->forw_ref)) {
653 errfunc (ERR_NONFATAL, "invalid effective address");
654 return -1;
655 } else
656 length += ea_data.size;
657 } else
658 errfunc (ERR_PANIC, "internal instruction table corrupt"
659 ": instruction code 0x%02X given", c);
661 return length;
664 static void gencode (long segment, long offset, int bits,
665 insn *ins, char *codes, long insn_end)
667 static char condval[] = { /* conditional opcodes */
668 0x7, 0x3, 0x2, 0x6, 0x2, 0x4, 0xF, 0xD, 0xC, 0xE, 0x6, 0x2,
669 0x3, 0x7, 0x3, 0x5, 0xE, 0xC, 0xD, 0xF, 0x1, 0xB, 0x9, 0x5,
670 0x0, 0xA, 0xA, 0xB, 0x8, 0x4
672 unsigned char c;
673 unsigned char bytes[4];
674 long data, size;
676 while (*codes)
677 switch (c = *codes++)
679 case 01: case 02: case 03:
680 out (offset, segment, codes, OUT_RAWDATA+c, NO_SEG, NO_SEG);
681 codes += c;
682 offset += c;
683 break;
685 case 04: case 06:
686 switch (ins->oprs[0].basereg)
688 case R_CS:
689 bytes[0] = 0x0E + (c == 0x04 ? 1 : 0); break;
690 case R_DS:
691 bytes[0] = 0x1E + (c == 0x04 ? 1 : 0); break;
692 case R_ES:
693 bytes[0] = 0x06 + (c == 0x04 ? 1 : 0); break;
694 case R_SS:
695 bytes[0] = 0x16 + (c == 0x04 ? 1 : 0); break;
696 default:
697 errfunc (ERR_PANIC, "bizarre 8086 segment register received");
699 out (offset, segment, bytes, OUT_RAWDATA+1, NO_SEG, NO_SEG);
700 offset++;
701 break;
703 case 05: case 07:
704 switch (ins->oprs[0].basereg) {
705 case R_FS: bytes[0] = 0xA0 + (c == 0x05 ? 1 : 0); break;
706 case R_GS: bytes[0] = 0xA8 + (c == 0x05 ? 1 : 0); break;
707 default:
708 errfunc (ERR_PANIC, "bizarre 386 segment register received");
710 out (offset, segment, bytes, OUT_RAWDATA+1, NO_SEG, NO_SEG);
711 offset++;
712 break;
714 case 010: case 011: case 012:
715 bytes[0] = *codes++ + regval(&ins->oprs[c-010]);
716 out (offset, segment, bytes, OUT_RAWDATA+1, NO_SEG, NO_SEG);
717 offset += 1;
718 break;
720 case 017:
721 bytes[0] = 0;
722 out (offset, segment, bytes, OUT_RAWDATA+1, NO_SEG, NO_SEG);
723 offset += 1;
724 break;
726 case 014: case 015: case 016:
727 if (ins->oprs[c-014].offset < -128
728 || ins->oprs[c-014].offset > 127)
730 errfunc (ERR_WARNING, "signed byte value exceeds bounds");
733 if (ins->oprs[c-014].segment != NO_SEG)
735 data = ins->oprs[c-014].offset;
736 out (offset, segment, &data, OUT_ADDRESS+1,
737 ins->oprs[c-014].segment, ins->oprs[c-014].wrt);
739 else {
740 bytes[0] = ins->oprs[c-014].offset;
741 out (offset, segment, bytes, OUT_RAWDATA+1, NO_SEG, NO_SEG);
743 offset += 1;
744 break;
746 case 020: case 021: case 022:
747 if (ins->oprs[c-020].offset < -256
748 || ins->oprs[c-020].offset > 255)
750 errfunc (ERR_WARNING, "byte value exceeds bounds");
752 if (ins->oprs[c-020].segment != NO_SEG) {
753 data = ins->oprs[c-020].offset;
754 out (offset, segment, &data, OUT_ADDRESS+1,
755 ins->oprs[c-020].segment, ins->oprs[c-020].wrt);
757 else {
758 bytes[0] = ins->oprs[c-020].offset;
759 out (offset, segment, bytes, OUT_RAWDATA+1, NO_SEG, NO_SEG);
761 offset += 1;
762 break;
764 case 024: case 025: case 026:
765 if (ins->oprs[c-024].offset < 0 || ins->oprs[c-024].offset > 255)
766 errfunc (ERR_WARNING, "unsigned byte value exceeds bounds");
767 if (ins->oprs[c-024].segment != NO_SEG) {
768 data = ins->oprs[c-024].offset;
769 out (offset, segment, &data, OUT_ADDRESS+1,
770 ins->oprs[c-024].segment, ins->oprs[c-024].wrt);
772 else {
773 bytes[0] = ins->oprs[c-024].offset;
774 out (offset, segment, bytes, OUT_RAWDATA+1, NO_SEG, NO_SEG);
776 offset += 1;
777 break;
779 case 030: case 031: case 032:
780 if (ins->oprs[c-030].segment == NO_SEG &&
781 ins->oprs[c-030].wrt == NO_SEG &&
782 (ins->oprs[c-030].offset < -65536L ||
783 ins->oprs[c-030].offset > 65535L))
785 errfunc (ERR_WARNING, "word value exceeds bounds");
787 data = ins->oprs[c-030].offset;
788 out (offset, segment, &data, OUT_ADDRESS+2,
789 ins->oprs[c-030].segment, ins->oprs[c-030].wrt);
790 offset += 2;
791 break;
793 case 034: case 035: case 036:
794 data = ins->oprs[c-034].offset;
795 size = ((ins->oprs[c-034].addr_size ?
796 ins->oprs[c-034].addr_size : bits) == 16 ? 2 : 4);
797 if (size==2 && (data < -65536L || data > 65535L))
798 errfunc (ERR_WARNING, "word value exceeds bounds");
799 out (offset, segment, &data, OUT_ADDRESS+size,
800 ins->oprs[c-034].segment, ins->oprs[c-034].wrt);
801 offset += size;
802 break;
804 case 037:
805 if (ins->oprs[0].segment == NO_SEG)
806 errfunc (ERR_NONFATAL, "value referenced by FAR is not"
807 " relocatable");
808 data = 0L;
809 out (offset, segment, &data, OUT_ADDRESS+2,
810 outfmt->segbase(1+ins->oprs[0].segment),
811 ins->oprs[0].wrt);
812 offset += 2;
813 break;
815 case 040: case 041: case 042:
816 data = ins->oprs[c-040].offset;
817 out (offset, segment, &data, OUT_ADDRESS+4,
818 ins->oprs[c-040].segment, ins->oprs[c-040].wrt);
819 offset += 4;
820 break;
822 case 050: case 051: case 052:
823 if (ins->oprs[c-050].segment != segment)
824 errfunc (ERR_NONFATAL, "short relative jump outside segment");
825 data = ins->oprs[c-050].offset - insn_end;
826 if (data > 127 || data < -128)
827 errfunc (ERR_NONFATAL, "short jump is out of range");
828 bytes[0] = data;
829 out (offset, segment, bytes, OUT_RAWDATA+1, NO_SEG, NO_SEG);
830 offset += 1;
831 break;
833 case 060: case 061: case 062:
834 if (ins->oprs[c-060].segment != segment) {
835 data = ins->oprs[c-060].offset;
836 out (offset, segment, &data, OUT_REL2ADR+insn_end-offset,
837 ins->oprs[c-060].segment, ins->oprs[c-060].wrt);
838 } else {
839 data = ins->oprs[c-060].offset - insn_end;
840 out (offset, segment, &data,
841 OUT_ADDRESS+2, NO_SEG, NO_SEG);
843 offset += 2;
844 break;
846 case 064: case 065: case 066:
847 size = ((ins->oprs[c-064].addr_size ?
848 ins->oprs[c-064].addr_size : bits) == 16 ? 2 : 4);
849 if (ins->oprs[c-064].segment != segment) {
850 data = ins->oprs[c-064].offset;
851 size = (bits == 16 ? OUT_REL2ADR : OUT_REL4ADR);
852 out (offset, segment, &data, size+insn_end-offset,
853 ins->oprs[c-064].segment, ins->oprs[c-064].wrt);
854 size = (bits == 16 ? 2 : 4);
855 } else {
856 data = ins->oprs[c-064].offset - insn_end;
857 out (offset, segment, &data,
858 OUT_ADDRESS+size, NO_SEG, NO_SEG);
860 offset += size;
861 break;
863 case 070: case 071: case 072:
864 if (ins->oprs[c-070].segment != segment) {
865 data = ins->oprs[c-070].offset;
866 out (offset, segment, &data, OUT_REL4ADR+insn_end-offset,
867 ins->oprs[c-070].segment, ins->oprs[c-070].wrt);
868 } else {
869 data = ins->oprs[c-070].offset - insn_end;
870 out (offset, segment, &data,
871 OUT_ADDRESS+4, NO_SEG, NO_SEG);
873 offset += 4;
874 break;
876 case 0130: case 0131: case 0132:
877 data = ins->oprs[c-0130].offset;
878 if (is_sbyte(ins, c-0130, 16)) {
879 out (offset, segment, &data, OUT_RAWDATA+1, NO_SEG, NO_SEG);
880 offset++;
881 } else {
882 if (ins->oprs[c-0130].segment == NO_SEG &&
883 ins->oprs[c-0130].wrt == NO_SEG &&
884 (data < -65536L || data > 65535L)) {
885 errfunc (ERR_WARNING, "word value exceeds bounds");
887 out (offset, segment, &data, OUT_ADDRESS+2,
888 ins->oprs[c-0130].segment, ins->oprs[c-0130].wrt);
889 offset += 2;
891 break;
893 case 0133: case 0134: case 0135:
894 codes++;
895 bytes[0] = *codes++;
896 if (is_sbyte(ins, c-0133, 16)) bytes[0] |= 2; /* s-bit */
897 out (offset, segment, bytes, OUT_RAWDATA+1, NO_SEG, NO_SEG);
898 offset++;
899 break;
901 case 0140: case 0141: case 0142:
902 data = ins->oprs[c-0140].offset;
903 if (is_sbyte(ins, c-0140, 32)) {
904 out (offset, segment, &data, OUT_RAWDATA+1, NO_SEG, NO_SEG);
905 offset++;
906 } else {
907 out (offset, segment, &data, OUT_ADDRESS+4,
908 ins->oprs[c-0140].segment, ins->oprs[c-0140].wrt);
909 offset += 4;
911 break;
913 case 0143: case 0144: case 0145:
914 codes++;
915 bytes[0] = *codes++;
916 if (is_sbyte(ins, c-0143, 32)) bytes[0] |= 2; /* s-bit */
917 out (offset, segment, bytes, OUT_RAWDATA+1, NO_SEG, NO_SEG);
918 offset++;
919 break;
921 case 0300: case 0301: case 0302:
922 if (chsize (&ins->oprs[c-0300], bits)) {
923 *bytes = 0x67;
924 out (offset, segment, bytes,
925 OUT_RAWDATA+1, NO_SEG, NO_SEG);
926 offset += 1;
927 } else
928 offset += 0;
929 break;
931 case 0310:
932 if (bits==32) {
933 *bytes = 0x67;
934 out (offset, segment, bytes,
935 OUT_RAWDATA+1, NO_SEG, NO_SEG);
936 offset += 1;
937 } else
938 offset += 0;
939 break;
941 case 0311:
942 if (bits==16) {
943 *bytes = 0x67;
944 out (offset, segment, bytes,
945 OUT_RAWDATA+1, NO_SEG, NO_SEG);
946 offset += 1;
947 } else
948 offset += 0;
949 break;
951 case 0312:
952 break;
954 case 0320:
955 if (bits==32) {
956 *bytes = 0x66;
957 out (offset, segment, bytes,
958 OUT_RAWDATA+1, NO_SEG, NO_SEG);
959 offset += 1;
960 } else
961 offset += 0;
962 break;
964 case 0321:
965 if (bits==16) {
966 *bytes = 0x66;
967 out (offset, segment, bytes,
968 OUT_RAWDATA+1, NO_SEG, NO_SEG);
969 offset += 1;
970 } else
971 offset += 0;
972 break;
974 case 0322:
975 break;
977 case 0330:
978 *bytes = *codes++ ^ condval[ins->condition];
979 out (offset, segment, bytes,
980 OUT_RAWDATA+1, NO_SEG, NO_SEG);
981 offset += 1;
982 break;
984 case 0331:
985 case 0332:
986 break;
988 case 0333:
989 *bytes = 0xF3;
990 out (offset, segment, bytes,
991 OUT_RAWDATA+1, NO_SEG, NO_SEG);
992 offset += 1;
993 break;
995 case 0340: case 0341: case 0342:
996 if (ins->oprs[0].segment != NO_SEG)
997 errfunc (ERR_PANIC, "non-constant BSS size in pass two");
998 else {
999 long size = ins->oprs[0].offset << (c-0340);
1000 if (size > 0)
1001 out (offset, segment, NULL,
1002 OUT_RESERVE+size, NO_SEG, NO_SEG);
1003 offset += size;
1005 break;
1007 case 0370: case 0371: case 0372:
1008 break;
1010 case 0373:
1011 *bytes = bits==16 ? 3 : 5;
1012 out (offset, segment, bytes,
1013 OUT_RAWDATA+1, NO_SEG, NO_SEG);
1014 offset += 1;
1015 break;
1017 default: /* can't do it by 'case' statements */
1018 if (c>=0100 && c<=0277) { /* it's an EA */
1019 ea ea_data;
1020 int rfield;
1021 unsigned char *p;
1022 long s;
1024 if (c<=0177) /* pick rfield from operand b */
1025 rfield = regval (&ins->oprs[c&7]);
1026 else /* rfield is constant */
1027 rfield = c & 7;
1029 if (!process_ea (&ins->oprs[(c>>3)&7], &ea_data, bits, rfield,
1030 ins->forw_ref))
1032 errfunc (ERR_NONFATAL, "invalid effective address");
1035 p = bytes;
1036 *p++ = ea_data.modrm;
1037 if (ea_data.sib_present)
1038 *p++ = ea_data.sib;
1040 s = p-bytes;
1041 out (offset, segment, bytes, OUT_RAWDATA + s,
1042 NO_SEG, NO_SEG);
1044 switch (ea_data.bytes) {
1045 case 0:
1046 break;
1047 case 1:
1048 if (ins->oprs[(c>>3)&7].segment != NO_SEG) {
1049 data = ins->oprs[(c>>3)&7].offset;
1050 out (offset, segment, &data, OUT_ADDRESS+1,
1051 ins->oprs[(c>>3)&7].segment,
1052 ins->oprs[(c>>3)&7].wrt);
1053 } else {
1054 *bytes = ins->oprs[(c>>3)&7].offset;
1055 out (offset, segment, bytes, OUT_RAWDATA+1,
1056 NO_SEG, NO_SEG);
1058 s++;
1059 break;
1060 case 2:
1061 case 4:
1062 data = ins->oprs[(c>>3)&7].offset;
1063 out (offset, segment, &data,
1064 OUT_ADDRESS+ea_data.bytes,
1065 ins->oprs[(c>>3)&7].segment, ins->oprs[(c>>3)&7].wrt);
1066 s += ea_data.bytes;
1067 break;
1069 offset += s;
1070 } else
1071 errfunc (ERR_PANIC, "internal instruction table corrupt"
1072 ": instruction code 0x%02X given", c);
1076 static int regval (operand *o)
1078 switch (o->basereg) {
1079 case R_EAX: case R_AX: case R_AL: case R_ES: case R_CR0: case R_DR0:
1080 case R_ST0: case R_MM0: case R_XMM0:
1081 return 0;
1082 case R_ECX: case R_CX: case R_CL: case R_CS: case R_DR1: case R_ST1:
1083 case R_MM1: case R_XMM1:
1084 return 1;
1085 case R_EDX: case R_DX: case R_DL: case R_SS: case R_CR2: case R_DR2:
1086 case R_ST2: case R_MM2: case R_XMM2:
1087 return 2;
1088 case R_EBX: case R_BX: case R_BL: case R_DS: case R_CR3: case R_DR3:
1089 case R_TR3: case R_ST3: case R_MM3: case R_XMM3:
1090 return 3;
1091 case R_ESP: case R_SP: case R_AH: case R_FS: case R_CR4: case R_TR4:
1092 case R_ST4: case R_MM4: case R_XMM4:
1093 return 4;
1094 case R_EBP: case R_BP: case R_CH: case R_GS: case R_TR5: case R_ST5:
1095 case R_MM5: case R_XMM5:
1096 return 5;
1097 case R_ESI: case R_SI: case R_DH: case R_DR6: case R_TR6: case R_ST6:
1098 case R_MM6: case R_XMM6:
1099 return 6;
1100 case R_EDI: case R_DI: case R_BH: case R_DR7: case R_TR7: case R_ST7:
1101 case R_MM7: case R_XMM7:
1102 return 7;
1103 default: /* panic */
1104 errfunc (ERR_PANIC, "invalid register operand given to regval()");
1105 return 0;
1109 static int matches (struct itemplate *itemp, insn *instruction)
1111 int i, size[3], asize, oprs, ret;
1113 ret = 100;
1116 * Check the opcode
1118 if (itemp->opcode != instruction->opcode) return 0;
1121 * Count the operands
1123 if (itemp->operands != instruction->operands) return 0;
1126 * Check that no spurious colons or TOs are present
1128 for (i=0; i<itemp->operands; i++)
1129 if (instruction->oprs[i].type & ~itemp->opd[i] & (COLON|TO))
1130 return 0;
1133 * Check that the operand flags all match up
1135 for (i=0; i<itemp->operands; i++)
1136 if (itemp->opd[i] & ~instruction->oprs[i].type ||
1137 ((itemp->opd[i] & SIZE_MASK) &&
1138 ((itemp->opd[i] ^ instruction->oprs[i].type) & SIZE_MASK)))
1140 if ((itemp->opd[i] & ~instruction->oprs[i].type & NON_SIZE) ||
1141 (instruction->oprs[i].type & SIZE_MASK))
1142 return 0;
1143 else
1144 /* ret = 1; */
1145 return 1;
1149 * Check operand sizes
1151 if (itemp->flags & IF_ARMASK) {
1152 size[0] = size[1] = size[2] = 0;
1154 switch (itemp->flags & IF_ARMASK) {
1155 case IF_AR0: i = 0; break;
1156 case IF_AR1: i = 1; break;
1157 case IF_AR2: i = 2; break;
1158 default: break; /* Shouldn't happen */
1160 if (itemp->flags & IF_SB) {
1161 size[i] = BITS8;
1162 } else if (itemp->flags & IF_SW) {
1163 size[i] = BITS16;
1164 } else if (itemp->flags & IF_SD) {
1165 size[i] = BITS32;
1167 } else {
1168 asize = 0;
1169 if (itemp->flags & IF_SB) {
1170 asize = BITS8;
1171 oprs = itemp->operands;
1172 } else if (itemp->flags & IF_SW) {
1173 asize = BITS16;
1174 oprs = itemp->operands;
1175 } else if (itemp->flags & IF_SD) {
1176 asize = BITS32;
1177 oprs = itemp->operands;
1179 size[0] = size[1] = size[2] = asize;
1182 if (itemp->flags & (IF_SM | IF_SM2)) {
1183 oprs = (itemp->flags & IF_SM2 ? 2 : itemp->operands);
1184 asize = 0;
1185 for (i=0; i<oprs; i++) {
1186 if ( (asize = itemp->opd[i] & SIZE_MASK) != 0) {
1187 int j;
1188 for (j=0; j<oprs; j++)
1189 size[j] = asize;
1190 break;
1193 } else {
1194 oprs = itemp->operands;
1197 for (i=0; i<itemp->operands; i++)
1198 if (!(itemp->opd[i] & SIZE_MASK) &&
1199 (instruction->oprs[i].type & SIZE_MASK & ~size[i]))
1200 /* ret = 2; */
1201 return 2;
1204 * Check template is okay at the set cpu level
1206 if ((itemp->flags & IF_PLEVEL) > cpu) return 3;
1209 * Check if special handling needed for Jumps
1211 if ((unsigned char)(itemp->code[0]) >= 0370) return 99;
1213 return ret;
1216 static ea *process_ea (operand *input, ea *output, int addrbits, int rfield,
1217 int forw_ref)
1219 if (!(REGISTER & ~input->type)) { /* it's a single register */
1220 static int regs[] = {
1221 R_AL, R_CL, R_DL, R_BL, R_AH, R_CH, R_DH, R_BH,
1222 R_AX, R_CX, R_DX, R_BX, R_SP, R_BP, R_SI, R_DI,
1223 R_EAX, R_ECX, R_EDX, R_EBX, R_ESP, R_EBP, R_ESI, R_EDI,
1224 R_MM0, R_MM1, R_MM2, R_MM3, R_MM4, R_MM5, R_MM6, R_MM7,
1225 R_XMM0, R_XMM1, R_XMM2, R_XMM3, R_XMM4, R_XMM5, R_XMM6, R_XMM7
1227 int i;
1229 for (i=0; i<elements(regs); i++)
1230 if (input->basereg == regs[i]) break;
1231 if (i<elements(regs)) {
1232 output->sib_present = FALSE;/* no SIB necessary */
1233 output->bytes = 0; /* no offset necessary either */
1234 output->modrm = 0xC0 | (rfield << 3) | (i & 7);
1236 else
1237 return NULL;
1238 } else { /* it's a memory reference */
1239 if (input->basereg==-1 && (input->indexreg==-1 || input->scale==0)) {
1240 /* it's a pure offset */
1241 if (input->addr_size)
1242 addrbits = input->addr_size;
1243 output->sib_present = FALSE;
1244 output->bytes = (addrbits==32 ? 4 : 2);
1245 output->modrm = (addrbits==32 ? 5 : 6) | (rfield << 3);
1247 else { /* it's an indirection */
1248 int i=input->indexreg, b=input->basereg, s=input->scale;
1249 long o=input->offset, seg=input->segment;
1250 int hb=input->hintbase, ht=input->hinttype;
1251 int t;
1253 if (s==0) i = -1; /* make this easy, at least */
1255 if (i==R_EAX || i==R_EBX || i==R_ECX || i==R_EDX
1256 || i==R_EBP || i==R_ESP || i==R_ESI || i==R_EDI
1257 || b==R_EAX || b==R_EBX || b==R_ECX || b==R_EDX
1258 || b==R_EBP || b==R_ESP || b==R_ESI || b==R_EDI) {
1259 /* it must be a 32-bit memory reference. Firstly we have
1260 * to check that all registers involved are type Exx. */
1261 if (i!=-1 && i!=R_EAX && i!=R_EBX && i!=R_ECX && i!=R_EDX
1262 && i!=R_EBP && i!=R_ESP && i!=R_ESI && i!=R_EDI)
1263 return NULL;
1264 if (b!=-1 && b!=R_EAX && b!=R_EBX && b!=R_ECX && b!=R_EDX
1265 && b!=R_EBP && b!=R_ESP && b!=R_ESI && b!=R_EDI)
1266 return NULL;
1268 /* While we're here, ensure the user didn't specify WORD. */
1269 if (input->addr_size == 16)
1270 return NULL;
1272 /* now reorganise base/index */
1273 if (s == 1 && b != i && b != -1 && i != -1 &&
1274 ((hb==b&&ht==EAH_NOTBASE) || (hb==i&&ht==EAH_MAKEBASE)))
1275 t = b, b = i, i = t; /* swap if hints say so */
1276 if (b==i) /* convert EAX+2*EAX to 3*EAX */
1277 b = -1, s++;
1278 if (b==-1 && s==1 && !(hb == i && ht == EAH_NOTBASE))
1279 b = i, i = -1; /* make single reg base, unless hint */
1280 if (((s==2 && i!=R_ESP && !(input->eaflags & EAF_TIMESTWO)) ||
1281 s==3 || s==5 || s==9) && b==-1)
1282 b = i, s--; /* convert 3*EAX to EAX+2*EAX */
1283 if (s==1 && i==R_ESP) /* swap ESP into base if scale is 1 */
1284 i = b, b = R_ESP;
1285 if (i==R_ESP || (s!=1 && s!=2 && s!=4 && s!=8 && i!=-1))
1286 return NULL; /* wrong, for various reasons */
1288 if (i==-1 && b!=R_ESP) {/* no SIB needed */
1289 int mod, rm;
1290 switch(b) {
1291 case R_EAX: rm = 0; break;
1292 case R_ECX: rm = 1; break;
1293 case R_EDX: rm = 2; break;
1294 case R_EBX: rm = 3; break;
1295 case R_EBP: rm = 5; break;
1296 case R_ESI: rm = 6; break;
1297 case R_EDI: rm = 7; break;
1298 case -1: rm = 5; break;
1299 default: /* should never happen */
1300 return NULL;
1302 if (b==-1 || (b!=R_EBP && o==0 &&
1303 seg==NO_SEG && !forw_ref &&
1304 !(input->eaflags &
1305 (EAF_BYTEOFFS|EAF_WORDOFFS))))
1306 mod = 0;
1307 else if (input->eaflags & EAF_BYTEOFFS ||
1308 (o>=-128 && o<=127 && seg==NO_SEG && !forw_ref &&
1309 !(input->eaflags & EAF_WORDOFFS))) {
1310 mod = 1;
1312 else
1313 mod = 2;
1315 output->sib_present = FALSE;
1316 output->bytes = (b==-1 || mod==2 ? 4 : mod);
1317 output->modrm = (mod<<6) | (rfield<<3) | rm;
1319 else { /* we need a SIB */
1320 int mod, scale, index, base;
1322 switch (b) {
1323 case R_EAX: base = 0; break;
1324 case R_ECX: base = 1; break;
1325 case R_EDX: base = 2; break;
1326 case R_EBX: base = 3; break;
1327 case R_ESP: base = 4; break;
1328 case R_EBP: case -1: base = 5; break;
1329 case R_ESI: base = 6; break;
1330 case R_EDI: base = 7; break;
1331 default: /* then what the smeg is it? */
1332 return NULL; /* panic */
1335 switch (i) {
1336 case R_EAX: index = 0; break;
1337 case R_ECX: index = 1; break;
1338 case R_EDX: index = 2; break;
1339 case R_EBX: index = 3; break;
1340 case -1: index = 4; break;
1341 case R_EBP: index = 5; break;
1342 case R_ESI: index = 6; break;
1343 case R_EDI: index = 7; break;
1344 default: /* then what the smeg is it? */
1345 return NULL; /* panic */
1348 if (i==-1) s = 1;
1349 switch (s) {
1350 case 1: scale = 0; break;
1351 case 2: scale = 1; break;
1352 case 4: scale = 2; break;
1353 case 8: scale = 3; break;
1354 default: /* then what the smeg is it? */
1355 return NULL; /* panic */
1358 if (b==-1 || (b!=R_EBP && o==0 &&
1359 seg==NO_SEG && !forw_ref &&
1360 !(input->eaflags &
1361 (EAF_BYTEOFFS|EAF_WORDOFFS))))
1362 mod = 0;
1363 else if (input->eaflags & EAF_BYTEOFFS ||
1364 (o>=-128 && o<=127 && seg==NO_SEG && !forw_ref &&
1365 !(input->eaflags & EAF_WORDOFFS)))
1366 mod = 1;
1367 else
1368 mod = 2;
1370 output->sib_present = TRUE;
1371 output->bytes = (b==-1 || mod==2 ? 4 : mod);
1372 output->modrm = (mod<<6) | (rfield<<3) | 4;
1373 output->sib = (scale<<6) | (index<<3) | base;
1376 else { /* it's 16-bit */
1377 int mod, rm;
1379 /* check all registers are BX, BP, SI or DI */
1380 if ((b!=-1 && b!=R_BP && b!=R_BX && b!=R_SI && b!=R_DI) ||
1381 (i!=-1 && i!=R_BP && i!=R_BX && i!=R_SI && i!=R_DI))
1382 return NULL;
1384 /* ensure the user didn't specify DWORD */
1385 if (input->addr_size == 32)
1386 return NULL;
1388 if (s!=1 && i!=-1) return NULL;/* no can do, in 16-bit EA */
1389 if (b==-1 && i!=-1) b ^= i ^= b ^= i; /* swap them round */
1390 if ((b==R_SI || b==R_DI) && i!=-1)
1391 b ^= i ^= b ^= i; /* have BX/BP as base, SI/DI index */
1392 if (b==i) return NULL;/* shouldn't ever happen, in theory */
1393 if (i!=-1 && b!=-1 &&
1394 (i==R_BP || i==R_BX || b==R_SI || b==R_DI))
1395 return NULL; /* invalid combinations */
1396 if (b==-1) /* pure offset: handled above */
1397 return NULL; /* so if it gets to here, panic! */
1399 rm = -1;
1400 if (i!=-1)
1401 switch (i*256 + b) {
1402 case R_SI*256+R_BX: rm=0; break;
1403 case R_DI*256+R_BX: rm=1; break;
1404 case R_SI*256+R_BP: rm=2; break;
1405 case R_DI*256+R_BP: rm=3; break;
1407 else
1408 switch (b) {
1409 case R_SI: rm=4; break;
1410 case R_DI: rm=5; break;
1411 case R_BP: rm=6; break;
1412 case R_BX: rm=7; break;
1414 if (rm==-1) /* can't happen, in theory */
1415 return NULL; /* so panic if it does */
1417 if (o==0 && seg==NO_SEG && !forw_ref && rm!=6 &&
1418 !(input->eaflags & (EAF_BYTEOFFS|EAF_WORDOFFS)))
1419 mod = 0;
1420 else if (input->eaflags & EAF_BYTEOFFS ||
1421 (o>=-128 && o<=127 && seg==NO_SEG && !forw_ref &&
1422 !(input->eaflags & EAF_WORDOFFS)))
1423 mod = 1;
1424 else
1425 mod = 2;
1427 output->sib_present = FALSE; /* no SIB - it's 16-bit */
1428 output->bytes = mod; /* bytes of offset needed */
1429 output->modrm = (mod<<6) | (rfield<<3) | rm;
1433 output->size = 1 + output->sib_present + output->bytes;
1434 return output;
1437 static int chsize (operand *input, int addrbits)
1439 if (!(MEMORY & ~input->type)) {
1440 int i=input->indexreg, b=input->basereg;
1442 if (input->scale==0) i = -1;
1444 if (i == -1 && b == -1) /* pure offset */
1445 return (input->addr_size != 0 && input->addr_size != addrbits);
1447 if (i==R_EAX || i==R_EBX || i==R_ECX || i==R_EDX
1448 || i==R_EBP || i==R_ESP || i==R_ESI || i==R_EDI
1449 || b==R_EAX || b==R_EBX || b==R_ECX || b==R_EDX
1450 || b==R_EBP || b==R_ESP || b==R_ESI || b==R_EDI)
1451 return (addrbits==16);
1452 else
1453 return (addrbits==32);
1455 else
1456 return 0;