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
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
79 extern struct itemplate
*nasm_instructions
[];
82 int sib_present
; /* is a SIB byte necessary? */
83 int bytes
; /* # of bytes of offset needed */
84 int size
; /* lazy - this is sib+bytes+1 */
85 unsigned char modrm
, sib
; /* the bytes themselves */
88 static unsigned long cpu
; /* cpu level received from nasm.c */
90 static struct ofmt
*outfmt
;
93 static long calcsize (long, long, int, insn
*, const char *);
94 static void gencode (long, long, int, insn
*, const char *, long);
95 static int regval (operand
*o
);
96 static int matches (struct itemplate
*, insn
*);
97 static ea
* process_ea (operand
*, ea
*, int, int, int);
98 static int chsize (operand
*, int);
101 * This routine wrappers the real output format's output routine,
102 * in order to pass a copy of the data off to the listing file
103 * generator at the same time.
105 static void out (long offset
, long segto
, const void *data
, unsigned long type
,
106 long segment
, long wrt
)
108 static long lineno
= 0; /* static!!! */
109 static char *lnfname
= NULL
;
111 if ((type
& OUT_TYPMASK
) == OUT_ADDRESS
) {
112 if (segment
!= NO_SEG
|| wrt
!= NO_SEG
) {
114 * This address is relocated. We must write it as
115 * OUT_ADDRESS, so there's no work to be done here.
117 list
->output (offset
, data
, type
);
120 unsigned char p
[4], *q
= p
;
122 * This is a non-relocated address, and we're going to
123 * convert it into RAWDATA format.
125 if ((type
& OUT_SIZMASK
) == 4) {
126 WRITELONG (q
, * (long *) data
);
127 list
->output (offset
, p
, OUT_RAWDATA
+4);
130 WRITESHORT (q
, * (long *) data
);
131 list
->output (offset
, p
, OUT_RAWDATA
+2);
135 else if ((type
& OUT_TYPMASK
) == OUT_RAWDATA
) {
136 list
->output (offset
, data
, type
);
138 else if ((type
& OUT_TYPMASK
) == OUT_RESERVE
) {
139 list
->output (offset
, NULL
, type
);
141 else if ((type
& OUT_TYPMASK
) == OUT_REL2ADR
||
142 (type
& OUT_TYPMASK
) == OUT_REL4ADR
) {
143 list
->output (offset
, data
, type
);
147 * this call to src_get determines when we call the
148 * debug-format-specific "linenum" function
149 * it updates lineno and lnfname to the current values
150 * returning 0 if "same as last time", -2 if lnfname
151 * changed, and the amount by which lineno changed,
152 * if it did. thus, these variables must be static
155 if (src_get(&lineno
,&lnfname
))
157 outfmt
->current_dfmt
->linenum(lnfname
,lineno
,segto
);
160 outfmt
->output (segto
, data
, type
, segment
, wrt
);
163 static int jmp_match (long segment
, long offset
, int bits
,
164 insn
*ins
, const char *code
)
166 unsigned char c
= code
[0];
169 if (c
!= 0370 && c
!= 0371) return 0;
170 if (ins
->oprs
[0].opflags
& OPFLAG_FORWARD
) {
171 if ((optimizing
<0 || (ins
->oprs
[0].type
& STRICT
))
172 && c
==0370) return 1;
173 else return (pass0
==0); /* match a forward reference */
175 isize
= calcsize (segment
, offset
, bits
, ins
, code
);
176 if (ins
->oprs
[0].segment
!= segment
) return 0;
177 isize
= ins
->oprs
[0].offset
- offset
- isize
; /* isize is now the delta */
178 if (isize
>= -128L && isize
<= 127L) return 1; /* it is byte size */
184 long assemble (long segment
, long offset
, int bits
, unsigned long cp
,
185 insn
*instruction
, struct ofmt
*output
, efunc error
,
188 struct itemplate
*temp
;
194 long wsize
= 0; /* size for DB etc. */
196 errfunc
= error
; /* to pass to other functions */
198 outfmt
= output
; /* likewise */
199 list
= listgen
; /* and again */
201 switch (instruction
->opcode
)
204 case I_DB
: wsize
= 1; break;
205 case I_DW
: wsize
= 2; break;
206 case I_DD
: wsize
= 4; break;
207 case I_DQ
: wsize
= 8; break;
208 case I_DT
: wsize
= 10; break;
213 long t
= instruction
->times
;
215 errfunc(ERR_PANIC
, "instruction->times < 0 (%ld) in assemble()",t
);
217 while (t
--) /* repeat TIMES times */
219 for (e
= instruction
->eops
; e
; e
= e
->next
)
221 if (e
->type
== EOT_DB_NUMBER
)
224 if (e
->segment
!= NO_SEG
)
225 errfunc (ERR_NONFATAL
,
226 "one-byte relocation attempted");
228 unsigned char out_byte
= e
->offset
;
229 out (offset
, segment
, &out_byte
, OUT_RAWDATA
+1,
233 else if (wsize
> 5) {
234 errfunc (ERR_NONFATAL
, "integer supplied to a D%c"
235 " instruction", wsize
==8 ? 'Q' : 'T');
238 out (offset
, segment
, &e
->offset
,
239 OUT_ADDRESS
+wsize
, e
->segment
,
243 else if (e
->type
== EOT_DB_STRING
)
247 out (offset
, segment
, e
->stringval
,
248 OUT_RAWDATA
+e
->stringlen
, NO_SEG
, NO_SEG
);
249 align
= e
->stringlen
% wsize
;
252 align
= wsize
- align
;
253 out (offset
, segment
, "\0\0\0\0\0\0\0\0",
254 OUT_RAWDATA
+align
, NO_SEG
, NO_SEG
);
256 offset
+= e
->stringlen
+ align
;
259 if (t
> 0 && t
== instruction
->times
-1)
262 * Dummy call to list->output to give the offset to the
265 list
->output (offset
, NULL
, OUT_RAWDATA
);
266 list
->uplevel (LIST_TIMES
);
269 if (instruction
->times
> 1)
270 list
->downlevel (LIST_TIMES
);
271 return offset
- start
;
274 if (instruction
->opcode
== I_INCBIN
)
276 static char fname
[FILENAME_MAX
];
279 char *prefix
= "", *combine
;
280 char** pPrevPath
= NULL
;
282 len
= FILENAME_MAX
-1;
283 if (len
> instruction
->eops
->stringlen
)
284 len
= instruction
->eops
->stringlen
;
285 strncpy (fname
, instruction
->eops
->stringval
, len
);
288 while (1) /* added by alexfru: 'incbin' uses include paths */
290 combine
= nasm_malloc(strlen(prefix
) + len
+ 1);
291 strcpy(combine
, prefix
);
292 strcat(combine
, fname
);
294 if ( (fp
= fopen(combine
, "rb")) != NULL
)
301 pPrevPath
= pp_get_include_path_ptr (pPrevPath
);
302 if (pPrevPath
== NULL
)
308 error (ERR_NONFATAL
, "`incbin': unable to open file `%s'", fname
);
309 else if (fseek(fp
, 0L, SEEK_END
) < 0)
310 error (ERR_NONFATAL
, "`incbin': unable to seek on file `%s'",
314 static char buf
[2048];
315 long t
= instruction
->times
;
319 if (instruction
->eops
->next
) {
320 base
= instruction
->eops
->next
->offset
;
322 if (instruction
->eops
->next
->next
&&
323 len
> instruction
->eops
->next
->next
->offset
)
324 len
= instruction
->eops
->next
->next
->offset
;
327 * Dummy call to list->output to give the offset to the
330 list
->output (offset
, NULL
, OUT_RAWDATA
);
331 list
->uplevel(LIST_INCBIN
);
336 fseek (fp
, base
, SEEK_SET
);
339 long m
= fread (buf
, 1, (l
>sizeof(buf
)?sizeof(buf
):l
),
343 * This shouldn't happen unless the file
344 * actually changes while we are reading
347 error (ERR_NONFATAL
, "`incbin': unexpected EOF while"
348 " reading file `%s'", fname
);
349 t
=0; /* Try to exit cleanly */
352 out (offset
, segment
, buf
, OUT_RAWDATA
+m
,
357 list
->downlevel(LIST_INCBIN
);
358 if (instruction
->times
> 1) {
360 * Dummy call to list->output to give the offset to the
363 list
->output (offset
, NULL
, OUT_RAWDATA
);
364 list
->uplevel(LIST_TIMES
);
365 list
->downlevel(LIST_TIMES
);
368 return instruction
->times
* len
;
370 return 0; /* if we're here, there's an error */
374 temp
= nasm_instructions
[instruction
->opcode
];
375 while (temp
->opcode
!= -1) {
376 int m
= matches (temp
, instruction
);
378 m
+= jmp_match(segment
, offset
, bits
, instruction
, temp
->code
);
380 if (m
== 100) /* matches! */
382 const char *codes
= temp
->code
;
383 long insn_size
= calcsize(segment
, offset
, bits
,
385 itimes
= instruction
->times
;
386 if (insn_size
< 0) /* shouldn't be, on pass two */
387 error (ERR_PANIC
, "errors made it through from pass one");
388 else while (itimes
--) {
389 for (j
=0; j
<instruction
->nprefix
; j
++) {
391 switch (instruction
->prefixes
[j
]) {
394 case P_REPNE
: case P_REPNZ
:
396 case P_REPE
: case P_REPZ
: case P_REP
:
398 case R_CS
: c
= 0x2E; break;
399 case R_DS
: c
= 0x3E; break;
400 case R_ES
: c
= 0x26; break;
401 case R_FS
: c
= 0x64; break;
402 case R_GS
: c
= 0x65; break;
403 case R_SS
: c
= 0x36; break;
406 error (ERR_NONFATAL
, "segr6 and segr7 cannot be used as prefixes");
426 "invalid instruction prefix");
429 out (offset
, segment
, &c
, OUT_RAWDATA
+1,
434 insn_end
= offset
+ insn_size
;
435 gencode (segment
, offset
, bits
, instruction
, codes
, insn_end
);
437 if (itimes
> 0 && itimes
== instruction
->times
-1) {
439 * Dummy call to list->output to give the offset to the
442 list
->output (offset
, NULL
, OUT_RAWDATA
);
443 list
->uplevel (LIST_TIMES
);
446 if (instruction
->times
> 1)
447 list
->downlevel (LIST_TIMES
);
448 return offset
- start
;
449 } else if (m
> 0 && m
> size_prob
) {
455 if (temp
->opcode
== -1) { /* didn't match any instruction */
456 if (size_prob
== 1) /* would have matched, but for size */
457 error (ERR_NONFATAL
, "operation size not specified");
458 else if (size_prob
== 2)
459 error (ERR_NONFATAL
, "mismatch in operand sizes");
460 else if (size_prob
== 3)
461 error (ERR_NONFATAL
, "no instruction for this cpu level");
464 "invalid combination of opcode and operands");
469 long insn_size (long segment
, long offset
, int bits
, unsigned long cp
,
470 insn
*instruction
, efunc error
)
472 struct itemplate
*temp
;
474 errfunc
= error
; /* to pass to other functions */
477 if (instruction
->opcode
== -1)
480 if (instruction
->opcode
== I_DB
||
481 instruction
->opcode
== I_DW
||
482 instruction
->opcode
== I_DD
||
483 instruction
->opcode
== I_DQ
||
484 instruction
->opcode
== I_DT
)
487 long isize
, osize
, wsize
= 0; /* placate gcc */
490 switch (instruction
->opcode
)
492 case I_DB
: wsize
= 1; break;
493 case I_DW
: wsize
= 2; break;
494 case I_DD
: wsize
= 4; break;
495 case I_DQ
: wsize
= 8; break;
496 case I_DT
: wsize
= 10; break;
499 for (e
= instruction
->eops
; e
; e
= e
->next
)
504 if (e
->type
== EOT_DB_NUMBER
)
506 else if (e
->type
== EOT_DB_STRING
)
507 osize
= e
->stringlen
;
509 align
= (-osize
) % wsize
;
512 isize
+= osize
+ align
;
514 return isize
* instruction
->times
;
517 if (instruction
->opcode
== I_INCBIN
)
519 char fname
[FILENAME_MAX
];
522 char *prefix
= "", *combine
;
523 char** pPrevPath
= NULL
;
525 len
= FILENAME_MAX
-1;
526 if (len
> instruction
->eops
->stringlen
)
527 len
= instruction
->eops
->stringlen
;
528 strncpy (fname
, instruction
->eops
->stringval
, len
);
531 while (1) /* added by alexfru: 'incbin' uses include paths */
533 combine
= nasm_malloc(strlen(prefix
) + len
+ 1);
534 strcpy(combine
, prefix
);
535 strcat(combine
, fname
);
537 if ( (fp
= fopen(combine
, "rb")) != NULL
)
544 pPrevPath
= pp_get_include_path_ptr (pPrevPath
);
545 if (pPrevPath
== NULL
)
551 error (ERR_NONFATAL
, "`incbin': unable to open file `%s'", fname
);
552 else if (fseek(fp
, 0L, SEEK_END
) < 0)
553 error (ERR_NONFATAL
, "`incbin': unable to seek on file `%s'",
559 if (instruction
->eops
->next
)
561 len
-= instruction
->eops
->next
->offset
;
562 if (instruction
->eops
->next
->next
&&
563 len
> instruction
->eops
->next
->next
->offset
)
565 len
= instruction
->eops
->next
->next
->offset
;
568 return instruction
->times
* len
;
570 return 0; /* if we're here, there's an error */
573 temp
= nasm_instructions
[instruction
->opcode
];
574 while (temp
->opcode
!= -1) {
575 int m
= matches(temp
, instruction
);
577 m
+= jmp_match(segment
, offset
, bits
, instruction
, temp
->code
);
580 /* we've matched an instruction. */
582 const char * codes
= temp
->code
;
585 isize
= calcsize(segment
, offset
, bits
, instruction
, codes
);
588 for (j
= 0; j
< instruction
->nprefix
; j
++)
590 if ((instruction
->prefixes
[j
] != P_A16
&&
591 instruction
->prefixes
[j
] != P_O16
&& bits
==16) ||
592 (instruction
->prefixes
[j
] != P_A32
&&
593 instruction
->prefixes
[j
] != P_O32
&& bits
==32))
598 return isize
* instruction
->times
;
602 return -1; /* didn't match any instruction */
606 /* check that opn[op] is a signed byte of size 16 or 32,
607 and return the signed value*/
608 static int is_sbyte (insn
*ins
, int op
, int size
)
613 ret
= !(ins
->forw_ref
&& ins
->oprs
[op
].opflags
) && /* dead in the water on forward reference or External */
615 !(ins
->oprs
[op
].type
& STRICT
) &&
616 ins
->oprs
[op
].wrt
==NO_SEG
&& ins
->oprs
[op
].segment
==NO_SEG
;
618 v
= ins
->oprs
[op
].offset
;
619 if (size
==16) v
= (signed short)v
; /* sign extend if 16 bits */
621 return ret
&& v
>=-128L && v
<=127L;
624 static long calcsize (long segment
, long offset
, int bits
,
625 insn
*ins
, const char *codes
)
630 (void) segment
; /* Don't warn that this parameter is unused */
631 (void) offset
; /* Don't warn that this parameter is unused */
633 while (*codes
) switch (c
= *codes
++) {
634 case 01: case 02: case 03:
635 codes
+= c
, length
+= c
; break;
636 case 04: case 05: case 06: case 07:
638 case 010: case 011: case 012:
639 codes
++, length
++; break;
642 case 014: case 015: case 016:
644 case 020: case 021: case 022:
646 case 024: case 025: case 026:
648 case 030: case 031: case 032:
650 case 034: case 035: case 036:
651 if ( ins
->oprs
[c
-034].type
& (BITS16
|BITS32
) )
652 length
+= (ins
->oprs
[c
-034].type
& BITS16
) ? 2 : 4;
654 length
+= (bits
== 16) ? 2 : 4;
658 case 040: case 041: case 042:
660 case 044: case 045: case 046:
661 length
+= ((ins
->oprs
[c
-044].addr_size
?
662 ins
->oprs
[c
-044].addr_size
: bits
) == 16 ? 2 : 4); break;
663 case 050: case 051: case 052:
665 case 060: case 061: case 062:
667 case 064: case 065: case 066:
668 if ( ins
->oprs
[c
-064].type
& (BITS16
|BITS32
) )
669 length
+= (ins
->oprs
[c
-064].type
& BITS16
) ? 2 : 4;
671 length
+= (bits
== 16) ? 2 : 4;
673 case 070: case 071: case 072:
675 case 0130: case 0131: case 0132:
676 length
+= is_sbyte(ins
, c
-0130, 16) ? 1 : 2; break;
677 case 0133: case 0134: case 0135:
678 codes
+=2; length
++; break;
679 case 0140: case 0141: case 0142:
680 length
+= is_sbyte(ins
, c
-0140, 32) ? 1 : 4; break;
681 case 0143: case 0144: case 0145:
682 codes
+=2; length
++; break;
683 case 0300: case 0301: case 0302:
684 length
+= chsize (&ins
->oprs
[c
-0300], bits
);
687 length
+= (bits
==32);
690 length
+= (bits
==16);
695 length
+= (bits
==32);
698 length
+= (bits
==16);
703 codes
++, length
++; break;
709 case 0340: case 0341: case 0342:
710 if (ins
->oprs
[0].segment
!= NO_SEG
)
711 errfunc (ERR_NONFATAL
, "attempt to reserve non-constant"
712 " quantity of BSS space");
714 length
+= ins
->oprs
[0].offset
<< (c
-0340);
716 case 0370: case 0371: case 0372:
720 default: /* can't do it by 'case' statements */
721 if (c
>=0100 && c
<=0277) { /* it's an EA */
723 if (!process_ea (&ins
->oprs
[(c
>>3)&7], &ea_data
, bits
, 0,
725 errfunc (ERR_NONFATAL
, "invalid effective address");
728 length
+= ea_data
.size
;
730 errfunc (ERR_PANIC
, "internal instruction table corrupt"
731 ": instruction code 0x%02X given", c
);
736 static void gencode (long segment
, long offset
, int bits
,
737 insn
*ins
, const char *codes
, long insn_end
)
739 static char condval
[] = { /* conditional opcodes */
740 0x7, 0x3, 0x2, 0x6, 0x2, 0x4, 0xF, 0xD, 0xC, 0xE, 0x6, 0x2,
741 0x3, 0x7, 0x3, 0x5, 0xE, 0xC, 0xD, 0xF, 0x1, 0xB, 0x9, 0x5,
742 0x0, 0xA, 0xA, 0xB, 0x8, 0x4
745 unsigned char bytes
[4];
749 switch (c
= *codes
++)
751 case 01: case 02: case 03:
752 out (offset
, segment
, codes
, OUT_RAWDATA
+c
, NO_SEG
, NO_SEG
);
758 switch (ins
->oprs
[0].basereg
)
761 bytes
[0] = 0x0E + (c
== 0x04 ? 1 : 0); break;
763 bytes
[0] = 0x1E + (c
== 0x04 ? 1 : 0); break;
765 bytes
[0] = 0x06 + (c
== 0x04 ? 1 : 0); break;
767 bytes
[0] = 0x16 + (c
== 0x04 ? 1 : 0); break;
769 errfunc (ERR_PANIC
, "bizarre 8086 segment register received");
771 out (offset
, segment
, bytes
, OUT_RAWDATA
+1, NO_SEG
, NO_SEG
);
776 switch (ins
->oprs
[0].basereg
) {
777 case R_FS
: bytes
[0] = 0xA0 + (c
== 0x05 ? 1 : 0); break;
778 case R_GS
: bytes
[0] = 0xA8 + (c
== 0x05 ? 1 : 0); break;
780 errfunc (ERR_PANIC
, "bizarre 386 segment register received");
782 out (offset
, segment
, bytes
, OUT_RAWDATA
+1, NO_SEG
, NO_SEG
);
786 case 010: case 011: case 012:
787 bytes
[0] = *codes
++ + regval(&ins
->oprs
[c
-010]);
788 out (offset
, segment
, bytes
, OUT_RAWDATA
+1, NO_SEG
, NO_SEG
);
794 out (offset
, segment
, bytes
, OUT_RAWDATA
+1, NO_SEG
, NO_SEG
);
798 case 014: case 015: case 016:
799 if (ins
->oprs
[c
-014].offset
< -128
800 || ins
->oprs
[c
-014].offset
> 127)
802 errfunc (ERR_WARNING
, "signed byte value exceeds bounds");
805 if (ins
->oprs
[c
-014].segment
!= NO_SEG
)
807 data
= ins
->oprs
[c
-014].offset
;
808 out (offset
, segment
, &data
, OUT_ADDRESS
+1,
809 ins
->oprs
[c
-014].segment
, ins
->oprs
[c
-014].wrt
);
812 bytes
[0] = ins
->oprs
[c
-014].offset
;
813 out (offset
, segment
, bytes
, OUT_RAWDATA
+1, NO_SEG
, NO_SEG
);
818 case 020: case 021: case 022:
819 if (ins
->oprs
[c
-020].offset
< -256
820 || ins
->oprs
[c
-020].offset
> 255)
822 errfunc (ERR_WARNING
, "byte value exceeds bounds");
824 if (ins
->oprs
[c
-020].segment
!= NO_SEG
) {
825 data
= ins
->oprs
[c
-020].offset
;
826 out (offset
, segment
, &data
, OUT_ADDRESS
+1,
827 ins
->oprs
[c
-020].segment
, ins
->oprs
[c
-020].wrt
);
830 bytes
[0] = ins
->oprs
[c
-020].offset
;
831 out (offset
, segment
, bytes
, OUT_RAWDATA
+1, NO_SEG
, NO_SEG
);
836 case 024: case 025: case 026:
837 if (ins
->oprs
[c
-024].offset
< 0 || ins
->oprs
[c
-024].offset
> 255)
838 errfunc (ERR_WARNING
, "unsigned byte value exceeds bounds");
839 if (ins
->oprs
[c
-024].segment
!= NO_SEG
) {
840 data
= ins
->oprs
[c
-024].offset
;
841 out (offset
, segment
, &data
, OUT_ADDRESS
+1,
842 ins
->oprs
[c
-024].segment
, ins
->oprs
[c
-024].wrt
);
845 bytes
[0] = ins
->oprs
[c
-024].offset
;
846 out (offset
, segment
, bytes
, OUT_RAWDATA
+1, NO_SEG
, NO_SEG
);
851 case 030: case 031: case 032:
852 if (ins
->oprs
[c
-030].segment
== NO_SEG
&&
853 ins
->oprs
[c
-030].wrt
== NO_SEG
&&
854 (ins
->oprs
[c
-030].offset
< -65536L ||
855 ins
->oprs
[c
-030].offset
> 65535L))
857 errfunc (ERR_WARNING
, "word value exceeds bounds");
859 data
= ins
->oprs
[c
-030].offset
;
860 out (offset
, segment
, &data
, OUT_ADDRESS
+2,
861 ins
->oprs
[c
-030].segment
, ins
->oprs
[c
-030].wrt
);
865 case 034: case 035: case 036:
866 if ( ins
->oprs
[c
-034].type
& (BITS16
|BITS32
) )
867 size
= (ins
->oprs
[c
-034].type
& BITS16
) ? 2 : 4;
869 size
= (bits
== 16) ? 2 : 4;
870 data
= ins
->oprs
[c
-034].offset
;
871 if (size
==2 && (data
< -65536L || data
> 65535L))
872 errfunc (ERR_WARNING
, "word value exceeds bounds");
873 out (offset
, segment
, &data
, OUT_ADDRESS
+size
,
874 ins
->oprs
[c
-034].segment
, ins
->oprs
[c
-034].wrt
);
879 if (ins
->oprs
[0].segment
== NO_SEG
)
880 errfunc (ERR_NONFATAL
, "value referenced by FAR is not"
883 out (offset
, segment
, &data
, OUT_ADDRESS
+2,
884 outfmt
->segbase(1+ins
->oprs
[0].segment
),
889 case 040: case 041: case 042:
890 data
= ins
->oprs
[c
-040].offset
;
891 out (offset
, segment
, &data
, OUT_ADDRESS
+4,
892 ins
->oprs
[c
-040].segment
, ins
->oprs
[c
-040].wrt
);
896 case 044: case 045: case 046:
897 data
= ins
->oprs
[c
-044].offset
;
898 size
= ((ins
->oprs
[c
-044].addr_size
?
899 ins
->oprs
[c
-044].addr_size
: bits
) == 16 ? 2 : 4);
900 if (size
==2 && (data
< -65536L || data
> 65535L))
901 errfunc (ERR_WARNING
, "word value exceeds bounds");
902 out (offset
, segment
, &data
, OUT_ADDRESS
+size
,
903 ins
->oprs
[c
-044].segment
, ins
->oprs
[c
-044].wrt
);
907 case 050: case 051: case 052:
908 if (ins
->oprs
[c
-050].segment
!= segment
)
909 errfunc (ERR_NONFATAL
, "short relative jump outside segment");
910 data
= ins
->oprs
[c
-050].offset
- insn_end
;
911 if (data
> 127 || data
< -128)
912 errfunc (ERR_NONFATAL
, "short jump is out of range");
914 out (offset
, segment
, bytes
, OUT_RAWDATA
+1, NO_SEG
, NO_SEG
);
918 case 060: case 061: case 062:
919 if (ins
->oprs
[c
-060].segment
!= segment
) {
920 data
= ins
->oprs
[c
-060].offset
;
921 out (offset
, segment
, &data
, OUT_REL2ADR
+insn_end
-offset
,
922 ins
->oprs
[c
-060].segment
, ins
->oprs
[c
-060].wrt
);
924 data
= ins
->oprs
[c
-060].offset
- insn_end
;
925 out (offset
, segment
, &data
,
926 OUT_ADDRESS
+2, NO_SEG
, NO_SEG
);
931 case 064: case 065: case 066:
932 if ( ins
->oprs
[c
-064].type
& (BITS16
|BITS32
) )
933 size
= (ins
->oprs
[c
-064].type
& BITS16
) ? 2 : 4;
935 size
= (bits
== 16) ? 2 : 4;
936 if (ins
->oprs
[c
-064].segment
!= segment
) {
937 long reltype
= (size
== 2 ? OUT_REL2ADR
: OUT_REL4ADR
);
938 data
= ins
->oprs
[c
-064].offset
;
939 out (offset
, segment
, &data
, reltype
+insn_end
-offset
,
940 ins
->oprs
[c
-064].segment
, ins
->oprs
[c
-064].wrt
);
942 data
= ins
->oprs
[c
-064].offset
- insn_end
;
943 out (offset
, segment
, &data
,
944 OUT_ADDRESS
+size
, NO_SEG
, NO_SEG
);
949 case 070: case 071: case 072:
950 if (ins
->oprs
[c
-070].segment
!= segment
) {
951 data
= ins
->oprs
[c
-070].offset
;
952 out (offset
, segment
, &data
, OUT_REL4ADR
+insn_end
-offset
,
953 ins
->oprs
[c
-070].segment
, ins
->oprs
[c
-070].wrt
);
955 data
= ins
->oprs
[c
-070].offset
- insn_end
;
956 out (offset
, segment
, &data
,
957 OUT_ADDRESS
+4, NO_SEG
, NO_SEG
);
962 case 0130: case 0131: case 0132:
963 data
= ins
->oprs
[c
-0130].offset
;
964 if (is_sbyte(ins
, c
-0130, 16)) {
966 out (offset
, segment
, bytes
, OUT_RAWDATA
+1, NO_SEG
, NO_SEG
);
969 if (ins
->oprs
[c
-0130].segment
== NO_SEG
&&
970 ins
->oprs
[c
-0130].wrt
== NO_SEG
&&
971 (data
< -65536L || data
> 65535L)) {
972 errfunc (ERR_WARNING
, "word value exceeds bounds");
974 out (offset
, segment
, &data
, OUT_ADDRESS
+2,
975 ins
->oprs
[c
-0130].segment
, ins
->oprs
[c
-0130].wrt
);
980 case 0133: case 0134: case 0135:
983 if (is_sbyte(ins
, c
-0133, 16)) bytes
[0] |= 2; /* s-bit */
984 out (offset
, segment
, bytes
, OUT_RAWDATA
+1, NO_SEG
, NO_SEG
);
988 case 0140: case 0141: case 0142:
989 data
= ins
->oprs
[c
-0140].offset
;
990 if (is_sbyte(ins
, c
-0140, 32)) {
992 out (offset
, segment
, bytes
, OUT_RAWDATA
+1, NO_SEG
, NO_SEG
);
995 out (offset
, segment
, &data
, OUT_ADDRESS
+4,
996 ins
->oprs
[c
-0140].segment
, ins
->oprs
[c
-0140].wrt
);
1001 case 0143: case 0144: case 0145:
1003 bytes
[0] = *codes
++;
1004 if (is_sbyte(ins
, c
-0143, 32)) bytes
[0] |= 2; /* s-bit */
1005 out (offset
, segment
, bytes
, OUT_RAWDATA
+1, NO_SEG
, NO_SEG
);
1009 case 0300: case 0301: case 0302:
1010 if (chsize (&ins
->oprs
[c
-0300], bits
)) {
1012 out (offset
, segment
, bytes
,
1013 OUT_RAWDATA
+1, NO_SEG
, NO_SEG
);
1022 out (offset
, segment
, bytes
,
1023 OUT_RAWDATA
+1, NO_SEG
, NO_SEG
);
1032 out (offset
, segment
, bytes
,
1033 OUT_RAWDATA
+1, NO_SEG
, NO_SEG
);
1045 out (offset
, segment
, bytes
,
1046 OUT_RAWDATA
+1, NO_SEG
, NO_SEG
);
1055 out (offset
, segment
, bytes
,
1056 OUT_RAWDATA
+1, NO_SEG
, NO_SEG
);
1066 *bytes
= *codes
++ ^ condval
[ins
->condition
];
1067 out (offset
, segment
, bytes
,
1068 OUT_RAWDATA
+1, NO_SEG
, NO_SEG
);
1078 out (offset
, segment
, bytes
,
1079 OUT_RAWDATA
+1, NO_SEG
, NO_SEG
);
1083 case 0340: case 0341: case 0342:
1084 if (ins
->oprs
[0].segment
!= NO_SEG
)
1085 errfunc (ERR_PANIC
, "non-constant BSS size in pass two");
1087 long size
= ins
->oprs
[0].offset
<< (c
-0340);
1089 out (offset
, segment
, NULL
,
1090 OUT_RESERVE
+size
, NO_SEG
, NO_SEG
);
1095 case 0370: case 0371: case 0372:
1099 *bytes
= bits
==16 ? 3 : 5;
1100 out (offset
, segment
, bytes
,
1101 OUT_RAWDATA
+1, NO_SEG
, NO_SEG
);
1105 default: /* can't do it by 'case' statements */
1106 if (c
>=0100 && c
<=0277) { /* it's an EA */
1112 if (c
<=0177) /* pick rfield from operand b */
1113 rfield
= regval (&ins
->oprs
[c
&7]);
1114 else /* rfield is constant */
1117 if (!process_ea (&ins
->oprs
[(c
>>3)&7], &ea_data
, bits
, rfield
,
1120 errfunc (ERR_NONFATAL
, "invalid effective address");
1124 *p
++ = ea_data
.modrm
;
1125 if (ea_data
.sib_present
)
1129 out (offset
, segment
, bytes
, OUT_RAWDATA
+ s
,
1132 switch (ea_data
.bytes
) {
1136 if (ins
->oprs
[(c
>>3)&7].segment
!= NO_SEG
) {
1137 data
= ins
->oprs
[(c
>>3)&7].offset
;
1138 out (offset
, segment
, &data
, OUT_ADDRESS
+1,
1139 ins
->oprs
[(c
>>3)&7].segment
,
1140 ins
->oprs
[(c
>>3)&7].wrt
);
1142 *bytes
= ins
->oprs
[(c
>>3)&7].offset
;
1143 out (offset
, segment
, bytes
, OUT_RAWDATA
+1,
1150 data
= ins
->oprs
[(c
>>3)&7].offset
;
1151 out (offset
, segment
, &data
,
1152 OUT_ADDRESS
+ea_data
.bytes
,
1153 ins
->oprs
[(c
>>3)&7].segment
, ins
->oprs
[(c
>>3)&7].wrt
);
1159 errfunc (ERR_PANIC
, "internal instruction table corrupt"
1160 ": instruction code 0x%02X given", c
);
1164 #include "regvals.c"
1166 static int regval (operand
*o
)
1168 if ( o
->basereg
< EXPR_REG_START
|| o
->basereg
>= REG_ENUM_LIMIT
) {
1169 errfunc (ERR_PANIC
, "invalid operand passed to regval()");
1171 return regvals
[o
->basereg
];
1174 static int matches (struct itemplate
*itemp
, insn
*instruction
)
1176 int i
, size
[3], asize
, oprs
, ret
;
1183 if (itemp
->opcode
!= instruction
->opcode
) return 0;
1186 * Count the operands
1188 if (itemp
->operands
!= instruction
->operands
) return 0;
1191 * Check that no spurious colons or TOs are present
1193 for (i
=0; i
<itemp
->operands
; i
++)
1194 if (instruction
->oprs
[i
].type
& ~itemp
->opd
[i
] & (COLON
|TO
))
1198 * Check that the operand flags all match up
1200 for (i
=0; i
<itemp
->operands
; i
++)
1201 if (itemp
->opd
[i
] & ~instruction
->oprs
[i
].type
||
1202 ((itemp
->opd
[i
] & SIZE_MASK
) &&
1203 ((itemp
->opd
[i
] ^ instruction
->oprs
[i
].type
) & SIZE_MASK
)))
1205 if ((itemp
->opd
[i
] & ~instruction
->oprs
[i
].type
& NON_SIZE
) ||
1206 (instruction
->oprs
[i
].type
& SIZE_MASK
))
1214 * Check operand sizes
1216 if (itemp
->flags
& IF_ARMASK
) {
1217 size
[0] = size
[1] = size
[2] = 0;
1219 switch (itemp
->flags
& IF_ARMASK
) {
1220 case IF_AR0
: i
= 0; break;
1221 case IF_AR1
: i
= 1; break;
1222 case IF_AR2
: i
= 2; break;
1223 default: break; /* Shouldn't happen */
1225 if (itemp
->flags
& IF_SB
) {
1227 } else if (itemp
->flags
& IF_SW
) {
1229 } else if (itemp
->flags
& IF_SD
) {
1234 if (itemp
->flags
& IF_SB
) {
1236 oprs
= itemp
->operands
;
1237 } else if (itemp
->flags
& IF_SW
) {
1239 oprs
= itemp
->operands
;
1240 } else if (itemp
->flags
& IF_SD
) {
1242 oprs
= itemp
->operands
;
1244 size
[0] = size
[1] = size
[2] = asize
;
1247 if (itemp
->flags
& (IF_SM
| IF_SM2
)) {
1248 oprs
= (itemp
->flags
& IF_SM2
? 2 : itemp
->operands
);
1250 for (i
=0; i
<oprs
; i
++) {
1251 if ( (asize
= itemp
->opd
[i
] & SIZE_MASK
) != 0) {
1253 for (j
=0; j
<oprs
; j
++)
1259 oprs
= itemp
->operands
;
1262 for (i
=0; i
<itemp
->operands
; i
++)
1263 if (!(itemp
->opd
[i
] & SIZE_MASK
) &&
1264 (instruction
->oprs
[i
].type
& SIZE_MASK
& ~size
[i
]))
1269 * Check template is okay at the set cpu level
1271 if ((itemp
->flags
& IF_PLEVEL
) > cpu
) return 3;
1274 * Check if special handling needed for Jumps
1276 if ((unsigned char)(itemp
->code
[0]) >= 0370) return 99;
1281 static ea
*process_ea (operand
*input
, ea
*output
, int addrbits
, int rfield
,
1284 if (!(REGISTER
& ~input
->type
)) { /* it's a single register */
1285 static int regs
[] = {
1286 R_AL
, R_CL
, R_DL
, R_BL
, R_AH
, R_CH
, R_DH
, R_BH
,
1287 R_AX
, R_CX
, R_DX
, R_BX
, R_SP
, R_BP
, R_SI
, R_DI
,
1288 R_EAX
, R_ECX
, R_EDX
, R_EBX
, R_ESP
, R_EBP
, R_ESI
, R_EDI
,
1289 R_MM0
, R_MM1
, R_MM2
, R_MM3
, R_MM4
, R_MM5
, R_MM6
, R_MM7
,
1290 R_XMM0
, R_XMM1
, R_XMM2
, R_XMM3
, R_XMM4
, R_XMM5
, R_XMM6
, R_XMM7
1294 for (i
=0; i
<elements(regs
); i
++)
1295 if (input
->basereg
== regs
[i
]) break;
1296 if (i
<elements(regs
)) {
1297 output
->sib_present
= FALSE
;/* no SIB necessary */
1298 output
->bytes
= 0; /* no offset necessary either */
1299 output
->modrm
= 0xC0 | (rfield
<< 3) | (i
& 7);
1303 } else { /* it's a memory reference */
1304 if (input
->basereg
==-1 && (input
->indexreg
==-1 || input
->scale
==0)) {
1305 /* it's a pure offset */
1306 if (input
->addr_size
)
1307 addrbits
= input
->addr_size
;
1308 output
->sib_present
= FALSE
;
1309 output
->bytes
= (addrbits
==32 ? 4 : 2);
1310 output
->modrm
= (addrbits
==32 ? 5 : 6) | (rfield
<< 3);
1312 else { /* it's an indirection */
1313 int i
=input
->indexreg
, b
=input
->basereg
, s
=input
->scale
;
1314 long o
=input
->offset
, seg
=input
->segment
;
1315 int hb
=input
->hintbase
, ht
=input
->hinttype
;
1318 if (s
==0) i
= -1; /* make this easy, at least */
1320 if (i
==R_EAX
|| i
==R_EBX
|| i
==R_ECX
|| i
==R_EDX
1321 || i
==R_EBP
|| i
==R_ESP
|| i
==R_ESI
|| i
==R_EDI
1322 || b
==R_EAX
|| b
==R_EBX
|| b
==R_ECX
|| b
==R_EDX
1323 || b
==R_EBP
|| b
==R_ESP
|| b
==R_ESI
|| b
==R_EDI
) {
1324 /* it must be a 32-bit memory reference. Firstly we have
1325 * to check that all registers involved are type Exx. */
1326 if (i
!=-1 && i
!=R_EAX
&& i
!=R_EBX
&& i
!=R_ECX
&& i
!=R_EDX
1327 && i
!=R_EBP
&& i
!=R_ESP
&& i
!=R_ESI
&& i
!=R_EDI
)
1329 if (b
!=-1 && b
!=R_EAX
&& b
!=R_EBX
&& b
!=R_ECX
&& b
!=R_EDX
1330 && b
!=R_EBP
&& b
!=R_ESP
&& b
!=R_ESI
&& b
!=R_EDI
)
1333 /* While we're here, ensure the user didn't specify WORD. */
1334 if (input
->addr_size
== 16)
1337 /* now reorganise base/index */
1338 if (s
== 1 && b
!= i
&& b
!= -1 && i
!= -1 &&
1339 ((hb
==b
&&ht
==EAH_NOTBASE
) || (hb
==i
&&ht
==EAH_MAKEBASE
)))
1340 t
= b
, b
= i
, i
= t
; /* swap if hints say so */
1341 if (b
==i
) /* convert EAX+2*EAX to 3*EAX */
1343 if (b
==-1 && s
==1 && !(hb
== i
&& ht
== EAH_NOTBASE
))
1344 b
= i
, i
= -1; /* make single reg base, unless hint */
1345 if (((s
==2 && i
!=R_ESP
&& !(input
->eaflags
& EAF_TIMESTWO
)) ||
1346 s
==3 || s
==5 || s
==9) && b
==-1)
1347 b
= i
, s
--; /* convert 3*EAX to EAX+2*EAX */
1348 if (i
==-1 && b
!=R_ESP
&& (input
->eaflags
& EAF_TIMESTWO
))
1349 i
= b
, b
= -1, s
= 1;
1350 /* convert [NOSPLIT EAX] to sib format with 0x0 displacement */
1351 if (s
==1 && i
==R_ESP
) /* swap ESP into base if scale is 1 */
1353 if (i
==R_ESP
|| (s
!=1 && s
!=2 && s
!=4 && s
!=8 && i
!=-1))
1354 return NULL
; /* wrong, for various reasons */
1356 if (i
==-1 && b
!=R_ESP
) {/* no SIB needed */
1359 case R_EAX
: rm
= 0; break;
1360 case R_ECX
: rm
= 1; break;
1361 case R_EDX
: rm
= 2; break;
1362 case R_EBX
: rm
= 3; break;
1363 case R_EBP
: rm
= 5; break;
1364 case R_ESI
: rm
= 6; break;
1365 case R_EDI
: rm
= 7; break;
1366 case -1: rm
= 5; break;
1367 default: /* should never happen */
1370 if (b
==-1 || (b
!=R_EBP
&& o
==0 &&
1371 seg
==NO_SEG
&& !forw_ref
&&
1373 (EAF_BYTEOFFS
|EAF_WORDOFFS
))))
1375 else if (input
->eaflags
& EAF_BYTEOFFS
||
1376 (o
>=-128 && o
<=127 && seg
==NO_SEG
&& !forw_ref
&&
1377 !(input
->eaflags
& EAF_WORDOFFS
))) {
1383 output
->sib_present
= FALSE
;
1384 output
->bytes
= (b
==-1 || mod
==2 ? 4 : mod
);
1385 output
->modrm
= (mod
<<6) | (rfield
<<3) | rm
;
1387 else { /* we need a SIB */
1388 int mod
, scale
, index
, base
;
1391 case R_EAX
: base
= 0; break;
1392 case R_ECX
: base
= 1; break;
1393 case R_EDX
: base
= 2; break;
1394 case R_EBX
: base
= 3; break;
1395 case R_ESP
: base
= 4; break;
1396 case R_EBP
: case -1: base
= 5; break;
1397 case R_ESI
: base
= 6; break;
1398 case R_EDI
: base
= 7; break;
1399 default: /* then what the smeg is it? */
1400 return NULL
; /* panic */
1404 case R_EAX
: index
= 0; break;
1405 case R_ECX
: index
= 1; break;
1406 case R_EDX
: index
= 2; break;
1407 case R_EBX
: index
= 3; break;
1408 case -1: index
= 4; break;
1409 case R_EBP
: index
= 5; break;
1410 case R_ESI
: index
= 6; break;
1411 case R_EDI
: index
= 7; break;
1412 default: /* then what the smeg is it? */
1413 return NULL
; /* panic */
1418 case 1: scale
= 0; break;
1419 case 2: scale
= 1; break;
1420 case 4: scale
= 2; break;
1421 case 8: scale
= 3; break;
1422 default: /* then what the smeg is it? */
1423 return NULL
; /* panic */
1426 if (b
==-1 || (b
!=R_EBP
&& o
==0 &&
1427 seg
==NO_SEG
&& !forw_ref
&&
1429 (EAF_BYTEOFFS
|EAF_WORDOFFS
))))
1431 else if (input
->eaflags
& EAF_BYTEOFFS
||
1432 (o
>=-128 && o
<=127 && seg
==NO_SEG
&& !forw_ref
&&
1433 !(input
->eaflags
& EAF_WORDOFFS
)))
1438 output
->sib_present
= TRUE
;
1439 output
->bytes
= (b
==-1 || mod
==2 ? 4 : mod
);
1440 output
->modrm
= (mod
<<6) | (rfield
<<3) | 4;
1441 output
->sib
= (scale
<<6) | (index
<<3) | base
;
1444 else { /* it's 16-bit */
1447 /* check all registers are BX, BP, SI or DI */
1448 if ((b
!=-1 && b
!=R_BP
&& b
!=R_BX
&& b
!=R_SI
&& b
!=R_DI
) ||
1449 (i
!=-1 && i
!=R_BP
&& i
!=R_BX
&& i
!=R_SI
&& i
!=R_DI
))
1452 /* ensure the user didn't specify DWORD */
1453 if (input
->addr_size
== 32)
1456 if (s
!=1 && i
!=-1) return NULL
;/* no can do, in 16-bit EA */
1457 if (b
==-1 && i
!=-1) { int tmp
= b
; b
= i
; i
= tmp
; } /* swap */
1458 if ((b
==R_SI
|| b
==R_DI
) && i
!=-1)
1459 { int tmp
= b
; b
= i
; i
= tmp
; }
1460 /* have BX/BP as base, SI/DI index */
1461 if (b
==i
) return NULL
;/* shouldn't ever happen, in theory */
1462 if (i
!=-1 && b
!=-1 &&
1463 (i
==R_BP
|| i
==R_BX
|| b
==R_SI
|| b
==R_DI
))
1464 return NULL
; /* invalid combinations */
1465 if (b
==-1) /* pure offset: handled above */
1466 return NULL
; /* so if it gets to here, panic! */
1470 switch (i
*256 + b
) {
1471 case R_SI
*256+R_BX
: rm
=0; break;
1472 case R_DI
*256+R_BX
: rm
=1; break;
1473 case R_SI
*256+R_BP
: rm
=2; break;
1474 case R_DI
*256+R_BP
: rm
=3; break;
1478 case R_SI
: rm
=4; break;
1479 case R_DI
: rm
=5; break;
1480 case R_BP
: rm
=6; break;
1481 case R_BX
: rm
=7; break;
1483 if (rm
==-1) /* can't happen, in theory */
1484 return NULL
; /* so panic if it does */
1486 if (o
==0 && seg
==NO_SEG
&& !forw_ref
&& rm
!=6 &&
1487 !(input
->eaflags
& (EAF_BYTEOFFS
|EAF_WORDOFFS
)))
1489 else if (input
->eaflags
& EAF_BYTEOFFS
||
1490 (o
>=-128 && o
<=127 && seg
==NO_SEG
&& !forw_ref
&&
1491 !(input
->eaflags
& EAF_WORDOFFS
)))
1496 output
->sib_present
= FALSE
; /* no SIB - it's 16-bit */
1497 output
->bytes
= mod
; /* bytes of offset needed */
1498 output
->modrm
= (mod
<<6) | (rfield
<<3) | rm
;
1502 output
->size
= 1 + output
->sib_present
+ output
->bytes
;
1506 static int chsize (operand
*input
, int addrbits
)
1508 if (!(MEMORY
& ~input
->type
)) {
1509 int i
=input
->indexreg
, b
=input
->basereg
;
1511 if (input
->scale
==0) i
= -1;
1513 if (i
== -1 && b
== -1) /* pure offset */
1514 return (input
->addr_size
!= 0 && input
->addr_size
!= addrbits
);
1516 if (i
==R_EAX
|| i
==R_EBX
|| i
==R_ECX
|| i
==R_EDX
1517 || i
==R_EBP
|| i
==R_ESP
|| i
==R_ESI
|| i
==R_EDI
1518 || b
==R_EAX
|| b
==R_EBX
|| b
==R_ECX
|| b
==R_EDX
1519 || b
==R_EBP
|| b
==R_ESP
|| b
==R_ESI
|| b
==R_EDI
)
1520 return (addrbits
==16);
1522 return (addrbits
==32);