blob: 4669ebd6f28fd04f0a0e42488d08d7d9011a1546 [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.
H. Peter Anvin0db11e22007-04-17 20:23:11 +000070 * \334 - LOCK prefix used instead of REX.R
Keith Kaniosb7a89542007-04-12 02:40:54 +000071 * \340 - reserve <operand 0> bytes of uninitialized storage.
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000072 * Operand 0 had better be a segmentless constant.
H. Peter Anvin788e6c12002-04-30 21:02:01 +000073 * \370,\371,\372 - match only if operand 0 meets byte jump criteria.
74 * 370 is used for Jcc, 371 is used for JMP.
H. Peter Anvinaf535c12002-04-30 20:59:21 +000075 * \373 - assemble 0x03 if bits==16, 0x05 if bits==32;
76 * used for conditional jump over longer jump
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000077 */
78
79#include <stdio.h>
80#include <string.h>
Keith Kaniosb7a89542007-04-12 02:40:54 +000081#include <inttypes.h>
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000082
83#include "nasm.h"
H. Peter Anvin6768eb72002-04-30 20:52:26 +000084#include "nasmlib.h"
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000085#include "assemble.h"
86#include "insns.h"
Frank Kotlerd0ed6fd2003-08-27 11:33:56 +000087#include "preproc.h"
Keith Kaniosb7a89542007-04-12 02:40:54 +000088#include "regvals.c"
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000089
90extern struct itemplate *nasm_instructions[];
91
92typedef struct {
Keith Kaniosb7a89542007-04-12 02:40:54 +000093 int sib_present; /* is a SIB byte necessary? */
94 int bytes; /* # of bytes of offset needed */
95 int size; /* lazy - this is sib+bytes+1 */
96 uint8_t modrm, sib, rex, rip; /* the bytes themselves */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000097} ea;
98
Keith Kaniosb7a89542007-04-12 02:40:54 +000099static uint32_t cpu; /* cpu level received from nasm.c */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000100static efunc errfunc;
101static struct ofmt *outfmt;
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000102static ListGen *list;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000103
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000104static int32_t calcsize(int32_t, int32_t, int, insn *, const char *);
105static void gencode(int32_t, int32_t, int, insn *, const char *, int32_t);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000106static int regval(operand * o);
Keith Kanios93f2e9a2007-04-14 00:10:59 +0000107// static int regflag(operand * o);
Keith Kaniosb7a89542007-04-12 02:40:54 +0000108static int matches(struct itemplate *, insn *, int bits);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000109static ea *process_ea(operand *, ea *, int, int, int);
110static int chsize(operand *, int);
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000111
H. Peter Anvin0db11e22007-04-17 20:23:11 +0000112static void assert_no_prefix(insn * ins, int prefix)
113{
114 int j;
115
116 for (j = 0; j < ins->nprefix; j++) {
117 if (ins->prefixes[j] == prefix) {
118 errfunc(ERR_NONFATAL, "invalid %s prefix", prefix_name(prefix));
119 break;
120 }
121 }
122}
123
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000124/*
125 * This routine wrappers the real output format's output routine,
126 * in order to pass a copy of the data off to the listing file
127 * generator at the same time.
128 */
Keith Kaniosb7a89542007-04-12 02:40:54 +0000129static void out(int32_t offset, int32_t segto, const void *data,
130 uint32_t type, int32_t segment, int32_t wrt)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000131{
Keith Kaniosb7a89542007-04-12 02:40:54 +0000132 static int32_t lineno = 0; /* static!!! */
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000133 static char *lnfname = NULL;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000134
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000135 if ((type & OUT_TYPMASK) == OUT_ADDRESS) {
H. Peter Anvine2c80182005-01-15 22:15:51 +0000136 if (segment != NO_SEG || wrt != NO_SEG) {
137 /*
138 * This address is relocated. We must write it as
139 * OUT_ADDRESS, so there's no work to be done here.
140 */
141 list->output(offset, data, type);
142 } else {
Keith Kaniosb7a89542007-04-12 02:40:54 +0000143 uint8_t p[8], *q = p;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000144 /*
145 * This is a non-relocated address, and we're going to
146 * convert it into RAWDATA format.
147 */
148 if ((type & OUT_SIZMASK) == 4) {
Keith Kaniosb7a89542007-04-12 02:40:54 +0000149 WRITELONG(q, *(int32_t *)data);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000150 list->output(offset, p, OUT_RAWDATA + 4);
Keith Kaniosb7a89542007-04-12 02:40:54 +0000151 } else if ((type & OUT_SIZMASK) == 8) {
152 WRITEDLONG(q, *(int64_t *)data);
153 list->output(offset, p, OUT_RAWDATA + 8);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000154 } else {
Keith Kaniosb7a89542007-04-12 02:40:54 +0000155 WRITESHORT(q, *(int32_t *)data);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000156 list->output(offset, p, OUT_RAWDATA + 2);
157 }
158 }
159 } else if ((type & OUT_TYPMASK) == OUT_RAWDATA) {
160 list->output(offset, data, type);
161 } else if ((type & OUT_TYPMASK) == OUT_RESERVE) {
162 list->output(offset, NULL, type);
163 } else if ((type & OUT_TYPMASK) == OUT_REL2ADR ||
164 (type & OUT_TYPMASK) == OUT_REL4ADR) {
165 list->output(offset, data, type);
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000166 }
167
Frank Kotlerabebb082003-09-06 04:45:37 +0000168 /*
169 * this call to src_get determines when we call the
170 * debug-format-specific "linenum" function
171 * it updates lineno and lnfname to the current values
172 * returning 0 if "same as last time", -2 if lnfname
173 * changed, and the amount by which lineno changed,
174 * if it did. thus, these variables must be static
175 */
176
H. Peter Anvine2c80182005-01-15 22:15:51 +0000177 if (src_get(&lineno, &lnfname)) {
178 outfmt->current_dfmt->linenum(lnfname, lineno, segto);
H. Peter Anvince616072002-04-30 21:02:23 +0000179 }
H. Peter Anvineba20a72002-04-30 20:53:55 +0000180
H. Peter Anvine2c80182005-01-15 22:15:51 +0000181 outfmt->output(segto, data, type, segment, wrt);
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000182}
183
Keith Kaniosb7a89542007-04-12 02:40:54 +0000184static int jmp_match(int32_t segment, int32_t offset, int bits,
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000185 insn * ins, const char *code)
H. Peter Anvine2c80182005-01-15 22:15:51 +0000186{
Keith Kaniosb7a89542007-04-12 02:40:54 +0000187 int32_t isize;
188 uint8_t c = code[0];
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000189
H. Peter Anvine2c80182005-01-15 22:15:51 +0000190 if (c != 0370 && c != 0371)
191 return 0;
H. Peter Anvin788e6c12002-04-30 21:02:01 +0000192 if (ins->oprs[0].opflags & OPFLAG_FORWARD) {
H. Peter Anvine2c80182005-01-15 22:15:51 +0000193 if ((optimizing < 0 || (ins->oprs[0].type & STRICT))
194 && c == 0370)
195 return 1;
196 else
197 return (pass0 == 0); /* match a forward reference */
H. Peter Anvin788e6c12002-04-30 21:02:01 +0000198 }
H. Peter Anvine2c80182005-01-15 22:15:51 +0000199 isize = calcsize(segment, offset, bits, ins, code);
200 if (ins->oprs[0].segment != segment)
201 return 0;
202 isize = ins->oprs[0].offset - offset - isize; /* isize is now the delta */
203 if (isize >= -128L && isize <= 127L)
204 return 1; /* it is byte size */
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000205
206 return 0;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000207}
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000208
Keith Kaniosb7a89542007-04-12 02:40:54 +0000209int32_t assemble(int32_t segment, int32_t offset, int bits, uint32_t cp,
H. Peter Anvine2c80182005-01-15 22:15:51 +0000210 insn * instruction, struct ofmt *output, efunc error,
211 ListGen * listgen)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000212{
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000213 struct itemplate *temp;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000214 int j;
215 int size_prob;
Keith Kaniosb7a89542007-04-12 02:40:54 +0000216 int32_t insn_end;
217 int32_t itimes;
218 int32_t start = offset;
219 int32_t wsize = 0; /* size for DB etc. */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000220
H. Peter Anvine2c80182005-01-15 22:15:51 +0000221 errfunc = error; /* to pass to other functions */
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000222 cpu = cp;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000223 outfmt = output; /* likewise */
224 list = listgen; /* and again */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000225
H. Peter Anvine2c80182005-01-15 22:15:51 +0000226 switch (instruction->opcode) {
227 case -1:
228 return 0;
229 case I_DB:
230 wsize = 1;
231 break;
232 case I_DW:
233 wsize = 2;
234 break;
235 case I_DD:
236 wsize = 4;
237 break;
238 case I_DQ:
239 wsize = 8;
240 break;
241 case I_DT:
242 wsize = 10;
243 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000244 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000245
H. Peter Anvineba20a72002-04-30 20:53:55 +0000246 if (wsize) {
H. Peter Anvine2c80182005-01-15 22:15:51 +0000247 extop *e;
Keith Kaniosb7a89542007-04-12 02:40:54 +0000248 int32_t t = instruction->times;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000249 if (t < 0)
250 errfunc(ERR_PANIC,
251 "instruction->times < 0 (%ld) in assemble()", t);
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000252
H. Peter Anvine2c80182005-01-15 22:15:51 +0000253 while (t--) { /* repeat TIMES times */
254 for (e = instruction->eops; e; e = e->next) {
255 if (e->type == EOT_DB_NUMBER) {
256 if (wsize == 1) {
257 if (e->segment != NO_SEG)
258 errfunc(ERR_NONFATAL,
259 "one-byte relocation attempted");
260 else {
Keith Kaniosb7a89542007-04-12 02:40:54 +0000261 uint8_t out_byte = e->offset;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000262 out(offset, segment, &out_byte,
263 OUT_RAWDATA + 1, NO_SEG, NO_SEG);
264 }
Keith Kanios61ff53c2007-04-14 18:54:52 +0000265 } else if (wsize > 8) {
266 errfunc(ERR_NONFATAL, "integer supplied to a DT"
267 " instruction");
H. Peter Anvine2c80182005-01-15 22:15:51 +0000268 } else
269 out(offset, segment, &e->offset,
270 OUT_ADDRESS + wsize, e->segment, e->wrt);
271 offset += wsize;
272 } else if (e->type == EOT_DB_STRING) {
273 int align;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000274
H. Peter Anvine2c80182005-01-15 22:15:51 +0000275 out(offset, segment, e->stringval,
276 OUT_RAWDATA + e->stringlen, NO_SEG, NO_SEG);
277 align = e->stringlen % wsize;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000278
H. Peter Anvine2c80182005-01-15 22:15:51 +0000279 if (align) {
280 align = wsize - align;
281 out(offset, segment, "\0\0\0\0\0\0\0\0",
282 OUT_RAWDATA + align, NO_SEG, NO_SEG);
283 }
284 offset += e->stringlen + align;
285 }
286 }
287 if (t > 0 && t == instruction->times - 1) {
288 /*
289 * Dummy call to list->output to give the offset to the
290 * listing module.
291 */
292 list->output(offset, NULL, OUT_RAWDATA);
293 list->uplevel(LIST_TIMES);
294 }
295 }
296 if (instruction->times > 1)
297 list->downlevel(LIST_TIMES);
298 return offset - start;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000299 }
300
H. Peter Anvine2c80182005-01-15 22:15:51 +0000301 if (instruction->opcode == I_INCBIN) {
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000302 static char fname[FILENAME_MAX];
H. Peter Anvine2c80182005-01-15 22:15:51 +0000303 FILE *fp;
Keith Kaniosb7a89542007-04-12 02:40:54 +0000304 int32_t len;
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000305 char *prefix = "", *combine;
306 char **pPrevPath = NULL;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000307
H. Peter Anvine2c80182005-01-15 22:15:51 +0000308 len = FILENAME_MAX - 1;
309 if (len > instruction->eops->stringlen)
310 len = instruction->eops->stringlen;
311 strncpy(fname, instruction->eops->stringval, len);
312 fname[len] = '\0';
H. Peter Anvineba20a72002-04-30 20:53:55 +0000313
Keith Kaniosb7a89542007-04-12 02:40:54 +0000314 while (1) { /* added by alexfru: 'incbin' uses include paths */
H. Peter Anvine2c80182005-01-15 22:15:51 +0000315 combine = nasm_malloc(strlen(prefix) + len + 1);
316 strcpy(combine, prefix);
317 strcat(combine, fname);
Frank Kotlerd0ed6fd2003-08-27 11:33:56 +0000318
H. Peter Anvine2c80182005-01-15 22:15:51 +0000319 if ((fp = fopen(combine, "rb")) != NULL) {
320 nasm_free(combine);
321 break;
322 }
Frank Kotlerd0ed6fd2003-08-27 11:33:56 +0000323
H. Peter Anvine2c80182005-01-15 22:15:51 +0000324 nasm_free(combine);
325 pPrevPath = pp_get_include_path_ptr(pPrevPath);
326 if (pPrevPath == NULL)
327 break;
328 prefix = *pPrevPath;
Frank Kotlerd0ed6fd2003-08-27 11:33:56 +0000329 }
330
331 if (fp == NULL)
H. Peter Anvine2c80182005-01-15 22:15:51 +0000332 error(ERR_NONFATAL, "`incbin': unable to open file `%s'",
333 fname);
334 else if (fseek(fp, 0L, SEEK_END) < 0)
335 error(ERR_NONFATAL, "`incbin': unable to seek on file `%s'",
336 fname);
337 else {
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000338 static char buf[2048];
Keith Kaniosb7a89542007-04-12 02:40:54 +0000339 int32_t t = instruction->times;
340 int32_t base = 0;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000341
H. Peter Anvine2c80182005-01-15 22:15:51 +0000342 len = ftell(fp);
343 if (instruction->eops->next) {
344 base = instruction->eops->next->offset;
345 len -= base;
346 if (instruction->eops->next->next &&
347 len > instruction->eops->next->next->offset)
348 len = instruction->eops->next->next->offset;
349 }
350 /*
351 * Dummy call to list->output to give the offset to the
352 * listing module.
353 */
354 list->output(offset, NULL, OUT_RAWDATA);
355 list->uplevel(LIST_INCBIN);
356 while (t--) {
Keith Kaniosb7a89542007-04-12 02:40:54 +0000357 int32_t l;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000358
H. Peter Anvine2c80182005-01-15 22:15:51 +0000359 fseek(fp, base, SEEK_SET);
360 l = len;
361 while (l > 0) {
Keith Kaniosb7a89542007-04-12 02:40:54 +0000362 int32_t m =
H. Peter Anvine2c80182005-01-15 22:15:51 +0000363 fread(buf, 1, (l > sizeof(buf) ? sizeof(buf) : l),
364 fp);
365 if (!m) {
366 /*
367 * This shouldn't happen unless the file
368 * actually changes while we are reading
369 * it.
370 */
371 error(ERR_NONFATAL,
372 "`incbin': unexpected EOF while"
373 " reading file `%s'", fname);
374 t = 0; /* Try to exit cleanly */
375 break;
376 }
377 out(offset, segment, buf, OUT_RAWDATA + m,
378 NO_SEG, NO_SEG);
379 l -= m;
380 }
381 }
382 list->downlevel(LIST_INCBIN);
383 if (instruction->times > 1) {
384 /*
385 * Dummy call to list->output to give the offset to the
386 * listing module.
387 */
388 list->output(offset, NULL, OUT_RAWDATA);
389 list->uplevel(LIST_TIMES);
390 list->downlevel(LIST_TIMES);
391 }
392 fclose(fp);
393 return instruction->times * len;
394 }
395 return 0; /* if we're here, there's an error */
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000396 }
397
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000398 size_prob = FALSE;
Keith Kaniosb7a89542007-04-12 02:40:54 +0000399
400 for (temp = nasm_instructions[instruction->opcode]; temp->opcode != -1; temp++){
401 int m = matches(temp, instruction, bits);
402
H. Peter Anvine2c80182005-01-15 22:15:51 +0000403 if (m == 99)
404 m += jmp_match(segment, offset, bits, instruction, temp->code);
H. Peter Anvineba20a72002-04-30 20:53:55 +0000405
H. Peter Anvine2c80182005-01-15 22:15:51 +0000406 if (m == 100) { /* matches! */
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000407 const char *codes = temp->code;
Keith Kaniosb7a89542007-04-12 02:40:54 +0000408 int32_t insn_size = calcsize(segment, offset, bits,
H. Peter Anvine2c80182005-01-15 22:15:51 +0000409 instruction, codes);
410 itimes = instruction->times;
411 if (insn_size < 0) /* shouldn't be, on pass two */
412 error(ERR_PANIC, "errors made it through from pass one");
413 else
414 while (itimes--) {
415 for (j = 0; j < instruction->nprefix; j++) {
Keith Kaniosb7a89542007-04-12 02:40:54 +0000416 uint8_t c = 0;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000417 switch (instruction->prefixes[j]) {
418 case P_LOCK:
419 c = 0xF0;
420 break;
421 case P_REPNE:
422 case P_REPNZ:
423 c = 0xF2;
424 break;
425 case P_REPE:
426 case P_REPZ:
427 case P_REP:
428 c = 0xF3;
429 break;
430 case R_CS:
Keith Kaniosfd5d9132007-04-16 15:46:46 +0000431 if (bits == 64) {
432 error(ERR_WARNING,
433 "cs segment base ignored in 64-bit mode");
434 }
H. Peter Anvine2c80182005-01-15 22:15:51 +0000435 c = 0x2E;
436 break;
437 case R_DS:
Keith Kaniosfd5d9132007-04-16 15:46:46 +0000438 if (bits == 64) {
439 error(ERR_WARNING,
440 "ds segment base ignored in 64-bit mode");
441 }
H. Peter Anvine2c80182005-01-15 22:15:51 +0000442 c = 0x3E;
443 break;
444 case R_ES:
Keith Kaniosfd5d9132007-04-16 15:46:46 +0000445 if (bits == 64) {
446 error(ERR_WARNING,
447 "es segment base ignored in 64-bit mode");
448 }
H. Peter Anvine2c80182005-01-15 22:15:51 +0000449 c = 0x26;
450 break;
451 case R_FS:
452 c = 0x64;
453 break;
454 case R_GS:
455 c = 0x65;
456 break;
457 case R_SS:
Keith Kaniosfd5d9132007-04-16 15:46:46 +0000458 if (bits == 64) {
459 error(ERR_WARNING,
460 "ss segment base ignored in 64-bit mode");
461 }
H. Peter Anvine2c80182005-01-15 22:15:51 +0000462 c = 0x36;
463 break;
464 case R_SEGR6:
465 case R_SEGR7:
466 error(ERR_NONFATAL,
467 "segr6 and segr7 cannot be used as prefixes");
468 break;
469 case P_A16:
Keith Kaniosb7a89542007-04-12 02:40:54 +0000470 if (bits == 64) {
H. Peter Anvin0db11e22007-04-17 20:23:11 +0000471 error(ERR_NONFATAL,
472 "16-bit addressing is not supported "
473 "in 64-bit mode");
Keith Kaniosb7a89542007-04-12 02:40:54 +0000474 break;
475 }
H. Peter Anvine2c80182005-01-15 22:15:51 +0000476 if (bits != 16)
477 c = 0x67;
478 break;
479 case P_A32:
480 if (bits != 32)
481 c = 0x67;
482 break;
483 case P_O16:
484 if (bits != 16)
485 c = 0x66;
486 break;
487 case P_O32:
Keith Kaniosb7a89542007-04-12 02:40:54 +0000488 if (bits == 16)
H. Peter Anvine2c80182005-01-15 22:15:51 +0000489 c = 0x66;
490 break;
491 default:
492 error(ERR_PANIC, "invalid instruction prefix");
493 }
494 if (c != 0) {
495 out(offset, segment, &c, OUT_RAWDATA + 1,
496 NO_SEG, NO_SEG);
497 offset++;
498 }
Keith Kaniosb7a89542007-04-12 02:40:54 +0000499 }
H. Peter Anvine2c80182005-01-15 22:15:51 +0000500 insn_end = offset + insn_size;
501 gencode(segment, offset, bits, instruction, codes,
502 insn_end);
503 offset += insn_size;
504 if (itimes > 0 && itimes == instruction->times - 1) {
505 /*
506 * Dummy call to list->output to give the offset to the
507 * listing module.
508 */
509 list->output(offset, NULL, OUT_RAWDATA);
510 list->uplevel(LIST_TIMES);
511 }
512 }
513 if (instruction->times > 1)
514 list->downlevel(LIST_TIMES);
515 return offset - start;
516 } else if (m > 0 && m > size_prob) {
517 size_prob = m;
518 }
Keith Kaniosb7a89542007-04-12 02:40:54 +0000519// temp++;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000520 }
H. Peter Anvineba20a72002-04-30 20:53:55 +0000521
H. Peter Anvine2c80182005-01-15 22:15:51 +0000522 if (temp->opcode == -1) { /* didn't match any instruction */
523 if (size_prob == 1) /* would have matched, but for size */
524 error(ERR_NONFATAL, "operation size not specified");
525 else if (size_prob == 2)
526 error(ERR_NONFATAL, "mismatch in operand sizes");
527 else if (size_prob == 3)
528 error(ERR_NONFATAL, "no instruction for this cpu level");
Keith Kaniosb7a89542007-04-12 02:40:54 +0000529 else if (size_prob == 4)
H. Peter Anvin0db11e22007-04-17 20:23:11 +0000530 error(ERR_NONFATAL, "instruction not supported in 64-bit mode");
531 else if (size_prob == 5)
532 error(ERR_NONFATAL, "invalid operands in non-64-bit mode");
H. Peter Anvine2c80182005-01-15 22:15:51 +0000533 else
534 error(ERR_NONFATAL,
535 "invalid combination of opcode and operands");
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000536 }
537 return 0;
538}
539
Keith Kaniosb7a89542007-04-12 02:40:54 +0000540int32_t insn_size(int32_t segment, int32_t offset, int bits, uint32_t cp,
H. Peter Anvine2c80182005-01-15 22:15:51 +0000541 insn * instruction, efunc error)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000542{
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000543 struct itemplate *temp;
544
H. Peter Anvine2c80182005-01-15 22:15:51 +0000545 errfunc = error; /* to pass to other functions */
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000546 cpu = cp;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000547
548 if (instruction->opcode == -1)
H. Peter Anvine2c80182005-01-15 22:15:51 +0000549 return 0;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000550
551 if (instruction->opcode == I_DB ||
H. Peter Anvine2c80182005-01-15 22:15:51 +0000552 instruction->opcode == I_DW ||
553 instruction->opcode == I_DD ||
554 instruction->opcode == I_DQ || instruction->opcode == I_DT) {
555 extop *e;
Keith Kaniosb7a89542007-04-12 02:40:54 +0000556 int32_t isize, osize, wsize = 0; /* placate gcc */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000557
H. Peter Anvine2c80182005-01-15 22:15:51 +0000558 isize = 0;
559 switch (instruction->opcode) {
560 case I_DB:
561 wsize = 1;
562 break;
563 case I_DW:
564 wsize = 2;
565 break;
566 case I_DD:
567 wsize = 4;
568 break;
569 case I_DQ:
570 wsize = 8;
571 break;
572 case I_DT:
573 wsize = 10;
574 break;
575 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000576
H. Peter Anvine2c80182005-01-15 22:15:51 +0000577 for (e = instruction->eops; e; e = e->next) {
Keith Kaniosb7a89542007-04-12 02:40:54 +0000578 int32_t align;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000579
H. Peter Anvine2c80182005-01-15 22:15:51 +0000580 osize = 0;
581 if (e->type == EOT_DB_NUMBER)
582 osize = 1;
583 else if (e->type == EOT_DB_STRING)
584 osize = e->stringlen;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000585
H. Peter Anvine2c80182005-01-15 22:15:51 +0000586 align = (-osize) % wsize;
587 if (align < 0)
588 align += wsize;
589 isize += osize + align;
590 }
591 return isize * instruction->times;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000592 }
593
H. Peter Anvine2c80182005-01-15 22:15:51 +0000594 if (instruction->opcode == I_INCBIN) {
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000595 char fname[FILENAME_MAX];
H. Peter Anvine2c80182005-01-15 22:15:51 +0000596 FILE *fp;
Keith Kaniosb7a89542007-04-12 02:40:54 +0000597 int32_t len;
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000598 char *prefix = "", *combine;
599 char **pPrevPath = NULL;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000600
H. Peter Anvine2c80182005-01-15 22:15:51 +0000601 len = FILENAME_MAX - 1;
602 if (len > instruction->eops->stringlen)
603 len = instruction->eops->stringlen;
604 strncpy(fname, instruction->eops->stringval, len);
605 fname[len] = '\0';
Frank Kotlerd0ed6fd2003-08-27 11:33:56 +0000606
H. Peter Anvine2c80182005-01-15 22:15:51 +0000607 while (1) { /* added by alexfru: 'incbin' uses include paths */
608 combine = nasm_malloc(strlen(prefix) + len + 1);
609 strcpy(combine, prefix);
610 strcat(combine, fname);
Frank Kotlerd0ed6fd2003-08-27 11:33:56 +0000611
H. Peter Anvine2c80182005-01-15 22:15:51 +0000612 if ((fp = fopen(combine, "rb")) != NULL) {
613 nasm_free(combine);
614 break;
615 }
Frank Kotlerd0ed6fd2003-08-27 11:33:56 +0000616
H. Peter Anvine2c80182005-01-15 22:15:51 +0000617 nasm_free(combine);
618 pPrevPath = pp_get_include_path_ptr(pPrevPath);
619 if (pPrevPath == NULL)
620 break;
621 prefix = *pPrevPath;
Frank Kotlerd0ed6fd2003-08-27 11:33:56 +0000622 }
623
624 if (fp == NULL)
H. Peter Anvine2c80182005-01-15 22:15:51 +0000625 error(ERR_NONFATAL, "`incbin': unable to open file `%s'",
626 fname);
627 else if (fseek(fp, 0L, SEEK_END) < 0)
628 error(ERR_NONFATAL, "`incbin': unable to seek on file `%s'",
629 fname);
630 else {
631 len = ftell(fp);
632 fclose(fp);
633 if (instruction->eops->next) {
634 len -= instruction->eops->next->offset;
635 if (instruction->eops->next->next &&
636 len > instruction->eops->next->next->offset) {
637 len = instruction->eops->next->next->offset;
638 }
639 }
640 return instruction->times * len;
641 }
642 return 0; /* if we're here, there's an error */
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000643 }
644
Keith Kaniosb7a89542007-04-12 02:40:54 +0000645 for (temp = nasm_instructions[instruction->opcode]; temp->opcode != -1; temp++) {
646 int m = matches(temp, instruction, bits);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000647 if (m == 99)
648 m += jmp_match(segment, offset, bits, instruction, temp->code);
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000649
H. Peter Anvine2c80182005-01-15 22:15:51 +0000650 if (m == 100) {
651 /* we've matched an instruction. */
Keith Kaniosb7a89542007-04-12 02:40:54 +0000652 int32_t isize;
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000653 const char *codes = temp->code;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000654 int j;
655
656 isize = calcsize(segment, offset, bits, instruction, codes);
657 if (isize < 0)
658 return -1;
659 for (j = 0; j < instruction->nprefix; j++) {
660 if ((instruction->prefixes[j] != P_A16 &&
661 instruction->prefixes[j] != P_O16 && bits == 16) ||
662 (instruction->prefixes[j] != P_A32 &&
Keith Kaniosfd5d9132007-04-16 15:46:46 +0000663 instruction->prefixes[j] != P_O32 && bits >= 32)) {
H. Peter Anvine2c80182005-01-15 22:15:51 +0000664 isize++;
665 }
666 }
667 return isize * instruction->times;
668 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000669 }
H. Peter Anvine2c80182005-01-15 22:15:51 +0000670 return -1; /* didn't match any instruction */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000671}
672
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000673/* check that opn[op] is a signed byte of size 16 or 32,
674 and return the signed value*/
H. Peter Anvine2c80182005-01-15 22:15:51 +0000675static int is_sbyte(insn * ins, int op, int size)
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000676{
Keith Kaniosb7a89542007-04-12 02:40:54 +0000677 int32_t v;
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000678 int ret;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000679
680 ret = !(ins->forw_ref && ins->oprs[op].opflags) && /* dead in the water on forward reference or External */
681 optimizing >= 0 &&
682 !(ins->oprs[op].type & STRICT) &&
683 ins->oprs[op].wrt == NO_SEG && ins->oprs[op].segment == NO_SEG;
H. Peter Anvin734b1882002-04-30 21:01:08 +0000684
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000685 v = ins->oprs[op].offset;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000686 if (size == 16)
Keith Kaniosb7a89542007-04-12 02:40:54 +0000687 v = (int16_t)v; /* sign extend if 16 bits */
H. Peter Anvine2c80182005-01-15 22:15:51 +0000688
689 return ret && v >= -128L && v <= 127L;
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000690}
691
Keith Kaniosb7a89542007-04-12 02:40:54 +0000692static int32_t calcsize(int32_t segment, int32_t offset, int bits,
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000693 insn * ins, const char *codes)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000694{
Keith Kaniosb7a89542007-04-12 02:40:54 +0000695 int32_t length = 0;
696 uint8_t c;
697 int t;
Keith Kaniosb7a89542007-04-12 02:40:54 +0000698 int rex_mask = 0xFF;
H. Peter Anvin0db11e22007-04-17 20:23:11 +0000699 int lock_is_rex_r = 0;
H. Peter Anvin8d7316a2007-04-18 02:27:18 +0000700 ins->rex = 0; /* Ensure REX is reset */
H. Peter Anvineba20a72002-04-30 20:53:55 +0000701
H. Peter Anvine2c80182005-01-15 22:15:51 +0000702 (void)segment; /* Don't warn that this parameter is unused */
703 (void)offset; /* Don't warn that this parameter is unused */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000704
H. Peter Anvine2c80182005-01-15 22:15:51 +0000705 while (*codes)
706 switch (c = *codes++) {
707 case 01:
708 case 02:
709 case 03:
710 codes += c, length += c;
711 break;
712 case 04:
713 case 05:
714 case 06:
715 case 07:
716 length++;
717 break;
718 case 010:
719 case 011:
720 case 012:
H. Peter Anvin0db11e22007-04-17 20:23:11 +0000721 t = regval(&ins->oprs[c - 010]);
722 if (t >= 0400 && t < 0500) { /* Calculate REX.B */
723 if (t < 0410 || (t >= 0440 && t < 0450))
724 ins->rex |= 0xF0; /* Set REX.0 */
725 else
726 ins->rex |= 0xF1; /* Set REX.B */
727 if (t >= 0440)
728 ins->rex |= 0xF8; /* Set REX.W */
729 }
H. Peter Anvine2c80182005-01-15 22:15:51 +0000730 codes++, length++;
731 break;
732 case 017:
733 length++;
734 break;
735 case 014:
736 case 015:
737 case 016:
738 length++;
739 break;
740 case 020:
741 case 021:
742 case 022:
743 length++;
744 break;
745 case 024:
746 case 025:
747 case 026:
748 length++;
749 break;
750 case 030:
751 case 031:
752 case 032:
753 length += 2;
754 break;
755 case 034:
756 case 035:
757 case 036:
Keith Kaniosb7a89542007-04-12 02:40:54 +0000758 if (ins->oprs[c - 034].type & (BITS16 | BITS32 | BITS64))
H. Peter Anvine2c80182005-01-15 22:15:51 +0000759 length += (ins->oprs[c - 034].type & BITS16) ? 2 : 4;
760 else
761 length += (bits == 16) ? 2 : 4;
762 break;
763 case 037:
764 length += 2;
765 break;
766 case 040:
767 case 041:
768 case 042:
769 length += 4;
770 break;
771 case 044:
772 case 045:
773 case 046:
774 length += ((ins->oprs[c - 044].addr_size ?
Keith Kaniosb7a89542007-04-12 02:40:54 +0000775 ins->oprs[c - 044].addr_size : bits) >> 3);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000776 break;
777 case 050:
778 case 051:
779 case 052:
780 length++;
781 break;
Keith Kaniosb7a89542007-04-12 02:40:54 +0000782 case 054:
783 case 055:
784 case 056:
785 length += 8; /* MOV reg64/imm */
786 break;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000787 case 060:
788 case 061:
789 case 062:
790 length += 2;
791 break;
792 case 064:
793 case 065:
794 case 066:
Keith Kaniosb7a89542007-04-12 02:40:54 +0000795 if (ins->oprs[c - 064].type & (BITS16 | BITS32 | BITS64))
H. Peter Anvine2c80182005-01-15 22:15:51 +0000796 length += (ins->oprs[c - 064].type & BITS16) ? 2 : 4;
797 else
798 length += (bits == 16) ? 2 : 4;
799 break;
800 case 070:
801 case 071:
802 case 072:
803 length += 4;
804 break;
805 case 0130:
806 case 0131:
807 case 0132:
808 length += is_sbyte(ins, c - 0130, 16) ? 1 : 2;
809 break;
810 case 0133:
811 case 0134:
812 case 0135:
813 codes += 2;
814 length++;
815 break;
816 case 0140:
817 case 0141:
818 case 0142:
819 length += is_sbyte(ins, c - 0140, 32) ? 1 : 4;
820 break;
821 case 0143:
822 case 0144:
823 case 0145:
824 codes += 2;
825 length++;
826 break;
827 case 0300:
828 case 0301:
Keith Kaniosb7a89542007-04-12 02:40:54 +0000829 case 0302:
H. Peter Anvin0db11e22007-04-17 20:23:11 +0000830 /* Calculate REX */
831 t = ins->oprs[c - 0300].basereg;
832 if (t >= EXPR_REG_START && t < REG_ENUM_LIMIT) {
833 t = regvals[t];
834 if ((t >= 0410 && t < 0440) || (t >= 0450 && t < 0500)) {
835 ins->rex |= 0xF1; /* Set REX.B */
836 }
837 }
H. Peter Anvine2c80182005-01-15 22:15:51 +0000838 length += chsize(&ins->oprs[c - 0300], bits);
839 break;
840 case 0310:
Keith Kaniosb7a89542007-04-12 02:40:54 +0000841 length += (bits != 16);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000842 break;
843 case 0311:
Keith Kaniosb7a89542007-04-12 02:40:54 +0000844 length += (bits != 32);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000845 break;
846 case 0312:
Keith Kaniosb7a89542007-04-12 02:40:54 +0000847 break;
848 case 0313:
849 length -= 1;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000850 break;
851 case 0320:
Keith Kaniosb7a89542007-04-12 02:40:54 +0000852 length += (bits != 16);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000853 break;
854 case 0321:
855 length += (bits == 16);
856 break;
857 case 0322:
858 break;
Keith Kaniosb7a89542007-04-12 02:40:54 +0000859 case 0323:
860 rex_mask = 0x07;
861 break;
862 case 0324:
H. Peter Anvin8d7316a2007-04-18 02:27:18 +0000863 ins->rex |= 0xF8;
864 break;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000865 case 0330:
866 codes++, length++;
867 break;
868 case 0331:
869 case 0332:
870 break;
871 case 0333:
872 length++;
873 break;
H. Peter Anvin0db11e22007-04-17 20:23:11 +0000874 case 0334:
875 assert_no_prefix(ins, P_LOCK);
876 lock_is_rex_r = 1;
877 break;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000878 case 0340:
879 case 0341:
880 case 0342:
881 if (ins->oprs[0].segment != NO_SEG)
882 errfunc(ERR_NONFATAL, "attempt to reserve non-constant"
883 " quantity of BSS space");
884 else
885 length += ins->oprs[0].offset << (c - 0340);
886 break;
887 case 0370:
888 case 0371:
889 case 0372:
890 break;
891 case 0373:
892 length++;
893 break;
894 default: /* can't do it by 'case' statements */
895 if (c >= 0100 && c <= 0277) { /* it's an EA */
896 ea ea_data;
Keith Kaniosb7a89542007-04-12 02:40:54 +0000897 int rfield;
898 ea_data.rex = 0; /* Ensure ea.REX is initially 0 */
899
H. Peter Anvin0db11e22007-04-17 20:23:11 +0000900 if (c <= 0177) /* pick rfield from operand b */
901 rfield = regval(&ins->oprs[c & 7]);
902 else
903 rfield = c & 7;
Keith Kaniosb7a89542007-04-12 02:40:54 +0000904
H. Peter Anvine2c80182005-01-15 22:15:51 +0000905 if (!process_ea
Keith Kaniosb7a89542007-04-12 02:40:54 +0000906 (&ins->oprs[(c >> 3) & 7], &ea_data, bits,
907 rfield, ins->forw_ref)) {
H. Peter Anvine2c80182005-01-15 22:15:51 +0000908 errfunc(ERR_NONFATAL, "invalid effective address");
909 return -1;
Keith Kaniosb7a89542007-04-12 02:40:54 +0000910 } else {
H. Peter Anvin0db11e22007-04-17 20:23:11 +0000911 ins->rex |= ea_data.rex;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000912 length += ea_data.size;
Keith Kaniosb7a89542007-04-12 02:40:54 +0000913 }
H. Peter Anvine2c80182005-01-15 22:15:51 +0000914 } else
915 errfunc(ERR_PANIC, "internal instruction table corrupt"
916 ": instruction code 0x%02X given", c);
917 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000918
H. Peter Anvin0db11e22007-04-17 20:23:11 +0000919 ins->rex &= rex_mask;
920 if (ins->rex) {
921 if (bits == 64 ||
H. Peter Anvin8d7316a2007-04-18 02:27:18 +0000922 (lock_is_rex_r && ins->rex == 0xf4 && cpu >= IF_X86_64)) {
H. Peter Anvin0db11e22007-04-17 20:23:11 +0000923 length++;
H. Peter Anvin8d7316a2007-04-18 02:27:18 +0000924 } else {
925 errfunc(ERR_NONFATAL, "invalid operands in non-64-bit mode");
926 return -1;
927 }
Keith Kaniosb7a89542007-04-12 02:40:54 +0000928 }
929
H. Peter Anvin0db11e22007-04-17 20:23:11 +0000930 return length;
931}
Keith Kaniosb7a89542007-04-12 02:40:54 +0000932
933static void gencode(int32_t segment, int32_t offset, int bits,
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000934 insn * ins, const char *codes, int32_t insn_end)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000935{
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000936 static char condval[] = { /* conditional opcodes */
H. Peter Anvine2c80182005-01-15 22:15:51 +0000937 0x7, 0x3, 0x2, 0x6, 0x2, 0x4, 0xF, 0xD, 0xC, 0xE, 0x6, 0x2,
938 0x3, 0x7, 0x3, 0x5, 0xE, 0xC, 0xD, 0xF, 0x1, 0xB, 0x9, 0x5,
939 0x0, 0xA, 0xA, 0xB, 0x8, 0x4
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000940 };
Keith Kaniosb7a89542007-04-12 02:40:54 +0000941 uint8_t c;
942 uint8_t bytes[4];
943 int32_t size;
944 int64_t data;
945
H. Peter Anvineba20a72002-04-30 20:53:55 +0000946 while (*codes)
H. Peter Anvine2c80182005-01-15 22:15:51 +0000947 switch (c = *codes++) {
948 case 01:
949 case 02:
950 case 03:
Keith Kaniosb7a89542007-04-12 02:40:54 +0000951 if(ins->rex && (bits == 64)) { /* REX Supercedes all other Prefixes */
952 ins->rex = (ins->rex&0x0F)+0x40;
953 out(offset, segment, &ins->rex, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
954 ins->rex = 0;
955 offset += 1;
956 }
H. Peter Anvine2c80182005-01-15 22:15:51 +0000957 out(offset, segment, codes, OUT_RAWDATA + c, NO_SEG, NO_SEG);
958 codes += c;
959 offset += c;
960 break;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000961
H. Peter Anvine2c80182005-01-15 22:15:51 +0000962 case 04:
963 case 06:
964 switch (ins->oprs[0].basereg) {
965 case R_CS:
966 bytes[0] = 0x0E + (c == 0x04 ? 1 : 0);
967 break;
968 case R_DS:
969 bytes[0] = 0x1E + (c == 0x04 ? 1 : 0);
970 break;
971 case R_ES:
972 bytes[0] = 0x06 + (c == 0x04 ? 1 : 0);
973 break;
974 case R_SS:
975 bytes[0] = 0x16 + (c == 0x04 ? 1 : 0);
976 break;
977 default:
978 errfunc(ERR_PANIC,
979 "bizarre 8086 segment register received");
980 }
981 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
982 offset++;
983 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000984
H. Peter Anvine2c80182005-01-15 22:15:51 +0000985 case 05:
986 case 07:
987 switch (ins->oprs[0].basereg) {
988 case R_FS:
989 bytes[0] = 0xA0 + (c == 0x05 ? 1 : 0);
990 break;
991 case R_GS:
992 bytes[0] = 0xA8 + (c == 0x05 ? 1 : 0);
993 break;
994 default:
995 errfunc(ERR_PANIC,
996 "bizarre 386 segment register received");
997 }
998 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
999 offset++;
1000 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001001
H. Peter Anvine2c80182005-01-15 22:15:51 +00001002 case 010:
1003 case 011:
1004 case 012:
Keith Kaniosb7a89542007-04-12 02:40:54 +00001005 if(ins->rex && (bits == 64)) { /* REX Supercedes all other Prefixes */
1006 ins->rex = (ins->rex&0x0F)+0x40;
1007 out(offset, segment, &ins->rex, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1008 ins->rex = 0;
1009 offset += 1;
1010 }
1011 bytes[0] = *codes++ + ((regval(&ins->oprs[c - 010])) & 7);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001012 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1013 offset += 1;
1014 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001015
H. Peter Anvine2c80182005-01-15 22:15:51 +00001016 case 017:
1017 bytes[0] = 0;
1018 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1019 offset += 1;
1020 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001021
H. Peter Anvine2c80182005-01-15 22:15:51 +00001022 case 014:
1023 case 015:
1024 case 016:
1025 if (ins->oprs[c - 014].offset < -128
1026 || ins->oprs[c - 014].offset > 127) {
1027 errfunc(ERR_WARNING, "signed byte value exceeds bounds");
1028 }
H. Peter Anvineba20a72002-04-30 20:53:55 +00001029
H. Peter Anvine2c80182005-01-15 22:15:51 +00001030 if (ins->oprs[c - 014].segment != NO_SEG) {
1031 data = ins->oprs[c - 014].offset;
1032 out(offset, segment, &data, OUT_ADDRESS + 1,
1033 ins->oprs[c - 014].segment, ins->oprs[c - 014].wrt);
1034 } else {
1035 bytes[0] = ins->oprs[c - 014].offset;
1036 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG,
1037 NO_SEG);
1038 }
1039 offset += 1;
1040 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001041
H. Peter Anvine2c80182005-01-15 22:15:51 +00001042 case 020:
1043 case 021:
1044 case 022:
1045 if (ins->oprs[c - 020].offset < -256
1046 || ins->oprs[c - 020].offset > 255) {
1047 errfunc(ERR_WARNING, "byte value exceeds bounds");
1048 }
1049 if (ins->oprs[c - 020].segment != NO_SEG) {
1050 data = ins->oprs[c - 020].offset;
1051 out(offset, segment, &data, OUT_ADDRESS + 1,
1052 ins->oprs[c - 020].segment, ins->oprs[c - 020].wrt);
1053 } else {
1054 bytes[0] = ins->oprs[c - 020].offset;
1055 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG,
1056 NO_SEG);
1057 }
1058 offset += 1;
1059 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001060
H. Peter Anvine2c80182005-01-15 22:15:51 +00001061 case 024:
1062 case 025:
1063 case 026:
1064 if (ins->oprs[c - 024].offset < 0
1065 || ins->oprs[c - 024].offset > 255)
1066 errfunc(ERR_WARNING, "unsigned byte value exceeds bounds");
1067 if (ins->oprs[c - 024].segment != NO_SEG) {
1068 data = ins->oprs[c - 024].offset;
1069 out(offset, segment, &data, OUT_ADDRESS + 1,
1070 ins->oprs[c - 024].segment, ins->oprs[c - 024].wrt);
1071 } else {
1072 bytes[0] = ins->oprs[c - 024].offset;
1073 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG,
1074 NO_SEG);
1075 }
1076 offset += 1;
1077 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001078
H. Peter Anvine2c80182005-01-15 22:15:51 +00001079 case 030:
1080 case 031:
1081 case 032:
1082 if (ins->oprs[c - 030].segment == NO_SEG &&
1083 ins->oprs[c - 030].wrt == NO_SEG &&
1084 (ins->oprs[c - 030].offset < -65536L ||
1085 ins->oprs[c - 030].offset > 65535L)) {
1086 errfunc(ERR_WARNING, "word value exceeds bounds");
1087 }
1088 data = ins->oprs[c - 030].offset;
1089 out(offset, segment, &data, OUT_ADDRESS + 2,
1090 ins->oprs[c - 030].segment, ins->oprs[c - 030].wrt);
1091 offset += 2;
1092 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001093
H. Peter Anvine2c80182005-01-15 22:15:51 +00001094 case 034:
1095 case 035:
1096 case 036:
1097 if (ins->oprs[c - 034].type & (BITS16 | BITS32))
1098 size = (ins->oprs[c - 034].type & BITS16) ? 2 : 4;
1099 else
1100 size = (bits == 16) ? 2 : 4;
1101 data = ins->oprs[c - 034].offset;
1102 if (size == 2 && (data < -65536L || data > 65535L))
1103 errfunc(ERR_WARNING, "word value exceeds bounds");
1104 out(offset, segment, &data, OUT_ADDRESS + size,
1105 ins->oprs[c - 034].segment, ins->oprs[c - 034].wrt);
1106 offset += size;
1107 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001108
H. Peter Anvine2c80182005-01-15 22:15:51 +00001109 case 037:
1110 if (ins->oprs[0].segment == NO_SEG)
1111 errfunc(ERR_NONFATAL, "value referenced by FAR is not"
1112 " relocatable");
1113 data = 0L;
1114 out(offset, segment, &data, OUT_ADDRESS + 2,
1115 outfmt->segbase(1 + ins->oprs[0].segment),
1116 ins->oprs[0].wrt);
1117 offset += 2;
1118 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001119
H. Peter Anvine2c80182005-01-15 22:15:51 +00001120 case 040:
1121 case 041:
1122 case 042:
1123 data = ins->oprs[c - 040].offset;
1124 out(offset, segment, &data, OUT_ADDRESS + 4,
1125 ins->oprs[c - 040].segment, ins->oprs[c - 040].wrt);
1126 offset += 4;
1127 break;
H. Peter Anvin3ba46772002-05-27 23:19:35 +00001128
H. Peter Anvine2c80182005-01-15 22:15:51 +00001129 case 044:
1130 case 045:
1131 case 046:
1132 data = ins->oprs[c - 044].offset;
1133 size = ((ins->oprs[c - 044].addr_size ?
Keith Kaniosb7a89542007-04-12 02:40:54 +00001134 ins->oprs[c - 044].addr_size : bits) >> 3);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001135 if (size == 2 && (data < -65536L || data > 65535L))
1136 errfunc(ERR_WARNING, "word value exceeds bounds");
1137 out(offset, segment, &data, OUT_ADDRESS + size,
1138 ins->oprs[c - 044].segment, ins->oprs[c - 044].wrt);
1139 offset += size;
1140 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001141
H. Peter Anvine2c80182005-01-15 22:15:51 +00001142 case 050:
1143 case 051:
1144 case 052:
1145 if (ins->oprs[c - 050].segment != segment)
1146 errfunc(ERR_NONFATAL,
1147 "short relative jump outside segment");
1148 data = ins->oprs[c - 050].offset - insn_end;
1149 if (data > 127 || data < -128)
1150 errfunc(ERR_NONFATAL, "short jump is out of range");
1151 bytes[0] = data;
1152 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1153 offset += 1;
1154 break;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001155
1156 case 054:
1157 case 055:
1158 case 056:
1159 data = (int64_t)ins->oprs[c - 054].offset;
1160 out(offset, segment, &data, OUT_ADDRESS + 8,
1161 ins->oprs[c - 054].segment, ins->oprs[c - 054].wrt);
1162 offset += 8;
1163 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001164
H. Peter Anvine2c80182005-01-15 22:15:51 +00001165 case 060:
1166 case 061:
1167 case 062:
1168 if (ins->oprs[c - 060].segment != segment) {
1169 data = ins->oprs[c - 060].offset;
1170 out(offset, segment, &data,
1171 OUT_REL2ADR + insn_end - offset,
1172 ins->oprs[c - 060].segment, ins->oprs[c - 060].wrt);
1173 } else {
1174 data = ins->oprs[c - 060].offset - insn_end;
1175 out(offset, segment, &data,
1176 OUT_ADDRESS + 2, NO_SEG, NO_SEG);
1177 }
1178 offset += 2;
1179 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001180
H. Peter Anvine2c80182005-01-15 22:15:51 +00001181 case 064:
1182 case 065:
1183 case 066:
Keith Kaniosb7a89542007-04-12 02:40:54 +00001184 if (ins->oprs[c - 064].type & (BITS16 | BITS32 | BITS64))
H. Peter Anvine2c80182005-01-15 22:15:51 +00001185 size = (ins->oprs[c - 064].type & BITS16) ? 2 : 4;
1186 else
1187 size = (bits == 16) ? 2 : 4;
1188 if (ins->oprs[c - 064].segment != segment) {
Keith Kaniosb7a89542007-04-12 02:40:54 +00001189 int32_t reltype = (size == 2 ? OUT_REL2ADR : OUT_REL4ADR);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001190 data = ins->oprs[c - 064].offset;
1191 out(offset, segment, &data, reltype + insn_end - offset,
1192 ins->oprs[c - 064].segment, ins->oprs[c - 064].wrt);
1193 } else {
1194 data = ins->oprs[c - 064].offset - insn_end;
1195 out(offset, segment, &data,
1196 OUT_ADDRESS + size, NO_SEG, NO_SEG);
1197 }
1198 offset += size;
1199 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001200
H. Peter Anvine2c80182005-01-15 22:15:51 +00001201 case 070:
1202 case 071:
1203 case 072:
1204 if (ins->oprs[c - 070].segment != segment) {
1205 data = ins->oprs[c - 070].offset;
1206 out(offset, segment, &data,
1207 OUT_REL4ADR + insn_end - offset,
1208 ins->oprs[c - 070].segment, ins->oprs[c - 070].wrt);
1209 } else {
1210 data = ins->oprs[c - 070].offset - insn_end;
1211 out(offset, segment, &data,
1212 OUT_ADDRESS + 4, NO_SEG, NO_SEG);
1213 }
1214 offset += 4;
1215 break;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001216
H. Peter Anvine2c80182005-01-15 22:15:51 +00001217 case 0130:
1218 case 0131:
1219 case 0132:
1220 data = ins->oprs[c - 0130].offset;
1221 if (is_sbyte(ins, c - 0130, 16)) {
1222 bytes[0] = data;
1223 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG,
1224 NO_SEG);
1225 offset++;
1226 } else {
1227 if (ins->oprs[c - 0130].segment == NO_SEG &&
1228 ins->oprs[c - 0130].wrt == NO_SEG &&
1229 (data < -65536L || data > 65535L)) {
1230 errfunc(ERR_WARNING, "word value exceeds bounds");
1231 }
1232 out(offset, segment, &data, OUT_ADDRESS + 2,
1233 ins->oprs[c - 0130].segment, ins->oprs[c - 0130].wrt);
1234 offset += 2;
1235 }
1236 break;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001237
H. Peter Anvine2c80182005-01-15 22:15:51 +00001238 case 0133:
1239 case 0134:
1240 case 0135:
Keith Kaniosb7a89542007-04-12 02:40:54 +00001241 if(ins->rex && (bits == 64)) { /* REX Supercedes all other Prefixes */
1242 ins->rex = (ins->rex&0x0F)+0x40;
1243 out(offset, segment, &ins->rex, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1244 ins->rex = 0;
1245 offset += 1;
1246 }
H. Peter Anvine2c80182005-01-15 22:15:51 +00001247 codes++;
1248 bytes[0] = *codes++;
1249 if (is_sbyte(ins, c - 0133, 16))
1250 bytes[0] |= 2; /* s-bit */
1251 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1252 offset++;
1253 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001254
H. Peter Anvine2c80182005-01-15 22:15:51 +00001255 case 0140:
1256 case 0141:
1257 case 0142:
1258 data = ins->oprs[c - 0140].offset;
1259 if (is_sbyte(ins, c - 0140, 32)) {
1260 bytes[0] = data;
1261 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG,
1262 NO_SEG);
1263 offset++;
1264 } else {
1265 out(offset, segment, &data, OUT_ADDRESS + 4,
1266 ins->oprs[c - 0140].segment, ins->oprs[c - 0140].wrt);
1267 offset += 4;
1268 }
1269 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001270
H. Peter Anvine2c80182005-01-15 22:15:51 +00001271 case 0143:
1272 case 0144:
1273 case 0145:
Keith Kaniosb7a89542007-04-12 02:40:54 +00001274 if(ins->rex && (bits == 64)) { /* REX Supercedes all other Prefixes */
1275 ins->rex = (ins->rex&0x0F)+0x40;
1276 out(offset, segment, &ins->rex, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1277 ins->rex = 0;
1278 offset += 1;
1279 }
H. Peter Anvine2c80182005-01-15 22:15:51 +00001280 codes++;
1281 bytes[0] = *codes++;
1282 if (is_sbyte(ins, c - 0143, 32))
1283 bytes[0] |= 2; /* s-bit */
1284 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1285 offset++;
1286 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001287
H. Peter Anvine2c80182005-01-15 22:15:51 +00001288 case 0300:
1289 case 0301:
1290 case 0302:
1291 if (chsize(&ins->oprs[c - 0300], bits)) {
1292 *bytes = 0x67;
1293 out(offset, segment, bytes,
1294 OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1295 offset += 1;
1296 } else
1297 offset += 0;
1298 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001299
H. Peter Anvine2c80182005-01-15 22:15:51 +00001300 case 0310:
Keith Kaniosb7a89542007-04-12 02:40:54 +00001301 if (bits != 16) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001302 *bytes = 0x67;
1303 out(offset, segment, bytes,
1304 OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1305 offset += 1;
1306 } else
1307 offset += 0;
1308 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001309
H. Peter Anvine2c80182005-01-15 22:15:51 +00001310 case 0311:
Keith Kaniosb7a89542007-04-12 02:40:54 +00001311 if (bits != 32) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001312 *bytes = 0x67;
1313 out(offset, segment, bytes,
1314 OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1315 offset += 1;
1316 } else
1317 offset += 0;
1318 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001319
H. Peter Anvine2c80182005-01-15 22:15:51 +00001320 case 0312:
1321 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001322
Keith Kaniosb7a89542007-04-12 02:40:54 +00001323 case 0313:
1324 ins->rex = 0;
1325 break;
1326
H. Peter Anvine2c80182005-01-15 22:15:51 +00001327 case 0320:
Keith Kaniosb7a89542007-04-12 02:40:54 +00001328 if (bits != 16) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001329 *bytes = 0x66;
1330 out(offset, segment, bytes,
1331 OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1332 offset += 1;
1333 } else
1334 offset += 0;
1335 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001336
H. Peter Anvine2c80182005-01-15 22:15:51 +00001337 case 0321:
1338 if (bits == 16) {
1339 *bytes = 0x66;
1340 out(offset, segment, bytes,
1341 OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1342 offset += 1;
1343 } else
1344 offset += 0;
1345 break;
H. Peter Anvinef7468f2002-04-30 20:57:59 +00001346
H. Peter Anvine2c80182005-01-15 22:15:51 +00001347 case 0322:
Keith Kaniosb7a89542007-04-12 02:40:54 +00001348 case 0323:
1349 break;
1350
1351 case 0324:
1352 ins->rex |= 0xF8;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001353 break;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001354
H. Peter Anvine2c80182005-01-15 22:15:51 +00001355 case 0330:
1356 *bytes = *codes++ ^ condval[ins->condition];
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 case 0331:
1362 case 0332:
1363 break;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001364
H. Peter Anvine2c80182005-01-15 22:15:51 +00001365 case 0333:
1366 *bytes = 0xF3;
1367 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1368 offset += 1;
1369 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001370
H. Peter Anvin0db11e22007-04-17 20:23:11 +00001371 case 0334:
1372 if (ins->rex & 0x04) {
1373 *bytes = 0xF0;
1374 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1375 offset += 1;
1376 }
1377 break;
1378
H. Peter Anvine2c80182005-01-15 22:15:51 +00001379 case 0340:
1380 case 0341:
1381 case 0342:
1382 if (ins->oprs[0].segment != NO_SEG)
1383 errfunc(ERR_PANIC, "non-constant BSS size in pass two");
1384 else {
Keith Kaniosb7a89542007-04-12 02:40:54 +00001385 int32_t size = ins->oprs[0].offset << (c - 0340);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001386 if (size > 0)
1387 out(offset, segment, NULL,
1388 OUT_RESERVE + size, NO_SEG, NO_SEG);
1389 offset += size;
1390 }
1391 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001392
H. Peter Anvine2c80182005-01-15 22:15:51 +00001393 case 0370:
1394 case 0371:
1395 case 0372:
1396 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001397
H. Peter Anvine2c80182005-01-15 22:15:51 +00001398 case 0373:
1399 *bytes = bits == 16 ? 3 : 5;
1400 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1401 offset += 1;
1402 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001403
H. Peter Anvine2c80182005-01-15 22:15:51 +00001404 default: /* can't do it by 'case' statements */
Keith Kaniosb7a89542007-04-12 02:40:54 +00001405 if ( c >= 0100 && c <= 0277) { /* it's an EA */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001406 ea ea_data;
1407 int rfield;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001408 uint8_t *p;
1409 int32_t s;
1410
H. Peter Anvine2c80182005-01-15 22:15:51 +00001411 if (c <= 0177) /* pick rfield from operand b */
1412 rfield = regval(&ins->oprs[c & 7]);
1413 else /* rfield is constant */
1414 rfield = c & 7;
1415
1416 if (!process_ea
1417 (&ins->oprs[(c >> 3) & 7], &ea_data, bits, rfield,
1418 ins->forw_ref)) {
1419 errfunc(ERR_NONFATAL, "invalid effective address");
1420 }
Keith Kaniosb7a89542007-04-12 02:40:54 +00001421
H. Peter Anvine2c80182005-01-15 22:15:51 +00001422 p = bytes;
1423 *p++ = ea_data.modrm;
1424 if (ea_data.sib_present)
1425 *p++ = ea_data.sib;
1426
1427 s = p - bytes;
1428 out(offset, segment, bytes, OUT_RAWDATA + s,
1429 NO_SEG, NO_SEG);
1430
1431 switch (ea_data.bytes) {
1432 case 0:
1433 break;
1434 case 1:
1435 if (ins->oprs[(c >> 3) & 7].segment != NO_SEG) {
1436 data = ins->oprs[(c >> 3) & 7].offset;
1437 out(offset, segment, &data, OUT_ADDRESS + 1,
1438 ins->oprs[(c >> 3) & 7].segment,
1439 ins->oprs[(c >> 3) & 7].wrt);
1440 } else {
1441 *bytes = ins->oprs[(c >> 3) & 7].offset;
1442 out(offset, segment, bytes, OUT_RAWDATA + 1,
1443 NO_SEG, NO_SEG);
1444 }
1445 s++;
1446 break;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001447 case 8:
H. Peter Anvine2c80182005-01-15 22:15:51 +00001448 case 2:
1449 case 4:
1450 data = ins->oprs[(c >> 3) & 7].offset;
Keith Kaniose83b3182007-04-16 14:31:54 +00001451 if (ea_data.rip && (ins->oprs[(c >> 3) & 7].segment == 0xFFFFFFFF))
1452 ea_data.rip = 0; /* Make distinction between Symbols and Immediates */
Keith Kaniosb7a89542007-04-12 02:40:54 +00001453 out(offset, segment, &data, /* RIP = Relative, not Absolute */
1454 (ea_data.rip ? OUT_REL4ADR : OUT_ADDRESS) + ea_data.bytes,
H. Peter Anvine2c80182005-01-15 22:15:51 +00001455 ins->oprs[(c >> 3) & 7].segment,
1456 ins->oprs[(c >> 3) & 7].wrt);
1457 s += ea_data.bytes;
1458 break;
1459 }
1460 offset += s;
1461 } else
1462 errfunc(ERR_PANIC, "internal instruction table corrupt"
1463 ": instruction code 0x%02X given", c);
1464 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001465}
1466
H. Peter Anvine2c80182005-01-15 22:15:51 +00001467static int regval(operand * o)
H. Peter Anvineba20a72002-04-30 20:53:55 +00001468{
H. Peter Anvine2c80182005-01-15 22:15:51 +00001469 if (o->basereg < EXPR_REG_START || o->basereg >= REG_ENUM_LIMIT) {
1470 errfunc(ERR_PANIC, "invalid operand passed to regval()");
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001471 }
H. Peter Anvin232badb2002-06-06 02:41:20 +00001472 return regvals[o->basereg];
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001473}
1474
Keith Kaniosb7a89542007-04-12 02:40:54 +00001475static int matches(struct itemplate *itemp, insn * instruction, int bits)
H. Peter Anvineba20a72002-04-30 20:53:55 +00001476{
Keith Kaniosb7a89542007-04-12 02:40:54 +00001477 int i, b, x, size[3], asize, oprs, ret;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001478
1479 ret = 100;
1480
1481 /*
1482 * Check the opcode
1483 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001484 if (itemp->opcode != instruction->opcode)
1485 return 0;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001486
1487 /*
1488 * Count the operands
1489 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001490 if (itemp->operands != instruction->operands)
1491 return 0;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001492
1493 /*
1494 * Check that no spurious colons or TOs are present
1495 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001496 for (i = 0; i < itemp->operands; i++)
1497 if (instruction->oprs[i].type & ~itemp->opd[i] & (COLON | TO))
1498 return 0;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001499
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001500 /*
1501 * Check that the operand flags all match up
1502 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001503 for (i = 0; i < itemp->operands; i++)
1504 if (itemp->opd[i] & ~instruction->oprs[i].type ||
1505 ((itemp->opd[i] & SIZE_MASK) &&
1506 ((itemp->opd[i] ^ instruction->oprs[i].type) & SIZE_MASK))) {
H. Peter Anvin5a640e12007-05-29 23:57:12 +00001507 if ((itemp->opd[i] & ~instruction->oprs[i].type & ~SIZE_MASK) ||
H. Peter Anvine2c80182005-01-15 22:15:51 +00001508 (instruction->oprs[i].type & SIZE_MASK))
1509 return 0;
1510 else
H. Peter Anvine2c80182005-01-15 22:15:51 +00001511 return 1;
1512 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001513
1514 /*
1515 * Check operand sizes
1516 */
H. Peter Anvinef7468f2002-04-30 20:57:59 +00001517 if (itemp->flags & IF_ARMASK) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001518 size[0] = size[1] = size[2] = 0;
H. Peter Anvinef7468f2002-04-30 20:57:59 +00001519
H. Peter Anvine2c80182005-01-15 22:15:51 +00001520 switch (itemp->flags & IF_ARMASK) {
1521 case IF_AR0:
1522 i = 0;
1523 break;
1524 case IF_AR1:
1525 i = 1;
1526 break;
1527 case IF_AR2:
1528 i = 2;
1529 break;
1530 default:
1531 break; /* Shouldn't happen */
1532 }
1533 if (itemp->flags & IF_SB) {
1534 size[i] = BITS8;
1535 } else if (itemp->flags & IF_SW) {
1536 size[i] = BITS16;
1537 } else if (itemp->flags & IF_SD) {
1538 size[i] = BITS32;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001539 } else if (itemp->flags & IF_SQ) {
1540 if (bits != 64)
H. Peter Anvin0db11e22007-04-17 20:23:11 +00001541 return 5;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001542 size[i] = BITS64;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001543 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001544 } else {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001545 asize = 0;
1546 if (itemp->flags & IF_SB) {
1547 asize = BITS8;
1548 oprs = itemp->operands;
1549 } else if (itemp->flags & IF_SW) {
1550 asize = BITS16;
1551 oprs = itemp->operands;
1552 } else if (itemp->flags & IF_SD) {
1553 asize = BITS32;
1554 oprs = itemp->operands;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001555 } else if (itemp->flags & IF_SQ) {
1556 if (bits != 64)
H. Peter Anvin0db11e22007-04-17 20:23:11 +00001557 return 5;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001558 asize = BITS64;
1559 oprs = itemp->operands;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001560 }
1561 size[0] = size[1] = size[2] = asize;
H. Peter Anvinef7468f2002-04-30 20:57:59 +00001562 }
Keith Kaniosb7a89542007-04-12 02:40:54 +00001563
H. Peter Anvinef7468f2002-04-30 20:57:59 +00001564 if (itemp->flags & (IF_SM | IF_SM2)) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001565 oprs = (itemp->flags & IF_SM2 ? 2 : itemp->operands);
1566 asize = 0;
1567 for (i = 0; i < oprs; i++) {
1568 if ((asize = itemp->opd[i] & SIZE_MASK) != 0) {
1569 int j;
1570 for (j = 0; j < oprs; j++)
1571 size[j] = asize;
1572 break;
1573 }
1574 }
H. Peter Anvinef7468f2002-04-30 20:57:59 +00001575 } else {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001576 oprs = itemp->operands;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001577 }
1578
Keith Kaniosb7a89542007-04-12 02:40:54 +00001579 for (i = 0; i < itemp->operands; i++) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001580 if (!(itemp->opd[i] & SIZE_MASK) &&
1581 (instruction->oprs[i].type & SIZE_MASK & ~size[i]))
H. Peter Anvine2c80182005-01-15 22:15:51 +00001582 return 2;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001583
Keith Kaniosb7a89542007-04-12 02:40:54 +00001584 if ( (((itemp->opd[i] & SIZE_MASK) == BITS64) ||
1585 ((instruction->oprs[i].type & SIZE_MASK) == BITS64))
1586 && bits != 64)
H. Peter Anvin0db11e22007-04-17 20:23:11 +00001587 return 5;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001588
1589 x = instruction->oprs[i].indexreg;
1590 b = instruction->oprs[i].basereg;
1591
1592 if (x != -1 && x >= EXPR_REG_START && x < REG_ENUM_LIMIT)
1593 x = regvals[x];
1594 if (b != -1 && b >= EXPR_REG_START && b < REG_ENUM_LIMIT)
1595 b = regvals[b];
1596
1597 if (((b >= 0400 && b <= 0500) || (x >= 0400 && x < 0500)) && bits != 64)
1598 return 2;
1599 }
1600
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001601 /*
1602 * Check template is okay at the set cpu level
1603 */
Keith Kaniosb7a89542007-04-12 02:40:54 +00001604 if (((itemp->flags & IF_PLEVEL) > cpu))
H. Peter Anvine2c80182005-01-15 22:15:51 +00001605 return 3;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001606
1607 /*
1608 * Check if instruction is available in long mode
1609 */
1610 if ((itemp->flags & IF_NOLONG) && (bits == 64))
1611 return 4;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001612
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001613 /*
1614 * Check if special handling needed for Jumps
1615 */
Keith Kaniosb7a89542007-04-12 02:40:54 +00001616 if ((uint8_t)(itemp->code[0]) >= 0370)
H. Peter Anvine2c80182005-01-15 22:15:51 +00001617 return 99;
1618
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001619 return ret;
1620}
1621
H. Peter Anvine2c80182005-01-15 22:15:51 +00001622static ea *process_ea(operand * input, ea * output, int addrbits,
1623 int rfield, int forw_ref)
H. Peter Anvineba20a72002-04-30 20:53:55 +00001624{
Keith Kaniosb7a89542007-04-12 02:40:54 +00001625
1626 int rip = FALSE; /* Used for RIP-relative addressing */
1627
1628
1629 if (!(REGISTER & ~input->type)) { /* register direct */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001630 int i;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001631 if ( input->basereg < EXPR_REG_START /* Verify as Register */
1632 || input->basereg >= REG_ENUM_LIMIT)
H. Peter Anvine2c80182005-01-15 22:15:51 +00001633 return NULL;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001634 i = regvals[input->basereg];
1635 if ( i >= 0100 && i < 0210) /* GPR's, MMX & XMM only */
1636 return NULL;
1637
1638 if (i >= 0400 && i < 0500) { /* Calculate REX.B */
1639 if (i < 0410 || (i >= 0440 && i < 0450))
1640 output->rex |= 0xF0; /* Set REX.0 */
1641 else
1642 output->rex |= 0xF1; /* Set REX.B */
1643 if (i >= 0440)
1644 output->rex |= 0xF8; /* Set REX.W */
1645 }
1646
1647 if ((rfield >= 0400 && rfield < 0500) || /* Calculate REX.R */
1648 (rfield >= 0120 && rfield < 0200 && /* Include CR/DR/TR... */
1649 !(rfield & 0010))) { /* ... extensions, only */
1650 if ((rfield >= 0400 && rfield < 0410) || (rfield >= 0440 && rfield < 0450))
1651 output->rex |= 0xF0; /* Set REX.0 */
1652 else
1653 output->rex |= 0xF4; /* Set REX.R */
1654 if (rfield >= 0440)
1655 output->rex |= 0xF8; /* Set REX.W */
1656 }
1657
1658 output->sib_present = FALSE; /* no SIB necessary */
1659 output->bytes = 0; /* no offset necessary either */
1660 output->modrm = 0xC0 | ((rfield & 7) << 3) | (i & 7);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001661 } else { /* it's a memory reference */
Keith Kaniosb7a89542007-04-12 02:40:54 +00001662
H. Peter Anvine2c80182005-01-15 22:15:51 +00001663 if (input->basereg == -1
1664 && (input->indexreg == -1 || input->scale == 0)) {
1665 /* it's a pure offset */
1666 if (input->addr_size)
1667 addrbits = input->addr_size;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001668
1669 if (rfield >= 0400 && rfield < 0500) { /* Calculate REX.R */
1670 if (rfield < 0410 || (rfield >= 0440 && rfield < 0450))
1671 output->rex |= 0xF0; /* Set REX.0 */
1672 else
1673 output->rex |= 0xF4; /* Set REX.R */
1674 if (rfield >= 0440)
1675 output->rex |= 0xF8; /* Set REX.W */
1676 }
1677
H. Peter Anvine2c80182005-01-15 22:15:51 +00001678 output->sib_present = FALSE;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001679 output->bytes = (addrbits != 16 ? 4 : 2);
1680 output->modrm = (addrbits != 16 ? 5 : 6) | ((rfield & 7) << 3);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001681 } else { /* it's an indirection */
1682 int i = input->indexreg, b = input->basereg, s = input->scale;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001683 int32_t o = input->offset, seg = input->segment;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001684 int hb = input->hintbase, ht = input->hinttype;
1685 int t;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001686 int it, bt;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001687
H. Peter Anvine2c80182005-01-15 22:15:51 +00001688 if (s == 0)
1689 i = -1; /* make this easy, at least */
Keith Kaniosb7a89542007-04-12 02:40:54 +00001690
1691 if (i != -1 && i >= EXPR_REG_START
1692 && i < REG_ENUM_LIMIT)
1693 it = regvals[i];
1694 else
1695 it = -1;
1696
1697 if (b != -1 && b >= EXPR_REG_START
1698 && b < REG_ENUM_LIMIT)
1699 bt = regvals[b];
1700 else
1701 bt = -1;
1702
1703 /* check for a 32/64-bit memory reference... */
1704 if ((it >= 0020 && it < 0030) || (it >= 0430 && it < 0460) ||
1705 (bt >= 0020 && bt < 0030) || (bt >= 0430 && bt < 0460) ||
1706 bt == 0500) {
1707 /* it must be a 32/64-bit memory reference. Firstly we have
1708 * to check that all registers involved are type E/Rxx. */
1709 t = 1;
1710 if (it != -1) {
1711 if (it < 0020 || (it >= 0030 && it < 0430) || it >= 0460)
1712 return NULL;
1713 if (it >= 0440)
1714 t = 2;
1715 else
1716 t = 0;
1717 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001718
Keith Kaniosb7a89542007-04-12 02:40:54 +00001719 if (bt != -1) {
1720 if (bt < 0020 || (bt >= 0030 && bt < 0430) || (bt >= 0460 && bt < 0500))
1721 return NULL;
1722 if (bt == 0500) {
1723 bt = b = -1;
1724 rip = TRUE;
1725 } else if (bt >= 0440) {
1726 if (t < 1)
1727 return NULL;
1728 } else {
1729 if (t > 1)
1730 return NULL;
1731 }
1732 }
1733
H. Peter Anvine2c80182005-01-15 22:15:51 +00001734 /* While we're here, ensure the user didn't specify WORD. */
1735 if (input->addr_size == 16)
1736 return NULL;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001737
Keith Kaniosb7a89542007-04-12 02:40:54 +00001738 /* now reorganize base/index */
1739 if (s == 1 && bt != it && bt != -1 && it != -1 &&
1740 ((hb == bt && ht == EAH_NOTBASE)
1741 || (hb == it && ht == EAH_MAKEBASE)))
1742 t = bt, bt = it, it = t; /* swap if hints say so */
1743 if (bt == it) /* convert EAX+2*EAX to 3*EAX */
1744 bt = -1, s++;
1745 if (bt == -1 && s == 1 && !(hb == it && ht == EAH_NOTBASE))
1746 bt = i, it = -1; /* make single reg base, unless hint */
1747 if (((s == 2 && (it & 7) != (REG_NUM_ESP & 7)
H. Peter Anvine2c80182005-01-15 22:15:51 +00001748 && !(input->eaflags & EAF_TIMESTWO)) || s == 3
Keith Kaniosb7a89542007-04-12 02:40:54 +00001749 || s == 5 || s == 9) && bt == -1)
1750 bt = it, s--; /* convert 3*EAX to EAX+2*EAX */
1751 if (it == -1 && (bt & 7) != (REG_NUM_ESP & 7)
H. Peter Anvine2c80182005-01-15 22:15:51 +00001752 && (input->eaflags & EAF_TIMESTWO))
Keith Kaniosb7a89542007-04-12 02:40:54 +00001753 it = bt, bt = -1, s = 1;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001754 /* convert [NOSPLIT EAX] to sib format with 0x0 displacement */
Keith Kaniosb7a89542007-04-12 02:40:54 +00001755 if (s == 1 && (it & 7) == (REG_NUM_ESP & 7)) /* swap ESP into base if scale is 1 */
1756 t = it, it = bt, bt = t;
1757 if ((it & 7) == (REG_NUM_ESP & 7)
1758 || (s != 1 && s != 2 && s != 4 && s != 8 && it != -1))
H. Peter Anvine2c80182005-01-15 22:15:51 +00001759 return NULL; /* wrong, for various reasons */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001760
Keith Kanios2cc61b32007-04-13 01:17:45 +00001761 if (i >= 0400 && i < 0500) { /* Calculate REX.X */
Keith Kaniosb7a89542007-04-12 02:40:54 +00001762 if (i < 0410 || (i >= 0440 && i < 0450))
1763 output->rex |= 0xF0; /* Set REX.0 */
1764 else
Keith Kanios2cc61b32007-04-13 01:17:45 +00001765 output->rex |= 0xF2; /* Set REX.X */
Keith Kaniosb7a89542007-04-12 02:40:54 +00001766 if (i >= 0440)
1767 output->rex |= 0xF8; /* Set REX.W */
1768 }
1769
1770 if (b >= 0400 && b < 0500) { /* Calculate REX.B */
1771 if (b < 0410 || (b >= 0440 && b < 0450))
1772 output->rex |= 0xF0; /* Set REX.0 */
1773 else
1774 output->rex |= 0xF1; /* Set REX.B */
1775 if (b >= 0440)
1776 output->rex |= 0xF8; /* Set REX.W */
1777 }
1778
1779 if (rfield >= 0400 && rfield < 0500) { /* Calculate REX.R */
1780 if (rfield < 0410 || (rfield >= 0440 && rfield < 0450))
1781 output->rex |= 0xF0; /* Set REX.0 */
1782 else
1783 output->rex |= 0xF4; /* Set REX.R */
1784 if (rfield >= 0440)
1785 output->rex |= 0xF8; /* Set REX.W */
1786 }
1787
1788 if (it == -1 && (bt & 7) != (REG_NUM_ESP & 7)) { /* no SIB needed */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001789 int mod, rm;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001790
1791 if (bt == -1) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001792 rm = 5;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001793 mod = 0;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001794 } else {
1795 rm = (bt & 7);
1796 if (rm != (REG_NUM_EBP & 7) && o == 0 &&
1797 seg == NO_SEG && !forw_ref &&
1798 !(input->eaflags &
1799 (EAF_BYTEOFFS | EAF_WORDOFFS)))
1800 mod = 0;
1801 else if (input->eaflags & EAF_BYTEOFFS ||
1802 (o >= -128 && o <= 127 && seg == NO_SEG
1803 && !forw_ref
1804 && !(input->eaflags & EAF_WORDOFFS)))
1805 mod = 1;
1806 else
1807 mod = 2;
1808 }
H. Peter Anvinea838272002-04-30 20:51:53 +00001809
H. Peter Anvine2c80182005-01-15 22:15:51 +00001810 output->sib_present = FALSE;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001811 output->bytes = (bt == -1 || mod == 2 ? 4 : mod);
1812 output->modrm = (mod << 6) | ((rfield & 7) << 3) | rm;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001813 } else { /* we need a SIB */
1814 int mod, scale, index, base;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001815
1816 if (it == -1)
1817 index = 4, s = 1;
1818 else
1819 index = (it & 7);
1820
H. Peter Anvine2c80182005-01-15 22:15:51 +00001821 switch (s) {
1822 case 1:
1823 scale = 0;
1824 break;
1825 case 2:
1826 scale = 1;
1827 break;
1828 case 4:
1829 scale = 2;
1830 break;
1831 case 8:
1832 scale = 3;
1833 break;
1834 default: /* then what the smeg is it? */
1835 return NULL; /* panic */
1836 }
Keith Kaniosb7a89542007-04-12 02:40:54 +00001837
1838 if (bt == -1) {
1839 base = 5;
1840 mod = 0;
1841 } else {
1842 base = (bt & 7);
1843 if (base != (REG_NUM_EBP & 7) && o == 0 &&
H. Peter Anvine2c80182005-01-15 22:15:51 +00001844 seg == NO_SEG && !forw_ref &&
1845 !(input->eaflags &
Keith Kaniosb7a89542007-04-12 02:40:54 +00001846 (EAF_BYTEOFFS | EAF_WORDOFFS)))
1847 mod = 0;
1848 else if (input->eaflags & EAF_BYTEOFFS ||
1849 (o >= -128 && o <= 127 && seg == NO_SEG
1850 && !forw_ref
1851 && !(input->eaflags & EAF_WORDOFFS)))
1852 mod = 1;
1853 else
1854 mod = 2;
1855 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001856
H. Peter Anvine2c80182005-01-15 22:15:51 +00001857 output->sib_present = TRUE;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001858 output->bytes = (bt == -1 || mod == 2 ? 4 : mod);
1859 output->modrm = (mod << 6) | ((rfield & 7) << 3) | 4;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001860 output->sib = (scale << 6) | (index << 3) | base;
1861 }
1862 } else { /* it's 16-bit */
1863 int mod, rm;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001864
1865 /* check for 64-bit long mode */
1866 if (addrbits == 64)
1867 return NULL;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001868
H. Peter Anvine2c80182005-01-15 22:15:51 +00001869 /* check all registers are BX, BP, SI or DI */
1870 if ((b != -1 && b != R_BP && b != R_BX && b != R_SI
1871 && b != R_DI) || (i != -1 && i != R_BP && i != R_BX
1872 && i != R_SI && i != R_DI))
1873 return NULL;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001874
Keith Kaniosb7a89542007-04-12 02:40:54 +00001875 /* ensure the user didn't specify DWORD/QWORD */
1876 if (input->addr_size == 32 || input->addr_size == 64)
H. Peter Anvine2c80182005-01-15 22:15:51 +00001877 return NULL;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001878
H. Peter Anvine2c80182005-01-15 22:15:51 +00001879 if (s != 1 && i != -1)
1880 return NULL; /* no can do, in 16-bit EA */
1881 if (b == -1 && i != -1) {
1882 int tmp = b;
1883 b = i;
1884 i = tmp;
1885 } /* swap */
1886 if ((b == R_SI || b == R_DI) && i != -1) {
1887 int tmp = b;
1888 b = i;
1889 i = tmp;
1890 }
1891 /* have BX/BP as base, SI/DI index */
1892 if (b == i)
1893 return NULL; /* shouldn't ever happen, in theory */
1894 if (i != -1 && b != -1 &&
1895 (i == R_BP || i == R_BX || b == R_SI || b == R_DI))
1896 return NULL; /* invalid combinations */
1897 if (b == -1) /* pure offset: handled above */
1898 return NULL; /* so if it gets to here, panic! */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001899
H. Peter Anvine2c80182005-01-15 22:15:51 +00001900 rm = -1;
1901 if (i != -1)
1902 switch (i * 256 + b) {
1903 case R_SI * 256 + R_BX:
1904 rm = 0;
1905 break;
1906 case R_DI * 256 + R_BX:
1907 rm = 1;
1908 break;
1909 case R_SI * 256 + R_BP:
1910 rm = 2;
1911 break;
1912 case R_DI * 256 + R_BP:
1913 rm = 3;
1914 break;
1915 } else
1916 switch (b) {
1917 case R_SI:
1918 rm = 4;
1919 break;
1920 case R_DI:
1921 rm = 5;
1922 break;
1923 case R_BP:
1924 rm = 6;
1925 break;
1926 case R_BX:
1927 rm = 7;
1928 break;
1929 }
1930 if (rm == -1) /* can't happen, in theory */
1931 return NULL; /* so panic if it does */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001932
H. Peter Anvine2c80182005-01-15 22:15:51 +00001933 if (o == 0 && seg == NO_SEG && !forw_ref && rm != 6 &&
1934 !(input->eaflags & (EAF_BYTEOFFS | EAF_WORDOFFS)))
1935 mod = 0;
1936 else if (input->eaflags & EAF_BYTEOFFS ||
1937 (o >= -128 && o <= 127 && seg == NO_SEG
1938 && !forw_ref
1939 && !(input->eaflags & EAF_WORDOFFS)))
1940 mod = 1;
1941 else
1942 mod = 2;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001943
H. Peter Anvine2c80182005-01-15 22:15:51 +00001944 output->sib_present = FALSE; /* no SIB - it's 16-bit */
1945 output->bytes = mod; /* bytes of offset needed */
Keith Kaniosb7a89542007-04-12 02:40:54 +00001946 output->modrm = (mod << 6) | ((rfield & 7) << 3) | rm;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001947 }
1948 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001949 }
Keith Kaniosb7a89542007-04-12 02:40:54 +00001950
1951 /* Process RIP-relative Addressing */
1952 if (rip) {
1953 if ((output->modrm & 0xC7) != 0x05)
1954 return NULL;
1955 output->rip = TRUE;
1956 } else {
1957 output->rip = FALSE;
1958 if (globalbits == 64 && /* Actual Disp32 needs blank SIB on x64 */
1959 !(output->sib_present) && ((output->modrm & 0xC7) == 0x05)) {
1960 output->sib_present = TRUE;
1961 output->modrm --; /* RM Field = 4 (forward to Base of SIB) */
1962 output->sib = (4 << 3) | 5; /* Index = 4 (none), Base = 5 */
1963 }
1964 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001965 output->size = 1 + output->sib_present + output->bytes;
1966 return output;
1967}
1968
H. Peter Anvine2c80182005-01-15 22:15:51 +00001969static int chsize(operand * input, int addrbits)
H. Peter Anvineba20a72002-04-30 20:53:55 +00001970{
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001971 if (!(MEMORY & ~input->type)) {
Keith Kaniosb7a89542007-04-12 02:40:54 +00001972 int i, b;
1973
1974 if ( input->indexreg < EXPR_REG_START /* Verify as Register */
1975 || input->indexreg >= REG_ENUM_LIMIT)
1976 i = -1;
1977 else
1978 i = regvals[input->indexreg];
1979
1980 if ( input->basereg < EXPR_REG_START /* Verify as Register */
1981 || input->basereg >= REG_ENUM_LIMIT)
1982 b = -1;
1983 else
1984 b = regvals[input->basereg];
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001985
H. Peter Anvine2c80182005-01-15 22:15:51 +00001986 if (input->scale == 0)
1987 i = -1;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001988
H. Peter Anvine2c80182005-01-15 22:15:51 +00001989 if (i == -1 && b == -1) /* pure offset */
1990 return (input->addr_size != 0 && input->addr_size != addrbits);
Keith Kaniosb7a89542007-04-12 02:40:54 +00001991
1992 if ((i >= 0020 && i < 0030) || (i >= 0430 && i < 0440) ||
1993 (b >= 0020 && b < 0030) || (b >= 0430 && b < 0440))
1994 return (addrbits != 32);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001995 else
1996 return (addrbits == 32);
1997 } else
1998 return 0;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001999}