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..\13 - a literal byte follows in the code stream, to be added
16 * to the register value of operand 0..3
17 * \14..\17 - a signed byte immediate operand, from operand 0..3
18 * \20..\23 - a byte immediate operand, from operand 0..3
19 * \24..\27 - an unsigned byte immediate operand, from operand 0..3
20 * \30..\33 - a word immediate operand, from operand 0..3
21 * \34..\37 - select between \3[0-3] and \4[0-3] depending on 16/32 bit
22 * assembly mode or the operand-size override on the operand
23 * \40..\43 - a long immediate operand, from operand 0..3
24 * \44..\47 - select between \3[0-3], \4[0-3] and \5[4-7]
25 * depending on assembly mode or the address-size override
27 * \50..\53 - a byte relative operand, from operand 0..3
28 * \54..\57 - a qword immediate operand, from operand 0..3
29 * \60..\63 - a word relative operand, from operand 0..3
30 * \64..\67 - select between \6[0-3] and \7[0-3] depending on 16/32 bit
31 * assembly mode or the operand-size override on the operand
32 * \70..\73 - a long relative operand, from operand 0..3
33 * \74..\77 - a word constant, from the _segment_ part of operand 0..3
34 * \1ab - a ModRM, calculated on EA in operand a, with the spare
35 * field the register value of operand b.
36 * \140..\143 - an immediate word or signed byte for operand 0..3
37 * \144..\147 - or 2 (s-field) into next opcode byte if operand 0..3
38 * is a signed byte rather than a word.
39 * \150..\153 - an immediate dword or signed byte for operand 0..3
40 * \154..\157 - or 2 (s-field) into next opcode byte if operand 0..3
41 * is a signed byte rather than a dword.
42 * \160..\163 - this instruction uses DREX rather than REX, with the
43 * OC0 field set to 0, and the dest field taken from
45 * \164..\167 - this instruction uses DREX rather than REX, with the
46 * OC0 field set to 1, and the dest field taken from
48 * \170 - encodes the literal byte 0. (Some compilers don't take
49 * kindly to a zero byte in the _middle_ of a compile time
50 * string constant, so I had to put this hack in.)
51 * \171 - placement of DREX suffix in the absence of an EA
52 * \2ab - a ModRM, calculated on EA in operand a, with the spare
53 * field equal to digit b.
54 * \310 - indicates fixed 16-bit address size, i.e. optional 0x67.
55 * \311 - indicates fixed 32-bit address size, i.e. optional 0x67.
56 * \312 - (disassembler only) marker on LOOP, LOOPxx instructions.
57 * \313 - indicates fixed 64-bit address size, 0x67 invalid.
58 * \320 - indicates fixed 16-bit operand size, i.e. optional 0x66.
59 * \321 - indicates fixed 32-bit operand size, i.e. optional 0x66.
60 * \322 - indicates that this instruction is only valid when the
61 * operand size is the default (instruction to disassembler,
62 * generates no code in the assembler)
63 * \323 - indicates fixed 64-bit operand size, REX on extensions only.
64 * \324 - indicates 64-bit operand size requiring REX prefix.
65 * \330 - a literal byte follows in the code stream, to be added
66 * to the condition code value of the instruction.
67 * \331 - instruction not valid with REP prefix. Hint for
68 * disassembler only; for SSE instructions.
69 * \332 - REP prefix (0xF2 byte) used as opcode extension.
70 * \333 - REP prefix (0xF3 byte) used as opcode extension.
71 * \334 - LOCK prefix used instead of REX.R
72 * \335 - disassemble a rep (0xF3 byte) prefix as repe not rep.
73 * \340 - reserve <operand 0> bytes of uninitialized storage.
74 * Operand 0 had better be a segmentless constant.
75 * \364 - operand-size prefix (0x66) not permitted
76 * \365 - address-size prefix (0x67) not permitted
77 * \366 - operand-size prefix (0x66) used as opcode extension
78 * \367 - address-size prefix (0x67) used as opcode extension
79 * \370,\371,\372 - match only if operand 0 meets byte jump criteria.
80 * 370 is used for Jcc, 371 is used for JMP.
81 * \373 - assemble 0x03 if bits==16, 0x05 if bits==32;
82 * used for conditional jump over longer jump
100 int sib_present
; /* is a SIB byte necessary? */
101 int bytes
; /* # of bytes of offset needed */
102 int size
; /* lazy - this is sib+bytes+1 */
103 uint8_t modrm
, sib
, rex
, rip
; /* the bytes themselves */
106 static uint32_t cpu
; /* cpu level received from nasm.c */
107 static efunc errfunc
;
108 static struct ofmt
*outfmt
;
109 static ListGen
*list
;
111 static int32_t calcsize(int32_t, int32_t, int, insn
*, const char *);
112 static void gencode(int32_t, int32_t, int, insn
*, const char *, int32_t);
113 static int matches(const struct itemplate
*, insn
*, int bits
);
114 static int32_t regflag(const operand
*);
115 static int32_t regval(const operand
*);
116 static int rexflags(int, int32_t, int);
117 static int op_rexflags(const operand
*, int);
118 static ea
*process_ea(operand
*, ea
*, int, int, int32_t, int);
119 static void add_asp(insn
*, int);
121 static int has_prefix(insn
* ins
, enum prefixes prefix
)
124 for (j
= 0; j
< ins
->nprefix
; j
++) {
125 if (ins
->prefixes
[j
] == prefix
)
131 static void assert_no_prefix(insn
* ins
, enum prefixes prefix
)
133 if (has_prefix(ins
, prefix
))
134 errfunc(ERR_NONFATAL
, "invalid %s prefix", prefix_name(prefix
));
138 * This routine wrappers the real output format's output routine,
139 * in order to pass a copy of the data off to the listing file
140 * generator at the same time.
142 static void out(int32_t offset
, int32_t segto
, const void *data
,
143 uint32_t type
, int32_t segment
, int32_t wrt
)
145 static int32_t lineno
= 0; /* static!!! */
146 static char *lnfname
= NULL
;
148 if ((type
& OUT_TYPMASK
) == OUT_ADDRESS
) {
149 if (segment
!= NO_SEG
|| wrt
!= NO_SEG
) {
151 * This address is relocated. We must write it as
152 * OUT_ADDRESS, so there's no work to be done here.
154 list
->output(offset
, data
, type
);
156 uint8_t p
[8], *q
= p
;
158 * This is a non-relocated address, and we're going to
159 * convert it into RAWDATA format.
161 if ((type
& OUT_SIZMASK
) == 4) {
162 WRITELONG(q
, *(int32_t *)data
);
163 list
->output(offset
, p
, OUT_RAWDATA
+ 4);
164 } else if ((type
& OUT_SIZMASK
) == 8) {
165 WRITEDLONG(q
, *(int64_t *)data
);
166 list
->output(offset
, p
, OUT_RAWDATA
+ 8);
168 WRITESHORT(q
, *(int32_t *)data
);
169 list
->output(offset
, p
, OUT_RAWDATA
+ 2);
172 } else if ((type
& OUT_TYPMASK
) == OUT_RAWDATA
) {
173 list
->output(offset
, data
, type
);
174 } else if ((type
& OUT_TYPMASK
) == OUT_RESERVE
) {
175 list
->output(offset
, NULL
, type
);
176 } else if ((type
& OUT_TYPMASK
) == OUT_REL2ADR
||
177 (type
& OUT_TYPMASK
) == OUT_REL4ADR
) {
178 list
->output(offset
, data
, type
);
182 * this call to src_get determines when we call the
183 * debug-format-specific "linenum" function
184 * it updates lineno and lnfname to the current values
185 * returning 0 if "same as last time", -2 if lnfname
186 * changed, and the amount by which lineno changed,
187 * if it did. thus, these variables must be static
190 if (src_get(&lineno
, &lnfname
)) {
191 outfmt
->current_dfmt
->linenum(lnfname
, lineno
, segto
);
194 outfmt
->output(segto
, data
, type
, segment
, wrt
);
197 static int jmp_match(int32_t segment
, int32_t offset
, int bits
,
198 insn
* ins
, const char *code
)
203 if (c
!= 0370 && c
!= 0371)
205 if (ins
->oprs
[0].opflags
& OPFLAG_FORWARD
) {
206 if ((optimizing
< 0 || (ins
->oprs
[0].type
& STRICT
))
210 return (pass0
== 0); /* match a forward reference */
212 isize
= calcsize(segment
, offset
, bits
, ins
, code
);
213 if (ins
->oprs
[0].segment
!= segment
)
215 isize
= ins
->oprs
[0].offset
- offset
- isize
; /* isize is now the delta */
216 if (isize
>= -128L && isize
<= 127L)
217 return 1; /* it is byte size */
222 int32_t assemble(int32_t segment
, int32_t offset
, int bits
, uint32_t cp
,
223 insn
* instruction
, struct ofmt
*output
, efunc error
,
226 const struct itemplate
*temp
;
231 int32_t start
= offset
;
232 int32_t wsize
= 0; /* size for DB etc. */
234 errfunc
= error
; /* to pass to other functions */
236 outfmt
= output
; /* likewise */
237 list
= listgen
; /* and again */
239 switch (instruction
->opcode
) {
266 int32_t t
= instruction
->times
;
269 "instruction->times < 0 (%ld) in assemble()", t
);
271 while (t
--) { /* repeat TIMES times */
272 for (e
= instruction
->eops
; e
; e
= e
->next
) {
273 if (e
->type
== EOT_DB_NUMBER
) {
275 if (e
->segment
!= NO_SEG
)
276 errfunc(ERR_NONFATAL
,
277 "one-byte relocation attempted");
279 uint8_t out_byte
= e
->offset
;
280 out(offset
, segment
, &out_byte
,
281 OUT_RAWDATA
+ 1, NO_SEG
, NO_SEG
);
283 } else if (wsize
> 8) {
284 errfunc(ERR_NONFATAL
, "integer supplied to a DT or DO"
287 out(offset
, segment
, &e
->offset
,
288 OUT_ADDRESS
+ wsize
, e
->segment
, e
->wrt
);
290 } else if (e
->type
== EOT_DB_STRING
) {
293 out(offset
, segment
, e
->stringval
,
294 OUT_RAWDATA
+ e
->stringlen
, NO_SEG
, NO_SEG
);
295 align
= e
->stringlen
% wsize
;
298 align
= wsize
- align
;
299 out(offset
, segment
, "\0\0\0\0\0\0\0\0",
300 OUT_RAWDATA
+ align
, NO_SEG
, NO_SEG
);
302 offset
+= e
->stringlen
+ align
;
305 if (t
> 0 && t
== instruction
->times
- 1) {
307 * Dummy call to list->output to give the offset to the
310 list
->output(offset
, NULL
, OUT_RAWDATA
);
311 list
->uplevel(LIST_TIMES
);
314 if (instruction
->times
> 1)
315 list
->downlevel(LIST_TIMES
);
316 return offset
- start
;
319 if (instruction
->opcode
== I_INCBIN
) {
320 static char fname
[FILENAME_MAX
];
323 char *prefix
= "", *combine
;
324 char **pPrevPath
= NULL
;
326 len
= FILENAME_MAX
- 1;
327 if (len
> instruction
->eops
->stringlen
)
328 len
= instruction
->eops
->stringlen
;
329 strncpy(fname
, instruction
->eops
->stringval
, len
);
332 while (1) { /* added by alexfru: 'incbin' uses include paths */
333 combine
= nasm_malloc(strlen(prefix
) + len
+ 1);
334 strcpy(combine
, prefix
);
335 strcat(combine
, fname
);
337 if ((fp
= fopen(combine
, "rb")) != NULL
) {
343 pPrevPath
= pp_get_include_path_ptr(pPrevPath
);
344 if (pPrevPath
== NULL
)
350 error(ERR_NONFATAL
, "`incbin': unable to open file `%s'",
352 else if (fseek(fp
, 0L, SEEK_END
) < 0)
353 error(ERR_NONFATAL
, "`incbin': unable to seek on file `%s'",
356 static char buf
[2048];
357 int32_t t
= instruction
->times
;
361 if (instruction
->eops
->next
) {
362 base
= instruction
->eops
->next
->offset
;
364 if (instruction
->eops
->next
->next
&&
365 len
> instruction
->eops
->next
->next
->offset
)
366 len
= instruction
->eops
->next
->next
->offset
;
369 * Dummy call to list->output to give the offset to the
372 list
->output(offset
, NULL
, OUT_RAWDATA
);
373 list
->uplevel(LIST_INCBIN
);
377 fseek(fp
, base
, SEEK_SET
);
381 fread(buf
, 1, (l
> sizeof(buf
) ? sizeof(buf
) : l
),
385 * This shouldn't happen unless the file
386 * actually changes while we are reading
390 "`incbin': unexpected EOF while"
391 " reading file `%s'", fname
);
392 t
= 0; /* Try to exit cleanly */
395 out(offset
, segment
, buf
, OUT_RAWDATA
+ m
,
400 list
->downlevel(LIST_INCBIN
);
401 if (instruction
->times
> 1) {
403 * Dummy call to list->output to give the offset to the
406 list
->output(offset
, NULL
, OUT_RAWDATA
);
407 list
->uplevel(LIST_TIMES
);
408 list
->downlevel(LIST_TIMES
);
411 return instruction
->times
* len
;
413 return 0; /* if we're here, there's an error */
416 /* Check to see if we need an address-size prefix */
417 add_asp(instruction
, bits
);
421 for (temp
= nasm_instructions
[instruction
->opcode
]; temp
->opcode
!= -1; temp
++){
422 int m
= matches(temp
, instruction
, bits
);
425 m
+= jmp_match(segment
, offset
, bits
, instruction
, temp
->code
);
427 if (m
== 100) { /* matches! */
428 const char *codes
= temp
->code
;
429 int32_t insn_size
= calcsize(segment
, offset
, bits
,
431 itimes
= instruction
->times
;
432 if (insn_size
< 0) /* shouldn't be, on pass two */
433 error(ERR_PANIC
, "errors made it through from pass one");
436 for (j
= 0; j
< instruction
->nprefix
; j
++) {
438 switch (instruction
->prefixes
[j
]) {
454 "cs segment base ignored in 64-bit mode");
461 "ds segment base ignored in 64-bit mode");
468 "es segment base ignored in 64-bit mode");
481 "ss segment base ignored in 64-bit mode");
488 "segr6 and segr7 cannot be used as prefixes");
493 "16-bit addressing is not supported "
513 error(ERR_PANIC
, "invalid instruction prefix");
516 out(offset
, segment
, &c
, OUT_RAWDATA
+ 1,
521 insn_end
= offset
+ insn_size
;
522 gencode(segment
, offset
, bits
, instruction
, codes
,
525 if (itimes
> 0 && itimes
== instruction
->times
- 1) {
527 * Dummy call to list->output to give the offset to the
530 list
->output(offset
, NULL
, OUT_RAWDATA
);
531 list
->uplevel(LIST_TIMES
);
534 if (instruction
->times
> 1)
535 list
->downlevel(LIST_TIMES
);
536 return offset
- start
;
537 } else if (m
> 0 && m
> size_prob
) {
543 if (temp
->opcode
== -1) { /* didn't match any instruction */
546 error(ERR_NONFATAL
, "operation size not specified");
549 error(ERR_NONFATAL
, "mismatch in operand sizes");
552 error(ERR_NONFATAL
, "no instruction for this cpu level");
555 error(ERR_NONFATAL
, "instruction not supported in 64-bit mode");
559 "invalid combination of opcode and operands");
566 int32_t insn_size(int32_t segment
, int32_t offset
, int bits
, uint32_t cp
,
567 insn
* instruction
, efunc error
)
569 const struct itemplate
*temp
;
571 errfunc
= error
; /* to pass to other functions */
574 if (instruction
->opcode
== -1)
577 if (instruction
->opcode
== I_DB
|| instruction
->opcode
== I_DW
||
578 instruction
->opcode
== I_DD
|| instruction
->opcode
== I_DQ
||
579 instruction
->opcode
== I_DT
|| instruction
->opcode
== I_DO
) {
581 int32_t isize
, osize
, wsize
= 0; /* placate gcc */
584 switch (instruction
->opcode
) {
607 for (e
= instruction
->eops
; e
; e
= e
->next
) {
611 if (e
->type
== EOT_DB_NUMBER
)
613 else if (e
->type
== EOT_DB_STRING
)
614 osize
= e
->stringlen
;
616 align
= (-osize
) % wsize
;
619 isize
+= osize
+ align
;
621 return isize
* instruction
->times
;
624 if (instruction
->opcode
== I_INCBIN
) {
625 char fname
[FILENAME_MAX
];
628 char *prefix
= "", *combine
;
629 char **pPrevPath
= NULL
;
631 len
= FILENAME_MAX
- 1;
632 if (len
> instruction
->eops
->stringlen
)
633 len
= instruction
->eops
->stringlen
;
634 strncpy(fname
, instruction
->eops
->stringval
, len
);
637 while (1) { /* added by alexfru: 'incbin' uses include paths */
638 combine
= nasm_malloc(strlen(prefix
) + len
+ 1);
639 strcpy(combine
, prefix
);
640 strcat(combine
, fname
);
642 if ((fp
= fopen(combine
, "rb")) != NULL
) {
648 pPrevPath
= pp_get_include_path_ptr(pPrevPath
);
649 if (pPrevPath
== NULL
)
655 error(ERR_NONFATAL
, "`incbin': unable to open file `%s'",
657 else if (fseek(fp
, 0L, SEEK_END
) < 0)
658 error(ERR_NONFATAL
, "`incbin': unable to seek on file `%s'",
663 if (instruction
->eops
->next
) {
664 len
-= instruction
->eops
->next
->offset
;
665 if (instruction
->eops
->next
->next
&&
666 len
> instruction
->eops
->next
->next
->offset
) {
667 len
= instruction
->eops
->next
->next
->offset
;
670 return instruction
->times
* len
;
672 return 0; /* if we're here, there's an error */
675 /* Check to see if we need an address-size prefix */
676 add_asp(instruction
, bits
);
678 for (temp
= nasm_instructions
[instruction
->opcode
]; temp
->opcode
!= -1; temp
++) {
679 int m
= matches(temp
, instruction
, bits
);
681 m
+= jmp_match(segment
, offset
, bits
, instruction
, temp
->code
);
684 /* we've matched an instruction. */
686 const char *codes
= temp
->code
;
689 isize
= calcsize(segment
, offset
, bits
, instruction
, codes
);
692 for (j
= 0; j
< instruction
->nprefix
; j
++) {
693 switch (instruction
->prefixes
[j
]) {
715 return isize
* instruction
->times
;
718 return -1; /* didn't match any instruction */
721 /* check that opn[op] is a signed byte of size 16 or 32,
722 and return the signed value*/
723 static int is_sbyte(insn
* ins
, int op
, int size
)
728 ret
= !(ins
->forw_ref
&& ins
->oprs
[op
].opflags
) && /* dead in the water on forward reference or External */
730 !(ins
->oprs
[op
].type
& STRICT
) &&
731 ins
->oprs
[op
].wrt
== NO_SEG
&& ins
->oprs
[op
].segment
== NO_SEG
;
733 v
= ins
->oprs
[op
].offset
;
735 v
= (int16_t)v
; /* sign extend if 16 bits */
737 return ret
&& v
>= -128L && v
<= 127L;
740 static int32_t calcsize(int32_t segment
, int32_t offset
, int bits
,
741 insn
* ins
, const char *codes
)
746 ins
->rex
= 0; /* Ensure REX is reset */
748 (void)segment
; /* Don't warn that this parameter is unused */
749 (void)offset
; /* Don't warn that this parameter is unused */
752 switch (c
= *codes
++) {
756 codes
+= c
, length
+= c
;
769 op_rexflags(&ins
->oprs
[c
- 010], REX_B
|REX_H
|REX_P
|REX_W
);
800 if (ins
->oprs
[c
- 034].type
& (BITS16
| BITS32
| BITS64
))
801 length
+= (ins
->oprs
[c
- 034].type
& BITS16
) ? 2 : 4;
803 length
+= (bits
== 16) ? 2 : 4;
815 length
+= ((ins
->oprs
[c
- 044].addr_size
?
816 ins
->oprs
[c
- 044].addr_size
: bits
) >> 3);
828 length
+= 8; /* MOV reg64/imm */
840 if (ins
->oprs
[c
- 064].type
& (BITS16
| BITS32
| BITS64
))
841 length
+= (ins
->oprs
[c
- 064].type
& BITS16
) ? 2 : 4;
843 length
+= (bits
== 16) ? 2 : 4;
861 length
+= is_sbyte(ins
, c
- 0140, 16) ? 1 : 2;
874 length
+= is_sbyte(ins
, c
- 0150, 32) ? 1 : 4;
889 ins
->drexdst
= regval(&ins
->oprs
[c
& 3]);
896 ins
->rex
|= REX_D
|REX_OC
;
897 ins
->drexdst
= regval(&ins
->oprs
[c
& 3]);
912 length
+= (bits
!= 16) && !has_prefix(ins
,P_A16
);
915 length
+= (bits
!= 32) && !has_prefix(ins
,P_A32
);
920 if (bits
!= 64 || has_prefix(ins
,P_A16
) || has_prefix(ins
,P_A32
))
924 length
+= (bits
!= 16);
927 length
+= (bits
== 16);
947 assert_no_prefix(ins
, P_LOCK
);
955 if (ins
->oprs
[0].segment
!= NO_SEG
)
956 errfunc(ERR_NONFATAL
, "attempt to reserve non-constant"
957 " quantity of BSS space");
959 length
+= ins
->oprs
[0].offset
<< (c
- 0340);
975 default: /* can't do it by 'case' statements */
976 if (c
>= 0100 && c
<= 0277) { /* it's an EA */
980 ea_data
.rex
= 0; /* Ensure ea.REX is initially 0 */
983 /* pick rfield from operand b */
984 rflags
= regflag(&ins
->oprs
[c
& 7]);
985 rfield
= regvals
[ins
->oprs
[c
& 7].basereg
];
992 (&ins
->oprs
[(c
>> 3) & 7], &ea_data
, bits
,
993 rfield
, rflags
, ins
->forw_ref
)) {
994 errfunc(ERR_NONFATAL
, "invalid effective address");
997 ins
->rex
|= ea_data
.rex
;
998 length
+= ea_data
.size
;
1001 errfunc(ERR_PANIC
, "internal instruction table corrupt"
1002 ": instruction code 0x%02X given", c
);
1005 ins
->rex
&= rex_mask
;
1007 if (ins
->rex
& REX_D
) {
1008 if (ins
->rex
& REX_H
) {
1009 errfunc(ERR_NONFATAL
, "cannot use high register in drex instruction");
1012 if (bits
!= 64 && ((ins
->rex
& (REX_W
|REX_X
|REX_B
)) ||
1013 ins
->drexdst
> 7)) {
1014 errfunc(ERR_NONFATAL
, "invalid operands in non-64-bit mode");
1018 } else if (ins
->rex
& REX_REAL
) {
1019 if (ins
->rex
& REX_H
) {
1020 errfunc(ERR_NONFATAL
, "cannot use high register in rex instruction");
1022 } else if (bits
== 64 ||
1023 ((ins
->rex
& REX_L
) &&
1024 !(ins
->rex
& (REX_P
|REX_W
|REX_X
|REX_B
)) &&
1025 cpu
>= IF_X86_64
)) {
1028 errfunc(ERR_NONFATAL
, "invalid operands in non-64-bit mode");
1036 #define EMIT_REX() \
1037 if (!(ins->rex & REX_D) && (ins->rex & REX_REAL) && (bits == 64)) { \
1038 ins->rex = (ins->rex & REX_REAL)|REX_P; \
1039 out(offset, segment, &ins->rex, OUT_RAWDATA+1, NO_SEG, NO_SEG); \
1044 static void gencode(int32_t segment
, int32_t offset
, int bits
,
1045 insn
* ins
, const char *codes
, int32_t insn_end
)
1047 static char condval
[] = { /* conditional opcodes */
1048 0x7, 0x3, 0x2, 0x6, 0x2, 0x4, 0xF, 0xD, 0xC, 0xE, 0x6, 0x2,
1049 0x3, 0x7, 0x3, 0x5, 0xE, 0xC, 0xD, 0xF, 0x1, 0xB, 0x9, 0x5,
1050 0x0, 0xA, 0xA, 0xB, 0x8, 0x4
1058 switch (c
= *codes
++) {
1063 out(offset
, segment
, codes
, OUT_RAWDATA
+ c
, NO_SEG
, NO_SEG
);
1070 switch (ins
->oprs
[0].basereg
) {
1072 bytes
[0] = 0x0E + (c
== 0x04 ? 1 : 0);
1075 bytes
[0] = 0x1E + (c
== 0x04 ? 1 : 0);
1078 bytes
[0] = 0x06 + (c
== 0x04 ? 1 : 0);
1081 bytes
[0] = 0x16 + (c
== 0x04 ? 1 : 0);
1085 "bizarre 8086 segment register received");
1087 out(offset
, segment
, bytes
, OUT_RAWDATA
+ 1, NO_SEG
, NO_SEG
);
1093 switch (ins
->oprs
[0].basereg
) {
1095 bytes
[0] = 0xA0 + (c
== 0x05 ? 1 : 0);
1098 bytes
[0] = 0xA8 + (c
== 0x05 ? 1 : 0);
1102 "bizarre 386 segment register received");
1104 out(offset
, segment
, bytes
, OUT_RAWDATA
+ 1, NO_SEG
, NO_SEG
);
1113 bytes
[0] = *codes
++ + ((regval(&ins
->oprs
[c
- 010])) & 7);
1114 out(offset
, segment
, bytes
, OUT_RAWDATA
+ 1, NO_SEG
, NO_SEG
);
1122 if (ins
->oprs
[c
- 014].offset
< -128
1123 || ins
->oprs
[c
- 014].offset
> 127) {
1124 errfunc(ERR_WARNING
, "signed byte value exceeds bounds");
1127 if (ins
->oprs
[c
- 014].segment
!= NO_SEG
) {
1128 data
= ins
->oprs
[c
- 014].offset
;
1129 out(offset
, segment
, &data
, OUT_ADDRESS
+ 1,
1130 ins
->oprs
[c
- 014].segment
, ins
->oprs
[c
- 014].wrt
);
1132 bytes
[0] = ins
->oprs
[c
- 014].offset
;
1133 out(offset
, segment
, bytes
, OUT_RAWDATA
+ 1, NO_SEG
,
1143 if (ins
->oprs
[c
- 020].offset
< -256
1144 || ins
->oprs
[c
- 020].offset
> 255) {
1145 errfunc(ERR_WARNING
, "byte value exceeds bounds");
1147 if (ins
->oprs
[c
- 020].segment
!= NO_SEG
) {
1148 data
= ins
->oprs
[c
- 020].offset
;
1149 out(offset
, segment
, &data
, OUT_ADDRESS
+ 1,
1150 ins
->oprs
[c
- 020].segment
, ins
->oprs
[c
- 020].wrt
);
1152 bytes
[0] = ins
->oprs
[c
- 020].offset
;
1153 out(offset
, segment
, bytes
, OUT_RAWDATA
+ 1, NO_SEG
,
1163 if (ins
->oprs
[c
- 024].offset
< 0
1164 || ins
->oprs
[c
- 024].offset
> 255)
1165 errfunc(ERR_WARNING
, "unsigned byte value exceeds bounds");
1166 if (ins
->oprs
[c
- 024].segment
!= NO_SEG
) {
1167 data
= ins
->oprs
[c
- 024].offset
;
1168 out(offset
, segment
, &data
, OUT_ADDRESS
+ 1,
1169 ins
->oprs
[c
- 024].segment
, ins
->oprs
[c
- 024].wrt
);
1171 bytes
[0] = ins
->oprs
[c
- 024].offset
;
1172 out(offset
, segment
, bytes
, OUT_RAWDATA
+ 1, NO_SEG
,
1182 if (ins
->oprs
[c
- 030].segment
== NO_SEG
&&
1183 ins
->oprs
[c
- 030].wrt
== NO_SEG
&&
1184 (ins
->oprs
[c
- 030].offset
< -65536L ||
1185 ins
->oprs
[c
- 030].offset
> 65535L)) {
1186 errfunc(ERR_WARNING
, "word value exceeds bounds");
1188 data
= ins
->oprs
[c
- 030].offset
;
1189 out(offset
, segment
, &data
, OUT_ADDRESS
+ 2,
1190 ins
->oprs
[c
- 030].segment
, ins
->oprs
[c
- 030].wrt
);
1198 if (ins
->oprs
[c
- 034].type
& (BITS16
| BITS32
))
1199 size
= (ins
->oprs
[c
- 034].type
& BITS16
) ? 2 : 4;
1201 size
= (bits
== 16) ? 2 : 4;
1202 data
= ins
->oprs
[c
- 034].offset
;
1203 if (size
== 2 && (data
< -65536L || data
> 65535L))
1204 errfunc(ERR_WARNING
, "word value exceeds bounds");
1205 out(offset
, segment
, &data
, OUT_ADDRESS
+ size
,
1206 ins
->oprs
[c
- 034].segment
, ins
->oprs
[c
- 034].wrt
);
1214 data
= ins
->oprs
[c
- 040].offset
;
1215 out(offset
, segment
, &data
, OUT_ADDRESS
+ 4,
1216 ins
->oprs
[c
- 040].segment
, ins
->oprs
[c
- 040].wrt
);
1224 data
= ins
->oprs
[c
- 044].offset
;
1225 size
= ((ins
->oprs
[c
- 044].addr_size
?
1226 ins
->oprs
[c
- 044].addr_size
: bits
) >> 3);
1227 if (size
== 2 && (data
< -65536L || data
> 65535L))
1228 errfunc(ERR_WARNING
, "word value exceeds bounds");
1229 out(offset
, segment
, &data
, OUT_ADDRESS
+ size
,
1230 ins
->oprs
[c
- 044].segment
, ins
->oprs
[c
- 044].wrt
);
1238 if (ins
->oprs
[c
- 050].segment
!= segment
)
1239 errfunc(ERR_NONFATAL
,
1240 "short relative jump outside segment");
1241 data
= ins
->oprs
[c
- 050].offset
- insn_end
;
1242 if (data
> 127 || data
< -128)
1243 errfunc(ERR_NONFATAL
, "short jump is out of range");
1245 out(offset
, segment
, bytes
, OUT_RAWDATA
+ 1, NO_SEG
, NO_SEG
);
1253 data
= (int64_t)ins
->oprs
[c
- 054].offset
;
1254 out(offset
, segment
, &data
, OUT_ADDRESS
+ 8,
1255 ins
->oprs
[c
- 054].segment
, ins
->oprs
[c
- 054].wrt
);
1263 if (ins
->oprs
[c
- 060].segment
!= segment
) {
1264 data
= ins
->oprs
[c
- 060].offset
;
1265 out(offset
, segment
, &data
,
1266 OUT_REL2ADR
+ insn_end
- offset
,
1267 ins
->oprs
[c
- 060].segment
, ins
->oprs
[c
- 060].wrt
);
1269 data
= ins
->oprs
[c
- 060].offset
- insn_end
;
1270 out(offset
, segment
, &data
,
1271 OUT_ADDRESS
+ 2, NO_SEG
, NO_SEG
);
1280 if (ins
->oprs
[c
- 064].type
& (BITS16
| BITS32
| BITS64
))
1281 size
= (ins
->oprs
[c
- 064].type
& BITS16
) ? 2 : 4;
1283 size
= (bits
== 16) ? 2 : 4;
1284 if (ins
->oprs
[c
- 064].segment
!= segment
) {
1285 int32_t reltype
= (size
== 2 ? OUT_REL2ADR
: OUT_REL4ADR
);
1286 data
= ins
->oprs
[c
- 064].offset
;
1287 out(offset
, segment
, &data
, reltype
+ insn_end
- offset
,
1288 ins
->oprs
[c
- 064].segment
, ins
->oprs
[c
- 064].wrt
);
1290 data
= ins
->oprs
[c
- 064].offset
- insn_end
;
1291 out(offset
, segment
, &data
,
1292 OUT_ADDRESS
+ size
, NO_SEG
, NO_SEG
);
1301 if (ins
->oprs
[c
- 070].segment
!= segment
) {
1302 data
= ins
->oprs
[c
- 070].offset
;
1303 out(offset
, segment
, &data
,
1304 OUT_REL4ADR
+ insn_end
- offset
,
1305 ins
->oprs
[c
- 070].segment
, ins
->oprs
[c
- 070].wrt
);
1307 data
= ins
->oprs
[c
- 070].offset
- insn_end
;
1308 out(offset
, segment
, &data
,
1309 OUT_ADDRESS
+ 4, NO_SEG
, NO_SEG
);
1318 if (ins
->oprs
[c
- 074].segment
== NO_SEG
)
1319 errfunc(ERR_NONFATAL
, "value referenced by FAR is not"
1322 out(offset
, segment
, &data
, OUT_ADDRESS
+ 2,
1323 outfmt
->segbase(1 + ins
->oprs
[c
- 074].segment
),
1324 ins
->oprs
[c
- 074].wrt
);
1332 data
= ins
->oprs
[c
- 0140].offset
;
1333 if (is_sbyte(ins
, c
- 0140, 16)) {
1335 out(offset
, segment
, bytes
, OUT_RAWDATA
+ 1, NO_SEG
,
1339 if (ins
->oprs
[c
- 0140].segment
== NO_SEG
&&
1340 ins
->oprs
[c
- 0140].wrt
== NO_SEG
&&
1341 (data
< -65536L || data
> 65535L)) {
1342 errfunc(ERR_WARNING
, "word value exceeds bounds");
1344 out(offset
, segment
, &data
, OUT_ADDRESS
+ 2,
1345 ins
->oprs
[c
- 0140].segment
, ins
->oprs
[c
- 0140].wrt
);
1356 bytes
[0] = *codes
++;
1357 if (is_sbyte(ins
, c
- 0144, 16))
1358 bytes
[0] |= 2; /* s-bit */
1359 out(offset
, segment
, bytes
, OUT_RAWDATA
+ 1, NO_SEG
, NO_SEG
);
1367 data
= ins
->oprs
[c
- 0150].offset
;
1368 if (is_sbyte(ins
, c
- 0150, 32)) {
1370 out(offset
, segment
, bytes
, OUT_RAWDATA
+ 1, NO_SEG
,
1374 out(offset
, segment
, &data
, OUT_ADDRESS
+ 4,
1375 ins
->oprs
[c
- 0150].segment
, ins
->oprs
[c
- 0150].wrt
);
1386 bytes
[0] = *codes
++;
1387 if (is_sbyte(ins
, c
- 0154, 32))
1388 bytes
[0] |= 2; /* s-bit */
1389 out(offset
, segment
, bytes
, OUT_RAWDATA
+ 1, NO_SEG
, NO_SEG
);
1406 out(offset
, segment
, bytes
, OUT_RAWDATA
+ 1, NO_SEG
, NO_SEG
);
1412 (ins
->drexdst
<< 4) |
1413 (ins
->rex
& REX_OC
? 0x08 : 0) |
1414 (ins
->rex
& (REX_R
|REX_X
|REX_B
));
1416 out(offset
, segment
, bytes
, OUT_RAWDATA
+ 1, NO_SEG
, NO_SEG
);
1427 if (bits
== 32 && !has_prefix(ins
,P_A16
)) {
1429 out(offset
, segment
, bytes
,
1430 OUT_RAWDATA
+ 1, NO_SEG
, NO_SEG
);
1437 if (bits
!= 32 && !has_prefix(ins
,P_A32
)) {
1439 out(offset
, segment
, bytes
,
1440 OUT_RAWDATA
+ 1, NO_SEG
, NO_SEG
);
1456 out(offset
, segment
, bytes
,
1457 OUT_RAWDATA
+ 1, NO_SEG
, NO_SEG
);
1466 out(offset
, segment
, bytes
,
1467 OUT_RAWDATA
+ 1, NO_SEG
, NO_SEG
);
1482 *bytes
= *codes
++ ^ condval
[ins
->condition
];
1483 out(offset
, segment
, bytes
, OUT_RAWDATA
+ 1, NO_SEG
, NO_SEG
);
1492 *bytes
= c
- 0332 + 0xF2;
1493 out(offset
, segment
, bytes
, OUT_RAWDATA
+ 1, NO_SEG
, NO_SEG
);
1498 if (ins
->rex
& REX_R
) {
1500 out(offset
, segment
, bytes
, OUT_RAWDATA
+ 1, NO_SEG
, NO_SEG
);
1503 ins
->rex
&= ~(REX_L
|REX_R
);
1512 if (ins
->oprs
[0].segment
!= NO_SEG
)
1513 errfunc(ERR_PANIC
, "non-constant BSS size in pass two");
1515 int32_t size
= ins
->oprs
[0].offset
<< (c
- 0340);
1517 out(offset
, segment
, NULL
,
1518 OUT_RESERVE
+ size
, NO_SEG
, NO_SEG
);
1529 *bytes
= c
- 0366 + 0x66;
1530 out(offset
, segment
, bytes
, OUT_RAWDATA
+ 1, NO_SEG
, NO_SEG
);
1540 *bytes
= bits
== 16 ? 3 : 5;
1541 out(offset
, segment
, bytes
, OUT_RAWDATA
+ 1, NO_SEG
, NO_SEG
);
1545 default: /* can't do it by 'case' statements */
1546 if (c
>= 0100 && c
<= 0277) { /* it's an EA */
1554 /* pick rfield from operand b */
1555 rflags
= regflag(&ins
->oprs
[c
& 7]);
1556 rfield
= regvals
[ins
->oprs
[c
& 7].basereg
];
1558 /* rfield is constant */
1564 (&ins
->oprs
[(c
>> 3) & 7], &ea_data
, bits
,
1565 rfield
, rflags
, ins
->forw_ref
)) {
1566 errfunc(ERR_NONFATAL
, "invalid effective address");
1570 *p
++ = ea_data
.modrm
;
1571 if (ea_data
.sib_present
)
1574 /* DREX suffixes come between the SIB and the displacement */
1575 if (ins
->rex
& REX_D
) {
1577 (ins
->drexdst
<< 4) |
1578 (ins
->rex
& REX_OC
? 0x08 : 0) |
1579 (ins
->rex
& (REX_R
|REX_X
|REX_B
));
1584 out(offset
, segment
, bytes
, OUT_RAWDATA
+ s
,
1587 switch (ea_data
.bytes
) {
1591 if (ins
->oprs
[(c
>> 3) & 7].segment
!= NO_SEG
) {
1592 data
= ins
->oprs
[(c
>> 3) & 7].offset
;
1593 out(offset
, segment
, &data
, OUT_ADDRESS
+ 1,
1594 ins
->oprs
[(c
>> 3) & 7].segment
,
1595 ins
->oprs
[(c
>> 3) & 7].wrt
);
1597 *bytes
= ins
->oprs
[(c
>> 3) & 7].offset
;
1598 out(offset
, segment
, bytes
, OUT_RAWDATA
+ 1,
1606 data
= ins
->oprs
[(c
>> 3) & 7].offset
;
1607 out(offset
, segment
, &data
,
1608 (ea_data
.rip
? OUT_REL4ADR
: OUT_ADDRESS
)
1610 ins
->oprs
[(c
>> 3) & 7].segment
,
1611 ins
->oprs
[(c
>> 3) & 7].wrt
);
1617 errfunc(ERR_PANIC
, "internal instruction table corrupt"
1618 ": instruction code 0x%02X given", c
);
1622 static int32_t regflag(const operand
* o
)
1624 if (o
->basereg
< EXPR_REG_START
|| o
->basereg
>= REG_ENUM_LIMIT
) {
1625 errfunc(ERR_PANIC
, "invalid operand passed to regflag()");
1627 return reg_flags
[o
->basereg
];
1630 static int32_t regval(const operand
* o
)
1632 if (o
->basereg
< EXPR_REG_START
|| o
->basereg
>= REG_ENUM_LIMIT
) {
1633 errfunc(ERR_PANIC
, "invalid operand passed to regval()");
1635 return regvals
[o
->basereg
];
1638 static int op_rexflags(const operand
* o
, int mask
)
1643 if (o
->basereg
< EXPR_REG_START
|| o
->basereg
>= REG_ENUM_LIMIT
) {
1644 errfunc(ERR_PANIC
, "invalid operand passed to op_rexflags()");
1647 flags
= reg_flags
[o
->basereg
];
1648 val
= regvals
[o
->basereg
];
1650 return rexflags(val
, flags
, mask
);
1653 static int rexflags(int val
, int32_t flags
, int mask
)
1658 rex
|= REX_B
|REX_X
|REX_R
;
1661 if (!(REG_HIGH
& ~flags
)) /* AH, CH, DH, BH */
1663 else if (!(REG8
& ~flags
) && val
>= 4) /* SPL, BPL, SIL, DIL */
1669 static int matches(const struct itemplate
*itemp
, insn
* instruction
, int bits
)
1671 int i
, size
[MAX_OPERANDS
], asize
, oprs
, ret
;
1678 if (itemp
->opcode
!= instruction
->opcode
)
1682 * Count the operands
1684 if (itemp
->operands
!= instruction
->operands
)
1688 * Check that no spurious colons or TOs are present
1690 for (i
= 0; i
< itemp
->operands
; i
++)
1691 if (instruction
->oprs
[i
].type
& ~itemp
->opd
[i
] & (COLON
| TO
))
1695 * Check that the operand flags all match up
1697 for (i
= 0; i
< itemp
->operands
; i
++) {
1698 if (itemp
->opd
[i
] & SAME_AS
) {
1699 int j
= itemp
->opd
[i
] & ~SAME_AS
;
1700 if (instruction
->oprs
[i
].type
!= instruction
->oprs
[j
].type
||
1701 instruction
->oprs
[i
].basereg
!= instruction
->oprs
[j
].basereg
)
1703 } else if (itemp
->opd
[i
] & ~instruction
->oprs
[i
].type
||
1704 ((itemp
->opd
[i
] & SIZE_MASK
) &&
1705 ((itemp
->opd
[i
] ^ instruction
->oprs
[i
].type
) & SIZE_MASK
))) {
1706 if ((itemp
->opd
[i
] & ~instruction
->oprs
[i
].type
& ~SIZE_MASK
) ||
1707 (instruction
->oprs
[i
].type
& SIZE_MASK
))
1715 * Check operand sizes
1717 if (itemp
->flags
& IF_ARMASK
) {
1718 memset(size
, 0, sizeof size
);
1720 switch (itemp
->flags
& IF_ARMASK
) {
1734 break; /* Shouldn't happen */
1736 switch (itemp
->flags
& IF_SMASK
) {
1757 switch (itemp
->flags
& IF_SMASK
) {
1760 oprs
= itemp
->operands
;
1764 oprs
= itemp
->operands
;
1768 oprs
= itemp
->operands
;
1772 oprs
= itemp
->operands
;
1776 oprs
= itemp
->operands
;
1781 for (i
= 0; i
< MAX_OPERANDS
; i
++)
1785 if (itemp
->flags
& (IF_SM
| IF_SM2
)) {
1786 oprs
= (itemp
->flags
& IF_SM2
? 2 : itemp
->operands
);
1788 for (i
= 0; i
< oprs
; i
++) {
1789 if ((asize
= itemp
->opd
[i
] & SIZE_MASK
) != 0) {
1791 for (j
= 0; j
< oprs
; j
++)
1797 oprs
= itemp
->operands
;
1800 for (i
= 0; i
< itemp
->operands
; i
++) {
1801 if (!(itemp
->opd
[i
] & SIZE_MASK
) &&
1802 (instruction
->oprs
[i
].type
& SIZE_MASK
& ~size
[i
]))
1807 * Check template is okay at the set cpu level
1809 if (((itemp
->flags
& IF_PLEVEL
) > cpu
))
1813 * Check if instruction is available in long mode
1815 if ((itemp
->flags
& IF_NOLONG
) && (bits
== 64))
1819 * Check if special handling needed for Jumps
1821 if ((uint8_t)(itemp
->code
[0]) >= 0370)
1827 static ea
*process_ea(operand
* input
, ea
* output
, int addrbits
,
1828 int rfield
, int32_t rflags
, int forw_ref
)
1830 output
->rip
= false;
1832 /* REX flags for the rfield operand */
1833 output
->rex
|= rexflags(rfield
, rflags
, REX_R
|REX_P
|REX_W
|REX_H
);
1835 if (!(REGISTER
& ~input
->type
)) { /* register direct */
1839 if (input
->basereg
< EXPR_REG_START
/* Verify as Register */
1840 || input
->basereg
>= REG_ENUM_LIMIT
)
1843 i
= regvals
[input
->basereg
];
1846 return NULL
; /* Invalid EA register */
1848 output
->rex
|= op_rexflags(input
, REX_B
|REX_P
|REX_W
|REX_H
);
1850 output
->sib_present
= false; /* no SIB necessary */
1851 output
->bytes
= 0; /* no offset necessary either */
1852 output
->modrm
= 0xC0 | ((rfield
& 7) << 3) | (i
& 7);
1853 } else { /* it's a memory reference */
1854 if (input
->basereg
== -1
1855 && (input
->indexreg
== -1 || input
->scale
== 0)) {
1856 /* it's a pure offset */
1857 if (input
->addr_size
)
1858 addrbits
= input
->addr_size
;
1860 if (globalbits
== 64 && (~input
->type
& IP_REL
)) {
1861 int scale
, index
, base
;
1862 output
->sib_present
= true;
1866 output
->sib
= (scale
<< 6) | (index
<< 3) | base
;
1868 output
->modrm
= 4 | ((rfield
& 7) << 3);
1869 output
->rip
= false;
1871 output
->sib_present
= false;
1872 output
->bytes
= (addrbits
!= 16 ? 4 : 2);
1873 output
->modrm
= (addrbits
!= 16 ? 5 : 6) | ((rfield
& 7) << 3);
1874 output
->rip
= globalbits
== 64;
1876 } else { /* it's an indirection */
1877 int i
= input
->indexreg
, b
= input
->basereg
, s
= input
->scale
;
1878 int32_t o
= input
->offset
, seg
= input
->segment
;
1879 int hb
= input
->hintbase
, ht
= input
->hinttype
;
1882 int32_t ix
, bx
; /* register flags */
1885 i
= -1; /* make this easy, at least */
1887 if (i
>= EXPR_REG_START
&& i
< REG_ENUM_LIMIT
) {
1895 if (b
!= -1 && b
>= EXPR_REG_START
&& b
< REG_ENUM_LIMIT
) {
1903 /* check for a 32/64-bit memory reference... */
1904 if ((ix
|bx
) & (BITS32
|BITS64
)) {
1905 /* it must be a 32/64-bit memory reference. Firstly we have
1906 * to check that all registers involved are type E/Rxx. */
1907 int32_t sok
= BITS32
|BITS64
;
1910 if (!(REG64
& ~ix
) || !(REG32
& ~ix
))
1918 return NULL
; /* Invalid register */
1919 if (~sok
& bx
& SIZE_MASK
)
1920 return NULL
; /* Invalid size */
1924 /* While we're here, ensure the user didn't specify WORD. */
1925 if (input
->addr_size
== 16 ||
1926 (input
->addr_size
== 32 && !(sok
& BITS32
)) ||
1927 (input
->addr_size
== 64 && !(sok
& BITS64
)))
1930 /* now reorganize base/index */
1931 if (s
== 1 && bt
!= it
&& bt
!= -1 && it
!= -1 &&
1932 ((hb
== b
&& ht
== EAH_NOTBASE
)
1933 || (hb
== i
&& ht
== EAH_MAKEBASE
))) {
1934 /* swap if hints say so */
1935 t
= bt
, bt
= it
, it
= t
;
1936 t
= bx
, bx
= ix
, ix
= t
;
1938 if (bt
== it
) /* convert EAX+2*EAX to 3*EAX */
1939 bt
= -1, bx
= 0, s
++;
1940 if (bt
== -1 && s
== 1 && !(hb
== it
&& ht
== EAH_NOTBASE
)) {
1941 /* make single reg base, unless hint */
1942 bt
= it
, bx
= ix
, it
= -1, ix
= 0;
1944 if (((s
== 2 && it
!= REG_NUM_ESP
1945 && !(input
->eaflags
& EAF_TIMESTWO
)) || s
== 3
1946 || s
== 5 || s
== 9) && bt
== -1)
1947 bt
= it
, bx
= ix
, s
--; /* convert 3*EAX to EAX+2*EAX */
1948 if (it
== -1 && (bt
& 7) != REG_NUM_ESP
1949 && (input
->eaflags
& EAF_TIMESTWO
))
1950 it
= bt
, ix
= bx
, bt
= -1, bx
= 0, s
= 1;
1951 /* convert [NOSPLIT EAX] to sib format with 0x0 displacement */
1952 if (s
== 1 && it
== REG_NUM_ESP
) {
1953 /* swap ESP into base if scale is 1 */
1954 t
= it
, it
= bt
, bt
= t
;
1955 t
= ix
, ix
= bx
, bx
= t
;
1957 if (it
== REG_NUM_ESP
1958 || (s
!= 1 && s
!= 2 && s
!= 4 && s
!= 8 && it
!= -1))
1959 return NULL
; /* wrong, for various reasons */
1961 output
->rex
|= rexflags(it
, ix
, REX_X
);
1962 output
->rex
|= rexflags(bt
, bx
, REX_B
);
1964 if (it
== -1 && (bt
& 7) != REG_NUM_ESP
) {
1973 if (rm
!= REG_NUM_EBP
&& o
== 0 &&
1974 seg
== NO_SEG
&& !forw_ref
&&
1976 (EAF_BYTEOFFS
| EAF_WORDOFFS
)))
1978 else if (input
->eaflags
& EAF_BYTEOFFS
||
1979 (o
>= -128 && o
<= 127 && seg
== NO_SEG
1981 && !(input
->eaflags
& EAF_WORDOFFS
)))
1987 output
->sib_present
= false;
1988 output
->bytes
= (bt
== -1 || mod
== 2 ? 4 : mod
);
1989 output
->modrm
= (mod
<< 6) | ((rfield
& 7) << 3) | rm
;
1992 int mod
, scale
, index
, base
;
2012 default: /* then what the smeg is it? */
2013 return NULL
; /* panic */
2021 if (base
!= REG_NUM_EBP
&& o
== 0 &&
2022 seg
== NO_SEG
&& !forw_ref
&&
2024 (EAF_BYTEOFFS
| EAF_WORDOFFS
)))
2026 else if (input
->eaflags
& EAF_BYTEOFFS
||
2027 (o
>= -128 && o
<= 127 && seg
== NO_SEG
2029 && !(input
->eaflags
& EAF_WORDOFFS
)))
2035 output
->sib_present
= true;
2036 output
->bytes
= (bt
== -1 || mod
== 2 ? 4 : mod
);
2037 output
->modrm
= (mod
<< 6) | ((rfield
& 7) << 3) | 4;
2038 output
->sib
= (scale
<< 6) | (index
<< 3) | base
;
2040 } else { /* it's 16-bit */
2043 /* check for 64-bit long mode */
2047 /* check all registers are BX, BP, SI or DI */
2048 if ((b
!= -1 && b
!= R_BP
&& b
!= R_BX
&& b
!= R_SI
2049 && b
!= R_DI
) || (i
!= -1 && i
!= R_BP
&& i
!= R_BX
2050 && i
!= R_SI
&& i
!= R_DI
))
2053 /* ensure the user didn't specify DWORD/QWORD */
2054 if (input
->addr_size
== 32 || input
->addr_size
== 64)
2057 if (s
!= 1 && i
!= -1)
2058 return NULL
; /* no can do, in 16-bit EA */
2059 if (b
== -1 && i
!= -1) {
2064 if ((b
== R_SI
|| b
== R_DI
) && i
!= -1) {
2069 /* have BX/BP as base, SI/DI index */
2071 return NULL
; /* shouldn't ever happen, in theory */
2072 if (i
!= -1 && b
!= -1 &&
2073 (i
== R_BP
|| i
== R_BX
|| b
== R_SI
|| b
== R_DI
))
2074 return NULL
; /* invalid combinations */
2075 if (b
== -1) /* pure offset: handled above */
2076 return NULL
; /* so if it gets to here, panic! */
2080 switch (i
* 256 + b
) {
2081 case R_SI
* 256 + R_BX
:
2084 case R_DI
* 256 + R_BX
:
2087 case R_SI
* 256 + R_BP
:
2090 case R_DI
* 256 + R_BP
:
2108 if (rm
== -1) /* can't happen, in theory */
2109 return NULL
; /* so panic if it does */
2111 if (o
== 0 && seg
== NO_SEG
&& !forw_ref
&& rm
!= 6 &&
2112 !(input
->eaflags
& (EAF_BYTEOFFS
| EAF_WORDOFFS
)))
2114 else if (input
->eaflags
& EAF_BYTEOFFS
||
2115 (o
>= -128 && o
<= 127 && seg
== NO_SEG
2117 && !(input
->eaflags
& EAF_WORDOFFS
)))
2122 output
->sib_present
= false; /* no SIB - it's 16-bit */
2123 output
->bytes
= mod
; /* bytes of offset needed */
2124 output
->modrm
= (mod
<< 6) | ((rfield
& 7) << 3) | rm
;
2129 output
->size
= 1 + output
->sib_present
+ output
->bytes
;
2133 static void add_asp(insn
*instruction
, int addrbits
)
2137 valid
= (addrbits
== 64) ? 64|32 : 32|16;
2139 for (j
= 0; j
< instruction
->operands
; j
++) {
2140 if (!(MEMORY
& ~instruction
->oprs
[j
].type
)) {
2143 /* Verify as Register */
2144 if (instruction
->oprs
[j
].indexreg
< EXPR_REG_START
2145 || instruction
->oprs
[j
].indexreg
>= REG_ENUM_LIMIT
)
2148 i
= reg_flags
[instruction
->oprs
[j
].indexreg
];
2150 /* Verify as Register */
2151 if (instruction
->oprs
[j
].basereg
< EXPR_REG_START
2152 || instruction
->oprs
[j
].basereg
>= REG_ENUM_LIMIT
)
2155 b
= reg_flags
[instruction
->oprs
[j
].basereg
];
2157 if (instruction
->oprs
[j
].scale
== 0)
2161 if (instruction
->oprs
[j
].addr_size
)
2162 valid
&= instruction
->oprs
[j
].addr_size
;
2181 if (valid
& addrbits
) {
2182 /* Don't do anything */
2183 } else if (valid
& ((addrbits
== 32) ? 16 : 32)) {
2184 /* Add an instruction size prefix */
2185 enum prefixes pref
= (addrbits
== 32) ? P_A16
: P_A32
;
2186 for (j
= 0; j
< instruction
->nprefix
; j
++) {
2187 if (instruction
->prefixes
[j
] == pref
)
2188 return; /* Already there */
2190 instruction
->prefixes
[j
] = pref
;
2191 instruction
->nprefix
++;
2194 errfunc(ERR_NONFATAL
, "impossible combination of address sizes");