blob: c5a6efd273b0897eaeae230733825f2ef20fff7e [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;
698 ins->rex = 0; /* Ensure REX is reset */
699 int rex_mask = 0xFF;
H. Peter Anvin0db11e22007-04-17 20:23:11 +0000700 int lock_is_rex_r = 0;
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:
863 length++;
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 ||
922 (lock_is_rex_r && ins->rex == 0xf4 && cpu >= IF_X86_64))
923 length++;
924 else
925 errfunc(ERR_NONFATAL, "invalid operands in non-64-bit mode");
Keith Kaniosb7a89542007-04-12 02:40:54 +0000926 }
927
H. Peter Anvin0db11e22007-04-17 20:23:11 +0000928 return length;
929}
Keith Kaniosb7a89542007-04-12 02:40:54 +0000930
931static void gencode(int32_t segment, int32_t offset, int bits,
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000932 insn * ins, const char *codes, int32_t insn_end)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000933{
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000934 static char condval[] = { /* conditional opcodes */
H. Peter Anvine2c80182005-01-15 22:15:51 +0000935 0x7, 0x3, 0x2, 0x6, 0x2, 0x4, 0xF, 0xD, 0xC, 0xE, 0x6, 0x2,
936 0x3, 0x7, 0x3, 0x5, 0xE, 0xC, 0xD, 0xF, 0x1, 0xB, 0x9, 0x5,
937 0x0, 0xA, 0xA, 0xB, 0x8, 0x4
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000938 };
Keith Kaniosb7a89542007-04-12 02:40:54 +0000939 uint8_t c;
940 uint8_t bytes[4];
941 int32_t size;
942 int64_t data;
943
H. Peter Anvineba20a72002-04-30 20:53:55 +0000944 while (*codes)
H. Peter Anvine2c80182005-01-15 22:15:51 +0000945 switch (c = *codes++) {
946 case 01:
947 case 02:
948 case 03:
Keith Kaniosb7a89542007-04-12 02:40:54 +0000949 if(ins->rex && (bits == 64)) { /* REX Supercedes all other Prefixes */
950 ins->rex = (ins->rex&0x0F)+0x40;
951 out(offset, segment, &ins->rex, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
952 ins->rex = 0;
953 offset += 1;
954 }
H. Peter Anvine2c80182005-01-15 22:15:51 +0000955 out(offset, segment, codes, OUT_RAWDATA + c, NO_SEG, NO_SEG);
956 codes += c;
957 offset += c;
958 break;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000959
H. Peter Anvine2c80182005-01-15 22:15:51 +0000960 case 04:
961 case 06:
962 switch (ins->oprs[0].basereg) {
963 case R_CS:
964 bytes[0] = 0x0E + (c == 0x04 ? 1 : 0);
965 break;
966 case R_DS:
967 bytes[0] = 0x1E + (c == 0x04 ? 1 : 0);
968 break;
969 case R_ES:
970 bytes[0] = 0x06 + (c == 0x04 ? 1 : 0);
971 break;
972 case R_SS:
973 bytes[0] = 0x16 + (c == 0x04 ? 1 : 0);
974 break;
975 default:
976 errfunc(ERR_PANIC,
977 "bizarre 8086 segment register received");
978 }
979 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
980 offset++;
981 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000982
H. Peter Anvine2c80182005-01-15 22:15:51 +0000983 case 05:
984 case 07:
985 switch (ins->oprs[0].basereg) {
986 case R_FS:
987 bytes[0] = 0xA0 + (c == 0x05 ? 1 : 0);
988 break;
989 case R_GS:
990 bytes[0] = 0xA8 + (c == 0x05 ? 1 : 0);
991 break;
992 default:
993 errfunc(ERR_PANIC,
994 "bizarre 386 segment register received");
995 }
996 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
997 offset++;
998 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000999
H. Peter Anvine2c80182005-01-15 22:15:51 +00001000 case 010:
1001 case 011:
1002 case 012:
Keith Kaniosb7a89542007-04-12 02:40:54 +00001003 if(ins->rex && (bits == 64)) { /* REX Supercedes all other Prefixes */
1004 ins->rex = (ins->rex&0x0F)+0x40;
1005 out(offset, segment, &ins->rex, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1006 ins->rex = 0;
1007 offset += 1;
1008 }
1009 bytes[0] = *codes++ + ((regval(&ins->oprs[c - 010])) & 7);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001010 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1011 offset += 1;
1012 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001013
H. Peter Anvine2c80182005-01-15 22:15:51 +00001014 case 017:
1015 bytes[0] = 0;
1016 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1017 offset += 1;
1018 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001019
H. Peter Anvine2c80182005-01-15 22:15:51 +00001020 case 014:
1021 case 015:
1022 case 016:
1023 if (ins->oprs[c - 014].offset < -128
1024 || ins->oprs[c - 014].offset > 127) {
1025 errfunc(ERR_WARNING, "signed byte value exceeds bounds");
1026 }
H. Peter Anvineba20a72002-04-30 20:53:55 +00001027
H. Peter Anvine2c80182005-01-15 22:15:51 +00001028 if (ins->oprs[c - 014].segment != NO_SEG) {
1029 data = ins->oprs[c - 014].offset;
1030 out(offset, segment, &data, OUT_ADDRESS + 1,
1031 ins->oprs[c - 014].segment, ins->oprs[c - 014].wrt);
1032 } else {
1033 bytes[0] = ins->oprs[c - 014].offset;
1034 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG,
1035 NO_SEG);
1036 }
1037 offset += 1;
1038 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001039
H. Peter Anvine2c80182005-01-15 22:15:51 +00001040 case 020:
1041 case 021:
1042 case 022:
1043 if (ins->oprs[c - 020].offset < -256
1044 || ins->oprs[c - 020].offset > 255) {
1045 errfunc(ERR_WARNING, "byte value exceeds bounds");
1046 }
1047 if (ins->oprs[c - 020].segment != NO_SEG) {
1048 data = ins->oprs[c - 020].offset;
1049 out(offset, segment, &data, OUT_ADDRESS + 1,
1050 ins->oprs[c - 020].segment, ins->oprs[c - 020].wrt);
1051 } else {
1052 bytes[0] = ins->oprs[c - 020].offset;
1053 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG,
1054 NO_SEG);
1055 }
1056 offset += 1;
1057 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001058
H. Peter Anvine2c80182005-01-15 22:15:51 +00001059 case 024:
1060 case 025:
1061 case 026:
1062 if (ins->oprs[c - 024].offset < 0
1063 || ins->oprs[c - 024].offset > 255)
1064 errfunc(ERR_WARNING, "unsigned byte value exceeds bounds");
1065 if (ins->oprs[c - 024].segment != NO_SEG) {
1066 data = ins->oprs[c - 024].offset;
1067 out(offset, segment, &data, OUT_ADDRESS + 1,
1068 ins->oprs[c - 024].segment, ins->oprs[c - 024].wrt);
1069 } else {
1070 bytes[0] = ins->oprs[c - 024].offset;
1071 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG,
1072 NO_SEG);
1073 }
1074 offset += 1;
1075 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001076
H. Peter Anvine2c80182005-01-15 22:15:51 +00001077 case 030:
1078 case 031:
1079 case 032:
1080 if (ins->oprs[c - 030].segment == NO_SEG &&
1081 ins->oprs[c - 030].wrt == NO_SEG &&
1082 (ins->oprs[c - 030].offset < -65536L ||
1083 ins->oprs[c - 030].offset > 65535L)) {
1084 errfunc(ERR_WARNING, "word value exceeds bounds");
1085 }
1086 data = ins->oprs[c - 030].offset;
1087 out(offset, segment, &data, OUT_ADDRESS + 2,
1088 ins->oprs[c - 030].segment, ins->oprs[c - 030].wrt);
1089 offset += 2;
1090 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001091
H. Peter Anvine2c80182005-01-15 22:15:51 +00001092 case 034:
1093 case 035:
1094 case 036:
1095 if (ins->oprs[c - 034].type & (BITS16 | BITS32))
1096 size = (ins->oprs[c - 034].type & BITS16) ? 2 : 4;
1097 else
1098 size = (bits == 16) ? 2 : 4;
1099 data = ins->oprs[c - 034].offset;
1100 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 - 034].segment, ins->oprs[c - 034].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 037:
1108 if (ins->oprs[0].segment == NO_SEG)
1109 errfunc(ERR_NONFATAL, "value referenced by FAR is not"
1110 " relocatable");
1111 data = 0L;
1112 out(offset, segment, &data, OUT_ADDRESS + 2,
1113 outfmt->segbase(1 + ins->oprs[0].segment),
1114 ins->oprs[0].wrt);
1115 offset += 2;
1116 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001117
H. Peter Anvine2c80182005-01-15 22:15:51 +00001118 case 040:
1119 case 041:
1120 case 042:
1121 data = ins->oprs[c - 040].offset;
1122 out(offset, segment, &data, OUT_ADDRESS + 4,
1123 ins->oprs[c - 040].segment, ins->oprs[c - 040].wrt);
1124 offset += 4;
1125 break;
H. Peter Anvin3ba46772002-05-27 23:19:35 +00001126
H. Peter Anvine2c80182005-01-15 22:15:51 +00001127 case 044:
1128 case 045:
1129 case 046:
1130 data = ins->oprs[c - 044].offset;
1131 size = ((ins->oprs[c - 044].addr_size ?
Keith Kaniosb7a89542007-04-12 02:40:54 +00001132 ins->oprs[c - 044].addr_size : bits) >> 3);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001133 if (size == 2 && (data < -65536L || data > 65535L))
1134 errfunc(ERR_WARNING, "word value exceeds bounds");
1135 out(offset, segment, &data, OUT_ADDRESS + size,
1136 ins->oprs[c - 044].segment, ins->oprs[c - 044].wrt);
1137 offset += size;
1138 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001139
H. Peter Anvine2c80182005-01-15 22:15:51 +00001140 case 050:
1141 case 051:
1142 case 052:
1143 if (ins->oprs[c - 050].segment != segment)
1144 errfunc(ERR_NONFATAL,
1145 "short relative jump outside segment");
1146 data = ins->oprs[c - 050].offset - insn_end;
1147 if (data > 127 || data < -128)
1148 errfunc(ERR_NONFATAL, "short jump is out of range");
1149 bytes[0] = data;
1150 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1151 offset += 1;
1152 break;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001153
1154 case 054:
1155 case 055:
1156 case 056:
1157 data = (int64_t)ins->oprs[c - 054].offset;
1158 out(offset, segment, &data, OUT_ADDRESS + 8,
1159 ins->oprs[c - 054].segment, ins->oprs[c - 054].wrt);
1160 offset += 8;
1161 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001162
H. Peter Anvine2c80182005-01-15 22:15:51 +00001163 case 060:
1164 case 061:
1165 case 062:
1166 if (ins->oprs[c - 060].segment != segment) {
1167 data = ins->oprs[c - 060].offset;
1168 out(offset, segment, &data,
1169 OUT_REL2ADR + insn_end - offset,
1170 ins->oprs[c - 060].segment, ins->oprs[c - 060].wrt);
1171 } else {
1172 data = ins->oprs[c - 060].offset - insn_end;
1173 out(offset, segment, &data,
1174 OUT_ADDRESS + 2, NO_SEG, NO_SEG);
1175 }
1176 offset += 2;
1177 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001178
H. Peter Anvine2c80182005-01-15 22:15:51 +00001179 case 064:
1180 case 065:
1181 case 066:
Keith Kaniosb7a89542007-04-12 02:40:54 +00001182 if (ins->oprs[c - 064].type & (BITS16 | BITS32 | BITS64))
H. Peter Anvine2c80182005-01-15 22:15:51 +00001183 size = (ins->oprs[c - 064].type & BITS16) ? 2 : 4;
1184 else
1185 size = (bits == 16) ? 2 : 4;
1186 if (ins->oprs[c - 064].segment != segment) {
Keith Kaniosb7a89542007-04-12 02:40:54 +00001187 int32_t reltype = (size == 2 ? OUT_REL2ADR : OUT_REL4ADR);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001188 data = ins->oprs[c - 064].offset;
1189 out(offset, segment, &data, reltype + insn_end - offset,
1190 ins->oprs[c - 064].segment, ins->oprs[c - 064].wrt);
1191 } else {
1192 data = ins->oprs[c - 064].offset - insn_end;
1193 out(offset, segment, &data,
1194 OUT_ADDRESS + size, NO_SEG, NO_SEG);
1195 }
1196 offset += size;
1197 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001198
H. Peter Anvine2c80182005-01-15 22:15:51 +00001199 case 070:
1200 case 071:
1201 case 072:
1202 if (ins->oprs[c - 070].segment != segment) {
1203 data = ins->oprs[c - 070].offset;
1204 out(offset, segment, &data,
1205 OUT_REL4ADR + insn_end - offset,
1206 ins->oprs[c - 070].segment, ins->oprs[c - 070].wrt);
1207 } else {
1208 data = ins->oprs[c - 070].offset - insn_end;
1209 out(offset, segment, &data,
1210 OUT_ADDRESS + 4, NO_SEG, NO_SEG);
1211 }
1212 offset += 4;
1213 break;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001214
H. Peter Anvine2c80182005-01-15 22:15:51 +00001215 case 0130:
1216 case 0131:
1217 case 0132:
1218 data = ins->oprs[c - 0130].offset;
1219 if (is_sbyte(ins, c - 0130, 16)) {
1220 bytes[0] = data;
1221 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG,
1222 NO_SEG);
1223 offset++;
1224 } else {
1225 if (ins->oprs[c - 0130].segment == NO_SEG &&
1226 ins->oprs[c - 0130].wrt == NO_SEG &&
1227 (data < -65536L || data > 65535L)) {
1228 errfunc(ERR_WARNING, "word value exceeds bounds");
1229 }
1230 out(offset, segment, &data, OUT_ADDRESS + 2,
1231 ins->oprs[c - 0130].segment, ins->oprs[c - 0130].wrt);
1232 offset += 2;
1233 }
1234 break;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001235
H. Peter Anvine2c80182005-01-15 22:15:51 +00001236 case 0133:
1237 case 0134:
1238 case 0135:
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 - 0133, 16))
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 0140:
1254 case 0141:
1255 case 0142:
1256 data = ins->oprs[c - 0140].offset;
1257 if (is_sbyte(ins, c - 0140, 32)) {
1258 bytes[0] = data;
1259 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG,
1260 NO_SEG);
1261 offset++;
1262 } else {
1263 out(offset, segment, &data, OUT_ADDRESS + 4,
1264 ins->oprs[c - 0140].segment, ins->oprs[c - 0140].wrt);
1265 offset += 4;
1266 }
1267 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001268
H. Peter Anvine2c80182005-01-15 22:15:51 +00001269 case 0143:
1270 case 0144:
1271 case 0145:
Keith Kaniosb7a89542007-04-12 02:40:54 +00001272 if(ins->rex && (bits == 64)) { /* REX Supercedes all other Prefixes */
1273 ins->rex = (ins->rex&0x0F)+0x40;
1274 out(offset, segment, &ins->rex, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1275 ins->rex = 0;
1276 offset += 1;
1277 }
H. Peter Anvine2c80182005-01-15 22:15:51 +00001278 codes++;
1279 bytes[0] = *codes++;
1280 if (is_sbyte(ins, c - 0143, 32))
1281 bytes[0] |= 2; /* s-bit */
1282 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1283 offset++;
1284 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001285
H. Peter Anvine2c80182005-01-15 22:15:51 +00001286 case 0300:
1287 case 0301:
1288 case 0302:
1289 if (chsize(&ins->oprs[c - 0300], bits)) {
1290 *bytes = 0x67;
1291 out(offset, segment, bytes,
1292 OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1293 offset += 1;
1294 } else
1295 offset += 0;
1296 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001297
H. Peter Anvine2c80182005-01-15 22:15:51 +00001298 case 0310:
Keith Kaniosb7a89542007-04-12 02:40:54 +00001299 if (bits != 16) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001300 *bytes = 0x67;
1301 out(offset, segment, bytes,
1302 OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1303 offset += 1;
1304 } else
1305 offset += 0;
1306 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001307
H. Peter Anvine2c80182005-01-15 22:15:51 +00001308 case 0311:
Keith Kaniosb7a89542007-04-12 02:40:54 +00001309 if (bits != 32) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001310 *bytes = 0x67;
1311 out(offset, segment, bytes,
1312 OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1313 offset += 1;
1314 } else
1315 offset += 0;
1316 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001317
H. Peter Anvine2c80182005-01-15 22:15:51 +00001318 case 0312:
1319 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001320
Keith Kaniosb7a89542007-04-12 02:40:54 +00001321 case 0313:
1322 ins->rex = 0;
1323 break;
1324
H. Peter Anvine2c80182005-01-15 22:15:51 +00001325 case 0320:
Keith Kaniosb7a89542007-04-12 02:40:54 +00001326 if (bits != 16) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001327 *bytes = 0x66;
1328 out(offset, segment, bytes,
1329 OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1330 offset += 1;
1331 } else
1332 offset += 0;
1333 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001334
H. Peter Anvine2c80182005-01-15 22:15:51 +00001335 case 0321:
1336 if (bits == 16) {
1337 *bytes = 0x66;
1338 out(offset, segment, bytes,
1339 OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1340 offset += 1;
1341 } else
1342 offset += 0;
1343 break;
H. Peter Anvinef7468f2002-04-30 20:57:59 +00001344
H. Peter Anvine2c80182005-01-15 22:15:51 +00001345 case 0322:
Keith Kaniosb7a89542007-04-12 02:40:54 +00001346 case 0323:
1347 break;
1348
1349 case 0324:
1350 ins->rex |= 0xF8;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001351 break;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001352
H. Peter Anvine2c80182005-01-15 22:15:51 +00001353 case 0330:
1354 *bytes = *codes++ ^ condval[ins->condition];
1355 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1356 offset += 1;
1357 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001358
H. Peter Anvine2c80182005-01-15 22:15:51 +00001359 case 0331:
1360 case 0332:
1361 break;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001362
H. Peter Anvine2c80182005-01-15 22:15:51 +00001363 case 0333:
1364 *bytes = 0xF3;
1365 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1366 offset += 1;
1367 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001368
H. Peter Anvin0db11e22007-04-17 20:23:11 +00001369 case 0334:
1370 if (ins->rex & 0x04) {
1371 *bytes = 0xF0;
1372 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1373 offset += 1;
1374 }
1375 break;
1376
H. Peter Anvine2c80182005-01-15 22:15:51 +00001377 case 0340:
1378 case 0341:
1379 case 0342:
1380 if (ins->oprs[0].segment != NO_SEG)
1381 errfunc(ERR_PANIC, "non-constant BSS size in pass two");
1382 else {
Keith Kaniosb7a89542007-04-12 02:40:54 +00001383 int32_t size = ins->oprs[0].offset << (c - 0340);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001384 if (size > 0)
1385 out(offset, segment, NULL,
1386 OUT_RESERVE + size, NO_SEG, NO_SEG);
1387 offset += size;
1388 }
1389 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001390
H. Peter Anvine2c80182005-01-15 22:15:51 +00001391 case 0370:
1392 case 0371:
1393 case 0372:
1394 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001395
H. Peter Anvine2c80182005-01-15 22:15:51 +00001396 case 0373:
1397 *bytes = bits == 16 ? 3 : 5;
1398 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1399 offset += 1;
1400 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001401
H. Peter Anvine2c80182005-01-15 22:15:51 +00001402 default: /* can't do it by 'case' statements */
Keith Kaniosb7a89542007-04-12 02:40:54 +00001403 if ( c >= 0100 && c <= 0277) { /* it's an EA */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001404 ea ea_data;
1405 int rfield;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001406 uint8_t *p;
1407 int32_t s;
1408
H. Peter Anvine2c80182005-01-15 22:15:51 +00001409 if (c <= 0177) /* pick rfield from operand b */
1410 rfield = regval(&ins->oprs[c & 7]);
1411 else /* rfield is constant */
1412 rfield = c & 7;
1413
1414 if (!process_ea
1415 (&ins->oprs[(c >> 3) & 7], &ea_data, bits, rfield,
1416 ins->forw_ref)) {
1417 errfunc(ERR_NONFATAL, "invalid effective address");
1418 }
Keith Kaniosb7a89542007-04-12 02:40:54 +00001419
H. Peter Anvine2c80182005-01-15 22:15:51 +00001420 p = bytes;
1421 *p++ = ea_data.modrm;
1422 if (ea_data.sib_present)
1423 *p++ = ea_data.sib;
1424
1425 s = p - bytes;
1426 out(offset, segment, bytes, OUT_RAWDATA + s,
1427 NO_SEG, NO_SEG);
1428
1429 switch (ea_data.bytes) {
1430 case 0:
1431 break;
1432 case 1:
1433 if (ins->oprs[(c >> 3) & 7].segment != NO_SEG) {
1434 data = ins->oprs[(c >> 3) & 7].offset;
1435 out(offset, segment, &data, OUT_ADDRESS + 1,
1436 ins->oprs[(c >> 3) & 7].segment,
1437 ins->oprs[(c >> 3) & 7].wrt);
1438 } else {
1439 *bytes = ins->oprs[(c >> 3) & 7].offset;
1440 out(offset, segment, bytes, OUT_RAWDATA + 1,
1441 NO_SEG, NO_SEG);
1442 }
1443 s++;
1444 break;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001445 case 8:
H. Peter Anvine2c80182005-01-15 22:15:51 +00001446 case 2:
1447 case 4:
1448 data = ins->oprs[(c >> 3) & 7].offset;
Keith Kaniose83b3182007-04-16 14:31:54 +00001449 if (ea_data.rip && (ins->oprs[(c >> 3) & 7].segment == 0xFFFFFFFF))
1450 ea_data.rip = 0; /* Make distinction between Symbols and Immediates */
Keith Kaniosb7a89542007-04-12 02:40:54 +00001451 out(offset, segment, &data, /* RIP = Relative, not Absolute */
1452 (ea_data.rip ? OUT_REL4ADR : OUT_ADDRESS) + ea_data.bytes,
H. Peter Anvine2c80182005-01-15 22:15:51 +00001453 ins->oprs[(c >> 3) & 7].segment,
1454 ins->oprs[(c >> 3) & 7].wrt);
1455 s += ea_data.bytes;
1456 break;
1457 }
1458 offset += s;
1459 } else
1460 errfunc(ERR_PANIC, "internal instruction table corrupt"
1461 ": instruction code 0x%02X given", c);
1462 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001463}
1464
H. Peter Anvine2c80182005-01-15 22:15:51 +00001465static int regval(operand * o)
H. Peter Anvineba20a72002-04-30 20:53:55 +00001466{
H. Peter Anvine2c80182005-01-15 22:15:51 +00001467 if (o->basereg < EXPR_REG_START || o->basereg >= REG_ENUM_LIMIT) {
1468 errfunc(ERR_PANIC, "invalid operand passed to regval()");
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001469 }
H. Peter Anvin232badb2002-06-06 02:41:20 +00001470 return regvals[o->basereg];
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001471}
1472
Keith Kaniosb7a89542007-04-12 02:40:54 +00001473static int matches(struct itemplate *itemp, insn * instruction, int bits)
H. Peter Anvineba20a72002-04-30 20:53:55 +00001474{
Keith Kaniosb7a89542007-04-12 02:40:54 +00001475 int i, b, x, size[3], asize, oprs, ret;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001476
1477 ret = 100;
1478
1479 /*
1480 * Check the opcode
1481 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001482 if (itemp->opcode != instruction->opcode)
1483 return 0;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001484
1485 /*
1486 * Count the operands
1487 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001488 if (itemp->operands != instruction->operands)
1489 return 0;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001490
1491 /*
1492 * Check that no spurious colons or TOs are present
1493 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001494 for (i = 0; i < itemp->operands; i++)
1495 if (instruction->oprs[i].type & ~itemp->opd[i] & (COLON | TO))
1496 return 0;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001497
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001498 /*
1499 * Check that the operand flags all match up
1500 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001501 for (i = 0; i < itemp->operands; i++)
1502 if (itemp->opd[i] & ~instruction->oprs[i].type ||
1503 ((itemp->opd[i] & SIZE_MASK) &&
1504 ((itemp->opd[i] ^ instruction->oprs[i].type) & SIZE_MASK))) {
1505 if ((itemp->opd[i] & ~instruction->oprs[i].type & NON_SIZE) ||
1506 (instruction->oprs[i].type & SIZE_MASK))
1507 return 0;
1508 else
H. Peter Anvine2c80182005-01-15 22:15:51 +00001509 return 1;
1510 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001511
1512 /*
1513 * Check operand sizes
1514 */
H. Peter Anvinef7468f2002-04-30 20:57:59 +00001515 if (itemp->flags & IF_ARMASK) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001516 size[0] = size[1] = size[2] = 0;
H. Peter Anvinef7468f2002-04-30 20:57:59 +00001517
H. Peter Anvine2c80182005-01-15 22:15:51 +00001518 switch (itemp->flags & IF_ARMASK) {
1519 case IF_AR0:
1520 i = 0;
1521 break;
1522 case IF_AR1:
1523 i = 1;
1524 break;
1525 case IF_AR2:
1526 i = 2;
1527 break;
1528 default:
1529 break; /* Shouldn't happen */
1530 }
1531 if (itemp->flags & IF_SB) {
1532 size[i] = BITS8;
1533 } else if (itemp->flags & IF_SW) {
1534 size[i] = BITS16;
1535 } else if (itemp->flags & IF_SD) {
1536 size[i] = BITS32;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001537 } else if (itemp->flags & IF_SQ) {
1538 if (bits != 64)
H. Peter Anvin0db11e22007-04-17 20:23:11 +00001539 return 5;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001540 size[i] = BITS64;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001541 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001542 } else {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001543 asize = 0;
1544 if (itemp->flags & IF_SB) {
1545 asize = BITS8;
1546 oprs = itemp->operands;
1547 } else if (itemp->flags & IF_SW) {
1548 asize = BITS16;
1549 oprs = itemp->operands;
1550 } else if (itemp->flags & IF_SD) {
1551 asize = BITS32;
1552 oprs = itemp->operands;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001553 } else if (itemp->flags & IF_SQ) {
1554 if (bits != 64)
H. Peter Anvin0db11e22007-04-17 20:23:11 +00001555 return 5;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001556 asize = BITS64;
1557 oprs = itemp->operands;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001558 }
1559 size[0] = size[1] = size[2] = asize;
H. Peter Anvinef7468f2002-04-30 20:57:59 +00001560 }
Keith Kaniosb7a89542007-04-12 02:40:54 +00001561
H. Peter Anvinef7468f2002-04-30 20:57:59 +00001562 if (itemp->flags & (IF_SM | IF_SM2)) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001563 oprs = (itemp->flags & IF_SM2 ? 2 : itemp->operands);
1564 asize = 0;
1565 for (i = 0; i < oprs; i++) {
1566 if ((asize = itemp->opd[i] & SIZE_MASK) != 0) {
1567 int j;
1568 for (j = 0; j < oprs; j++)
1569 size[j] = asize;
1570 break;
1571 }
1572 }
H. Peter Anvinef7468f2002-04-30 20:57:59 +00001573 } else {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001574 oprs = itemp->operands;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001575 }
1576
Keith Kaniosb7a89542007-04-12 02:40:54 +00001577 for (i = 0; i < itemp->operands; i++) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001578 if (!(itemp->opd[i] & SIZE_MASK) &&
1579 (instruction->oprs[i].type & SIZE_MASK & ~size[i]))
H. Peter Anvine2c80182005-01-15 22:15:51 +00001580 return 2;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001581
Keith Kaniosb7a89542007-04-12 02:40:54 +00001582 if ( (((itemp->opd[i] & SIZE_MASK) == BITS64) ||
1583 ((instruction->oprs[i].type & SIZE_MASK) == BITS64))
1584 && bits != 64)
H. Peter Anvin0db11e22007-04-17 20:23:11 +00001585 return 5;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001586
1587 x = instruction->oprs[i].indexreg;
1588 b = instruction->oprs[i].basereg;
1589
1590 if (x != -1 && x >= EXPR_REG_START && x < REG_ENUM_LIMIT)
1591 x = regvals[x];
1592 if (b != -1 && b >= EXPR_REG_START && b < REG_ENUM_LIMIT)
1593 b = regvals[b];
1594
1595 if (((b >= 0400 && b <= 0500) || (x >= 0400 && x < 0500)) && bits != 64)
1596 return 2;
1597 }
1598
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001599 /*
1600 * Check template is okay at the set cpu level
1601 */
Keith Kaniosb7a89542007-04-12 02:40:54 +00001602 if (((itemp->flags & IF_PLEVEL) > cpu))
H. Peter Anvine2c80182005-01-15 22:15:51 +00001603 return 3;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001604
1605 /*
1606 * Check if instruction is available in long mode
1607 */
1608 if ((itemp->flags & IF_NOLONG) && (bits == 64))
1609 return 4;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001610
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001611 /*
1612 * Check if special handling needed for Jumps
1613 */
Keith Kaniosb7a89542007-04-12 02:40:54 +00001614 if ((uint8_t)(itemp->code[0]) >= 0370)
H. Peter Anvine2c80182005-01-15 22:15:51 +00001615 return 99;
1616
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001617 return ret;
1618}
1619
H. Peter Anvine2c80182005-01-15 22:15:51 +00001620static ea *process_ea(operand * input, ea * output, int addrbits,
1621 int rfield, int forw_ref)
H. Peter Anvineba20a72002-04-30 20:53:55 +00001622{
Keith Kaniosb7a89542007-04-12 02:40:54 +00001623
1624 int rip = FALSE; /* Used for RIP-relative addressing */
1625
1626
1627 if (!(REGISTER & ~input->type)) { /* register direct */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001628 int i;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001629 if ( input->basereg < EXPR_REG_START /* Verify as Register */
1630 || input->basereg >= REG_ENUM_LIMIT)
H. Peter Anvine2c80182005-01-15 22:15:51 +00001631 return NULL;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001632 i = regvals[input->basereg];
1633 if ( i >= 0100 && i < 0210) /* GPR's, MMX & XMM only */
1634 return NULL;
1635
1636 if (i >= 0400 && i < 0500) { /* Calculate REX.B */
1637 if (i < 0410 || (i >= 0440 && i < 0450))
1638 output->rex |= 0xF0; /* Set REX.0 */
1639 else
1640 output->rex |= 0xF1; /* Set REX.B */
1641 if (i >= 0440)
1642 output->rex |= 0xF8; /* Set REX.W */
1643 }
1644
1645 if ((rfield >= 0400 && rfield < 0500) || /* Calculate REX.R */
1646 (rfield >= 0120 && rfield < 0200 && /* Include CR/DR/TR... */
1647 !(rfield & 0010))) { /* ... extensions, only */
1648 if ((rfield >= 0400 && rfield < 0410) || (rfield >= 0440 && rfield < 0450))
1649 output->rex |= 0xF0; /* Set REX.0 */
1650 else
1651 output->rex |= 0xF4; /* Set REX.R */
1652 if (rfield >= 0440)
1653 output->rex |= 0xF8; /* Set REX.W */
1654 }
1655
1656 output->sib_present = FALSE; /* no SIB necessary */
1657 output->bytes = 0; /* no offset necessary either */
1658 output->modrm = 0xC0 | ((rfield & 7) << 3) | (i & 7);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001659 } else { /* it's a memory reference */
Keith Kaniosb7a89542007-04-12 02:40:54 +00001660
H. Peter Anvine2c80182005-01-15 22:15:51 +00001661 if (input->basereg == -1
1662 && (input->indexreg == -1 || input->scale == 0)) {
1663 /* it's a pure offset */
1664 if (input->addr_size)
1665 addrbits = input->addr_size;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001666
1667 if (rfield >= 0400 && rfield < 0500) { /* Calculate REX.R */
1668 if (rfield < 0410 || (rfield >= 0440 && rfield < 0450))
1669 output->rex |= 0xF0; /* Set REX.0 */
1670 else
1671 output->rex |= 0xF4; /* Set REX.R */
1672 if (rfield >= 0440)
1673 output->rex |= 0xF8; /* Set REX.W */
1674 }
1675
H. Peter Anvine2c80182005-01-15 22:15:51 +00001676 output->sib_present = FALSE;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001677 output->bytes = (addrbits != 16 ? 4 : 2);
1678 output->modrm = (addrbits != 16 ? 5 : 6) | ((rfield & 7) << 3);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001679 } else { /* it's an indirection */
1680 int i = input->indexreg, b = input->basereg, s = input->scale;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001681 int32_t o = input->offset, seg = input->segment;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001682 int hb = input->hintbase, ht = input->hinttype;
1683 int t;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001684 int it, bt;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001685
H. Peter Anvine2c80182005-01-15 22:15:51 +00001686 if (s == 0)
1687 i = -1; /* make this easy, at least */
Keith Kaniosb7a89542007-04-12 02:40:54 +00001688
1689 if (i != -1 && i >= EXPR_REG_START
1690 && i < REG_ENUM_LIMIT)
1691 it = regvals[i];
1692 else
1693 it = -1;
1694
1695 if (b != -1 && b >= EXPR_REG_START
1696 && b < REG_ENUM_LIMIT)
1697 bt = regvals[b];
1698 else
1699 bt = -1;
1700
1701 /* check for a 32/64-bit memory reference... */
1702 if ((it >= 0020 && it < 0030) || (it >= 0430 && it < 0460) ||
1703 (bt >= 0020 && bt < 0030) || (bt >= 0430 && bt < 0460) ||
1704 bt == 0500) {
1705 /* it must be a 32/64-bit memory reference. Firstly we have
1706 * to check that all registers involved are type E/Rxx. */
1707 t = 1;
1708 if (it != -1) {
1709 if (it < 0020 || (it >= 0030 && it < 0430) || it >= 0460)
1710 return NULL;
1711 if (it >= 0440)
1712 t = 2;
1713 else
1714 t = 0;
1715 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001716
Keith Kaniosb7a89542007-04-12 02:40:54 +00001717 if (bt != -1) {
1718 if (bt < 0020 || (bt >= 0030 && bt < 0430) || (bt >= 0460 && bt < 0500))
1719 return NULL;
1720 if (bt == 0500) {
1721 bt = b = -1;
1722 rip = TRUE;
1723 } else if (bt >= 0440) {
1724 if (t < 1)
1725 return NULL;
1726 } else {
1727 if (t > 1)
1728 return NULL;
1729 }
1730 }
1731
H. Peter Anvine2c80182005-01-15 22:15:51 +00001732 /* While we're here, ensure the user didn't specify WORD. */
1733 if (input->addr_size == 16)
1734 return NULL;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001735
Keith Kaniosb7a89542007-04-12 02:40:54 +00001736 /* now reorganize base/index */
1737 if (s == 1 && bt != it && bt != -1 && it != -1 &&
1738 ((hb == bt && ht == EAH_NOTBASE)
1739 || (hb == it && ht == EAH_MAKEBASE)))
1740 t = bt, bt = it, it = t; /* swap if hints say so */
1741 if (bt == it) /* convert EAX+2*EAX to 3*EAX */
1742 bt = -1, s++;
1743 if (bt == -1 && s == 1 && !(hb == it && ht == EAH_NOTBASE))
1744 bt = i, it = -1; /* make single reg base, unless hint */
1745 if (((s == 2 && (it & 7) != (REG_NUM_ESP & 7)
H. Peter Anvine2c80182005-01-15 22:15:51 +00001746 && !(input->eaflags & EAF_TIMESTWO)) || s == 3
Keith Kaniosb7a89542007-04-12 02:40:54 +00001747 || s == 5 || s == 9) && bt == -1)
1748 bt = it, s--; /* convert 3*EAX to EAX+2*EAX */
1749 if (it == -1 && (bt & 7) != (REG_NUM_ESP & 7)
H. Peter Anvine2c80182005-01-15 22:15:51 +00001750 && (input->eaflags & EAF_TIMESTWO))
Keith Kaniosb7a89542007-04-12 02:40:54 +00001751 it = bt, bt = -1, s = 1;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001752 /* convert [NOSPLIT EAX] to sib format with 0x0 displacement */
Keith Kaniosb7a89542007-04-12 02:40:54 +00001753 if (s == 1 && (it & 7) == (REG_NUM_ESP & 7)) /* swap ESP into base if scale is 1 */
1754 t = it, it = bt, bt = t;
1755 if ((it & 7) == (REG_NUM_ESP & 7)
1756 || (s != 1 && s != 2 && s != 4 && s != 8 && it != -1))
H. Peter Anvine2c80182005-01-15 22:15:51 +00001757 return NULL; /* wrong, for various reasons */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001758
Keith Kanios2cc61b32007-04-13 01:17:45 +00001759 if (i >= 0400 && i < 0500) { /* Calculate REX.X */
Keith Kaniosb7a89542007-04-12 02:40:54 +00001760 if (i < 0410 || (i >= 0440 && i < 0450))
1761 output->rex |= 0xF0; /* Set REX.0 */
1762 else
Keith Kanios2cc61b32007-04-13 01:17:45 +00001763 output->rex |= 0xF2; /* Set REX.X */
Keith Kaniosb7a89542007-04-12 02:40:54 +00001764 if (i >= 0440)
1765 output->rex |= 0xF8; /* Set REX.W */
1766 }
1767
1768 if (b >= 0400 && b < 0500) { /* Calculate REX.B */
1769 if (b < 0410 || (b >= 0440 && b < 0450))
1770 output->rex |= 0xF0; /* Set REX.0 */
1771 else
1772 output->rex |= 0xF1; /* Set REX.B */
1773 if (b >= 0440)
1774 output->rex |= 0xF8; /* Set REX.W */
1775 }
1776
1777 if (rfield >= 0400 && rfield < 0500) { /* Calculate REX.R */
1778 if (rfield < 0410 || (rfield >= 0440 && rfield < 0450))
1779 output->rex |= 0xF0; /* Set REX.0 */
1780 else
1781 output->rex |= 0xF4; /* Set REX.R */
1782 if (rfield >= 0440)
1783 output->rex |= 0xF8; /* Set REX.W */
1784 }
1785
1786 if (it == -1 && (bt & 7) != (REG_NUM_ESP & 7)) { /* no SIB needed */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001787 int mod, rm;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001788
1789 if (bt == -1) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001790 rm = 5;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001791 mod = 0;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001792 } else {
1793 rm = (bt & 7);
1794 if (rm != (REG_NUM_EBP & 7) && o == 0 &&
1795 seg == NO_SEG && !forw_ref &&
1796 !(input->eaflags &
1797 (EAF_BYTEOFFS | EAF_WORDOFFS)))
1798 mod = 0;
1799 else if (input->eaflags & EAF_BYTEOFFS ||
1800 (o >= -128 && o <= 127 && seg == NO_SEG
1801 && !forw_ref
1802 && !(input->eaflags & EAF_WORDOFFS)))
1803 mod = 1;
1804 else
1805 mod = 2;
1806 }
H. Peter Anvinea838272002-04-30 20:51:53 +00001807
H. Peter Anvine2c80182005-01-15 22:15:51 +00001808 output->sib_present = FALSE;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001809 output->bytes = (bt == -1 || mod == 2 ? 4 : mod);
1810 output->modrm = (mod << 6) | ((rfield & 7) << 3) | rm;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001811 } else { /* we need a SIB */
1812 int mod, scale, index, base;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001813
1814 if (it == -1)
1815 index = 4, s = 1;
1816 else
1817 index = (it & 7);
1818
H. Peter Anvine2c80182005-01-15 22:15:51 +00001819 switch (s) {
1820 case 1:
1821 scale = 0;
1822 break;
1823 case 2:
1824 scale = 1;
1825 break;
1826 case 4:
1827 scale = 2;
1828 break;
1829 case 8:
1830 scale = 3;
1831 break;
1832 default: /* then what the smeg is it? */
1833 return NULL; /* panic */
1834 }
Keith Kaniosb7a89542007-04-12 02:40:54 +00001835
1836 if (bt == -1) {
1837 base = 5;
1838 mod = 0;
1839 } else {
1840 base = (bt & 7);
1841 if (base != (REG_NUM_EBP & 7) && o == 0 &&
H. Peter Anvine2c80182005-01-15 22:15:51 +00001842 seg == NO_SEG && !forw_ref &&
1843 !(input->eaflags &
Keith Kaniosb7a89542007-04-12 02:40:54 +00001844 (EAF_BYTEOFFS | EAF_WORDOFFS)))
1845 mod = 0;
1846 else if (input->eaflags & EAF_BYTEOFFS ||
1847 (o >= -128 && o <= 127 && seg == NO_SEG
1848 && !forw_ref
1849 && !(input->eaflags & EAF_WORDOFFS)))
1850 mod = 1;
1851 else
1852 mod = 2;
1853 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001854
H. Peter Anvine2c80182005-01-15 22:15:51 +00001855 output->sib_present = TRUE;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001856 output->bytes = (bt == -1 || mod == 2 ? 4 : mod);
1857 output->modrm = (mod << 6) | ((rfield & 7) << 3) | 4;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001858 output->sib = (scale << 6) | (index << 3) | base;
1859 }
1860 } else { /* it's 16-bit */
1861 int mod, rm;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001862
1863 /* check for 64-bit long mode */
1864 if (addrbits == 64)
1865 return NULL;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001866
H. Peter Anvine2c80182005-01-15 22:15:51 +00001867 /* check all registers are BX, BP, SI or DI */
1868 if ((b != -1 && b != R_BP && b != R_BX && b != R_SI
1869 && b != R_DI) || (i != -1 && i != R_BP && i != R_BX
1870 && i != R_SI && i != R_DI))
1871 return NULL;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001872
Keith Kaniosb7a89542007-04-12 02:40:54 +00001873 /* ensure the user didn't specify DWORD/QWORD */
1874 if (input->addr_size == 32 || input->addr_size == 64)
H. Peter Anvine2c80182005-01-15 22:15:51 +00001875 return NULL;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001876
H. Peter Anvine2c80182005-01-15 22:15:51 +00001877 if (s != 1 && i != -1)
1878 return NULL; /* no can do, in 16-bit EA */
1879 if (b == -1 && i != -1) {
1880 int tmp = b;
1881 b = i;
1882 i = tmp;
1883 } /* swap */
1884 if ((b == R_SI || b == R_DI) && i != -1) {
1885 int tmp = b;
1886 b = i;
1887 i = tmp;
1888 }
1889 /* have BX/BP as base, SI/DI index */
1890 if (b == i)
1891 return NULL; /* shouldn't ever happen, in theory */
1892 if (i != -1 && b != -1 &&
1893 (i == R_BP || i == R_BX || b == R_SI || b == R_DI))
1894 return NULL; /* invalid combinations */
1895 if (b == -1) /* pure offset: handled above */
1896 return NULL; /* so if it gets to here, panic! */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001897
H. Peter Anvine2c80182005-01-15 22:15:51 +00001898 rm = -1;
1899 if (i != -1)
1900 switch (i * 256 + b) {
1901 case R_SI * 256 + R_BX:
1902 rm = 0;
1903 break;
1904 case R_DI * 256 + R_BX:
1905 rm = 1;
1906 break;
1907 case R_SI * 256 + R_BP:
1908 rm = 2;
1909 break;
1910 case R_DI * 256 + R_BP:
1911 rm = 3;
1912 break;
1913 } else
1914 switch (b) {
1915 case R_SI:
1916 rm = 4;
1917 break;
1918 case R_DI:
1919 rm = 5;
1920 break;
1921 case R_BP:
1922 rm = 6;
1923 break;
1924 case R_BX:
1925 rm = 7;
1926 break;
1927 }
1928 if (rm == -1) /* can't happen, in theory */
1929 return NULL; /* so panic if it does */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001930
H. Peter Anvine2c80182005-01-15 22:15:51 +00001931 if (o == 0 && seg == NO_SEG && !forw_ref && rm != 6 &&
1932 !(input->eaflags & (EAF_BYTEOFFS | EAF_WORDOFFS)))
1933 mod = 0;
1934 else if (input->eaflags & EAF_BYTEOFFS ||
1935 (o >= -128 && o <= 127 && seg == NO_SEG
1936 && !forw_ref
1937 && !(input->eaflags & EAF_WORDOFFS)))
1938 mod = 1;
1939 else
1940 mod = 2;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001941
H. Peter Anvine2c80182005-01-15 22:15:51 +00001942 output->sib_present = FALSE; /* no SIB - it's 16-bit */
1943 output->bytes = mod; /* bytes of offset needed */
Keith Kaniosb7a89542007-04-12 02:40:54 +00001944 output->modrm = (mod << 6) | ((rfield & 7) << 3) | rm;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001945 }
1946 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001947 }
Keith Kaniosb7a89542007-04-12 02:40:54 +00001948
1949 /* Process RIP-relative Addressing */
1950 if (rip) {
1951 if ((output->modrm & 0xC7) != 0x05)
1952 return NULL;
1953 output->rip = TRUE;
1954 } else {
1955 output->rip = FALSE;
1956 if (globalbits == 64 && /* Actual Disp32 needs blank SIB on x64 */
1957 !(output->sib_present) && ((output->modrm & 0xC7) == 0x05)) {
1958 output->sib_present = TRUE;
1959 output->modrm --; /* RM Field = 4 (forward to Base of SIB) */
1960 output->sib = (4 << 3) | 5; /* Index = 4 (none), Base = 5 */
1961 }
1962 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001963 output->size = 1 + output->sib_present + output->bytes;
1964 return output;
1965}
1966
H. Peter Anvine2c80182005-01-15 22:15:51 +00001967static int chsize(operand * input, int addrbits)
H. Peter Anvineba20a72002-04-30 20:53:55 +00001968{
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001969 if (!(MEMORY & ~input->type)) {
Keith Kaniosb7a89542007-04-12 02:40:54 +00001970 int i, b;
1971
1972 if ( input->indexreg < EXPR_REG_START /* Verify as Register */
1973 || input->indexreg >= REG_ENUM_LIMIT)
1974 i = -1;
1975 else
1976 i = regvals[input->indexreg];
1977
1978 if ( input->basereg < EXPR_REG_START /* Verify as Register */
1979 || input->basereg >= REG_ENUM_LIMIT)
1980 b = -1;
1981 else
1982 b = regvals[input->basereg];
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001983
H. Peter Anvine2c80182005-01-15 22:15:51 +00001984 if (input->scale == 0)
1985 i = -1;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001986
H. Peter Anvine2c80182005-01-15 22:15:51 +00001987 if (i == -1 && b == -1) /* pure offset */
1988 return (input->addr_size != 0 && input->addr_size != addrbits);
Keith Kaniosb7a89542007-04-12 02:40:54 +00001989
1990 if ((i >= 0020 && i < 0030) || (i >= 0430 && i < 0440) ||
1991 (b >= 0020 && b < 0030) || (b >= 0430 && b < 0440))
1992 return (addrbits != 32);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001993 else
1994 return (addrbits == 32);
1995 } else
1996 return 0;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001997}