blob: 114354cc9b489a7f05ff3fc2e1b1c1da57219b1d [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:
418 c = 0x2E;
419 break;
420 case R_DS:
421 c = 0x3E;
422 break;
423 case R_ES:
424 c = 0x26;
425 break;
426 case R_FS:
427 c = 0x64;
428 break;
429 case R_GS:
430 c = 0x65;
431 break;
432 case R_SS:
433 c = 0x36;
434 break;
435 case R_SEGR6:
436 case R_SEGR7:
437 error(ERR_NONFATAL,
438 "segr6 and segr7 cannot be used as prefixes");
439 break;
440 case P_A16:
Keith Kaniosb7a89542007-04-12 02:40:54 +0000441 if (bits == 64) {
442 error(ERR_PANIC, "16-bit addressing is depreciated in long mode");
443 break;
444 }
H. Peter Anvine2c80182005-01-15 22:15:51 +0000445 if (bits != 16)
446 c = 0x67;
447 break;
448 case P_A32:
449 if (bits != 32)
450 c = 0x67;
451 break;
452 case P_O16:
453 if (bits != 16)
454 c = 0x66;
455 break;
456 case P_O32:
Keith Kaniosb7a89542007-04-12 02:40:54 +0000457 if (bits == 16)
H. Peter Anvine2c80182005-01-15 22:15:51 +0000458 c = 0x66;
459 break;
460 default:
461 error(ERR_PANIC, "invalid instruction prefix");
462 }
463 if (c != 0) {
464 out(offset, segment, &c, OUT_RAWDATA + 1,
465 NO_SEG, NO_SEG);
466 offset++;
467 }
Keith Kaniosb7a89542007-04-12 02:40:54 +0000468 }
H. Peter Anvine2c80182005-01-15 22:15:51 +0000469 insn_end = offset + insn_size;
470 gencode(segment, offset, bits, instruction, codes,
471 insn_end);
472 offset += insn_size;
473 if (itimes > 0 && itimes == instruction->times - 1) {
474 /*
475 * Dummy call to list->output to give the offset to the
476 * listing module.
477 */
478 list->output(offset, NULL, OUT_RAWDATA);
479 list->uplevel(LIST_TIMES);
480 }
481 }
482 if (instruction->times > 1)
483 list->downlevel(LIST_TIMES);
484 return offset - start;
485 } else if (m > 0 && m > size_prob) {
486 size_prob = m;
487 }
Keith Kaniosb7a89542007-04-12 02:40:54 +0000488// temp++;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000489 }
H. Peter Anvineba20a72002-04-30 20:53:55 +0000490
H. Peter Anvine2c80182005-01-15 22:15:51 +0000491 if (temp->opcode == -1) { /* didn't match any instruction */
492 if (size_prob == 1) /* would have matched, but for size */
493 error(ERR_NONFATAL, "operation size not specified");
494 else if (size_prob == 2)
495 error(ERR_NONFATAL, "mismatch in operand sizes");
496 else if (size_prob == 3)
497 error(ERR_NONFATAL, "no instruction for this cpu level");
Keith Kaniosb7a89542007-04-12 02:40:54 +0000498 else if (size_prob == 4)
499 error(ERR_NONFATAL, "instruction depreciated in long mode");
H. Peter Anvine2c80182005-01-15 22:15:51 +0000500 else
501 error(ERR_NONFATAL,
502 "invalid combination of opcode and operands");
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000503 }
504 return 0;
505}
506
Keith Kaniosb7a89542007-04-12 02:40:54 +0000507int32_t insn_size(int32_t segment, int32_t offset, int bits, uint32_t cp,
H. Peter Anvine2c80182005-01-15 22:15:51 +0000508 insn * instruction, efunc error)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000509{
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000510 struct itemplate *temp;
511
H. Peter Anvine2c80182005-01-15 22:15:51 +0000512 errfunc = error; /* to pass to other functions */
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000513 cpu = cp;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000514
515 if (instruction->opcode == -1)
H. Peter Anvine2c80182005-01-15 22:15:51 +0000516 return 0;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000517
518 if (instruction->opcode == I_DB ||
H. Peter Anvine2c80182005-01-15 22:15:51 +0000519 instruction->opcode == I_DW ||
520 instruction->opcode == I_DD ||
521 instruction->opcode == I_DQ || instruction->opcode == I_DT) {
522 extop *e;
Keith Kaniosb7a89542007-04-12 02:40:54 +0000523 int32_t isize, osize, wsize = 0; /* placate gcc */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000524
H. Peter Anvine2c80182005-01-15 22:15:51 +0000525 isize = 0;
526 switch (instruction->opcode) {
527 case I_DB:
528 wsize = 1;
529 break;
530 case I_DW:
531 wsize = 2;
532 break;
533 case I_DD:
534 wsize = 4;
535 break;
536 case I_DQ:
537 wsize = 8;
538 break;
539 case I_DT:
540 wsize = 10;
541 break;
542 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000543
H. Peter Anvine2c80182005-01-15 22:15:51 +0000544 for (e = instruction->eops; e; e = e->next) {
Keith Kaniosb7a89542007-04-12 02:40:54 +0000545 int32_t align;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000546
H. Peter Anvine2c80182005-01-15 22:15:51 +0000547 osize = 0;
548 if (e->type == EOT_DB_NUMBER)
549 osize = 1;
550 else if (e->type == EOT_DB_STRING)
551 osize = e->stringlen;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000552
H. Peter Anvine2c80182005-01-15 22:15:51 +0000553 align = (-osize) % wsize;
554 if (align < 0)
555 align += wsize;
556 isize += osize + align;
557 }
558 return isize * instruction->times;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000559 }
560
H. Peter Anvine2c80182005-01-15 22:15:51 +0000561 if (instruction->opcode == I_INCBIN) {
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000562 char fname[FILENAME_MAX];
H. Peter Anvine2c80182005-01-15 22:15:51 +0000563 FILE *fp;
Keith Kaniosb7a89542007-04-12 02:40:54 +0000564 int32_t len;
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000565 char *prefix = "", *combine;
566 char **pPrevPath = NULL;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000567
H. Peter Anvine2c80182005-01-15 22:15:51 +0000568 len = FILENAME_MAX - 1;
569 if (len > instruction->eops->stringlen)
570 len = instruction->eops->stringlen;
571 strncpy(fname, instruction->eops->stringval, len);
572 fname[len] = '\0';
Frank Kotlerd0ed6fd2003-08-27 11:33:56 +0000573
H. Peter Anvine2c80182005-01-15 22:15:51 +0000574 while (1) { /* added by alexfru: 'incbin' uses include paths */
575 combine = nasm_malloc(strlen(prefix) + len + 1);
576 strcpy(combine, prefix);
577 strcat(combine, fname);
Frank Kotlerd0ed6fd2003-08-27 11:33:56 +0000578
H. Peter Anvine2c80182005-01-15 22:15:51 +0000579 if ((fp = fopen(combine, "rb")) != NULL) {
580 nasm_free(combine);
581 break;
582 }
Frank Kotlerd0ed6fd2003-08-27 11:33:56 +0000583
H. Peter Anvine2c80182005-01-15 22:15:51 +0000584 nasm_free(combine);
585 pPrevPath = pp_get_include_path_ptr(pPrevPath);
586 if (pPrevPath == NULL)
587 break;
588 prefix = *pPrevPath;
Frank Kotlerd0ed6fd2003-08-27 11:33:56 +0000589 }
590
591 if (fp == NULL)
H. Peter Anvine2c80182005-01-15 22:15:51 +0000592 error(ERR_NONFATAL, "`incbin': unable to open file `%s'",
593 fname);
594 else if (fseek(fp, 0L, SEEK_END) < 0)
595 error(ERR_NONFATAL, "`incbin': unable to seek on file `%s'",
596 fname);
597 else {
598 len = ftell(fp);
599 fclose(fp);
600 if (instruction->eops->next) {
601 len -= instruction->eops->next->offset;
602 if (instruction->eops->next->next &&
603 len > instruction->eops->next->next->offset) {
604 len = instruction->eops->next->next->offset;
605 }
606 }
607 return instruction->times * len;
608 }
609 return 0; /* if we're here, there's an error */
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000610 }
611
Keith Kaniosb7a89542007-04-12 02:40:54 +0000612 for (temp = nasm_instructions[instruction->opcode]; temp->opcode != -1; temp++) {
613 int m = matches(temp, instruction, bits);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000614 if (m == 99)
615 m += jmp_match(segment, offset, bits, instruction, temp->code);
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000616
H. Peter Anvine2c80182005-01-15 22:15:51 +0000617 if (m == 100) {
618 /* we've matched an instruction. */
Keith Kaniosb7a89542007-04-12 02:40:54 +0000619 int32_t isize;
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000620 const char *codes = temp->code;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000621 int j;
622
623 isize = calcsize(segment, offset, bits, instruction, codes);
624 if (isize < 0)
625 return -1;
626 for (j = 0; j < instruction->nprefix; j++) {
627 if ((instruction->prefixes[j] != P_A16 &&
628 instruction->prefixes[j] != P_O16 && bits == 16) ||
629 (instruction->prefixes[j] != P_A32 &&
Keith Kaniosb7a89542007-04-12 02:40:54 +0000630 instruction->prefixes[j] != P_O32 && bits == 32) ||
631 (instruction->prefixes[j] == P_A32 &&
632 instruction->prefixes[j] != P_O32 && bits == 64)) {
H. Peter Anvine2c80182005-01-15 22:15:51 +0000633 isize++;
634 }
635 }
636 return isize * instruction->times;
637 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000638 }
H. Peter Anvine2c80182005-01-15 22:15:51 +0000639 return -1; /* didn't match any instruction */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000640}
641
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000642/* check that opn[op] is a signed byte of size 16 or 32,
643 and return the signed value*/
H. Peter Anvine2c80182005-01-15 22:15:51 +0000644static int is_sbyte(insn * ins, int op, int size)
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000645{
Keith Kaniosb7a89542007-04-12 02:40:54 +0000646 int32_t v;
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000647 int ret;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000648
649 ret = !(ins->forw_ref && ins->oprs[op].opflags) && /* dead in the water on forward reference or External */
650 optimizing >= 0 &&
651 !(ins->oprs[op].type & STRICT) &&
652 ins->oprs[op].wrt == NO_SEG && ins->oprs[op].segment == NO_SEG;
H. Peter Anvin734b1882002-04-30 21:01:08 +0000653
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000654 v = ins->oprs[op].offset;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000655 if (size == 16)
Keith Kaniosb7a89542007-04-12 02:40:54 +0000656 v = (int16_t)v; /* sign extend if 16 bits */
H. Peter Anvine2c80182005-01-15 22:15:51 +0000657
658 return ret && v >= -128L && v <= 127L;
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000659}
660
Keith Kaniosb7a89542007-04-12 02:40:54 +0000661static int32_t calcsize(int32_t segment, int32_t offset, int bits,
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000662 insn * ins, const char *codes)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000663{
Keith Kaniosb7a89542007-04-12 02:40:54 +0000664 int32_t length = 0;
665 uint8_t c;
666 int t;
667 ins->rex = 0; /* Ensure REX is reset */
668 int rex_mask = 0xFF;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000669
H. Peter Anvine2c80182005-01-15 22:15:51 +0000670 (void)segment; /* Don't warn that this parameter is unused */
671 (void)offset; /* Don't warn that this parameter is unused */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000672
H. Peter Anvine2c80182005-01-15 22:15:51 +0000673 while (*codes)
674 switch (c = *codes++) {
675 case 01:
676 case 02:
677 case 03:
678 codes += c, length += c;
679 break;
680 case 04:
681 case 05:
682 case 06:
683 case 07:
684 length++;
685 break;
686 case 010:
687 case 011:
688 case 012:
Keith Kaniosb7a89542007-04-12 02:40:54 +0000689 if (bits == 64) {
690 t = regval(&ins->oprs[c - 010]);
691 if (t >= 0400 && t < 0500) { /* Calculate REX.B */
692 if (t < 0410 || (t >= 0440 && t < 0450))
693 ins->rex |= 0xF0; /* Set REX.0 */
694 else
695 ins->rex |= 0xF1; /* Set REX.B */
696 if (t >= 0440)
697 ins->rex |= 0xF8; /* Set REX.W */
698 }
699 }
H. Peter Anvine2c80182005-01-15 22:15:51 +0000700 codes++, length++;
701 break;
702 case 017:
703 length++;
704 break;
705 case 014:
706 case 015:
707 case 016:
708 length++;
709 break;
710 case 020:
711 case 021:
712 case 022:
713 length++;
714 break;
715 case 024:
716 case 025:
717 case 026:
718 length++;
719 break;
720 case 030:
721 case 031:
722 case 032:
723 length += 2;
724 break;
725 case 034:
726 case 035:
727 case 036:
Keith Kaniosb7a89542007-04-12 02:40:54 +0000728 if (ins->oprs[c - 034].type & (BITS16 | BITS32 | BITS64))
H. Peter Anvine2c80182005-01-15 22:15:51 +0000729 length += (ins->oprs[c - 034].type & BITS16) ? 2 : 4;
730 else
731 length += (bits == 16) ? 2 : 4;
732 break;
733 case 037:
734 length += 2;
735 break;
736 case 040:
737 case 041:
738 case 042:
739 length += 4;
740 break;
741 case 044:
742 case 045:
743 case 046:
744 length += ((ins->oprs[c - 044].addr_size ?
Keith Kaniosb7a89542007-04-12 02:40:54 +0000745 ins->oprs[c - 044].addr_size : bits) >> 3);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000746 break;
747 case 050:
748 case 051:
749 case 052:
750 length++;
751 break;
Keith Kaniosb7a89542007-04-12 02:40:54 +0000752 case 054:
753 case 055:
754 case 056:
755 length += 8; /* MOV reg64/imm */
756 break;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000757 case 060:
758 case 061:
759 case 062:
760 length += 2;
761 break;
762 case 064:
763 case 065:
764 case 066:
Keith Kaniosb7a89542007-04-12 02:40:54 +0000765 if (ins->oprs[c - 064].type & (BITS16 | BITS32 | BITS64))
H. Peter Anvine2c80182005-01-15 22:15:51 +0000766 length += (ins->oprs[c - 064].type & BITS16) ? 2 : 4;
767 else
768 length += (bits == 16) ? 2 : 4;
769 break;
770 case 070:
771 case 071:
772 case 072:
773 length += 4;
774 break;
775 case 0130:
776 case 0131:
777 case 0132:
778 length += is_sbyte(ins, c - 0130, 16) ? 1 : 2;
779 break;
780 case 0133:
781 case 0134:
782 case 0135:
783 codes += 2;
784 length++;
785 break;
786 case 0140:
787 case 0141:
788 case 0142:
789 length += is_sbyte(ins, c - 0140, 32) ? 1 : 4;
790 break;
791 case 0143:
792 case 0144:
793 case 0145:
794 codes += 2;
795 length++;
796 break;
797 case 0300:
798 case 0301:
Keith Kaniosb7a89542007-04-12 02:40:54 +0000799 case 0302:
800 if (bits == 64) { /* Calculate REX */
801 t = ins->oprs[c - 0300].basereg;
802 if (t >= EXPR_REG_START && t < REG_ENUM_LIMIT) {
803 t = regvals[t];
804 if ((t >= 0410 && t < 0440) || (t >= 0450 && t < 0500)) {
805 ins->rex |= 0xF1; /* Set REX.B */
806 }
807 }
808 }
H. Peter Anvine2c80182005-01-15 22:15:51 +0000809 length += chsize(&ins->oprs[c - 0300], bits);
810 break;
811 case 0310:
Keith Kaniosb7a89542007-04-12 02:40:54 +0000812 length += (bits != 16);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000813 break;
814 case 0311:
Keith Kaniosb7a89542007-04-12 02:40:54 +0000815 length += (bits != 32);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000816 break;
817 case 0312:
Keith Kaniosb7a89542007-04-12 02:40:54 +0000818 break;
819 case 0313:
820 length -= 1;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000821 break;
822 case 0320:
Keith Kaniosb7a89542007-04-12 02:40:54 +0000823 length += (bits != 16);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000824 break;
825 case 0321:
826 length += (bits == 16);
827 break;
828 case 0322:
829 break;
Keith Kaniosb7a89542007-04-12 02:40:54 +0000830 case 0323:
831 rex_mask = 0x07;
832 break;
833 case 0324:
834 length++;
835 break;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000836 case 0330:
837 codes++, length++;
838 break;
839 case 0331:
840 case 0332:
841 break;
842 case 0333:
843 length++;
844 break;
845 case 0340:
846 case 0341:
847 case 0342:
848 if (ins->oprs[0].segment != NO_SEG)
849 errfunc(ERR_NONFATAL, "attempt to reserve non-constant"
850 " quantity of BSS space");
851 else
852 length += ins->oprs[0].offset << (c - 0340);
853 break;
854 case 0370:
855 case 0371:
856 case 0372:
857 break;
858 case 0373:
859 length++;
860 break;
861 default: /* can't do it by 'case' statements */
862 if (c >= 0100 && c <= 0277) { /* it's an EA */
863 ea ea_data;
Keith Kaniosb7a89542007-04-12 02:40:54 +0000864 int rfield;
865 ea_data.rex = 0; /* Ensure ea.REX is initially 0 */
866
867 if (bits == 64) {
868 if (c <= 0177) /* pick rfield from operand b */
869 rfield = regval(&ins->oprs[c & 7]);
870 else
871 rfield = c & 7;
872 } else
873 rfield = 0;
874
H. Peter Anvine2c80182005-01-15 22:15:51 +0000875 if (!process_ea
Keith Kaniosb7a89542007-04-12 02:40:54 +0000876 (&ins->oprs[(c >> 3) & 7], &ea_data, bits,
877 rfield, ins->forw_ref)) {
H. Peter Anvine2c80182005-01-15 22:15:51 +0000878 errfunc(ERR_NONFATAL, "invalid effective address");
879 return -1;
Keith Kaniosb7a89542007-04-12 02:40:54 +0000880 } else {
881 if (bits == 64)
882 ins->rex |= ea_data.rex;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000883 length += ea_data.size;
Keith Kaniosb7a89542007-04-12 02:40:54 +0000884 }
H. Peter Anvine2c80182005-01-15 22:15:51 +0000885 } else
886 errfunc(ERR_PANIC, "internal instruction table corrupt"
887 ": instruction code 0x%02X given", c);
888 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000889
Keith Kaniosb7a89542007-04-12 02:40:54 +0000890 if (bits == 64) {
891 ins->rex &= rex_mask;
892 if (ins->rex)
893 length += 1;
894 }
895
896return length; }
897
898static void gencode(int32_t segment, int32_t offset, int bits,
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000899 insn * ins, const char *codes, int32_t insn_end)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000900{
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000901 static char condval[] = { /* conditional opcodes */
H. Peter Anvine2c80182005-01-15 22:15:51 +0000902 0x7, 0x3, 0x2, 0x6, 0x2, 0x4, 0xF, 0xD, 0xC, 0xE, 0x6, 0x2,
903 0x3, 0x7, 0x3, 0x5, 0xE, 0xC, 0xD, 0xF, 0x1, 0xB, 0x9, 0x5,
904 0x0, 0xA, 0xA, 0xB, 0x8, 0x4
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000905 };
Keith Kaniosb7a89542007-04-12 02:40:54 +0000906 uint8_t c;
907 uint8_t bytes[4];
908 int32_t size;
909 int64_t data;
910
H. Peter Anvineba20a72002-04-30 20:53:55 +0000911 while (*codes)
H. Peter Anvine2c80182005-01-15 22:15:51 +0000912 switch (c = *codes++) {
913 case 01:
914 case 02:
915 case 03:
Keith Kaniosb7a89542007-04-12 02:40:54 +0000916 if(ins->rex && (bits == 64)) { /* REX Supercedes all other Prefixes */
917 ins->rex = (ins->rex&0x0F)+0x40;
918 out(offset, segment, &ins->rex, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
919 ins->rex = 0;
920 offset += 1;
921 }
H. Peter Anvine2c80182005-01-15 22:15:51 +0000922 out(offset, segment, codes, OUT_RAWDATA + c, NO_SEG, NO_SEG);
923 codes += c;
924 offset += c;
925 break;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000926
H. Peter Anvine2c80182005-01-15 22:15:51 +0000927 case 04:
928 case 06:
929 switch (ins->oprs[0].basereg) {
930 case R_CS:
931 bytes[0] = 0x0E + (c == 0x04 ? 1 : 0);
932 break;
933 case R_DS:
934 bytes[0] = 0x1E + (c == 0x04 ? 1 : 0);
935 break;
936 case R_ES:
937 bytes[0] = 0x06 + (c == 0x04 ? 1 : 0);
938 break;
939 case R_SS:
940 bytes[0] = 0x16 + (c == 0x04 ? 1 : 0);
941 break;
942 default:
943 errfunc(ERR_PANIC,
944 "bizarre 8086 segment register received");
945 }
946 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
947 offset++;
948 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000949
H. Peter Anvine2c80182005-01-15 22:15:51 +0000950 case 05:
951 case 07:
952 switch (ins->oprs[0].basereg) {
953 case R_FS:
954 bytes[0] = 0xA0 + (c == 0x05 ? 1 : 0);
955 break;
956 case R_GS:
957 bytes[0] = 0xA8 + (c == 0x05 ? 1 : 0);
958 break;
959 default:
960 errfunc(ERR_PANIC,
961 "bizarre 386 segment register received");
962 }
963 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
964 offset++;
965 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000966
H. Peter Anvine2c80182005-01-15 22:15:51 +0000967 case 010:
968 case 011:
969 case 012:
Keith Kaniosb7a89542007-04-12 02:40:54 +0000970 if(ins->rex && (bits == 64)) { /* REX Supercedes all other Prefixes */
971 ins->rex = (ins->rex&0x0F)+0x40;
972 out(offset, segment, &ins->rex, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
973 ins->rex = 0;
974 offset += 1;
975 }
976 bytes[0] = *codes++ + ((regval(&ins->oprs[c - 010])) & 7);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000977 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
978 offset += 1;
979 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000980
H. Peter Anvine2c80182005-01-15 22:15:51 +0000981 case 017:
982 bytes[0] = 0;
983 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
984 offset += 1;
985 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000986
H. Peter Anvine2c80182005-01-15 22:15:51 +0000987 case 014:
988 case 015:
989 case 016:
990 if (ins->oprs[c - 014].offset < -128
991 || ins->oprs[c - 014].offset > 127) {
992 errfunc(ERR_WARNING, "signed byte value exceeds bounds");
993 }
H. Peter Anvineba20a72002-04-30 20:53:55 +0000994
H. Peter Anvine2c80182005-01-15 22:15:51 +0000995 if (ins->oprs[c - 014].segment != NO_SEG) {
996 data = ins->oprs[c - 014].offset;
997 out(offset, segment, &data, OUT_ADDRESS + 1,
998 ins->oprs[c - 014].segment, ins->oprs[c - 014].wrt);
999 } else {
1000 bytes[0] = ins->oprs[c - 014].offset;
1001 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG,
1002 NO_SEG);
1003 }
1004 offset += 1;
1005 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001006
H. Peter Anvine2c80182005-01-15 22:15:51 +00001007 case 020:
1008 case 021:
1009 case 022:
1010 if (ins->oprs[c - 020].offset < -256
1011 || ins->oprs[c - 020].offset > 255) {
1012 errfunc(ERR_WARNING, "byte value exceeds bounds");
1013 }
1014 if (ins->oprs[c - 020].segment != NO_SEG) {
1015 data = ins->oprs[c - 020].offset;
1016 out(offset, segment, &data, OUT_ADDRESS + 1,
1017 ins->oprs[c - 020].segment, ins->oprs[c - 020].wrt);
1018 } else {
1019 bytes[0] = ins->oprs[c - 020].offset;
1020 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG,
1021 NO_SEG);
1022 }
1023 offset += 1;
1024 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001025
H. Peter Anvine2c80182005-01-15 22:15:51 +00001026 case 024:
1027 case 025:
1028 case 026:
1029 if (ins->oprs[c - 024].offset < 0
1030 || ins->oprs[c - 024].offset > 255)
1031 errfunc(ERR_WARNING, "unsigned byte value exceeds bounds");
1032 if (ins->oprs[c - 024].segment != NO_SEG) {
1033 data = ins->oprs[c - 024].offset;
1034 out(offset, segment, &data, OUT_ADDRESS + 1,
1035 ins->oprs[c - 024].segment, ins->oprs[c - 024].wrt);
1036 } else {
1037 bytes[0] = ins->oprs[c - 024].offset;
1038 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG,
1039 NO_SEG);
1040 }
1041 offset += 1;
1042 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001043
H. Peter Anvine2c80182005-01-15 22:15:51 +00001044 case 030:
1045 case 031:
1046 case 032:
1047 if (ins->oprs[c - 030].segment == NO_SEG &&
1048 ins->oprs[c - 030].wrt == NO_SEG &&
1049 (ins->oprs[c - 030].offset < -65536L ||
1050 ins->oprs[c - 030].offset > 65535L)) {
1051 errfunc(ERR_WARNING, "word value exceeds bounds");
1052 }
1053 data = ins->oprs[c - 030].offset;
1054 out(offset, segment, &data, OUT_ADDRESS + 2,
1055 ins->oprs[c - 030].segment, ins->oprs[c - 030].wrt);
1056 offset += 2;
1057 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001058
H. Peter Anvine2c80182005-01-15 22:15:51 +00001059 case 034:
1060 case 035:
1061 case 036:
1062 if (ins->oprs[c - 034].type & (BITS16 | BITS32))
1063 size = (ins->oprs[c - 034].type & BITS16) ? 2 : 4;
1064 else
1065 size = (bits == 16) ? 2 : 4;
1066 data = ins->oprs[c - 034].offset;
1067 if (size == 2 && (data < -65536L || data > 65535L))
1068 errfunc(ERR_WARNING, "word value exceeds bounds");
1069 out(offset, segment, &data, OUT_ADDRESS + size,
1070 ins->oprs[c - 034].segment, ins->oprs[c - 034].wrt);
1071 offset += size;
1072 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001073
H. Peter Anvine2c80182005-01-15 22:15:51 +00001074 case 037:
1075 if (ins->oprs[0].segment == NO_SEG)
1076 errfunc(ERR_NONFATAL, "value referenced by FAR is not"
1077 " relocatable");
1078 data = 0L;
1079 out(offset, segment, &data, OUT_ADDRESS + 2,
1080 outfmt->segbase(1 + ins->oprs[0].segment),
1081 ins->oprs[0].wrt);
1082 offset += 2;
1083 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001084
H. Peter Anvine2c80182005-01-15 22:15:51 +00001085 case 040:
1086 case 041:
1087 case 042:
1088 data = ins->oprs[c - 040].offset;
1089 out(offset, segment, &data, OUT_ADDRESS + 4,
1090 ins->oprs[c - 040].segment, ins->oprs[c - 040].wrt);
1091 offset += 4;
1092 break;
H. Peter Anvin3ba46772002-05-27 23:19:35 +00001093
H. Peter Anvine2c80182005-01-15 22:15:51 +00001094 case 044:
1095 case 045:
1096 case 046:
1097 data = ins->oprs[c - 044].offset;
1098 size = ((ins->oprs[c - 044].addr_size ?
Keith Kaniosb7a89542007-04-12 02:40:54 +00001099 ins->oprs[c - 044].addr_size : bits) >> 3);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001100 if (size == 2 && (data < -65536L || data > 65535L))
1101 errfunc(ERR_WARNING, "word value exceeds bounds");
1102 out(offset, segment, &data, OUT_ADDRESS + size,
1103 ins->oprs[c - 044].segment, ins->oprs[c - 044].wrt);
1104 offset += size;
1105 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001106
H. Peter Anvine2c80182005-01-15 22:15:51 +00001107 case 050:
1108 case 051:
1109 case 052:
1110 if (ins->oprs[c - 050].segment != segment)
1111 errfunc(ERR_NONFATAL,
1112 "short relative jump outside segment");
1113 data = ins->oprs[c - 050].offset - insn_end;
1114 if (data > 127 || data < -128)
1115 errfunc(ERR_NONFATAL, "short jump is out of range");
1116 bytes[0] = data;
1117 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1118 offset += 1;
1119 break;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001120
1121 case 054:
1122 case 055:
1123 case 056:
1124 data = (int64_t)ins->oprs[c - 054].offset;
1125 out(offset, segment, &data, OUT_ADDRESS + 8,
1126 ins->oprs[c - 054].segment, ins->oprs[c - 054].wrt);
1127 offset += 8;
1128 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001129
H. Peter Anvine2c80182005-01-15 22:15:51 +00001130 case 060:
1131 case 061:
1132 case 062:
1133 if (ins->oprs[c - 060].segment != segment) {
1134 data = ins->oprs[c - 060].offset;
1135 out(offset, segment, &data,
1136 OUT_REL2ADR + insn_end - offset,
1137 ins->oprs[c - 060].segment, ins->oprs[c - 060].wrt);
1138 } else {
1139 data = ins->oprs[c - 060].offset - insn_end;
1140 out(offset, segment, &data,
1141 OUT_ADDRESS + 2, NO_SEG, NO_SEG);
1142 }
1143 offset += 2;
1144 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001145
H. Peter Anvine2c80182005-01-15 22:15:51 +00001146 case 064:
1147 case 065:
1148 case 066:
Keith Kaniosb7a89542007-04-12 02:40:54 +00001149 if (ins->oprs[c - 064].type & (BITS16 | BITS32 | BITS64))
H. Peter Anvine2c80182005-01-15 22:15:51 +00001150 size = (ins->oprs[c - 064].type & BITS16) ? 2 : 4;
1151 else
1152 size = (bits == 16) ? 2 : 4;
1153 if (ins->oprs[c - 064].segment != segment) {
Keith Kaniosb7a89542007-04-12 02:40:54 +00001154 int32_t reltype = (size == 2 ? OUT_REL2ADR : OUT_REL4ADR);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001155 data = ins->oprs[c - 064].offset;
1156 out(offset, segment, &data, reltype + insn_end - offset,
1157 ins->oprs[c - 064].segment, ins->oprs[c - 064].wrt);
1158 } else {
1159 data = ins->oprs[c - 064].offset - insn_end;
1160 out(offset, segment, &data,
1161 OUT_ADDRESS + size, NO_SEG, NO_SEG);
1162 }
1163 offset += size;
1164 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001165
H. Peter Anvine2c80182005-01-15 22:15:51 +00001166 case 070:
1167 case 071:
1168 case 072:
1169 if (ins->oprs[c - 070].segment != segment) {
1170 data = ins->oprs[c - 070].offset;
1171 out(offset, segment, &data,
1172 OUT_REL4ADR + insn_end - offset,
1173 ins->oprs[c - 070].segment, ins->oprs[c - 070].wrt);
1174 } else {
1175 data = ins->oprs[c - 070].offset - insn_end;
1176 out(offset, segment, &data,
1177 OUT_ADDRESS + 4, NO_SEG, NO_SEG);
1178 }
1179 offset += 4;
1180 break;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001181
H. Peter Anvine2c80182005-01-15 22:15:51 +00001182 case 0130:
1183 case 0131:
1184 case 0132:
1185 data = ins->oprs[c - 0130].offset;
1186 if (is_sbyte(ins, c - 0130, 16)) {
1187 bytes[0] = data;
1188 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG,
1189 NO_SEG);
1190 offset++;
1191 } else {
1192 if (ins->oprs[c - 0130].segment == NO_SEG &&
1193 ins->oprs[c - 0130].wrt == NO_SEG &&
1194 (data < -65536L || data > 65535L)) {
1195 errfunc(ERR_WARNING, "word value exceeds bounds");
1196 }
1197 out(offset, segment, &data, OUT_ADDRESS + 2,
1198 ins->oprs[c - 0130].segment, ins->oprs[c - 0130].wrt);
1199 offset += 2;
1200 }
1201 break;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001202
H. Peter Anvine2c80182005-01-15 22:15:51 +00001203 case 0133:
1204 case 0134:
1205 case 0135:
Keith Kaniosb7a89542007-04-12 02:40:54 +00001206 if(ins->rex && (bits == 64)) { /* REX Supercedes all other Prefixes */
1207 ins->rex = (ins->rex&0x0F)+0x40;
1208 out(offset, segment, &ins->rex, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1209 ins->rex = 0;
1210 offset += 1;
1211 }
H. Peter Anvine2c80182005-01-15 22:15:51 +00001212 codes++;
1213 bytes[0] = *codes++;
1214 if (is_sbyte(ins, c - 0133, 16))
1215 bytes[0] |= 2; /* s-bit */
1216 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1217 offset++;
1218 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001219
H. Peter Anvine2c80182005-01-15 22:15:51 +00001220 case 0140:
1221 case 0141:
1222 case 0142:
1223 data = ins->oprs[c - 0140].offset;
1224 if (is_sbyte(ins, c - 0140, 32)) {
1225 bytes[0] = data;
1226 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG,
1227 NO_SEG);
1228 offset++;
1229 } else {
1230 out(offset, segment, &data, OUT_ADDRESS + 4,
1231 ins->oprs[c - 0140].segment, ins->oprs[c - 0140].wrt);
1232 offset += 4;
1233 }
1234 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001235
H. Peter Anvine2c80182005-01-15 22:15:51 +00001236 case 0143:
1237 case 0144:
1238 case 0145:
Keith Kaniosb7a89542007-04-12 02:40:54 +00001239 if(ins->rex && (bits == 64)) { /* REX Supercedes all other Prefixes */
1240 ins->rex = (ins->rex&0x0F)+0x40;
1241 out(offset, segment, &ins->rex, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1242 ins->rex = 0;
1243 offset += 1;
1244 }
H. Peter Anvine2c80182005-01-15 22:15:51 +00001245 codes++;
1246 bytes[0] = *codes++;
1247 if (is_sbyte(ins, c - 0143, 32))
1248 bytes[0] |= 2; /* s-bit */
1249 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1250 offset++;
1251 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001252
H. Peter Anvine2c80182005-01-15 22:15:51 +00001253 case 0300:
1254 case 0301:
1255 case 0302:
1256 if (chsize(&ins->oprs[c - 0300], bits)) {
1257 *bytes = 0x67;
1258 out(offset, segment, bytes,
1259 OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1260 offset += 1;
1261 } else
1262 offset += 0;
1263 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001264
H. Peter Anvine2c80182005-01-15 22:15:51 +00001265 case 0310:
Keith Kaniosb7a89542007-04-12 02:40:54 +00001266 if (bits != 16) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001267 *bytes = 0x67;
1268 out(offset, segment, bytes,
1269 OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1270 offset += 1;
1271 } else
1272 offset += 0;
1273 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001274
H. Peter Anvine2c80182005-01-15 22:15:51 +00001275 case 0311:
Keith Kaniosb7a89542007-04-12 02:40:54 +00001276 if (bits != 32) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001277 *bytes = 0x67;
1278 out(offset, segment, bytes,
1279 OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1280 offset += 1;
1281 } else
1282 offset += 0;
1283 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001284
H. Peter Anvine2c80182005-01-15 22:15:51 +00001285 case 0312:
1286 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001287
Keith Kaniosb7a89542007-04-12 02:40:54 +00001288 case 0313:
1289 ins->rex = 0;
1290 break;
1291
H. Peter Anvine2c80182005-01-15 22:15:51 +00001292 case 0320:
Keith Kaniosb7a89542007-04-12 02:40:54 +00001293 if (bits != 16) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001294 *bytes = 0x66;
1295 out(offset, segment, bytes,
1296 OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1297 offset += 1;
1298 } else
1299 offset += 0;
1300 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001301
H. Peter Anvine2c80182005-01-15 22:15:51 +00001302 case 0321:
1303 if (bits == 16) {
1304 *bytes = 0x66;
1305 out(offset, segment, bytes,
1306 OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1307 offset += 1;
1308 } else
1309 offset += 0;
1310 break;
H. Peter Anvinef7468f2002-04-30 20:57:59 +00001311
H. Peter Anvine2c80182005-01-15 22:15:51 +00001312 case 0322:
Keith Kaniosb7a89542007-04-12 02:40:54 +00001313 case 0323:
1314 break;
1315
1316 case 0324:
1317 ins->rex |= 0xF8;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001318 break;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001319
H. Peter Anvine2c80182005-01-15 22:15:51 +00001320 case 0330:
1321 *bytes = *codes++ ^ condval[ins->condition];
1322 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1323 offset += 1;
1324 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001325
H. Peter Anvine2c80182005-01-15 22:15:51 +00001326 case 0331:
1327 case 0332:
1328 break;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001329
H. Peter Anvine2c80182005-01-15 22:15:51 +00001330 case 0333:
1331 *bytes = 0xF3;
1332 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1333 offset += 1;
1334 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001335
H. Peter Anvine2c80182005-01-15 22:15:51 +00001336 case 0340:
1337 case 0341:
1338 case 0342:
1339 if (ins->oprs[0].segment != NO_SEG)
1340 errfunc(ERR_PANIC, "non-constant BSS size in pass two");
1341 else {
Keith Kaniosb7a89542007-04-12 02:40:54 +00001342 int32_t size = ins->oprs[0].offset << (c - 0340);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001343 if (size > 0)
1344 out(offset, segment, NULL,
1345 OUT_RESERVE + size, NO_SEG, NO_SEG);
1346 offset += size;
1347 }
1348 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001349
H. Peter Anvine2c80182005-01-15 22:15:51 +00001350 case 0370:
1351 case 0371:
1352 case 0372:
1353 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001354
H. Peter Anvine2c80182005-01-15 22:15:51 +00001355 case 0373:
1356 *bytes = bits == 16 ? 3 : 5;
1357 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1358 offset += 1;
1359 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001360
H. Peter Anvine2c80182005-01-15 22:15:51 +00001361 default: /* can't do it by 'case' statements */
Keith Kaniosb7a89542007-04-12 02:40:54 +00001362 if ( c >= 0100 && c <= 0277) { /* it's an EA */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001363 ea ea_data;
1364 int rfield;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001365 uint8_t *p;
1366 int32_t s;
1367
H. Peter Anvine2c80182005-01-15 22:15:51 +00001368 if (c <= 0177) /* pick rfield from operand b */
1369 rfield = regval(&ins->oprs[c & 7]);
1370 else /* rfield is constant */
1371 rfield = c & 7;
1372
1373 if (!process_ea
1374 (&ins->oprs[(c >> 3) & 7], &ea_data, bits, rfield,
1375 ins->forw_ref)) {
1376 errfunc(ERR_NONFATAL, "invalid effective address");
1377 }
Keith Kaniosb7a89542007-04-12 02:40:54 +00001378
H. Peter Anvine2c80182005-01-15 22:15:51 +00001379 p = bytes;
1380 *p++ = ea_data.modrm;
1381 if (ea_data.sib_present)
1382 *p++ = ea_data.sib;
1383
1384 s = p - bytes;
1385 out(offset, segment, bytes, OUT_RAWDATA + s,
1386 NO_SEG, NO_SEG);
1387
1388 switch (ea_data.bytes) {
1389 case 0:
1390 break;
1391 case 1:
1392 if (ins->oprs[(c >> 3) & 7].segment != NO_SEG) {
1393 data = ins->oprs[(c >> 3) & 7].offset;
1394 out(offset, segment, &data, OUT_ADDRESS + 1,
1395 ins->oprs[(c >> 3) & 7].segment,
1396 ins->oprs[(c >> 3) & 7].wrt);
1397 } else {
1398 *bytes = ins->oprs[(c >> 3) & 7].offset;
1399 out(offset, segment, bytes, OUT_RAWDATA + 1,
1400 NO_SEG, NO_SEG);
1401 }
1402 s++;
1403 break;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001404 case 8:
H. Peter Anvine2c80182005-01-15 22:15:51 +00001405 case 2:
1406 case 4:
1407 data = ins->oprs[(c >> 3) & 7].offset;
Keith Kanios3faf9382007-04-15 22:08:30 +00001408 if (ea_data.rip && data && (ins->oprs[(c >> 3) & 7].type == MEMORY))
1409 ea_data.rip = 0; /* Make distinction between Symbols and Immediates */
Keith Kaniosb7a89542007-04-12 02:40:54 +00001410 out(offset, segment, &data, /* RIP = Relative, not Absolute */
1411 (ea_data.rip ? OUT_REL4ADR : OUT_ADDRESS) + ea_data.bytes,
H. Peter Anvine2c80182005-01-15 22:15:51 +00001412 ins->oprs[(c >> 3) & 7].segment,
1413 ins->oprs[(c >> 3) & 7].wrt);
1414 s += ea_data.bytes;
1415 break;
1416 }
1417 offset += s;
1418 } else
1419 errfunc(ERR_PANIC, "internal instruction table corrupt"
1420 ": instruction code 0x%02X given", c);
1421 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001422}
1423
H. Peter Anvine2c80182005-01-15 22:15:51 +00001424static int regval(operand * o)
H. Peter Anvineba20a72002-04-30 20:53:55 +00001425{
H. Peter Anvine2c80182005-01-15 22:15:51 +00001426 if (o->basereg < EXPR_REG_START || o->basereg >= REG_ENUM_LIMIT) {
1427 errfunc(ERR_PANIC, "invalid operand passed to regval()");
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001428 }
H. Peter Anvin232badb2002-06-06 02:41:20 +00001429 return regvals[o->basereg];
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001430}
1431
Keith Kaniosb7a89542007-04-12 02:40:54 +00001432static int matches(struct itemplate *itemp, insn * instruction, int bits)
H. Peter Anvineba20a72002-04-30 20:53:55 +00001433{
Keith Kaniosb7a89542007-04-12 02:40:54 +00001434 int i, b, x, size[3], asize, oprs, ret;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001435
1436 ret = 100;
1437
1438 /*
1439 * Check the opcode
1440 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001441 if (itemp->opcode != instruction->opcode)
1442 return 0;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001443
1444 /*
1445 * Count the operands
1446 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001447 if (itemp->operands != instruction->operands)
1448 return 0;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001449
1450 /*
1451 * Check that no spurious colons or TOs are present
1452 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001453 for (i = 0; i < itemp->operands; i++)
1454 if (instruction->oprs[i].type & ~itemp->opd[i] & (COLON | TO))
1455 return 0;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001456
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001457 /*
1458 * Check that the operand flags all match up
1459 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001460 for (i = 0; i < itemp->operands; i++)
1461 if (itemp->opd[i] & ~instruction->oprs[i].type ||
1462 ((itemp->opd[i] & SIZE_MASK) &&
1463 ((itemp->opd[i] ^ instruction->oprs[i].type) & SIZE_MASK))) {
1464 if ((itemp->opd[i] & ~instruction->oprs[i].type & NON_SIZE) ||
1465 (instruction->oprs[i].type & SIZE_MASK))
1466 return 0;
1467 else
H. Peter Anvine2c80182005-01-15 22:15:51 +00001468 return 1;
1469 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001470
1471 /*
1472 * Check operand sizes
1473 */
H. Peter Anvinef7468f2002-04-30 20:57:59 +00001474 if (itemp->flags & IF_ARMASK) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001475 size[0] = size[1] = size[2] = 0;
H. Peter Anvinef7468f2002-04-30 20:57:59 +00001476
H. Peter Anvine2c80182005-01-15 22:15:51 +00001477 switch (itemp->flags & IF_ARMASK) {
1478 case IF_AR0:
1479 i = 0;
1480 break;
1481 case IF_AR1:
1482 i = 1;
1483 break;
1484 case IF_AR2:
1485 i = 2;
1486 break;
1487 default:
1488 break; /* Shouldn't happen */
1489 }
1490 if (itemp->flags & IF_SB) {
1491 size[i] = BITS8;
1492 } else if (itemp->flags & IF_SW) {
1493 size[i] = BITS16;
1494 } else if (itemp->flags & IF_SD) {
1495 size[i] = BITS32;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001496 } else if (itemp->flags & IF_SQ) {
1497 if (bits != 64)
1498 return 2;
1499 size[i] = BITS64;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001500 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001501 } else {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001502 asize = 0;
1503 if (itemp->flags & IF_SB) {
1504 asize = BITS8;
1505 oprs = itemp->operands;
1506 } else if (itemp->flags & IF_SW) {
1507 asize = BITS16;
1508 oprs = itemp->operands;
1509 } else if (itemp->flags & IF_SD) {
1510 asize = BITS32;
1511 oprs = itemp->operands;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001512 } else if (itemp->flags & IF_SQ) {
1513 if (bits != 64)
1514 return 2;
1515 asize = BITS64;
1516 oprs = itemp->operands;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001517 }
1518 size[0] = size[1] = size[2] = asize;
H. Peter Anvinef7468f2002-04-30 20:57:59 +00001519 }
Keith Kaniosb7a89542007-04-12 02:40:54 +00001520
H. Peter Anvinef7468f2002-04-30 20:57:59 +00001521 if (itemp->flags & (IF_SM | IF_SM2)) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001522 oprs = (itemp->flags & IF_SM2 ? 2 : itemp->operands);
1523 asize = 0;
1524 for (i = 0; i < oprs; i++) {
1525 if ((asize = itemp->opd[i] & SIZE_MASK) != 0) {
1526 int j;
1527 for (j = 0; j < oprs; j++)
1528 size[j] = asize;
1529 break;
1530 }
1531 }
H. Peter Anvinef7468f2002-04-30 20:57:59 +00001532 } else {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001533 oprs = itemp->operands;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001534 }
1535
Keith Kaniosb7a89542007-04-12 02:40:54 +00001536 for (i = 0; i < itemp->operands; i++) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001537 if (!(itemp->opd[i] & SIZE_MASK) &&
1538 (instruction->oprs[i].type & SIZE_MASK & ~size[i]))
H. Peter Anvine2c80182005-01-15 22:15:51 +00001539 return 2;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001540
Keith Kaniosb7a89542007-04-12 02:40:54 +00001541 if ( (((itemp->opd[i] & SIZE_MASK) == BITS64) ||
1542 ((instruction->oprs[i].type & SIZE_MASK) == BITS64))
1543 && bits != 64)
1544 return 2;
1545
1546 x = instruction->oprs[i].indexreg;
1547 b = instruction->oprs[i].basereg;
1548
1549 if (x != -1 && x >= EXPR_REG_START && x < REG_ENUM_LIMIT)
1550 x = regvals[x];
1551 if (b != -1 && b >= EXPR_REG_START && b < REG_ENUM_LIMIT)
1552 b = regvals[b];
1553
1554 if (((b >= 0400 && b <= 0500) || (x >= 0400 && x < 0500)) && bits != 64)
1555 return 2;
1556 }
1557
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001558 /*
1559 * Check template is okay at the set cpu level
1560 */
Keith Kaniosb7a89542007-04-12 02:40:54 +00001561 if (((itemp->flags & IF_PLEVEL) > cpu))
H. Peter Anvine2c80182005-01-15 22:15:51 +00001562 return 3;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001563
1564 /*
1565 * Check if instruction is available in long mode
1566 */
1567 if ((itemp->flags & IF_NOLONG) && (bits == 64))
1568 return 4;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001569
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001570 /*
1571 * Check if special handling needed for Jumps
1572 */
Keith Kaniosb7a89542007-04-12 02:40:54 +00001573 if ((uint8_t)(itemp->code[0]) >= 0370)
H. Peter Anvine2c80182005-01-15 22:15:51 +00001574 return 99;
1575
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001576 return ret;
1577}
1578
H. Peter Anvine2c80182005-01-15 22:15:51 +00001579static ea *process_ea(operand * input, ea * output, int addrbits,
1580 int rfield, int forw_ref)
H. Peter Anvineba20a72002-04-30 20:53:55 +00001581{
Keith Kaniosb7a89542007-04-12 02:40:54 +00001582
1583 int rip = FALSE; /* Used for RIP-relative addressing */
1584
1585
1586 if (!(REGISTER & ~input->type)) { /* register direct */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001587 int i;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001588 if ( input->basereg < EXPR_REG_START /* Verify as Register */
1589 || input->basereg >= REG_ENUM_LIMIT)
H. Peter Anvine2c80182005-01-15 22:15:51 +00001590 return NULL;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001591 i = regvals[input->basereg];
1592 if ( i >= 0100 && i < 0210) /* GPR's, MMX & XMM only */
1593 return NULL;
1594
1595 if (i >= 0400 && i < 0500) { /* Calculate REX.B */
1596 if (i < 0410 || (i >= 0440 && i < 0450))
1597 output->rex |= 0xF0; /* Set REX.0 */
1598 else
1599 output->rex |= 0xF1; /* Set REX.B */
1600 if (i >= 0440)
1601 output->rex |= 0xF8; /* Set REX.W */
1602 }
1603
1604 if ((rfield >= 0400 && rfield < 0500) || /* Calculate REX.R */
1605 (rfield >= 0120 && rfield < 0200 && /* Include CR/DR/TR... */
1606 !(rfield & 0010))) { /* ... extensions, only */
1607 if ((rfield >= 0400 && rfield < 0410) || (rfield >= 0440 && rfield < 0450))
1608 output->rex |= 0xF0; /* Set REX.0 */
1609 else
1610 output->rex |= 0xF4; /* Set REX.R */
1611 if (rfield >= 0440)
1612 output->rex |= 0xF8; /* Set REX.W */
1613 }
1614
1615 output->sib_present = FALSE; /* no SIB necessary */
1616 output->bytes = 0; /* no offset necessary either */
1617 output->modrm = 0xC0 | ((rfield & 7) << 3) | (i & 7);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001618 } else { /* it's a memory reference */
Keith Kaniosb7a89542007-04-12 02:40:54 +00001619
H. Peter Anvine2c80182005-01-15 22:15:51 +00001620 if (input->basereg == -1
1621 && (input->indexreg == -1 || input->scale == 0)) {
1622 /* it's a pure offset */
1623 if (input->addr_size)
1624 addrbits = input->addr_size;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001625
1626 if (rfield >= 0400 && rfield < 0500) { /* Calculate REX.R */
1627 if (rfield < 0410 || (rfield >= 0440 && rfield < 0450))
1628 output->rex |= 0xF0; /* Set REX.0 */
1629 else
1630 output->rex |= 0xF4; /* Set REX.R */
1631 if (rfield >= 0440)
1632 output->rex |= 0xF8; /* Set REX.W */
1633 }
1634
H. Peter Anvine2c80182005-01-15 22:15:51 +00001635 output->sib_present = FALSE;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001636 output->bytes = (addrbits != 16 ? 4 : 2);
1637 output->modrm = (addrbits != 16 ? 5 : 6) | ((rfield & 7) << 3);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001638 } else { /* it's an indirection */
1639 int i = input->indexreg, b = input->basereg, s = input->scale;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001640 int32_t o = input->offset, seg = input->segment;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001641 int hb = input->hintbase, ht = input->hinttype;
1642 int t;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001643 int it, bt;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001644
H. Peter Anvine2c80182005-01-15 22:15:51 +00001645 if (s == 0)
1646 i = -1; /* make this easy, at least */
Keith Kaniosb7a89542007-04-12 02:40:54 +00001647
1648 if (i != -1 && i >= EXPR_REG_START
1649 && i < REG_ENUM_LIMIT)
1650 it = regvals[i];
1651 else
1652 it = -1;
1653
1654 if (b != -1 && b >= EXPR_REG_START
1655 && b < REG_ENUM_LIMIT)
1656 bt = regvals[b];
1657 else
1658 bt = -1;
1659
1660 /* check for a 32/64-bit memory reference... */
1661 if ((it >= 0020 && it < 0030) || (it >= 0430 && it < 0460) ||
1662 (bt >= 0020 && bt < 0030) || (bt >= 0430 && bt < 0460) ||
1663 bt == 0500) {
1664 /* it must be a 32/64-bit memory reference. Firstly we have
1665 * to check that all registers involved are type E/Rxx. */
1666 t = 1;
1667 if (it != -1) {
1668 if (it < 0020 || (it >= 0030 && it < 0430) || it >= 0460)
1669 return NULL;
1670 if (it >= 0440)
1671 t = 2;
1672 else
1673 t = 0;
1674 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001675
Keith Kaniosb7a89542007-04-12 02:40:54 +00001676 if (bt != -1) {
1677 if (bt < 0020 || (bt >= 0030 && bt < 0430) || (bt >= 0460 && bt < 0500))
1678 return NULL;
1679 if (bt == 0500) {
1680 bt = b = -1;
1681 rip = TRUE;
1682 } else if (bt >= 0440) {
1683 if (t < 1)
1684 return NULL;
1685 } else {
1686 if (t > 1)
1687 return NULL;
1688 }
1689 }
1690
H. Peter Anvine2c80182005-01-15 22:15:51 +00001691 /* While we're here, ensure the user didn't specify WORD. */
1692 if (input->addr_size == 16)
1693 return NULL;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001694
Keith Kaniosb7a89542007-04-12 02:40:54 +00001695 /* now reorganize base/index */
1696 if (s == 1 && bt != it && bt != -1 && it != -1 &&
1697 ((hb == bt && ht == EAH_NOTBASE)
1698 || (hb == it && ht == EAH_MAKEBASE)))
1699 t = bt, bt = it, it = t; /* swap if hints say so */
1700 if (bt == it) /* convert EAX+2*EAX to 3*EAX */
1701 bt = -1, s++;
1702 if (bt == -1 && s == 1 && !(hb == it && ht == EAH_NOTBASE))
1703 bt = i, it = -1; /* make single reg base, unless hint */
1704 if (((s == 2 && (it & 7) != (REG_NUM_ESP & 7)
H. Peter Anvine2c80182005-01-15 22:15:51 +00001705 && !(input->eaflags & EAF_TIMESTWO)) || s == 3
Keith Kaniosb7a89542007-04-12 02:40:54 +00001706 || s == 5 || s == 9) && bt == -1)
1707 bt = it, s--; /* convert 3*EAX to EAX+2*EAX */
1708 if (it == -1 && (bt & 7) != (REG_NUM_ESP & 7)
H. Peter Anvine2c80182005-01-15 22:15:51 +00001709 && (input->eaflags & EAF_TIMESTWO))
Keith Kaniosb7a89542007-04-12 02:40:54 +00001710 it = bt, bt = -1, s = 1;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001711 /* convert [NOSPLIT EAX] to sib format with 0x0 displacement */
Keith Kaniosb7a89542007-04-12 02:40:54 +00001712 if (s == 1 && (it & 7) == (REG_NUM_ESP & 7)) /* swap ESP into base if scale is 1 */
1713 t = it, it = bt, bt = t;
1714 if ((it & 7) == (REG_NUM_ESP & 7)
1715 || (s != 1 && s != 2 && s != 4 && s != 8 && it != -1))
H. Peter Anvine2c80182005-01-15 22:15:51 +00001716 return NULL; /* wrong, for various reasons */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001717
Keith Kanios2cc61b32007-04-13 01:17:45 +00001718 if (i >= 0400 && i < 0500) { /* Calculate REX.X */
Keith Kaniosb7a89542007-04-12 02:40:54 +00001719 if (i < 0410 || (i >= 0440 && i < 0450))
1720 output->rex |= 0xF0; /* Set REX.0 */
1721 else
Keith Kanios2cc61b32007-04-13 01:17:45 +00001722 output->rex |= 0xF2; /* Set REX.X */
Keith Kaniosb7a89542007-04-12 02:40:54 +00001723 if (i >= 0440)
1724 output->rex |= 0xF8; /* Set REX.W */
1725 }
1726
1727 if (b >= 0400 && b < 0500) { /* Calculate REX.B */
1728 if (b < 0410 || (b >= 0440 && b < 0450))
1729 output->rex |= 0xF0; /* Set REX.0 */
1730 else
1731 output->rex |= 0xF1; /* Set REX.B */
1732 if (b >= 0440)
1733 output->rex |= 0xF8; /* Set REX.W */
1734 }
1735
1736 if (rfield >= 0400 && rfield < 0500) { /* Calculate REX.R */
1737 if (rfield < 0410 || (rfield >= 0440 && rfield < 0450))
1738 output->rex |= 0xF0; /* Set REX.0 */
1739 else
1740 output->rex |= 0xF4; /* Set REX.R */
1741 if (rfield >= 0440)
1742 output->rex |= 0xF8; /* Set REX.W */
1743 }
1744
1745 if (it == -1 && (bt & 7) != (REG_NUM_ESP & 7)) { /* no SIB needed */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001746 int mod, rm;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001747
1748 if (bt == -1) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001749 rm = 5;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001750 mod = 0;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001751 } else {
1752 rm = (bt & 7);
1753 if (rm != (REG_NUM_EBP & 7) && o == 0 &&
1754 seg == NO_SEG && !forw_ref &&
1755 !(input->eaflags &
1756 (EAF_BYTEOFFS | EAF_WORDOFFS)))
1757 mod = 0;
1758 else if (input->eaflags & EAF_BYTEOFFS ||
1759 (o >= -128 && o <= 127 && seg == NO_SEG
1760 && !forw_ref
1761 && !(input->eaflags & EAF_WORDOFFS)))
1762 mod = 1;
1763 else
1764 mod = 2;
1765 }
H. Peter Anvinea838272002-04-30 20:51:53 +00001766
H. Peter Anvine2c80182005-01-15 22:15:51 +00001767 output->sib_present = FALSE;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001768 output->bytes = (bt == -1 || mod == 2 ? 4 : mod);
1769 output->modrm = (mod << 6) | ((rfield & 7) << 3) | rm;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001770 } else { /* we need a SIB */
1771 int mod, scale, index, base;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001772
1773 if (it == -1)
1774 index = 4, s = 1;
1775 else
1776 index = (it & 7);
1777
H. Peter Anvine2c80182005-01-15 22:15:51 +00001778 switch (s) {
1779 case 1:
1780 scale = 0;
1781 break;
1782 case 2:
1783 scale = 1;
1784 break;
1785 case 4:
1786 scale = 2;
1787 break;
1788 case 8:
1789 scale = 3;
1790 break;
1791 default: /* then what the smeg is it? */
1792 return NULL; /* panic */
1793 }
Keith Kaniosb7a89542007-04-12 02:40:54 +00001794
1795 if (bt == -1) {
1796 base = 5;
1797 mod = 0;
1798 } else {
1799 base = (bt & 7);
1800 if (base != (REG_NUM_EBP & 7) && o == 0 &&
H. Peter Anvine2c80182005-01-15 22:15:51 +00001801 seg == NO_SEG && !forw_ref &&
1802 !(input->eaflags &
Keith Kaniosb7a89542007-04-12 02:40:54 +00001803 (EAF_BYTEOFFS | EAF_WORDOFFS)))
1804 mod = 0;
1805 else if (input->eaflags & EAF_BYTEOFFS ||
1806 (o >= -128 && o <= 127 && seg == NO_SEG
1807 && !forw_ref
1808 && !(input->eaflags & EAF_WORDOFFS)))
1809 mod = 1;
1810 else
1811 mod = 2;
1812 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001813
H. Peter Anvine2c80182005-01-15 22:15:51 +00001814 output->sib_present = TRUE;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001815 output->bytes = (bt == -1 || mod == 2 ? 4 : mod);
1816 output->modrm = (mod << 6) | ((rfield & 7) << 3) | 4;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001817 output->sib = (scale << 6) | (index << 3) | base;
1818 }
1819 } else { /* it's 16-bit */
1820 int mod, rm;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001821
1822 /* check for 64-bit long mode */
1823 if (addrbits == 64)
1824 return NULL;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001825
H. Peter Anvine2c80182005-01-15 22:15:51 +00001826 /* check all registers are BX, BP, SI or DI */
1827 if ((b != -1 && b != R_BP && b != R_BX && b != R_SI
1828 && b != R_DI) || (i != -1 && i != R_BP && i != R_BX
1829 && i != R_SI && i != R_DI))
1830 return NULL;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001831
Keith Kaniosb7a89542007-04-12 02:40:54 +00001832 /* ensure the user didn't specify DWORD/QWORD */
1833 if (input->addr_size == 32 || input->addr_size == 64)
H. Peter Anvine2c80182005-01-15 22:15:51 +00001834 return NULL;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001835
H. Peter Anvine2c80182005-01-15 22:15:51 +00001836 if (s != 1 && i != -1)
1837 return NULL; /* no can do, in 16-bit EA */
1838 if (b == -1 && i != -1) {
1839 int tmp = b;
1840 b = i;
1841 i = tmp;
1842 } /* swap */
1843 if ((b == R_SI || b == R_DI) && i != -1) {
1844 int tmp = b;
1845 b = i;
1846 i = tmp;
1847 }
1848 /* have BX/BP as base, SI/DI index */
1849 if (b == i)
1850 return NULL; /* shouldn't ever happen, in theory */
1851 if (i != -1 && b != -1 &&
1852 (i == R_BP || i == R_BX || b == R_SI || b == R_DI))
1853 return NULL; /* invalid combinations */
1854 if (b == -1) /* pure offset: handled above */
1855 return NULL; /* so if it gets to here, panic! */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001856
H. Peter Anvine2c80182005-01-15 22:15:51 +00001857 rm = -1;
1858 if (i != -1)
1859 switch (i * 256 + b) {
1860 case R_SI * 256 + R_BX:
1861 rm = 0;
1862 break;
1863 case R_DI * 256 + R_BX:
1864 rm = 1;
1865 break;
1866 case R_SI * 256 + R_BP:
1867 rm = 2;
1868 break;
1869 case R_DI * 256 + R_BP:
1870 rm = 3;
1871 break;
1872 } else
1873 switch (b) {
1874 case R_SI:
1875 rm = 4;
1876 break;
1877 case R_DI:
1878 rm = 5;
1879 break;
1880 case R_BP:
1881 rm = 6;
1882 break;
1883 case R_BX:
1884 rm = 7;
1885 break;
1886 }
1887 if (rm == -1) /* can't happen, in theory */
1888 return NULL; /* so panic if it does */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001889
H. Peter Anvine2c80182005-01-15 22:15:51 +00001890 if (o == 0 && seg == NO_SEG && !forw_ref && rm != 6 &&
1891 !(input->eaflags & (EAF_BYTEOFFS | EAF_WORDOFFS)))
1892 mod = 0;
1893 else if (input->eaflags & EAF_BYTEOFFS ||
1894 (o >= -128 && o <= 127 && seg == NO_SEG
1895 && !forw_ref
1896 && !(input->eaflags & EAF_WORDOFFS)))
1897 mod = 1;
1898 else
1899 mod = 2;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001900
H. Peter Anvine2c80182005-01-15 22:15:51 +00001901 output->sib_present = FALSE; /* no SIB - it's 16-bit */
1902 output->bytes = mod; /* bytes of offset needed */
Keith Kaniosb7a89542007-04-12 02:40:54 +00001903 output->modrm = (mod << 6) | ((rfield & 7) << 3) | rm;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001904 }
1905 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001906 }
Keith Kaniosb7a89542007-04-12 02:40:54 +00001907
1908 /* Process RIP-relative Addressing */
1909 if (rip) {
1910 if ((output->modrm & 0xC7) != 0x05)
1911 return NULL;
1912 output->rip = TRUE;
1913 } else {
1914 output->rip = FALSE;
1915 if (globalbits == 64 && /* Actual Disp32 needs blank SIB on x64 */
1916 !(output->sib_present) && ((output->modrm & 0xC7) == 0x05)) {
1917 output->sib_present = TRUE;
1918 output->modrm --; /* RM Field = 4 (forward to Base of SIB) */
1919 output->sib = (4 << 3) | 5; /* Index = 4 (none), Base = 5 */
1920 }
1921 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001922 output->size = 1 + output->sib_present + output->bytes;
1923 return output;
1924}
1925
H. Peter Anvine2c80182005-01-15 22:15:51 +00001926static int chsize(operand * input, int addrbits)
H. Peter Anvineba20a72002-04-30 20:53:55 +00001927{
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001928 if (!(MEMORY & ~input->type)) {
Keith Kaniosb7a89542007-04-12 02:40:54 +00001929 int i, b;
1930
1931 if ( input->indexreg < EXPR_REG_START /* Verify as Register */
1932 || input->indexreg >= REG_ENUM_LIMIT)
1933 i = -1;
1934 else
1935 i = regvals[input->indexreg];
1936
1937 if ( input->basereg < EXPR_REG_START /* Verify as Register */
1938 || input->basereg >= REG_ENUM_LIMIT)
1939 b = -1;
1940 else
1941 b = regvals[input->basereg];
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001942
H. Peter Anvine2c80182005-01-15 22:15:51 +00001943 if (input->scale == 0)
1944 i = -1;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001945
H. Peter Anvine2c80182005-01-15 22:15:51 +00001946 if (i == -1 && b == -1) /* pure offset */
1947 return (input->addr_size != 0 && input->addr_size != addrbits);
Keith Kaniosb7a89542007-04-12 02:40:54 +00001948
1949 if ((i >= 0020 && i < 0030) || (i >= 0430 && i < 0440) ||
1950 (b >= 0020 && b < 0030) || (b >= 0430 && b < 0440))
1951 return (addrbits != 32);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001952 else
1953 return (addrbits == 32);
1954 } else
1955 return 0;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001956}