blob: b66ba42e5f31ce017855bc624738b702de5da5cf [file] [log] [blame]
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001/* assemble.c code generation for the Netwide Assembler
2 *
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.
7 *
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
H. Peter Anvin3ba46772002-05-27 23:19:35 +000025 * assembly mode or the operand-size override on the operand
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000026 * \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
H. Peter Anvinb061d592007-04-16 02:02:06 +000028 * \44, \45, \46 - select between \3[012], \4[012] and \5[456]
29 * depending on assembly mode or the address-size override
30 * on the operand.
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000031 * \50, \51, \52 - a byte relative operand, from operand 0, 1 or 2
Keith Kaniosb7a89542007-04-12 02:40:54 +000032 * \54, \55, \56 - a qword immediate operand, from operand 0, 1 or 2
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000033 * \60, \61, \62 - a word relative operand, from operand 0, 1 or 2
34 * \64, \65, \66 - select between \6[012] and \7[012] depending on 16/32 bit
H. Peter Anvin17799b42002-05-21 03:31:21 +000035 * assembly mode or the operand-size override on the operand
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000036 * \70, \71, \72 - a long relative operand, from operand 0, 1 or 2
37 * \1ab - a ModRM, calculated on EA in operand a, with the spare
38 * field the register value of operand b.
H. Peter Anvinaf535c12002-04-30 20:59:21 +000039 * \130,\131,\132 - an immediate word or signed byte for operand 0, 1, or 2
40 * \133,\134,\135 - or 2 (s-field) into next opcode byte if operand 0, 1, or 2
41 * is a signed byte rather than a word.
42 * \140,\141,\142 - an immediate dword or signed byte for operand 0, 1, or 2
43 * \143,\144,\145 - or 2 (s-field) into next opcode byte if operand 0, 1, or 2
44 * is a signed byte rather than a dword.
Keith Kaniosb7a89542007-04-12 02:40:54 +000045 * \150,\151,\152 - an immediate qword or signed byte for operand 0, 1, or 2
46 * \153,\154,\155 - or 2 (s-field) into next opcode byte if operand 0, 1, or 2
47 * is a signed byte rather than a qword.
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000048 * \2ab - a ModRM, calculated on EA in operand a, with the spare
49 * field equal to digit b.
50 * \30x - might be an 0x67 byte, depending on the address size of
51 * the memory reference in operand x.
52 * \310 - indicates fixed 16-bit address size, i.e. optional 0x67.
53 * \311 - indicates fixed 32-bit address size, i.e. optional 0x67.
H. Peter Anvinaf535c12002-04-30 20:59:21 +000054 * \312 - (disassembler only) marker on LOOP, LOOPxx instructions.
Keith Kaniosb7a89542007-04-12 02:40:54 +000055 * \313 - indicates fixed 64-bit address size, no REX required.
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000056 * \320 - indicates fixed 16-bit operand size, i.e. optional 0x66.
57 * \321 - indicates fixed 32-bit operand size, i.e. optional 0x66.
58 * \322 - indicates that this instruction is only valid when the
59 * operand size is the default (instruction to disassembler,
60 * generates no code in the assembler)
Keith Kaniosb7a89542007-04-12 02:40:54 +000061 * \323 - indicates fixed 64-bit operand size, REX on extensions, only.
62 * \324 - indicates 64-bit operand size requiring REX prefix.
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000063 * \330 - a literal byte follows in the code stream, to be added
64 * to the condition code value of the instruction.
H. Peter Anvinef7468f2002-04-30 20:57:59 +000065 * \331 - instruction not valid with REP prefix. Hint for
66 * disassembler only; for SSE instructions.
67 * \332 - disassemble a rep (0xF3 byte) prefix as repe not rep.
68 * \333 - REP prefix (0xF3 byte); for SSE instructions. Not encoded
69 * as a literal byte in order to aid the disassembler.
Keith Kaniosb7a89542007-04-12 02:40:54 +000070 * \340 - reserve <operand 0> bytes of uninitialized storage.
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000071 * Operand 0 had better be a segmentless constant.
H. Peter Anvin788e6c12002-04-30 21:02:01 +000072 * \370,\371,\372 - match only if operand 0 meets byte jump criteria.
73 * 370 is used for Jcc, 371 is used for JMP.
H. Peter Anvinaf535c12002-04-30 20:59:21 +000074 * \373 - assemble 0x03 if bits==16, 0x05 if bits==32;
75 * used for conditional jump over longer jump
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000076 */
77
78#include <stdio.h>
79#include <string.h>
Keith Kaniosb7a89542007-04-12 02:40:54 +000080#include <inttypes.h>
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000081
82#include "nasm.h"
H. Peter Anvin6768eb72002-04-30 20:52:26 +000083#include "nasmlib.h"
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000084#include "assemble.h"
85#include "insns.h"
Frank Kotlerd0ed6fd2003-08-27 11:33:56 +000086#include "preproc.h"
Keith Kaniosb7a89542007-04-12 02:40:54 +000087#include "regvals.c"
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000088
89extern struct itemplate *nasm_instructions[];
90
91typedef struct {
Keith Kaniosb7a89542007-04-12 02:40:54 +000092 int sib_present; /* is a SIB byte necessary? */
93 int bytes; /* # of bytes of offset needed */
94 int size; /* lazy - this is sib+bytes+1 */
95 uint8_t modrm, sib, rex, rip; /* the bytes themselves */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000096} ea;
97
Keith Kaniosb7a89542007-04-12 02:40:54 +000098static uint32_t cpu; /* cpu level received from nasm.c */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000099static efunc errfunc;
100static struct ofmt *outfmt;
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000101static ListGen *list;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000102
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000103static int32_t calcsize(int32_t, int32_t, int, insn *, const char *);
104static void gencode(int32_t, int32_t, int, insn *, const char *, int32_t);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000105static int regval(operand * o);
Keith Kanios93f2e9a2007-04-14 00:10:59 +0000106// static int regflag(operand * o);
Keith Kaniosb7a89542007-04-12 02:40:54 +0000107static int matches(struct itemplate *, insn *, int bits);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000108static ea *process_ea(operand *, ea *, int, int, int);
109static int chsize(operand *, int);
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000110
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000111/*
112 * This routine wrappers the real output format's output routine,
113 * in order to pass a copy of the data off to the listing file
114 * generator at the same time.
115 */
Keith Kaniosb7a89542007-04-12 02:40:54 +0000116static void out(int32_t offset, int32_t segto, const void *data,
117 uint32_t type, int32_t segment, int32_t wrt)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000118{
Keith Kaniosb7a89542007-04-12 02:40:54 +0000119 static int32_t lineno = 0; /* static!!! */
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000120 static char *lnfname = NULL;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000121
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000122 if ((type & OUT_TYPMASK) == OUT_ADDRESS) {
H. Peter Anvine2c80182005-01-15 22:15:51 +0000123 if (segment != NO_SEG || wrt != NO_SEG) {
124 /*
125 * This address is relocated. We must write it as
126 * OUT_ADDRESS, so there's no work to be done here.
127 */
128 list->output(offset, data, type);
129 } else {
Keith Kaniosb7a89542007-04-12 02:40:54 +0000130 uint8_t p[8], *q = p;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000131 /*
132 * This is a non-relocated address, and we're going to
133 * convert it into RAWDATA format.
134 */
135 if ((type & OUT_SIZMASK) == 4) {
Keith Kaniosb7a89542007-04-12 02:40:54 +0000136 WRITELONG(q, *(int32_t *)data);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000137 list->output(offset, p, OUT_RAWDATA + 4);
Keith Kaniosb7a89542007-04-12 02:40:54 +0000138 } else if ((type & OUT_SIZMASK) == 8) {
139 WRITEDLONG(q, *(int64_t *)data);
140 list->output(offset, p, OUT_RAWDATA + 8);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000141 } else {
Keith Kaniosb7a89542007-04-12 02:40:54 +0000142 WRITESHORT(q, *(int32_t *)data);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000143 list->output(offset, p, OUT_RAWDATA + 2);
144 }
145 }
146 } else if ((type & OUT_TYPMASK) == OUT_RAWDATA) {
147 list->output(offset, data, type);
148 } else if ((type & OUT_TYPMASK) == OUT_RESERVE) {
149 list->output(offset, NULL, type);
150 } else if ((type & OUT_TYPMASK) == OUT_REL2ADR ||
151 (type & OUT_TYPMASK) == OUT_REL4ADR) {
152 list->output(offset, data, type);
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000153 }
154
Frank Kotlerabebb082003-09-06 04:45:37 +0000155 /*
156 * this call to src_get determines when we call the
157 * debug-format-specific "linenum" function
158 * it updates lineno and lnfname to the current values
159 * returning 0 if "same as last time", -2 if lnfname
160 * changed, and the amount by which lineno changed,
161 * if it did. thus, these variables must be static
162 */
163
H. Peter Anvine2c80182005-01-15 22:15:51 +0000164 if (src_get(&lineno, &lnfname)) {
165 outfmt->current_dfmt->linenum(lnfname, lineno, segto);
H. Peter Anvince616072002-04-30 21:02:23 +0000166 }
H. Peter Anvineba20a72002-04-30 20:53:55 +0000167
H. Peter Anvine2c80182005-01-15 22:15:51 +0000168 outfmt->output(segto, data, type, segment, wrt);
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000169}
170
Keith Kaniosb7a89542007-04-12 02:40:54 +0000171static int jmp_match(int32_t segment, int32_t offset, int bits,
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000172 insn * ins, const char *code)
H. Peter Anvine2c80182005-01-15 22:15:51 +0000173{
Keith Kaniosb7a89542007-04-12 02:40:54 +0000174 int32_t isize;
175 uint8_t c = code[0];
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000176
H. Peter Anvine2c80182005-01-15 22:15:51 +0000177 if (c != 0370 && c != 0371)
178 return 0;
H. Peter Anvin788e6c12002-04-30 21:02:01 +0000179 if (ins->oprs[0].opflags & OPFLAG_FORWARD) {
H. Peter Anvine2c80182005-01-15 22:15:51 +0000180 if ((optimizing < 0 || (ins->oprs[0].type & STRICT))
181 && c == 0370)
182 return 1;
183 else
184 return (pass0 == 0); /* match a forward reference */
H. Peter Anvin788e6c12002-04-30 21:02:01 +0000185 }
H. Peter Anvine2c80182005-01-15 22:15:51 +0000186 isize = calcsize(segment, offset, bits, ins, code);
187 if (ins->oprs[0].segment != segment)
188 return 0;
189 isize = ins->oprs[0].offset - offset - isize; /* isize is now the delta */
190 if (isize >= -128L && isize <= 127L)
191 return 1; /* it is byte size */
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000192
193 return 0;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000194}
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000195
Keith Kaniosb7a89542007-04-12 02:40:54 +0000196int32_t assemble(int32_t segment, int32_t offset, int bits, uint32_t cp,
H. Peter Anvine2c80182005-01-15 22:15:51 +0000197 insn * instruction, struct ofmt *output, efunc error,
198 ListGen * listgen)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000199{
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000200 struct itemplate *temp;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000201 int j;
202 int size_prob;
Keith Kaniosb7a89542007-04-12 02:40:54 +0000203 int32_t insn_end;
204 int32_t itimes;
205 int32_t start = offset;
206 int32_t wsize = 0; /* size for DB etc. */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000207
H. Peter Anvine2c80182005-01-15 22:15:51 +0000208 errfunc = error; /* to pass to other functions */
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000209 cpu = cp;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000210 outfmt = output; /* likewise */
211 list = listgen; /* and again */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000212
H. Peter Anvine2c80182005-01-15 22:15:51 +0000213 switch (instruction->opcode) {
214 case -1:
215 return 0;
216 case I_DB:
217 wsize = 1;
218 break;
219 case I_DW:
220 wsize = 2;
221 break;
222 case I_DD:
223 wsize = 4;
224 break;
225 case I_DQ:
226 wsize = 8;
227 break;
228 case I_DT:
229 wsize = 10;
230 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000231 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000232
H. Peter Anvineba20a72002-04-30 20:53:55 +0000233 if (wsize) {
H. Peter Anvine2c80182005-01-15 22:15:51 +0000234 extop *e;
Keith Kaniosb7a89542007-04-12 02:40:54 +0000235 int32_t t = instruction->times;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000236 if (t < 0)
237 errfunc(ERR_PANIC,
238 "instruction->times < 0 (%ld) in assemble()", t);
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000239
H. Peter Anvine2c80182005-01-15 22:15:51 +0000240 while (t--) { /* repeat TIMES times */
241 for (e = instruction->eops; e; e = e->next) {
242 if (e->type == EOT_DB_NUMBER) {
243 if (wsize == 1) {
244 if (e->segment != NO_SEG)
245 errfunc(ERR_NONFATAL,
246 "one-byte relocation attempted");
247 else {
Keith Kaniosb7a89542007-04-12 02:40:54 +0000248 uint8_t out_byte = e->offset;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000249 out(offset, segment, &out_byte,
250 OUT_RAWDATA + 1, NO_SEG, NO_SEG);
251 }
Keith Kanios61ff53c2007-04-14 18:54:52 +0000252 } else if (wsize > 8) {
253 errfunc(ERR_NONFATAL, "integer supplied to a DT"
254 " instruction");
H. Peter Anvine2c80182005-01-15 22:15:51 +0000255 } else
256 out(offset, segment, &e->offset,
257 OUT_ADDRESS + wsize, e->segment, e->wrt);
258 offset += wsize;
259 } else if (e->type == EOT_DB_STRING) {
260 int align;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000261
H. Peter Anvine2c80182005-01-15 22:15:51 +0000262 out(offset, segment, e->stringval,
263 OUT_RAWDATA + e->stringlen, NO_SEG, NO_SEG);
264 align = e->stringlen % wsize;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000265
H. Peter Anvine2c80182005-01-15 22:15:51 +0000266 if (align) {
267 align = wsize - align;
268 out(offset, segment, "\0\0\0\0\0\0\0\0",
269 OUT_RAWDATA + align, NO_SEG, NO_SEG);
270 }
271 offset += e->stringlen + align;
272 }
273 }
274 if (t > 0 && t == instruction->times - 1) {
275 /*
276 * Dummy call to list->output to give the offset to the
277 * listing module.
278 */
279 list->output(offset, NULL, OUT_RAWDATA);
280 list->uplevel(LIST_TIMES);
281 }
282 }
283 if (instruction->times > 1)
284 list->downlevel(LIST_TIMES);
285 return offset - start;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000286 }
287
H. Peter Anvine2c80182005-01-15 22:15:51 +0000288 if (instruction->opcode == I_INCBIN) {
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000289 static char fname[FILENAME_MAX];
H. Peter Anvine2c80182005-01-15 22:15:51 +0000290 FILE *fp;
Keith Kaniosb7a89542007-04-12 02:40:54 +0000291 int32_t len;
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000292 char *prefix = "", *combine;
293 char **pPrevPath = NULL;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000294
H. Peter Anvine2c80182005-01-15 22:15:51 +0000295 len = FILENAME_MAX - 1;
296 if (len > instruction->eops->stringlen)
297 len = instruction->eops->stringlen;
298 strncpy(fname, instruction->eops->stringval, len);
299 fname[len] = '\0';
H. Peter Anvineba20a72002-04-30 20:53:55 +0000300
Keith Kaniosb7a89542007-04-12 02:40:54 +0000301 while (1) { /* added by alexfru: 'incbin' uses include paths */
H. Peter Anvine2c80182005-01-15 22:15:51 +0000302 combine = nasm_malloc(strlen(prefix) + len + 1);
303 strcpy(combine, prefix);
304 strcat(combine, fname);
Frank Kotlerd0ed6fd2003-08-27 11:33:56 +0000305
H. Peter Anvine2c80182005-01-15 22:15:51 +0000306 if ((fp = fopen(combine, "rb")) != NULL) {
307 nasm_free(combine);
308 break;
309 }
Frank Kotlerd0ed6fd2003-08-27 11:33:56 +0000310
H. Peter Anvine2c80182005-01-15 22:15:51 +0000311 nasm_free(combine);
312 pPrevPath = pp_get_include_path_ptr(pPrevPath);
313 if (pPrevPath == NULL)
314 break;
315 prefix = *pPrevPath;
Frank Kotlerd0ed6fd2003-08-27 11:33:56 +0000316 }
317
318 if (fp == NULL)
H. Peter Anvine2c80182005-01-15 22:15:51 +0000319 error(ERR_NONFATAL, "`incbin': unable to open file `%s'",
320 fname);
321 else if (fseek(fp, 0L, SEEK_END) < 0)
322 error(ERR_NONFATAL, "`incbin': unable to seek on file `%s'",
323 fname);
324 else {
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000325 static char buf[2048];
Keith Kaniosb7a89542007-04-12 02:40:54 +0000326 int32_t t = instruction->times;
327 int32_t base = 0;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000328
H. Peter Anvine2c80182005-01-15 22:15:51 +0000329 len = ftell(fp);
330 if (instruction->eops->next) {
331 base = instruction->eops->next->offset;
332 len -= base;
333 if (instruction->eops->next->next &&
334 len > instruction->eops->next->next->offset)
335 len = instruction->eops->next->next->offset;
336 }
337 /*
338 * Dummy call to list->output to give the offset to the
339 * listing module.
340 */
341 list->output(offset, NULL, OUT_RAWDATA);
342 list->uplevel(LIST_INCBIN);
343 while (t--) {
Keith Kaniosb7a89542007-04-12 02:40:54 +0000344 int32_t l;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000345
H. Peter Anvine2c80182005-01-15 22:15:51 +0000346 fseek(fp, base, SEEK_SET);
347 l = len;
348 while (l > 0) {
Keith Kaniosb7a89542007-04-12 02:40:54 +0000349 int32_t m =
H. Peter Anvine2c80182005-01-15 22:15:51 +0000350 fread(buf, 1, (l > sizeof(buf) ? sizeof(buf) : l),
351 fp);
352 if (!m) {
353 /*
354 * This shouldn't happen unless the file
355 * actually changes while we are reading
356 * it.
357 */
358 error(ERR_NONFATAL,
359 "`incbin': unexpected EOF while"
360 " reading file `%s'", fname);
361 t = 0; /* Try to exit cleanly */
362 break;
363 }
364 out(offset, segment, buf, OUT_RAWDATA + m,
365 NO_SEG, NO_SEG);
366 l -= m;
367 }
368 }
369 list->downlevel(LIST_INCBIN);
370 if (instruction->times > 1) {
371 /*
372 * Dummy call to list->output to give the offset to the
373 * listing module.
374 */
375 list->output(offset, NULL, OUT_RAWDATA);
376 list->uplevel(LIST_TIMES);
377 list->downlevel(LIST_TIMES);
378 }
379 fclose(fp);
380 return instruction->times * len;
381 }
382 return 0; /* if we're here, there's an error */
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000383 }
384
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000385 size_prob = FALSE;
Keith Kaniosb7a89542007-04-12 02:40:54 +0000386
387 for (temp = nasm_instructions[instruction->opcode]; temp->opcode != -1; temp++){
388 int m = matches(temp, instruction, bits);
389
H. Peter Anvine2c80182005-01-15 22:15:51 +0000390 if (m == 99)
391 m += jmp_match(segment, offset, bits, instruction, temp->code);
H. Peter Anvineba20a72002-04-30 20:53:55 +0000392
H. Peter Anvine2c80182005-01-15 22:15:51 +0000393 if (m == 100) { /* matches! */
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000394 const char *codes = temp->code;
Keith Kaniosb7a89542007-04-12 02:40:54 +0000395 int32_t insn_size = calcsize(segment, offset, bits,
H. Peter Anvine2c80182005-01-15 22:15:51 +0000396 instruction, codes);
397 itimes = instruction->times;
398 if (insn_size < 0) /* shouldn't be, on pass two */
399 error(ERR_PANIC, "errors made it through from pass one");
400 else
401 while (itimes--) {
402 for (j = 0; j < instruction->nprefix; j++) {
Keith Kaniosb7a89542007-04-12 02:40:54 +0000403 uint8_t c = 0;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000404 switch (instruction->prefixes[j]) {
405 case P_LOCK:
406 c = 0xF0;
407 break;
408 case P_REPNE:
409 case P_REPNZ:
410 c = 0xF2;
411 break;
412 case P_REPE:
413 case P_REPZ:
414 case P_REP:
415 c = 0xF3;
416 break;
417 case R_CS:
Keith Kaniosfd5d9132007-04-16 15:46:46 +0000418 if (bits == 64) {
419 error(ERR_WARNING,
420 "cs segment base ignored in 64-bit mode");
421 }
H. Peter Anvine2c80182005-01-15 22:15:51 +0000422 c = 0x2E;
423 break;
424 case R_DS:
Keith Kaniosfd5d9132007-04-16 15:46:46 +0000425 if (bits == 64) {
426 error(ERR_WARNING,
427 "ds segment base ignored in 64-bit mode");
428 }
H. Peter Anvine2c80182005-01-15 22:15:51 +0000429 c = 0x3E;
430 break;
431 case R_ES:
Keith Kaniosfd5d9132007-04-16 15:46:46 +0000432 if (bits == 64) {
433 error(ERR_WARNING,
434 "es segment base ignored in 64-bit mode");
435 }
H. Peter Anvine2c80182005-01-15 22:15:51 +0000436 c = 0x26;
437 break;
438 case R_FS:
439 c = 0x64;
440 break;
441 case R_GS:
442 c = 0x65;
443 break;
444 case R_SS:
Keith Kaniosfd5d9132007-04-16 15:46:46 +0000445 if (bits == 64) {
446 error(ERR_WARNING,
447 "ss segment base ignored in 64-bit mode");
448 }
H. Peter Anvine2c80182005-01-15 22:15:51 +0000449 c = 0x36;
450 break;
451 case R_SEGR6:
452 case R_SEGR7:
453 error(ERR_NONFATAL,
454 "segr6 and segr7 cannot be used as prefixes");
455 break;
456 case P_A16:
Keith Kaniosb7a89542007-04-12 02:40:54 +0000457 if (bits == 64) {
Keith Kaniosfd5d9132007-04-16 15:46:46 +0000458 error(ERR_PANIC, "16-bit addressing is deprecated in 64-bit mode");
Keith Kaniosb7a89542007-04-12 02:40:54 +0000459 break;
460 }
H. Peter Anvine2c80182005-01-15 22:15:51 +0000461 if (bits != 16)
462 c = 0x67;
463 break;
464 case P_A32:
465 if (bits != 32)
466 c = 0x67;
467 break;
468 case P_O16:
469 if (bits != 16)
470 c = 0x66;
471 break;
472 case P_O32:
Keith Kaniosb7a89542007-04-12 02:40:54 +0000473 if (bits == 16)
H. Peter Anvine2c80182005-01-15 22:15:51 +0000474 c = 0x66;
475 break;
476 default:
477 error(ERR_PANIC, "invalid instruction prefix");
478 }
479 if (c != 0) {
480 out(offset, segment, &c, OUT_RAWDATA + 1,
481 NO_SEG, NO_SEG);
482 offset++;
483 }
Keith Kaniosb7a89542007-04-12 02:40:54 +0000484 }
H. Peter Anvine2c80182005-01-15 22:15:51 +0000485 insn_end = offset + insn_size;
486 gencode(segment, offset, bits, instruction, codes,
487 insn_end);
488 offset += insn_size;
489 if (itimes > 0 && itimes == instruction->times - 1) {
490 /*
491 * Dummy call to list->output to give the offset to the
492 * listing module.
493 */
494 list->output(offset, NULL, OUT_RAWDATA);
495 list->uplevel(LIST_TIMES);
496 }
497 }
498 if (instruction->times > 1)
499 list->downlevel(LIST_TIMES);
500 return offset - start;
501 } else if (m > 0 && m > size_prob) {
502 size_prob = m;
503 }
Keith Kaniosb7a89542007-04-12 02:40:54 +0000504// temp++;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000505 }
H. Peter Anvineba20a72002-04-30 20:53:55 +0000506
H. Peter Anvine2c80182005-01-15 22:15:51 +0000507 if (temp->opcode == -1) { /* didn't match any instruction */
508 if (size_prob == 1) /* would have matched, but for size */
509 error(ERR_NONFATAL, "operation size not specified");
510 else if (size_prob == 2)
511 error(ERR_NONFATAL, "mismatch in operand sizes");
512 else if (size_prob == 3)
513 error(ERR_NONFATAL, "no instruction for this cpu level");
Keith Kaniosb7a89542007-04-12 02:40:54 +0000514 else if (size_prob == 4)
Keith Kaniosfd5d9132007-04-16 15:46:46 +0000515 error(ERR_NONFATAL, "instruction deprecated in 64-bit mode");
H. Peter Anvine2c80182005-01-15 22:15:51 +0000516 else
517 error(ERR_NONFATAL,
518 "invalid combination of opcode and operands");
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000519 }
520 return 0;
521}
522
Keith Kaniosb7a89542007-04-12 02:40:54 +0000523int32_t insn_size(int32_t segment, int32_t offset, int bits, uint32_t cp,
H. Peter Anvine2c80182005-01-15 22:15:51 +0000524 insn * instruction, efunc error)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000525{
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000526 struct itemplate *temp;
527
H. Peter Anvine2c80182005-01-15 22:15:51 +0000528 errfunc = error; /* to pass to other functions */
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000529 cpu = cp;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000530
531 if (instruction->opcode == -1)
H. Peter Anvine2c80182005-01-15 22:15:51 +0000532 return 0;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000533
534 if (instruction->opcode == I_DB ||
H. Peter Anvine2c80182005-01-15 22:15:51 +0000535 instruction->opcode == I_DW ||
536 instruction->opcode == I_DD ||
537 instruction->opcode == I_DQ || instruction->opcode == I_DT) {
538 extop *e;
Keith Kaniosb7a89542007-04-12 02:40:54 +0000539 int32_t isize, osize, wsize = 0; /* placate gcc */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000540
H. Peter Anvine2c80182005-01-15 22:15:51 +0000541 isize = 0;
542 switch (instruction->opcode) {
543 case I_DB:
544 wsize = 1;
545 break;
546 case I_DW:
547 wsize = 2;
548 break;
549 case I_DD:
550 wsize = 4;
551 break;
552 case I_DQ:
553 wsize = 8;
554 break;
555 case I_DT:
556 wsize = 10;
557 break;
558 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000559
H. Peter Anvine2c80182005-01-15 22:15:51 +0000560 for (e = instruction->eops; e; e = e->next) {
Keith Kaniosb7a89542007-04-12 02:40:54 +0000561 int32_t align;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000562
H. Peter Anvine2c80182005-01-15 22:15:51 +0000563 osize = 0;
564 if (e->type == EOT_DB_NUMBER)
565 osize = 1;
566 else if (e->type == EOT_DB_STRING)
567 osize = e->stringlen;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000568
H. Peter Anvine2c80182005-01-15 22:15:51 +0000569 align = (-osize) % wsize;
570 if (align < 0)
571 align += wsize;
572 isize += osize + align;
573 }
574 return isize * instruction->times;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000575 }
576
H. Peter Anvine2c80182005-01-15 22:15:51 +0000577 if (instruction->opcode == I_INCBIN) {
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000578 char fname[FILENAME_MAX];
H. Peter Anvine2c80182005-01-15 22:15:51 +0000579 FILE *fp;
Keith Kaniosb7a89542007-04-12 02:40:54 +0000580 int32_t len;
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000581 char *prefix = "", *combine;
582 char **pPrevPath = NULL;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000583
H. Peter Anvine2c80182005-01-15 22:15:51 +0000584 len = FILENAME_MAX - 1;
585 if (len > instruction->eops->stringlen)
586 len = instruction->eops->stringlen;
587 strncpy(fname, instruction->eops->stringval, len);
588 fname[len] = '\0';
Frank Kotlerd0ed6fd2003-08-27 11:33:56 +0000589
H. Peter Anvine2c80182005-01-15 22:15:51 +0000590 while (1) { /* added by alexfru: 'incbin' uses include paths */
591 combine = nasm_malloc(strlen(prefix) + len + 1);
592 strcpy(combine, prefix);
593 strcat(combine, fname);
Frank Kotlerd0ed6fd2003-08-27 11:33:56 +0000594
H. Peter Anvine2c80182005-01-15 22:15:51 +0000595 if ((fp = fopen(combine, "rb")) != NULL) {
596 nasm_free(combine);
597 break;
598 }
Frank Kotlerd0ed6fd2003-08-27 11:33:56 +0000599
H. Peter Anvine2c80182005-01-15 22:15:51 +0000600 nasm_free(combine);
601 pPrevPath = pp_get_include_path_ptr(pPrevPath);
602 if (pPrevPath == NULL)
603 break;
604 prefix = *pPrevPath;
Frank Kotlerd0ed6fd2003-08-27 11:33:56 +0000605 }
606
607 if (fp == NULL)
H. Peter Anvine2c80182005-01-15 22:15:51 +0000608 error(ERR_NONFATAL, "`incbin': unable to open file `%s'",
609 fname);
610 else if (fseek(fp, 0L, SEEK_END) < 0)
611 error(ERR_NONFATAL, "`incbin': unable to seek on file `%s'",
612 fname);
613 else {
614 len = ftell(fp);
615 fclose(fp);
616 if (instruction->eops->next) {
617 len -= instruction->eops->next->offset;
618 if (instruction->eops->next->next &&
619 len > instruction->eops->next->next->offset) {
620 len = instruction->eops->next->next->offset;
621 }
622 }
623 return instruction->times * len;
624 }
625 return 0; /* if we're here, there's an error */
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000626 }
627
Keith Kaniosb7a89542007-04-12 02:40:54 +0000628 for (temp = nasm_instructions[instruction->opcode]; temp->opcode != -1; temp++) {
629 int m = matches(temp, instruction, bits);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000630 if (m == 99)
631 m += jmp_match(segment, offset, bits, instruction, temp->code);
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000632
H. Peter Anvine2c80182005-01-15 22:15:51 +0000633 if (m == 100) {
634 /* we've matched an instruction. */
Keith Kaniosb7a89542007-04-12 02:40:54 +0000635 int32_t isize;
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000636 const char *codes = temp->code;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000637 int j;
638
639 isize = calcsize(segment, offset, bits, instruction, codes);
640 if (isize < 0)
641 return -1;
642 for (j = 0; j < instruction->nprefix; j++) {
643 if ((instruction->prefixes[j] != P_A16 &&
644 instruction->prefixes[j] != P_O16 && bits == 16) ||
645 (instruction->prefixes[j] != P_A32 &&
Keith Kaniosfd5d9132007-04-16 15:46:46 +0000646 instruction->prefixes[j] != P_O32 && bits >= 32)) {
H. Peter Anvine2c80182005-01-15 22:15:51 +0000647 isize++;
648 }
649 }
650 return isize * instruction->times;
651 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000652 }
H. Peter Anvine2c80182005-01-15 22:15:51 +0000653 return -1; /* didn't match any instruction */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000654}
655
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000656/* check that opn[op] is a signed byte of size 16 or 32,
657 and return the signed value*/
H. Peter Anvine2c80182005-01-15 22:15:51 +0000658static int is_sbyte(insn * ins, int op, int size)
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000659{
Keith Kaniosb7a89542007-04-12 02:40:54 +0000660 int32_t v;
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000661 int ret;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000662
663 ret = !(ins->forw_ref && ins->oprs[op].opflags) && /* dead in the water on forward reference or External */
664 optimizing >= 0 &&
665 !(ins->oprs[op].type & STRICT) &&
666 ins->oprs[op].wrt == NO_SEG && ins->oprs[op].segment == NO_SEG;
H. Peter Anvin734b1882002-04-30 21:01:08 +0000667
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000668 v = ins->oprs[op].offset;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000669 if (size == 16)
Keith Kaniosb7a89542007-04-12 02:40:54 +0000670 v = (int16_t)v; /* sign extend if 16 bits */
H. Peter Anvine2c80182005-01-15 22:15:51 +0000671
672 return ret && v >= -128L && v <= 127L;
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000673}
674
Keith Kaniosb7a89542007-04-12 02:40:54 +0000675static int32_t calcsize(int32_t segment, int32_t offset, int bits,
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000676 insn * ins, const char *codes)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000677{
Keith Kaniosb7a89542007-04-12 02:40:54 +0000678 int32_t length = 0;
679 uint8_t c;
680 int t;
681 ins->rex = 0; /* Ensure REX is reset */
682 int rex_mask = 0xFF;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000683
H. Peter Anvine2c80182005-01-15 22:15:51 +0000684 (void)segment; /* Don't warn that this parameter is unused */
685 (void)offset; /* Don't warn that this parameter is unused */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000686
H. Peter Anvine2c80182005-01-15 22:15:51 +0000687 while (*codes)
688 switch (c = *codes++) {
689 case 01:
690 case 02:
691 case 03:
692 codes += c, length += c;
693 break;
694 case 04:
695 case 05:
696 case 06:
697 case 07:
698 length++;
699 break;
700 case 010:
701 case 011:
702 case 012:
Keith Kaniosb7a89542007-04-12 02:40:54 +0000703 if (bits == 64) {
704 t = regval(&ins->oprs[c - 010]);
705 if (t >= 0400 && t < 0500) { /* Calculate REX.B */
706 if (t < 0410 || (t >= 0440 && t < 0450))
707 ins->rex |= 0xF0; /* Set REX.0 */
708 else
709 ins->rex |= 0xF1; /* Set REX.B */
710 if (t >= 0440)
711 ins->rex |= 0xF8; /* Set REX.W */
712 }
713 }
H. Peter Anvine2c80182005-01-15 22:15:51 +0000714 codes++, length++;
715 break;
716 case 017:
717 length++;
718 break;
719 case 014:
720 case 015:
721 case 016:
722 length++;
723 break;
724 case 020:
725 case 021:
726 case 022:
727 length++;
728 break;
729 case 024:
730 case 025:
731 case 026:
732 length++;
733 break;
734 case 030:
735 case 031:
736 case 032:
737 length += 2;
738 break;
739 case 034:
740 case 035:
741 case 036:
Keith Kaniosb7a89542007-04-12 02:40:54 +0000742 if (ins->oprs[c - 034].type & (BITS16 | BITS32 | BITS64))
H. Peter Anvine2c80182005-01-15 22:15:51 +0000743 length += (ins->oprs[c - 034].type & BITS16) ? 2 : 4;
744 else
745 length += (bits == 16) ? 2 : 4;
746 break;
747 case 037:
748 length += 2;
749 break;
750 case 040:
751 case 041:
752 case 042:
753 length += 4;
754 break;
755 case 044:
756 case 045:
757 case 046:
758 length += ((ins->oprs[c - 044].addr_size ?
Keith Kaniosb7a89542007-04-12 02:40:54 +0000759 ins->oprs[c - 044].addr_size : bits) >> 3);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000760 break;
761 case 050:
762 case 051:
763 case 052:
764 length++;
765 break;
Keith Kaniosb7a89542007-04-12 02:40:54 +0000766 case 054:
767 case 055:
768 case 056:
769 length += 8; /* MOV reg64/imm */
770 break;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000771 case 060:
772 case 061:
773 case 062:
774 length += 2;
775 break;
776 case 064:
777 case 065:
778 case 066:
Keith Kaniosb7a89542007-04-12 02:40:54 +0000779 if (ins->oprs[c - 064].type & (BITS16 | BITS32 | BITS64))
H. Peter Anvine2c80182005-01-15 22:15:51 +0000780 length += (ins->oprs[c - 064].type & BITS16) ? 2 : 4;
781 else
782 length += (bits == 16) ? 2 : 4;
783 break;
784 case 070:
785 case 071:
786 case 072:
787 length += 4;
788 break;
789 case 0130:
790 case 0131:
791 case 0132:
792 length += is_sbyte(ins, c - 0130, 16) ? 1 : 2;
793 break;
794 case 0133:
795 case 0134:
796 case 0135:
797 codes += 2;
798 length++;
799 break;
800 case 0140:
801 case 0141:
802 case 0142:
803 length += is_sbyte(ins, c - 0140, 32) ? 1 : 4;
804 break;
805 case 0143:
806 case 0144:
807 case 0145:
808 codes += 2;
809 length++;
810 break;
811 case 0300:
812 case 0301:
Keith Kaniosb7a89542007-04-12 02:40:54 +0000813 case 0302:
814 if (bits == 64) { /* Calculate REX */
815 t = ins->oprs[c - 0300].basereg;
816 if (t >= EXPR_REG_START && t < REG_ENUM_LIMIT) {
817 t = regvals[t];
818 if ((t >= 0410 && t < 0440) || (t >= 0450 && t < 0500)) {
819 ins->rex |= 0xF1; /* Set REX.B */
820 }
821 }
822 }
H. Peter Anvine2c80182005-01-15 22:15:51 +0000823 length += chsize(&ins->oprs[c - 0300], bits);
824 break;
825 case 0310:
Keith Kaniosb7a89542007-04-12 02:40:54 +0000826 length += (bits != 16);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000827 break;
828 case 0311:
Keith Kaniosb7a89542007-04-12 02:40:54 +0000829 length += (bits != 32);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000830 break;
831 case 0312:
Keith Kaniosb7a89542007-04-12 02:40:54 +0000832 break;
833 case 0313:
834 length -= 1;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000835 break;
836 case 0320:
Keith Kaniosb7a89542007-04-12 02:40:54 +0000837 length += (bits != 16);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000838 break;
839 case 0321:
840 length += (bits == 16);
841 break;
842 case 0322:
843 break;
Keith Kaniosb7a89542007-04-12 02:40:54 +0000844 case 0323:
845 rex_mask = 0x07;
846 break;
847 case 0324:
848 length++;
849 break;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000850 case 0330:
851 codes++, length++;
852 break;
853 case 0331:
854 case 0332:
855 break;
856 case 0333:
857 length++;
858 break;
859 case 0340:
860 case 0341:
861 case 0342:
862 if (ins->oprs[0].segment != NO_SEG)
863 errfunc(ERR_NONFATAL, "attempt to reserve non-constant"
864 " quantity of BSS space");
865 else
866 length += ins->oprs[0].offset << (c - 0340);
867 break;
868 case 0370:
869 case 0371:
870 case 0372:
871 break;
872 case 0373:
873 length++;
874 break;
875 default: /* can't do it by 'case' statements */
876 if (c >= 0100 && c <= 0277) { /* it's an EA */
877 ea ea_data;
Keith Kaniosb7a89542007-04-12 02:40:54 +0000878 int rfield;
879 ea_data.rex = 0; /* Ensure ea.REX is initially 0 */
880
881 if (bits == 64) {
882 if (c <= 0177) /* pick rfield from operand b */
883 rfield = regval(&ins->oprs[c & 7]);
884 else
885 rfield = c & 7;
886 } else
887 rfield = 0;
888
H. Peter Anvine2c80182005-01-15 22:15:51 +0000889 if (!process_ea
Keith Kaniosb7a89542007-04-12 02:40:54 +0000890 (&ins->oprs[(c >> 3) & 7], &ea_data, bits,
891 rfield, ins->forw_ref)) {
H. Peter Anvine2c80182005-01-15 22:15:51 +0000892 errfunc(ERR_NONFATAL, "invalid effective address");
893 return -1;
Keith Kaniosb7a89542007-04-12 02:40:54 +0000894 } else {
895 if (bits == 64)
896 ins->rex |= ea_data.rex;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000897 length += ea_data.size;
Keith Kaniosb7a89542007-04-12 02:40:54 +0000898 }
H. Peter Anvine2c80182005-01-15 22:15:51 +0000899 } else
900 errfunc(ERR_PANIC, "internal instruction table corrupt"
901 ": instruction code 0x%02X given", c);
902 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000903
Keith Kaniosb7a89542007-04-12 02:40:54 +0000904 if (bits == 64) {
905 ins->rex &= rex_mask;
906 if (ins->rex)
907 length += 1;
908 }
909
910return length; }
911
912static void gencode(int32_t segment, int32_t offset, int bits,
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000913 insn * ins, const char *codes, int32_t insn_end)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000914{
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000915 static char condval[] = { /* conditional opcodes */
H. Peter Anvine2c80182005-01-15 22:15:51 +0000916 0x7, 0x3, 0x2, 0x6, 0x2, 0x4, 0xF, 0xD, 0xC, 0xE, 0x6, 0x2,
917 0x3, 0x7, 0x3, 0x5, 0xE, 0xC, 0xD, 0xF, 0x1, 0xB, 0x9, 0x5,
918 0x0, 0xA, 0xA, 0xB, 0x8, 0x4
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000919 };
Keith Kaniosb7a89542007-04-12 02:40:54 +0000920 uint8_t c;
921 uint8_t bytes[4];
922 int32_t size;
923 int64_t data;
924
H. Peter Anvineba20a72002-04-30 20:53:55 +0000925 while (*codes)
H. Peter Anvine2c80182005-01-15 22:15:51 +0000926 switch (c = *codes++) {
927 case 01:
928 case 02:
929 case 03:
Keith Kaniosb7a89542007-04-12 02:40:54 +0000930 if(ins->rex && (bits == 64)) { /* REX Supercedes all other Prefixes */
931 ins->rex = (ins->rex&0x0F)+0x40;
932 out(offset, segment, &ins->rex, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
933 ins->rex = 0;
934 offset += 1;
935 }
H. Peter Anvine2c80182005-01-15 22:15:51 +0000936 out(offset, segment, codes, OUT_RAWDATA + c, NO_SEG, NO_SEG);
937 codes += c;
938 offset += c;
939 break;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000940
H. Peter Anvine2c80182005-01-15 22:15:51 +0000941 case 04:
942 case 06:
943 switch (ins->oprs[0].basereg) {
944 case R_CS:
945 bytes[0] = 0x0E + (c == 0x04 ? 1 : 0);
946 break;
947 case R_DS:
948 bytes[0] = 0x1E + (c == 0x04 ? 1 : 0);
949 break;
950 case R_ES:
951 bytes[0] = 0x06 + (c == 0x04 ? 1 : 0);
952 break;
953 case R_SS:
954 bytes[0] = 0x16 + (c == 0x04 ? 1 : 0);
955 break;
956 default:
957 errfunc(ERR_PANIC,
958 "bizarre 8086 segment register received");
959 }
960 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
961 offset++;
962 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000963
H. Peter Anvine2c80182005-01-15 22:15:51 +0000964 case 05:
965 case 07:
966 switch (ins->oprs[0].basereg) {
967 case R_FS:
968 bytes[0] = 0xA0 + (c == 0x05 ? 1 : 0);
969 break;
970 case R_GS:
971 bytes[0] = 0xA8 + (c == 0x05 ? 1 : 0);
972 break;
973 default:
974 errfunc(ERR_PANIC,
975 "bizarre 386 segment register received");
976 }
977 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
978 offset++;
979 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000980
H. Peter Anvine2c80182005-01-15 22:15:51 +0000981 case 010:
982 case 011:
983 case 012:
Keith Kaniosb7a89542007-04-12 02:40:54 +0000984 if(ins->rex && (bits == 64)) { /* REX Supercedes all other Prefixes */
985 ins->rex = (ins->rex&0x0F)+0x40;
986 out(offset, segment, &ins->rex, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
987 ins->rex = 0;
988 offset += 1;
989 }
990 bytes[0] = *codes++ + ((regval(&ins->oprs[c - 010])) & 7);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000991 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
992 offset += 1;
993 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000994
H. Peter Anvine2c80182005-01-15 22:15:51 +0000995 case 017:
996 bytes[0] = 0;
997 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
998 offset += 1;
999 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001000
H. Peter Anvine2c80182005-01-15 22:15:51 +00001001 case 014:
1002 case 015:
1003 case 016:
1004 if (ins->oprs[c - 014].offset < -128
1005 || ins->oprs[c - 014].offset > 127) {
1006 errfunc(ERR_WARNING, "signed byte value exceeds bounds");
1007 }
H. Peter Anvineba20a72002-04-30 20:53:55 +00001008
H. Peter Anvine2c80182005-01-15 22:15:51 +00001009 if (ins->oprs[c - 014].segment != NO_SEG) {
1010 data = ins->oprs[c - 014].offset;
1011 out(offset, segment, &data, OUT_ADDRESS + 1,
1012 ins->oprs[c - 014].segment, ins->oprs[c - 014].wrt);
1013 } else {
1014 bytes[0] = ins->oprs[c - 014].offset;
1015 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG,
1016 NO_SEG);
1017 }
1018 offset += 1;
1019 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001020
H. Peter Anvine2c80182005-01-15 22:15:51 +00001021 case 020:
1022 case 021:
1023 case 022:
1024 if (ins->oprs[c - 020].offset < -256
1025 || ins->oprs[c - 020].offset > 255) {
1026 errfunc(ERR_WARNING, "byte value exceeds bounds");
1027 }
1028 if (ins->oprs[c - 020].segment != NO_SEG) {
1029 data = ins->oprs[c - 020].offset;
1030 out(offset, segment, &data, OUT_ADDRESS + 1,
1031 ins->oprs[c - 020].segment, ins->oprs[c - 020].wrt);
1032 } else {
1033 bytes[0] = ins->oprs[c - 020].offset;
1034 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG,
1035 NO_SEG);
1036 }
1037 offset += 1;
1038 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001039
H. Peter Anvine2c80182005-01-15 22:15:51 +00001040 case 024:
1041 case 025:
1042 case 026:
1043 if (ins->oprs[c - 024].offset < 0
1044 || ins->oprs[c - 024].offset > 255)
1045 errfunc(ERR_WARNING, "unsigned byte value exceeds bounds");
1046 if (ins->oprs[c - 024].segment != NO_SEG) {
1047 data = ins->oprs[c - 024].offset;
1048 out(offset, segment, &data, OUT_ADDRESS + 1,
1049 ins->oprs[c - 024].segment, ins->oprs[c - 024].wrt);
1050 } else {
1051 bytes[0] = ins->oprs[c - 024].offset;
1052 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG,
1053 NO_SEG);
1054 }
1055 offset += 1;
1056 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001057
H. Peter Anvine2c80182005-01-15 22:15:51 +00001058 case 030:
1059 case 031:
1060 case 032:
1061 if (ins->oprs[c - 030].segment == NO_SEG &&
1062 ins->oprs[c - 030].wrt == NO_SEG &&
1063 (ins->oprs[c - 030].offset < -65536L ||
1064 ins->oprs[c - 030].offset > 65535L)) {
1065 errfunc(ERR_WARNING, "word value exceeds bounds");
1066 }
1067 data = ins->oprs[c - 030].offset;
1068 out(offset, segment, &data, OUT_ADDRESS + 2,
1069 ins->oprs[c - 030].segment, ins->oprs[c - 030].wrt);
1070 offset += 2;
1071 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001072
H. Peter Anvine2c80182005-01-15 22:15:51 +00001073 case 034:
1074 case 035:
1075 case 036:
1076 if (ins->oprs[c - 034].type & (BITS16 | BITS32))
1077 size = (ins->oprs[c - 034].type & BITS16) ? 2 : 4;
1078 else
1079 size = (bits == 16) ? 2 : 4;
1080 data = ins->oprs[c - 034].offset;
1081 if (size == 2 && (data < -65536L || data > 65535L))
1082 errfunc(ERR_WARNING, "word value exceeds bounds");
1083 out(offset, segment, &data, OUT_ADDRESS + size,
1084 ins->oprs[c - 034].segment, ins->oprs[c - 034].wrt);
1085 offset += size;
1086 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001087
H. Peter Anvine2c80182005-01-15 22:15:51 +00001088 case 037:
1089 if (ins->oprs[0].segment == NO_SEG)
1090 errfunc(ERR_NONFATAL, "value referenced by FAR is not"
1091 " relocatable");
1092 data = 0L;
1093 out(offset, segment, &data, OUT_ADDRESS + 2,
1094 outfmt->segbase(1 + ins->oprs[0].segment),
1095 ins->oprs[0].wrt);
1096 offset += 2;
1097 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001098
H. Peter Anvine2c80182005-01-15 22:15:51 +00001099 case 040:
1100 case 041:
1101 case 042:
1102 data = ins->oprs[c - 040].offset;
1103 out(offset, segment, &data, OUT_ADDRESS + 4,
1104 ins->oprs[c - 040].segment, ins->oprs[c - 040].wrt);
1105 offset += 4;
1106 break;
H. Peter Anvin3ba46772002-05-27 23:19:35 +00001107
H. Peter Anvine2c80182005-01-15 22:15:51 +00001108 case 044:
1109 case 045:
1110 case 046:
1111 data = ins->oprs[c - 044].offset;
1112 size = ((ins->oprs[c - 044].addr_size ?
Keith Kaniosb7a89542007-04-12 02:40:54 +00001113 ins->oprs[c - 044].addr_size : bits) >> 3);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001114 if (size == 2 && (data < -65536L || data > 65535L))
1115 errfunc(ERR_WARNING, "word value exceeds bounds");
1116 out(offset, segment, &data, OUT_ADDRESS + size,
1117 ins->oprs[c - 044].segment, ins->oprs[c - 044].wrt);
1118 offset += size;
1119 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001120
H. Peter Anvine2c80182005-01-15 22:15:51 +00001121 case 050:
1122 case 051:
1123 case 052:
1124 if (ins->oprs[c - 050].segment != segment)
1125 errfunc(ERR_NONFATAL,
1126 "short relative jump outside segment");
1127 data = ins->oprs[c - 050].offset - insn_end;
1128 if (data > 127 || data < -128)
1129 errfunc(ERR_NONFATAL, "short jump is out of range");
1130 bytes[0] = data;
1131 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1132 offset += 1;
1133 break;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001134
1135 case 054:
1136 case 055:
1137 case 056:
1138 data = (int64_t)ins->oprs[c - 054].offset;
1139 out(offset, segment, &data, OUT_ADDRESS + 8,
1140 ins->oprs[c - 054].segment, ins->oprs[c - 054].wrt);
1141 offset += 8;
1142 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001143
H. Peter Anvine2c80182005-01-15 22:15:51 +00001144 case 060:
1145 case 061:
1146 case 062:
1147 if (ins->oprs[c - 060].segment != segment) {
1148 data = ins->oprs[c - 060].offset;
1149 out(offset, segment, &data,
1150 OUT_REL2ADR + insn_end - offset,
1151 ins->oprs[c - 060].segment, ins->oprs[c - 060].wrt);
1152 } else {
1153 data = ins->oprs[c - 060].offset - insn_end;
1154 out(offset, segment, &data,
1155 OUT_ADDRESS + 2, NO_SEG, NO_SEG);
1156 }
1157 offset += 2;
1158 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001159
H. Peter Anvine2c80182005-01-15 22:15:51 +00001160 case 064:
1161 case 065:
1162 case 066:
Keith Kaniosb7a89542007-04-12 02:40:54 +00001163 if (ins->oprs[c - 064].type & (BITS16 | BITS32 | BITS64))
H. Peter Anvine2c80182005-01-15 22:15:51 +00001164 size = (ins->oprs[c - 064].type & BITS16) ? 2 : 4;
1165 else
1166 size = (bits == 16) ? 2 : 4;
1167 if (ins->oprs[c - 064].segment != segment) {
Keith Kaniosb7a89542007-04-12 02:40:54 +00001168 int32_t reltype = (size == 2 ? OUT_REL2ADR : OUT_REL4ADR);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001169 data = ins->oprs[c - 064].offset;
1170 out(offset, segment, &data, reltype + insn_end - offset,
1171 ins->oprs[c - 064].segment, ins->oprs[c - 064].wrt);
1172 } else {
1173 data = ins->oprs[c - 064].offset - insn_end;
1174 out(offset, segment, &data,
1175 OUT_ADDRESS + size, NO_SEG, NO_SEG);
1176 }
1177 offset += size;
1178 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001179
H. Peter Anvine2c80182005-01-15 22:15:51 +00001180 case 070:
1181 case 071:
1182 case 072:
1183 if (ins->oprs[c - 070].segment != segment) {
1184 data = ins->oprs[c - 070].offset;
1185 out(offset, segment, &data,
1186 OUT_REL4ADR + insn_end - offset,
1187 ins->oprs[c - 070].segment, ins->oprs[c - 070].wrt);
1188 } else {
1189 data = ins->oprs[c - 070].offset - insn_end;
1190 out(offset, segment, &data,
1191 OUT_ADDRESS + 4, NO_SEG, NO_SEG);
1192 }
1193 offset += 4;
1194 break;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001195
H. Peter Anvine2c80182005-01-15 22:15:51 +00001196 case 0130:
1197 case 0131:
1198 case 0132:
1199 data = ins->oprs[c - 0130].offset;
1200 if (is_sbyte(ins, c - 0130, 16)) {
1201 bytes[0] = data;
1202 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG,
1203 NO_SEG);
1204 offset++;
1205 } else {
1206 if (ins->oprs[c - 0130].segment == NO_SEG &&
1207 ins->oprs[c - 0130].wrt == NO_SEG &&
1208 (data < -65536L || data > 65535L)) {
1209 errfunc(ERR_WARNING, "word value exceeds bounds");
1210 }
1211 out(offset, segment, &data, OUT_ADDRESS + 2,
1212 ins->oprs[c - 0130].segment, ins->oprs[c - 0130].wrt);
1213 offset += 2;
1214 }
1215 break;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001216
H. Peter Anvine2c80182005-01-15 22:15:51 +00001217 case 0133:
1218 case 0134:
1219 case 0135:
Keith Kaniosb7a89542007-04-12 02:40:54 +00001220 if(ins->rex && (bits == 64)) { /* REX Supercedes all other Prefixes */
1221 ins->rex = (ins->rex&0x0F)+0x40;
1222 out(offset, segment, &ins->rex, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1223 ins->rex = 0;
1224 offset += 1;
1225 }
H. Peter Anvine2c80182005-01-15 22:15:51 +00001226 codes++;
1227 bytes[0] = *codes++;
1228 if (is_sbyte(ins, c - 0133, 16))
1229 bytes[0] |= 2; /* s-bit */
1230 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1231 offset++;
1232 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001233
H. Peter Anvine2c80182005-01-15 22:15:51 +00001234 case 0140:
1235 case 0141:
1236 case 0142:
1237 data = ins->oprs[c - 0140].offset;
1238 if (is_sbyte(ins, c - 0140, 32)) {
1239 bytes[0] = data;
1240 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG,
1241 NO_SEG);
1242 offset++;
1243 } else {
1244 out(offset, segment, &data, OUT_ADDRESS + 4,
1245 ins->oprs[c - 0140].segment, ins->oprs[c - 0140].wrt);
1246 offset += 4;
1247 }
1248 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001249
H. Peter Anvine2c80182005-01-15 22:15:51 +00001250 case 0143:
1251 case 0144:
1252 case 0145:
Keith Kaniosb7a89542007-04-12 02:40:54 +00001253 if(ins->rex && (bits == 64)) { /* REX Supercedes all other Prefixes */
1254 ins->rex = (ins->rex&0x0F)+0x40;
1255 out(offset, segment, &ins->rex, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1256 ins->rex = 0;
1257 offset += 1;
1258 }
H. Peter Anvine2c80182005-01-15 22:15:51 +00001259 codes++;
1260 bytes[0] = *codes++;
1261 if (is_sbyte(ins, c - 0143, 32))
1262 bytes[0] |= 2; /* s-bit */
1263 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1264 offset++;
1265 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001266
H. Peter Anvine2c80182005-01-15 22:15:51 +00001267 case 0300:
1268 case 0301:
1269 case 0302:
1270 if (chsize(&ins->oprs[c - 0300], bits)) {
1271 *bytes = 0x67;
1272 out(offset, segment, bytes,
1273 OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1274 offset += 1;
1275 } else
1276 offset += 0;
1277 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001278
H. Peter Anvine2c80182005-01-15 22:15:51 +00001279 case 0310:
Keith Kaniosb7a89542007-04-12 02:40:54 +00001280 if (bits != 16) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001281 *bytes = 0x67;
1282 out(offset, segment, bytes,
1283 OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1284 offset += 1;
1285 } else
1286 offset += 0;
1287 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001288
H. Peter Anvine2c80182005-01-15 22:15:51 +00001289 case 0311:
Keith Kaniosb7a89542007-04-12 02:40:54 +00001290 if (bits != 32) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001291 *bytes = 0x67;
1292 out(offset, segment, bytes,
1293 OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1294 offset += 1;
1295 } else
1296 offset += 0;
1297 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001298
H. Peter Anvine2c80182005-01-15 22:15:51 +00001299 case 0312:
1300 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001301
Keith Kaniosb7a89542007-04-12 02:40:54 +00001302 case 0313:
1303 ins->rex = 0;
1304 break;
1305
H. Peter Anvine2c80182005-01-15 22:15:51 +00001306 case 0320:
Keith Kaniosb7a89542007-04-12 02:40:54 +00001307 if (bits != 16) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001308 *bytes = 0x66;
1309 out(offset, segment, bytes,
1310 OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1311 offset += 1;
1312 } else
1313 offset += 0;
1314 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001315
H. Peter Anvine2c80182005-01-15 22:15:51 +00001316 case 0321:
1317 if (bits == 16) {
1318 *bytes = 0x66;
1319 out(offset, segment, bytes,
1320 OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1321 offset += 1;
1322 } else
1323 offset += 0;
1324 break;
H. Peter Anvinef7468f2002-04-30 20:57:59 +00001325
H. Peter Anvine2c80182005-01-15 22:15:51 +00001326 case 0322:
Keith Kaniosb7a89542007-04-12 02:40:54 +00001327 case 0323:
1328 break;
1329
1330 case 0324:
1331 ins->rex |= 0xF8;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001332 break;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001333
H. Peter Anvine2c80182005-01-15 22:15:51 +00001334 case 0330:
1335 *bytes = *codes++ ^ condval[ins->condition];
1336 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1337 offset += 1;
1338 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001339
H. Peter Anvine2c80182005-01-15 22:15:51 +00001340 case 0331:
1341 case 0332:
1342 break;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001343
H. Peter Anvine2c80182005-01-15 22:15:51 +00001344 case 0333:
1345 *bytes = 0xF3;
1346 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1347 offset += 1;
1348 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001349
H. Peter Anvine2c80182005-01-15 22:15:51 +00001350 case 0340:
1351 case 0341:
1352 case 0342:
1353 if (ins->oprs[0].segment != NO_SEG)
1354 errfunc(ERR_PANIC, "non-constant BSS size in pass two");
1355 else {
Keith Kaniosb7a89542007-04-12 02:40:54 +00001356 int32_t size = ins->oprs[0].offset << (c - 0340);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001357 if (size > 0)
1358 out(offset, segment, NULL,
1359 OUT_RESERVE + size, NO_SEG, NO_SEG);
1360 offset += size;
1361 }
1362 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001363
H. Peter Anvine2c80182005-01-15 22:15:51 +00001364 case 0370:
1365 case 0371:
1366 case 0372:
1367 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001368
H. Peter Anvine2c80182005-01-15 22:15:51 +00001369 case 0373:
1370 *bytes = bits == 16 ? 3 : 5;
1371 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1372 offset += 1;
1373 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001374
H. Peter Anvine2c80182005-01-15 22:15:51 +00001375 default: /* can't do it by 'case' statements */
Keith Kaniosb7a89542007-04-12 02:40:54 +00001376 if ( c >= 0100 && c <= 0277) { /* it's an EA */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001377 ea ea_data;
1378 int rfield;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001379 uint8_t *p;
1380 int32_t s;
1381
H. Peter Anvine2c80182005-01-15 22:15:51 +00001382 if (c <= 0177) /* pick rfield from operand b */
1383 rfield = regval(&ins->oprs[c & 7]);
1384 else /* rfield is constant */
1385 rfield = c & 7;
1386
1387 if (!process_ea
1388 (&ins->oprs[(c >> 3) & 7], &ea_data, bits, rfield,
1389 ins->forw_ref)) {
1390 errfunc(ERR_NONFATAL, "invalid effective address");
1391 }
Keith Kaniosb7a89542007-04-12 02:40:54 +00001392
H. Peter Anvine2c80182005-01-15 22:15:51 +00001393 p = bytes;
1394 *p++ = ea_data.modrm;
1395 if (ea_data.sib_present)
1396 *p++ = ea_data.sib;
1397
1398 s = p - bytes;
1399 out(offset, segment, bytes, OUT_RAWDATA + s,
1400 NO_SEG, NO_SEG);
1401
1402 switch (ea_data.bytes) {
1403 case 0:
1404 break;
1405 case 1:
1406 if (ins->oprs[(c >> 3) & 7].segment != NO_SEG) {
1407 data = ins->oprs[(c >> 3) & 7].offset;
1408 out(offset, segment, &data, OUT_ADDRESS + 1,
1409 ins->oprs[(c >> 3) & 7].segment,
1410 ins->oprs[(c >> 3) & 7].wrt);
1411 } else {
1412 *bytes = ins->oprs[(c >> 3) & 7].offset;
1413 out(offset, segment, bytes, OUT_RAWDATA + 1,
1414 NO_SEG, NO_SEG);
1415 }
1416 s++;
1417 break;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001418 case 8:
H. Peter Anvine2c80182005-01-15 22:15:51 +00001419 case 2:
1420 case 4:
1421 data = ins->oprs[(c >> 3) & 7].offset;
Keith Kaniose83b3182007-04-16 14:31:54 +00001422 if (ea_data.rip && (ins->oprs[(c >> 3) & 7].segment == 0xFFFFFFFF))
1423 ea_data.rip = 0; /* Make distinction between Symbols and Immediates */
Keith Kaniosb7a89542007-04-12 02:40:54 +00001424 out(offset, segment, &data, /* RIP = Relative, not Absolute */
1425 (ea_data.rip ? OUT_REL4ADR : OUT_ADDRESS) + ea_data.bytes,
H. Peter Anvine2c80182005-01-15 22:15:51 +00001426 ins->oprs[(c >> 3) & 7].segment,
1427 ins->oprs[(c >> 3) & 7].wrt);
1428 s += ea_data.bytes;
1429 break;
1430 }
1431 offset += s;
1432 } else
1433 errfunc(ERR_PANIC, "internal instruction table corrupt"
1434 ": instruction code 0x%02X given", c);
1435 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001436}
1437
H. Peter Anvine2c80182005-01-15 22:15:51 +00001438static int regval(operand * o)
H. Peter Anvineba20a72002-04-30 20:53:55 +00001439{
H. Peter Anvine2c80182005-01-15 22:15:51 +00001440 if (o->basereg < EXPR_REG_START || o->basereg >= REG_ENUM_LIMIT) {
1441 errfunc(ERR_PANIC, "invalid operand passed to regval()");
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001442 }
H. Peter Anvin232badb2002-06-06 02:41:20 +00001443 return regvals[o->basereg];
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001444}
1445
Keith Kaniosb7a89542007-04-12 02:40:54 +00001446static int matches(struct itemplate *itemp, insn * instruction, int bits)
H. Peter Anvineba20a72002-04-30 20:53:55 +00001447{
Keith Kaniosb7a89542007-04-12 02:40:54 +00001448 int i, b, x, size[3], asize, oprs, ret;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001449
1450 ret = 100;
1451
1452 /*
1453 * Check the opcode
1454 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001455 if (itemp->opcode != instruction->opcode)
1456 return 0;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001457
1458 /*
1459 * Count the operands
1460 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001461 if (itemp->operands != instruction->operands)
1462 return 0;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001463
1464 /*
1465 * Check that no spurious colons or TOs are present
1466 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001467 for (i = 0; i < itemp->operands; i++)
1468 if (instruction->oprs[i].type & ~itemp->opd[i] & (COLON | TO))
1469 return 0;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001470
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001471 /*
1472 * Check that the operand flags all match up
1473 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001474 for (i = 0; i < itemp->operands; i++)
1475 if (itemp->opd[i] & ~instruction->oprs[i].type ||
1476 ((itemp->opd[i] & SIZE_MASK) &&
1477 ((itemp->opd[i] ^ instruction->oprs[i].type) & SIZE_MASK))) {
1478 if ((itemp->opd[i] & ~instruction->oprs[i].type & NON_SIZE) ||
1479 (instruction->oprs[i].type & SIZE_MASK))
1480 return 0;
1481 else
H. Peter Anvine2c80182005-01-15 22:15:51 +00001482 return 1;
1483 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001484
1485 /*
1486 * Check operand sizes
1487 */
H. Peter Anvinef7468f2002-04-30 20:57:59 +00001488 if (itemp->flags & IF_ARMASK) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001489 size[0] = size[1] = size[2] = 0;
H. Peter Anvinef7468f2002-04-30 20:57:59 +00001490
H. Peter Anvine2c80182005-01-15 22:15:51 +00001491 switch (itemp->flags & IF_ARMASK) {
1492 case IF_AR0:
1493 i = 0;
1494 break;
1495 case IF_AR1:
1496 i = 1;
1497 break;
1498 case IF_AR2:
1499 i = 2;
1500 break;
1501 default:
1502 break; /* Shouldn't happen */
1503 }
1504 if (itemp->flags & IF_SB) {
1505 size[i] = BITS8;
1506 } else if (itemp->flags & IF_SW) {
1507 size[i] = BITS16;
1508 } else if (itemp->flags & IF_SD) {
1509 size[i] = BITS32;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001510 } else if (itemp->flags & IF_SQ) {
1511 if (bits != 64)
1512 return 2;
1513 size[i] = BITS64;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001514 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001515 } else {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001516 asize = 0;
1517 if (itemp->flags & IF_SB) {
1518 asize = BITS8;
1519 oprs = itemp->operands;
1520 } else if (itemp->flags & IF_SW) {
1521 asize = BITS16;
1522 oprs = itemp->operands;
1523 } else if (itemp->flags & IF_SD) {
1524 asize = BITS32;
1525 oprs = itemp->operands;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001526 } else if (itemp->flags & IF_SQ) {
1527 if (bits != 64)
1528 return 2;
1529 asize = BITS64;
1530 oprs = itemp->operands;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001531 }
1532 size[0] = size[1] = size[2] = asize;
H. Peter Anvinef7468f2002-04-30 20:57:59 +00001533 }
Keith Kaniosb7a89542007-04-12 02:40:54 +00001534
H. Peter Anvinef7468f2002-04-30 20:57:59 +00001535 if (itemp->flags & (IF_SM | IF_SM2)) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001536 oprs = (itemp->flags & IF_SM2 ? 2 : itemp->operands);
1537 asize = 0;
1538 for (i = 0; i < oprs; i++) {
1539 if ((asize = itemp->opd[i] & SIZE_MASK) != 0) {
1540 int j;
1541 for (j = 0; j < oprs; j++)
1542 size[j] = asize;
1543 break;
1544 }
1545 }
H. Peter Anvinef7468f2002-04-30 20:57:59 +00001546 } else {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001547 oprs = itemp->operands;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001548 }
1549
Keith Kaniosb7a89542007-04-12 02:40:54 +00001550 for (i = 0; i < itemp->operands; i++) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001551 if (!(itemp->opd[i] & SIZE_MASK) &&
1552 (instruction->oprs[i].type & SIZE_MASK & ~size[i]))
H. Peter Anvine2c80182005-01-15 22:15:51 +00001553 return 2;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001554
Keith Kaniosb7a89542007-04-12 02:40:54 +00001555 if ( (((itemp->opd[i] & SIZE_MASK) == BITS64) ||
1556 ((instruction->oprs[i].type & SIZE_MASK) == BITS64))
1557 && bits != 64)
1558 return 2;
1559
1560 x = instruction->oprs[i].indexreg;
1561 b = instruction->oprs[i].basereg;
1562
1563 if (x != -1 && x >= EXPR_REG_START && x < REG_ENUM_LIMIT)
1564 x = regvals[x];
1565 if (b != -1 && b >= EXPR_REG_START && b < REG_ENUM_LIMIT)
1566 b = regvals[b];
1567
1568 if (((b >= 0400 && b <= 0500) || (x >= 0400 && x < 0500)) && bits != 64)
1569 return 2;
1570 }
1571
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001572 /*
1573 * Check template is okay at the set cpu level
1574 */
Keith Kaniosb7a89542007-04-12 02:40:54 +00001575 if (((itemp->flags & IF_PLEVEL) > cpu))
H. Peter Anvine2c80182005-01-15 22:15:51 +00001576 return 3;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001577
1578 /*
1579 * Check if instruction is available in long mode
1580 */
1581 if ((itemp->flags & IF_NOLONG) && (bits == 64))
1582 return 4;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001583
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001584 /*
1585 * Check if special handling needed for Jumps
1586 */
Keith Kaniosb7a89542007-04-12 02:40:54 +00001587 if ((uint8_t)(itemp->code[0]) >= 0370)
H. Peter Anvine2c80182005-01-15 22:15:51 +00001588 return 99;
1589
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001590 return ret;
1591}
1592
H. Peter Anvine2c80182005-01-15 22:15:51 +00001593static ea *process_ea(operand * input, ea * output, int addrbits,
1594 int rfield, int forw_ref)
H. Peter Anvineba20a72002-04-30 20:53:55 +00001595{
Keith Kaniosb7a89542007-04-12 02:40:54 +00001596
1597 int rip = FALSE; /* Used for RIP-relative addressing */
1598
1599
1600 if (!(REGISTER & ~input->type)) { /* register direct */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001601 int i;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001602 if ( input->basereg < EXPR_REG_START /* Verify as Register */
1603 || input->basereg >= REG_ENUM_LIMIT)
H. Peter Anvine2c80182005-01-15 22:15:51 +00001604 return NULL;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001605 i = regvals[input->basereg];
1606 if ( i >= 0100 && i < 0210) /* GPR's, MMX & XMM only */
1607 return NULL;
1608
1609 if (i >= 0400 && i < 0500) { /* Calculate REX.B */
1610 if (i < 0410 || (i >= 0440 && i < 0450))
1611 output->rex |= 0xF0; /* Set REX.0 */
1612 else
1613 output->rex |= 0xF1; /* Set REX.B */
1614 if (i >= 0440)
1615 output->rex |= 0xF8; /* Set REX.W */
1616 }
1617
1618 if ((rfield >= 0400 && rfield < 0500) || /* Calculate REX.R */
1619 (rfield >= 0120 && rfield < 0200 && /* Include CR/DR/TR... */
1620 !(rfield & 0010))) { /* ... extensions, only */
1621 if ((rfield >= 0400 && rfield < 0410) || (rfield >= 0440 && rfield < 0450))
1622 output->rex |= 0xF0; /* Set REX.0 */
1623 else
1624 output->rex |= 0xF4; /* Set REX.R */
1625 if (rfield >= 0440)
1626 output->rex |= 0xF8; /* Set REX.W */
1627 }
1628
1629 output->sib_present = FALSE; /* no SIB necessary */
1630 output->bytes = 0; /* no offset necessary either */
1631 output->modrm = 0xC0 | ((rfield & 7) << 3) | (i & 7);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001632 } else { /* it's a memory reference */
Keith Kaniosb7a89542007-04-12 02:40:54 +00001633
H. Peter Anvine2c80182005-01-15 22:15:51 +00001634 if (input->basereg == -1
1635 && (input->indexreg == -1 || input->scale == 0)) {
1636 /* it's a pure offset */
1637 if (input->addr_size)
1638 addrbits = input->addr_size;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001639
1640 if (rfield >= 0400 && rfield < 0500) { /* Calculate REX.R */
1641 if (rfield < 0410 || (rfield >= 0440 && rfield < 0450))
1642 output->rex |= 0xF0; /* Set REX.0 */
1643 else
1644 output->rex |= 0xF4; /* Set REX.R */
1645 if (rfield >= 0440)
1646 output->rex |= 0xF8; /* Set REX.W */
1647 }
1648
H. Peter Anvine2c80182005-01-15 22:15:51 +00001649 output->sib_present = FALSE;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001650 output->bytes = (addrbits != 16 ? 4 : 2);
1651 output->modrm = (addrbits != 16 ? 5 : 6) | ((rfield & 7) << 3);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001652 } else { /* it's an indirection */
1653 int i = input->indexreg, b = input->basereg, s = input->scale;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001654 int32_t o = input->offset, seg = input->segment;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001655 int hb = input->hintbase, ht = input->hinttype;
1656 int t;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001657 int it, bt;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001658
H. Peter Anvine2c80182005-01-15 22:15:51 +00001659 if (s == 0)
1660 i = -1; /* make this easy, at least */
Keith Kaniosb7a89542007-04-12 02:40:54 +00001661
1662 if (i != -1 && i >= EXPR_REG_START
1663 && i < REG_ENUM_LIMIT)
1664 it = regvals[i];
1665 else
1666 it = -1;
1667
1668 if (b != -1 && b >= EXPR_REG_START
1669 && b < REG_ENUM_LIMIT)
1670 bt = regvals[b];
1671 else
1672 bt = -1;
1673
1674 /* check for a 32/64-bit memory reference... */
1675 if ((it >= 0020 && it < 0030) || (it >= 0430 && it < 0460) ||
1676 (bt >= 0020 && bt < 0030) || (bt >= 0430 && bt < 0460) ||
1677 bt == 0500) {
1678 /* it must be a 32/64-bit memory reference. Firstly we have
1679 * to check that all registers involved are type E/Rxx. */
1680 t = 1;
1681 if (it != -1) {
1682 if (it < 0020 || (it >= 0030 && it < 0430) || it >= 0460)
1683 return NULL;
1684 if (it >= 0440)
1685 t = 2;
1686 else
1687 t = 0;
1688 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001689
Keith Kaniosb7a89542007-04-12 02:40:54 +00001690 if (bt != -1) {
1691 if (bt < 0020 || (bt >= 0030 && bt < 0430) || (bt >= 0460 && bt < 0500))
1692 return NULL;
1693 if (bt == 0500) {
1694 bt = b = -1;
1695 rip = TRUE;
1696 } else if (bt >= 0440) {
1697 if (t < 1)
1698 return NULL;
1699 } else {
1700 if (t > 1)
1701 return NULL;
1702 }
1703 }
1704
H. Peter Anvine2c80182005-01-15 22:15:51 +00001705 /* While we're here, ensure the user didn't specify WORD. */
1706 if (input->addr_size == 16)
1707 return NULL;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001708
Keith Kaniosb7a89542007-04-12 02:40:54 +00001709 /* now reorganize base/index */
1710 if (s == 1 && bt != it && bt != -1 && it != -1 &&
1711 ((hb == bt && ht == EAH_NOTBASE)
1712 || (hb == it && ht == EAH_MAKEBASE)))
1713 t = bt, bt = it, it = t; /* swap if hints say so */
1714 if (bt == it) /* convert EAX+2*EAX to 3*EAX */
1715 bt = -1, s++;
1716 if (bt == -1 && s == 1 && !(hb == it && ht == EAH_NOTBASE))
1717 bt = i, it = -1; /* make single reg base, unless hint */
1718 if (((s == 2 && (it & 7) != (REG_NUM_ESP & 7)
H. Peter Anvine2c80182005-01-15 22:15:51 +00001719 && !(input->eaflags & EAF_TIMESTWO)) || s == 3
Keith Kaniosb7a89542007-04-12 02:40:54 +00001720 || s == 5 || s == 9) && bt == -1)
1721 bt = it, s--; /* convert 3*EAX to EAX+2*EAX */
1722 if (it == -1 && (bt & 7) != (REG_NUM_ESP & 7)
H. Peter Anvine2c80182005-01-15 22:15:51 +00001723 && (input->eaflags & EAF_TIMESTWO))
Keith Kaniosb7a89542007-04-12 02:40:54 +00001724 it = bt, bt = -1, s = 1;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001725 /* convert [NOSPLIT EAX] to sib format with 0x0 displacement */
Keith Kaniosb7a89542007-04-12 02:40:54 +00001726 if (s == 1 && (it & 7) == (REG_NUM_ESP & 7)) /* swap ESP into base if scale is 1 */
1727 t = it, it = bt, bt = t;
1728 if ((it & 7) == (REG_NUM_ESP & 7)
1729 || (s != 1 && s != 2 && s != 4 && s != 8 && it != -1))
H. Peter Anvine2c80182005-01-15 22:15:51 +00001730 return NULL; /* wrong, for various reasons */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001731
Keith Kanios2cc61b32007-04-13 01:17:45 +00001732 if (i >= 0400 && i < 0500) { /* Calculate REX.X */
Keith Kaniosb7a89542007-04-12 02:40:54 +00001733 if (i < 0410 || (i >= 0440 && i < 0450))
1734 output->rex |= 0xF0; /* Set REX.0 */
1735 else
Keith Kanios2cc61b32007-04-13 01:17:45 +00001736 output->rex |= 0xF2; /* Set REX.X */
Keith Kaniosb7a89542007-04-12 02:40:54 +00001737 if (i >= 0440)
1738 output->rex |= 0xF8; /* Set REX.W */
1739 }
1740
1741 if (b >= 0400 && b < 0500) { /* Calculate REX.B */
1742 if (b < 0410 || (b >= 0440 && b < 0450))
1743 output->rex |= 0xF0; /* Set REX.0 */
1744 else
1745 output->rex |= 0xF1; /* Set REX.B */
1746 if (b >= 0440)
1747 output->rex |= 0xF8; /* Set REX.W */
1748 }
1749
1750 if (rfield >= 0400 && rfield < 0500) { /* Calculate REX.R */
1751 if (rfield < 0410 || (rfield >= 0440 && rfield < 0450))
1752 output->rex |= 0xF0; /* Set REX.0 */
1753 else
1754 output->rex |= 0xF4; /* Set REX.R */
1755 if (rfield >= 0440)
1756 output->rex |= 0xF8; /* Set REX.W */
1757 }
1758
1759 if (it == -1 && (bt & 7) != (REG_NUM_ESP & 7)) { /* no SIB needed */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001760 int mod, rm;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001761
1762 if (bt == -1) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001763 rm = 5;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001764 mod = 0;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001765 } else {
1766 rm = (bt & 7);
1767 if (rm != (REG_NUM_EBP & 7) && o == 0 &&
1768 seg == NO_SEG && !forw_ref &&
1769 !(input->eaflags &
1770 (EAF_BYTEOFFS | EAF_WORDOFFS)))
1771 mod = 0;
1772 else if (input->eaflags & EAF_BYTEOFFS ||
1773 (o >= -128 && o <= 127 && seg == NO_SEG
1774 && !forw_ref
1775 && !(input->eaflags & EAF_WORDOFFS)))
1776 mod = 1;
1777 else
1778 mod = 2;
1779 }
H. Peter Anvinea838272002-04-30 20:51:53 +00001780
H. Peter Anvine2c80182005-01-15 22:15:51 +00001781 output->sib_present = FALSE;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001782 output->bytes = (bt == -1 || mod == 2 ? 4 : mod);
1783 output->modrm = (mod << 6) | ((rfield & 7) << 3) | rm;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001784 } else { /* we need a SIB */
1785 int mod, scale, index, base;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001786
1787 if (it == -1)
1788 index = 4, s = 1;
1789 else
1790 index = (it & 7);
1791
H. Peter Anvine2c80182005-01-15 22:15:51 +00001792 switch (s) {
1793 case 1:
1794 scale = 0;
1795 break;
1796 case 2:
1797 scale = 1;
1798 break;
1799 case 4:
1800 scale = 2;
1801 break;
1802 case 8:
1803 scale = 3;
1804 break;
1805 default: /* then what the smeg is it? */
1806 return NULL; /* panic */
1807 }
Keith Kaniosb7a89542007-04-12 02:40:54 +00001808
1809 if (bt == -1) {
1810 base = 5;
1811 mod = 0;
1812 } else {
1813 base = (bt & 7);
1814 if (base != (REG_NUM_EBP & 7) && o == 0 &&
H. Peter Anvine2c80182005-01-15 22:15:51 +00001815 seg == NO_SEG && !forw_ref &&
1816 !(input->eaflags &
Keith Kaniosb7a89542007-04-12 02:40:54 +00001817 (EAF_BYTEOFFS | EAF_WORDOFFS)))
1818 mod = 0;
1819 else if (input->eaflags & EAF_BYTEOFFS ||
1820 (o >= -128 && o <= 127 && seg == NO_SEG
1821 && !forw_ref
1822 && !(input->eaflags & EAF_WORDOFFS)))
1823 mod = 1;
1824 else
1825 mod = 2;
1826 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001827
H. Peter Anvine2c80182005-01-15 22:15:51 +00001828 output->sib_present = TRUE;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001829 output->bytes = (bt == -1 || mod == 2 ? 4 : mod);
1830 output->modrm = (mod << 6) | ((rfield & 7) << 3) | 4;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001831 output->sib = (scale << 6) | (index << 3) | base;
1832 }
1833 } else { /* it's 16-bit */
1834 int mod, rm;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001835
1836 /* check for 64-bit long mode */
1837 if (addrbits == 64)
1838 return NULL;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001839
H. Peter Anvine2c80182005-01-15 22:15:51 +00001840 /* check all registers are BX, BP, SI or DI */
1841 if ((b != -1 && b != R_BP && b != R_BX && b != R_SI
1842 && b != R_DI) || (i != -1 && i != R_BP && i != R_BX
1843 && i != R_SI && i != R_DI))
1844 return NULL;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001845
Keith Kaniosb7a89542007-04-12 02:40:54 +00001846 /* ensure the user didn't specify DWORD/QWORD */
1847 if (input->addr_size == 32 || input->addr_size == 64)
H. Peter Anvine2c80182005-01-15 22:15:51 +00001848 return NULL;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001849
H. Peter Anvine2c80182005-01-15 22:15:51 +00001850 if (s != 1 && i != -1)
1851 return NULL; /* no can do, in 16-bit EA */
1852 if (b == -1 && i != -1) {
1853 int tmp = b;
1854 b = i;
1855 i = tmp;
1856 } /* swap */
1857 if ((b == R_SI || b == R_DI) && i != -1) {
1858 int tmp = b;
1859 b = i;
1860 i = tmp;
1861 }
1862 /* have BX/BP as base, SI/DI index */
1863 if (b == i)
1864 return NULL; /* shouldn't ever happen, in theory */
1865 if (i != -1 && b != -1 &&
1866 (i == R_BP || i == R_BX || b == R_SI || b == R_DI))
1867 return NULL; /* invalid combinations */
1868 if (b == -1) /* pure offset: handled above */
1869 return NULL; /* so if it gets to here, panic! */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001870
H. Peter Anvine2c80182005-01-15 22:15:51 +00001871 rm = -1;
1872 if (i != -1)
1873 switch (i * 256 + b) {
1874 case R_SI * 256 + R_BX:
1875 rm = 0;
1876 break;
1877 case R_DI * 256 + R_BX:
1878 rm = 1;
1879 break;
1880 case R_SI * 256 + R_BP:
1881 rm = 2;
1882 break;
1883 case R_DI * 256 + R_BP:
1884 rm = 3;
1885 break;
1886 } else
1887 switch (b) {
1888 case R_SI:
1889 rm = 4;
1890 break;
1891 case R_DI:
1892 rm = 5;
1893 break;
1894 case R_BP:
1895 rm = 6;
1896 break;
1897 case R_BX:
1898 rm = 7;
1899 break;
1900 }
1901 if (rm == -1) /* can't happen, in theory */
1902 return NULL; /* so panic if it does */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001903
H. Peter Anvine2c80182005-01-15 22:15:51 +00001904 if (o == 0 && seg == NO_SEG && !forw_ref && rm != 6 &&
1905 !(input->eaflags & (EAF_BYTEOFFS | EAF_WORDOFFS)))
1906 mod = 0;
1907 else if (input->eaflags & EAF_BYTEOFFS ||
1908 (o >= -128 && o <= 127 && seg == NO_SEG
1909 && !forw_ref
1910 && !(input->eaflags & EAF_WORDOFFS)))
1911 mod = 1;
1912 else
1913 mod = 2;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001914
H. Peter Anvine2c80182005-01-15 22:15:51 +00001915 output->sib_present = FALSE; /* no SIB - it's 16-bit */
1916 output->bytes = mod; /* bytes of offset needed */
Keith Kaniosb7a89542007-04-12 02:40:54 +00001917 output->modrm = (mod << 6) | ((rfield & 7) << 3) | rm;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001918 }
1919 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001920 }
Keith Kaniosb7a89542007-04-12 02:40:54 +00001921
1922 /* Process RIP-relative Addressing */
1923 if (rip) {
1924 if ((output->modrm & 0xC7) != 0x05)
1925 return NULL;
1926 output->rip = TRUE;
1927 } else {
1928 output->rip = FALSE;
1929 if (globalbits == 64 && /* Actual Disp32 needs blank SIB on x64 */
1930 !(output->sib_present) && ((output->modrm & 0xC7) == 0x05)) {
1931 output->sib_present = TRUE;
1932 output->modrm --; /* RM Field = 4 (forward to Base of SIB) */
1933 output->sib = (4 << 3) | 5; /* Index = 4 (none), Base = 5 */
1934 }
1935 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001936 output->size = 1 + output->sib_present + output->bytes;
1937 return output;
1938}
1939
H. Peter Anvine2c80182005-01-15 22:15:51 +00001940static int chsize(operand * input, int addrbits)
H. Peter Anvineba20a72002-04-30 20:53:55 +00001941{
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001942 if (!(MEMORY & ~input->type)) {
Keith Kaniosb7a89542007-04-12 02:40:54 +00001943 int i, b;
1944
1945 if ( input->indexreg < EXPR_REG_START /* Verify as Register */
1946 || input->indexreg >= REG_ENUM_LIMIT)
1947 i = -1;
1948 else
1949 i = regvals[input->indexreg];
1950
1951 if ( input->basereg < EXPR_REG_START /* Verify as Register */
1952 || input->basereg >= REG_ENUM_LIMIT)
1953 b = -1;
1954 else
1955 b = regvals[input->basereg];
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001956
H. Peter Anvine2c80182005-01-15 22:15:51 +00001957 if (input->scale == 0)
1958 i = -1;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001959
H. Peter Anvine2c80182005-01-15 22:15:51 +00001960 if (i == -1 && b == -1) /* pure offset */
1961 return (input->addr_size != 0 && input->addr_size != addrbits);
Keith Kaniosb7a89542007-04-12 02:40:54 +00001962
1963 if ((i >= 0020 && i < 0030) || (i >= 0430 && i < 0440) ||
1964 (b >= 0020 && b < 0030) || (b >= 0430 && b < 0440))
1965 return (addrbits != 32);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001966 else
1967 return (addrbits == 32);
1968 } else
1969 return 0;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001970}