blob: e538454819ae1e6f48b06549f093f51fa0f88a6d [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
H. Peter Anvin7eb4a382007-09-17 15:49:30 -070015 * \10..\13 - a literal byte follows in the code stream, to be added
16 * to the register value of operand 0..3
17 * \14..\17 - a signed byte immediate operand, from operand 0..3
18 * \20..\23 - a byte immediate operand, from operand 0..3
19 * \24..\27 - an unsigned byte immediate operand, from operand 0..3
20 * \30..\33 - a word immediate operand, from operand 0..3
21 * \34..\37 - select between \3[0-3] and \4[0-3] depending on 16/32 bit
H. Peter Anvin3ba46772002-05-27 23:19:35 +000022 * assembly mode or the operand-size override on the operand
H. Peter Anvin7eb4a382007-09-17 15:49:30 -070023 * \40..\43 - a long immediate operand, from operand 0..3
24 * \44..\47 - select between \3[0-3], \4[0-3] and \5[4-7]
H. Peter Anvinb061d592007-04-16 02:02:06 +000025 * depending on assembly mode or the address-size override
26 * on the operand.
H. Peter Anvin7eb4a382007-09-17 15:49:30 -070027 * \50..\53 - a byte relative operand, from operand 0..3
28 * \54..\57 - a qword immediate operand, from operand 0..3
29 * \60..\63 - a word relative operand, from operand 0..3
30 * \64..\67 - select between \6[0-3] and \7[0-3] depending on 16/32 bit
H. Peter Anvin17799b42002-05-21 03:31:21 +000031 * assembly mode or the operand-size override on the operand
H. Peter Anvin7eb4a382007-09-17 15:49:30 -070032 * \70..\73 - a long relative operand, from operand 0..3
33 * \74..\77 - a word constant, from the _segment_ part of operand 0..3
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000034 * \1ab - a ModRM, calculated on EA in operand a, with the spare
35 * field the register value of operand b.
H. Peter Anvin7eb4a382007-09-17 15:49:30 -070036 * \140..\143 - an immediate word or signed byte for operand 0..3
37 * \144..\147 - or 2 (s-field) into next opcode byte if operand 0..3
H. Peter Anvinaf535c12002-04-30 20:59:21 +000038 * is a signed byte rather than a word.
H. Peter Anvin7eb4a382007-09-17 15:49:30 -070039 * \150..\153 - an immediate dword or signed byte for operand 0..3
40 * \154..\157 - or 2 (s-field) into next opcode byte if operand 0..3
H. Peter Anvinaf535c12002-04-30 20:59:21 +000041 * is a signed byte rather than a dword.
H. Peter Anvin401c07e2007-09-17 16:55:04 -070042 * \160..\163 - this instruction uses DREX rather than REX, with the
43 * OC0 field set to 0, and the dest field taken from
44 * operand 0..3.
45 * \164..\167 - this instruction uses DREX rather than REX, with the
46 * OC0 field set to 1, and the dest field taken from
47 * operand 0..3.
H. Peter Anvin7eb4a382007-09-17 15:49:30 -070048 * \170 - encodes the literal byte 0. (Some compilers don't take
49 * kindly to a zero byte in the _middle_ of a compile time
50 * string constant, so I had to put this hack in.)
H. Peter Anvin401c07e2007-09-17 16:55:04 -070051 * \171 - placement of DREX suffix in the absence of an EA
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000052 * \2ab - a ModRM, calculated on EA in operand a, with the spare
53 * field equal to digit b.
54 * \30x - might be an 0x67 byte, depending on the address size of
55 * the memory reference in operand x.
56 * \310 - indicates fixed 16-bit address size, i.e. optional 0x67.
57 * \311 - indicates fixed 32-bit address size, i.e. optional 0x67.
Keith Kanios48af1772007-08-17 07:37:52 +000058 * \312 - (disassembler only) marker on LOOP, LOOPxx instructions.
H. Peter Anvince2b3972007-05-30 22:21:11 +000059 * \313 - indicates fixed 64-bit address size, 0x67 invalid.
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000060 * \320 - indicates fixed 16-bit operand size, i.e. optional 0x66.
61 * \321 - indicates fixed 32-bit operand size, i.e. optional 0x66.
62 * \322 - indicates that this instruction is only valid when the
63 * operand size is the default (instruction to disassembler,
64 * generates no code in the assembler)
H. Peter Anvince2b3972007-05-30 22:21:11 +000065 * \323 - indicates fixed 64-bit operand size, REX on extensions only.
Keith Kaniosb7a89542007-04-12 02:40:54 +000066 * \324 - indicates 64-bit operand size requiring REX prefix.
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000067 * \330 - a literal byte follows in the code stream, to be added
68 * to the condition code value of the instruction.
Keith Kanios48af1772007-08-17 07:37:52 +000069 * \331 - instruction not valid with REP prefix. Hint for
H. Peter Anvinef7468f2002-04-30 20:57:59 +000070 * disassembler only; for SSE instructions.
H. Peter Anvincb9b6902007-09-12 21:58:51 -070071 * \332 - REP prefix (0xF2 byte) used as opcode extension.
72 * \333 - REP prefix (0xF3 byte) used as opcode extension.
Keith Kanios48af1772007-08-17 07:37:52 +000073 * \334 - LOCK prefix used instead of REX.R
H. Peter Anvincb9b6902007-09-12 21:58:51 -070074 * \335 - disassemble a rep (0xF3 byte) prefix as repe not rep.
Keith Kaniosb7a89542007-04-12 02:40:54 +000075 * \340 - reserve <operand 0> bytes of uninitialized storage.
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000076 * Operand 0 had better be a segmentless constant.
H. Peter Anvin62cb6062007-09-11 22:44:03 +000077 * \364 - operand-size prefix (0x66) not permitted
78 * \365 - address-size prefix (0x67) not permitted
79 * \366 - operand-size prefix (0x66) used as opcode extension
80 * \367 - address-size prefix (0x67) used as opcode extension
H. Peter Anvin788e6c12002-04-30 21:02:01 +000081 * \370,\371,\372 - match only if operand 0 meets byte jump criteria.
82 * 370 is used for Jcc, 371 is used for JMP.
H. Peter Anvinaf535c12002-04-30 20:59:21 +000083 * \373 - assemble 0x03 if bits==16, 0x05 if bits==32;
84 * used for conditional jump over longer jump
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000085 */
86
87#include <stdio.h>
88#include <string.h>
Keith Kaniosb7a89542007-04-12 02:40:54 +000089#include <inttypes.h>
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000090
91#include "nasm.h"
H. Peter Anvin6768eb72002-04-30 20:52:26 +000092#include "nasmlib.h"
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000093#include "assemble.h"
94#include "insns.h"
Frank Kotlerd0ed6fd2003-08-27 11:33:56 +000095#include "preproc.h"
H. Peter Anvin3df97a72007-05-30 03:25:21 +000096#include "regflags.c"
Keith Kaniosb7a89542007-04-12 02:40:54 +000097#include "regvals.c"
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000098
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000099typedef struct {
Keith Kaniosb7a89542007-04-12 02:40:54 +0000100 int sib_present; /* is a SIB byte necessary? */
101 int bytes; /* # of bytes of offset needed */
102 int size; /* lazy - this is sib+bytes+1 */
103 uint8_t modrm, sib, rex, rip; /* the bytes themselves */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000104} ea;
105
Keith Kaniosb7a89542007-04-12 02:40:54 +0000106static uint32_t cpu; /* cpu level received from nasm.c */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000107static efunc errfunc;
108static struct ofmt *outfmt;
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000109static ListGen *list;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000110
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000111static int32_t calcsize(int32_t, int32_t, int, insn *, const char *);
112static void gencode(int32_t, int32_t, int, insn *, const char *, int32_t);
H. Peter Anvin3360d792007-09-11 04:16:57 +0000113static int matches(const struct itemplate *, insn *, int bits);
H. Peter Anvin3df97a72007-05-30 03:25:21 +0000114static int32_t regflag(const operand *);
115static int32_t regval(const operand *);
116static int rexflags(int, int32_t, int);
117static int op_rexflags(const operand *, int);
H. Peter Anvin5b0e3ec2007-07-07 02:01:08 +0000118static ea *process_ea(operand *, ea *, int, int, int32_t, int);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000119static int chsize(operand *, int);
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000120
H. Peter Anvin0db11e22007-04-17 20:23:11 +0000121static void assert_no_prefix(insn * ins, int prefix)
122{
123 int j;
124
125 for (j = 0; j < ins->nprefix; j++) {
126 if (ins->prefixes[j] == prefix) {
127 errfunc(ERR_NONFATAL, "invalid %s prefix", prefix_name(prefix));
128 break;
129 }
130 }
131}
132
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000133/*
134 * This routine wrappers the real output format's output routine,
135 * in order to pass a copy of the data off to the listing file
136 * generator at the same time.
137 */
Keith Kaniosb7a89542007-04-12 02:40:54 +0000138static void out(int32_t offset, int32_t segto, const void *data,
139 uint32_t type, int32_t segment, int32_t wrt)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000140{
Keith Kaniosb7a89542007-04-12 02:40:54 +0000141 static int32_t lineno = 0; /* static!!! */
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000142 static char *lnfname = NULL;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000143
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000144 if ((type & OUT_TYPMASK) == OUT_ADDRESS) {
H. Peter Anvine2c80182005-01-15 22:15:51 +0000145 if (segment != NO_SEG || wrt != NO_SEG) {
146 /*
147 * This address is relocated. We must write it as
148 * OUT_ADDRESS, so there's no work to be done here.
149 */
150 list->output(offset, data, type);
151 } else {
Keith Kaniosb7a89542007-04-12 02:40:54 +0000152 uint8_t p[8], *q = p;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000153 /*
154 * This is a non-relocated address, and we're going to
155 * convert it into RAWDATA format.
156 */
157 if ((type & OUT_SIZMASK) == 4) {
Keith Kaniosb7a89542007-04-12 02:40:54 +0000158 WRITELONG(q, *(int32_t *)data);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000159 list->output(offset, p, OUT_RAWDATA + 4);
Keith Kaniosb7a89542007-04-12 02:40:54 +0000160 } else if ((type & OUT_SIZMASK) == 8) {
161 WRITEDLONG(q, *(int64_t *)data);
162 list->output(offset, p, OUT_RAWDATA + 8);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000163 } else {
Keith Kaniosb7a89542007-04-12 02:40:54 +0000164 WRITESHORT(q, *(int32_t *)data);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000165 list->output(offset, p, OUT_RAWDATA + 2);
166 }
167 }
168 } else if ((type & OUT_TYPMASK) == OUT_RAWDATA) {
169 list->output(offset, data, type);
170 } else if ((type & OUT_TYPMASK) == OUT_RESERVE) {
171 list->output(offset, NULL, type);
172 } else if ((type & OUT_TYPMASK) == OUT_REL2ADR ||
173 (type & OUT_TYPMASK) == OUT_REL4ADR) {
174 list->output(offset, data, type);
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000175 }
176
Frank Kotlerabebb082003-09-06 04:45:37 +0000177 /*
178 * this call to src_get determines when we call the
179 * debug-format-specific "linenum" function
180 * it updates lineno and lnfname to the current values
181 * returning 0 if "same as last time", -2 if lnfname
182 * changed, and the amount by which lineno changed,
183 * if it did. thus, these variables must be static
184 */
185
H. Peter Anvine2c80182005-01-15 22:15:51 +0000186 if (src_get(&lineno, &lnfname)) {
187 outfmt->current_dfmt->linenum(lnfname, lineno, segto);
H. Peter Anvince616072002-04-30 21:02:23 +0000188 }
H. Peter Anvineba20a72002-04-30 20:53:55 +0000189
H. Peter Anvine2c80182005-01-15 22:15:51 +0000190 outfmt->output(segto, data, type, segment, wrt);
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000191}
192
Keith Kaniosb7a89542007-04-12 02:40:54 +0000193static int jmp_match(int32_t segment, int32_t offset, int bits,
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000194 insn * ins, const char *code)
H. Peter Anvine2c80182005-01-15 22:15:51 +0000195{
Keith Kaniosb7a89542007-04-12 02:40:54 +0000196 int32_t isize;
197 uint8_t c = code[0];
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000198
H. Peter Anvine2c80182005-01-15 22:15:51 +0000199 if (c != 0370 && c != 0371)
200 return 0;
H. Peter Anvin788e6c12002-04-30 21:02:01 +0000201 if (ins->oprs[0].opflags & OPFLAG_FORWARD) {
H. Peter Anvine2c80182005-01-15 22:15:51 +0000202 if ((optimizing < 0 || (ins->oprs[0].type & STRICT))
203 && c == 0370)
204 return 1;
205 else
206 return (pass0 == 0); /* match a forward reference */
H. Peter Anvin788e6c12002-04-30 21:02:01 +0000207 }
H. Peter Anvine2c80182005-01-15 22:15:51 +0000208 isize = calcsize(segment, offset, bits, ins, code);
209 if (ins->oprs[0].segment != segment)
210 return 0;
211 isize = ins->oprs[0].offset - offset - isize; /* isize is now the delta */
212 if (isize >= -128L && isize <= 127L)
213 return 1; /* it is byte size */
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000214
215 return 0;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000216}
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000217
Keith Kaniosb7a89542007-04-12 02:40:54 +0000218int32_t assemble(int32_t segment, int32_t offset, int bits, uint32_t cp,
H. Peter Anvine2c80182005-01-15 22:15:51 +0000219 insn * instruction, struct ofmt *output, efunc error,
220 ListGen * listgen)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000221{
H. Peter Anvin3360d792007-09-11 04:16:57 +0000222 const struct itemplate *temp;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000223 int j;
224 int size_prob;
Keith Kaniosb7a89542007-04-12 02:40:54 +0000225 int32_t insn_end;
226 int32_t itimes;
227 int32_t start = offset;
228 int32_t wsize = 0; /* size for DB etc. */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000229
H. Peter Anvine2c80182005-01-15 22:15:51 +0000230 errfunc = error; /* to pass to other functions */
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000231 cpu = cp;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000232 outfmt = output; /* likewise */
233 list = listgen; /* and again */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000234
H. Peter Anvine2c80182005-01-15 22:15:51 +0000235 switch (instruction->opcode) {
236 case -1:
237 return 0;
238 case I_DB:
239 wsize = 1;
240 break;
241 case I_DW:
242 wsize = 2;
243 break;
244 case I_DD:
245 wsize = 4;
246 break;
247 case I_DQ:
248 wsize = 8;
249 break;
250 case I_DT:
251 wsize = 10;
252 break;
H. Peter Anvin16b0a332007-09-12 20:27:41 -0700253 default:
254 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000255 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000256
H. Peter Anvineba20a72002-04-30 20:53:55 +0000257 if (wsize) {
H. Peter Anvine2c80182005-01-15 22:15:51 +0000258 extop *e;
Keith Kaniosb7a89542007-04-12 02:40:54 +0000259 int32_t t = instruction->times;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000260 if (t < 0)
261 errfunc(ERR_PANIC,
262 "instruction->times < 0 (%ld) in assemble()", t);
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000263
H. Peter Anvine2c80182005-01-15 22:15:51 +0000264 while (t--) { /* repeat TIMES times */
265 for (e = instruction->eops; e; e = e->next) {
266 if (e->type == EOT_DB_NUMBER) {
267 if (wsize == 1) {
268 if (e->segment != NO_SEG)
269 errfunc(ERR_NONFATAL,
270 "one-byte relocation attempted");
271 else {
Keith Kaniosb7a89542007-04-12 02:40:54 +0000272 uint8_t out_byte = e->offset;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000273 out(offset, segment, &out_byte,
274 OUT_RAWDATA + 1, NO_SEG, NO_SEG);
275 }
Keith Kanios61ff53c2007-04-14 18:54:52 +0000276 } else if (wsize > 8) {
277 errfunc(ERR_NONFATAL, "integer supplied to a DT"
278 " instruction");
H. Peter Anvine2c80182005-01-15 22:15:51 +0000279 } else
280 out(offset, segment, &e->offset,
281 OUT_ADDRESS + wsize, e->segment, e->wrt);
282 offset += wsize;
283 } else if (e->type == EOT_DB_STRING) {
284 int align;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000285
H. Peter Anvine2c80182005-01-15 22:15:51 +0000286 out(offset, segment, e->stringval,
287 OUT_RAWDATA + e->stringlen, NO_SEG, NO_SEG);
288 align = e->stringlen % wsize;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000289
H. Peter Anvine2c80182005-01-15 22:15:51 +0000290 if (align) {
291 align = wsize - align;
292 out(offset, segment, "\0\0\0\0\0\0\0\0",
293 OUT_RAWDATA + align, NO_SEG, NO_SEG);
294 }
295 offset += e->stringlen + align;
296 }
297 }
298 if (t > 0 && t == instruction->times - 1) {
299 /*
300 * Dummy call to list->output to give the offset to the
301 * listing module.
302 */
303 list->output(offset, NULL, OUT_RAWDATA);
304 list->uplevel(LIST_TIMES);
305 }
306 }
307 if (instruction->times > 1)
308 list->downlevel(LIST_TIMES);
309 return offset - start;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000310 }
311
H. Peter Anvine2c80182005-01-15 22:15:51 +0000312 if (instruction->opcode == I_INCBIN) {
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000313 static char fname[FILENAME_MAX];
H. Peter Anvine2c80182005-01-15 22:15:51 +0000314 FILE *fp;
Keith Kaniosb7a89542007-04-12 02:40:54 +0000315 int32_t len;
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000316 char *prefix = "", *combine;
317 char **pPrevPath = NULL;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000318
H. Peter Anvine2c80182005-01-15 22:15:51 +0000319 len = FILENAME_MAX - 1;
320 if (len > instruction->eops->stringlen)
321 len = instruction->eops->stringlen;
322 strncpy(fname, instruction->eops->stringval, len);
323 fname[len] = '\0';
H. Peter Anvineba20a72002-04-30 20:53:55 +0000324
Keith Kaniosb7a89542007-04-12 02:40:54 +0000325 while (1) { /* added by alexfru: 'incbin' uses include paths */
H. Peter Anvine2c80182005-01-15 22:15:51 +0000326 combine = nasm_malloc(strlen(prefix) + len + 1);
327 strcpy(combine, prefix);
328 strcat(combine, fname);
Frank Kotlerd0ed6fd2003-08-27 11:33:56 +0000329
H. Peter Anvine2c80182005-01-15 22:15:51 +0000330 if ((fp = fopen(combine, "rb")) != NULL) {
331 nasm_free(combine);
332 break;
333 }
Frank Kotlerd0ed6fd2003-08-27 11:33:56 +0000334
H. Peter Anvine2c80182005-01-15 22:15:51 +0000335 nasm_free(combine);
336 pPrevPath = pp_get_include_path_ptr(pPrevPath);
337 if (pPrevPath == NULL)
338 break;
339 prefix = *pPrevPath;
Frank Kotlerd0ed6fd2003-08-27 11:33:56 +0000340 }
341
342 if (fp == NULL)
H. Peter Anvine2c80182005-01-15 22:15:51 +0000343 error(ERR_NONFATAL, "`incbin': unable to open file `%s'",
344 fname);
345 else if (fseek(fp, 0L, SEEK_END) < 0)
346 error(ERR_NONFATAL, "`incbin': unable to seek on file `%s'",
347 fname);
348 else {
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000349 static char buf[2048];
Keith Kaniosb7a89542007-04-12 02:40:54 +0000350 int32_t t = instruction->times;
351 int32_t base = 0;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000352
H. Peter Anvine2c80182005-01-15 22:15:51 +0000353 len = ftell(fp);
354 if (instruction->eops->next) {
355 base = instruction->eops->next->offset;
356 len -= base;
357 if (instruction->eops->next->next &&
358 len > instruction->eops->next->next->offset)
359 len = instruction->eops->next->next->offset;
360 }
361 /*
362 * Dummy call to list->output to give the offset to the
363 * listing module.
364 */
365 list->output(offset, NULL, OUT_RAWDATA);
366 list->uplevel(LIST_INCBIN);
367 while (t--) {
Keith Kaniosb7a89542007-04-12 02:40:54 +0000368 int32_t l;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000369
H. Peter Anvine2c80182005-01-15 22:15:51 +0000370 fseek(fp, base, SEEK_SET);
371 l = len;
372 while (l > 0) {
Keith Kaniosb7a89542007-04-12 02:40:54 +0000373 int32_t m =
H. Peter Anvine2c80182005-01-15 22:15:51 +0000374 fread(buf, 1, (l > sizeof(buf) ? sizeof(buf) : l),
375 fp);
376 if (!m) {
377 /*
378 * This shouldn't happen unless the file
379 * actually changes while we are reading
380 * it.
381 */
382 error(ERR_NONFATAL,
383 "`incbin': unexpected EOF while"
384 " reading file `%s'", fname);
385 t = 0; /* Try to exit cleanly */
386 break;
387 }
388 out(offset, segment, buf, OUT_RAWDATA + m,
389 NO_SEG, NO_SEG);
390 l -= m;
391 }
392 }
393 list->downlevel(LIST_INCBIN);
394 if (instruction->times > 1) {
395 /*
396 * Dummy call to list->output to give the offset to the
397 * listing module.
398 */
399 list->output(offset, NULL, OUT_RAWDATA);
400 list->uplevel(LIST_TIMES);
401 list->downlevel(LIST_TIMES);
402 }
403 fclose(fp);
404 return instruction->times * len;
405 }
406 return 0; /* if we're here, there's an error */
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000407 }
408
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000409 size_prob = FALSE;
Keith Kaniosb7a89542007-04-12 02:40:54 +0000410
411 for (temp = nasm_instructions[instruction->opcode]; temp->opcode != -1; temp++){
412 int m = matches(temp, instruction, bits);
413
H. Peter Anvine2c80182005-01-15 22:15:51 +0000414 if (m == 99)
415 m += jmp_match(segment, offset, bits, instruction, temp->code);
H. Peter Anvineba20a72002-04-30 20:53:55 +0000416
H. Peter Anvine2c80182005-01-15 22:15:51 +0000417 if (m == 100) { /* matches! */
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000418 const char *codes = temp->code;
Keith Kaniosb7a89542007-04-12 02:40:54 +0000419 int32_t insn_size = calcsize(segment, offset, bits,
H. Peter Anvine2c80182005-01-15 22:15:51 +0000420 instruction, codes);
421 itimes = instruction->times;
422 if (insn_size < 0) /* shouldn't be, on pass two */
423 error(ERR_PANIC, "errors made it through from pass one");
424 else
425 while (itimes--) {
426 for (j = 0; j < instruction->nprefix; j++) {
Keith Kaniosb7a89542007-04-12 02:40:54 +0000427 uint8_t c = 0;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000428 switch (instruction->prefixes[j]) {
429 case P_LOCK:
430 c = 0xF0;
431 break;
432 case P_REPNE:
433 case P_REPNZ:
434 c = 0xF2;
435 break;
436 case P_REPE:
437 case P_REPZ:
438 case P_REP:
439 c = 0xF3;
440 break;
441 case R_CS:
Keith Kaniosfd5d9132007-04-16 15:46:46 +0000442 if (bits == 64) {
443 error(ERR_WARNING,
444 "cs segment base ignored in 64-bit mode");
445 }
H. Peter Anvine2c80182005-01-15 22:15:51 +0000446 c = 0x2E;
447 break;
448 case R_DS:
Keith Kaniosfd5d9132007-04-16 15:46:46 +0000449 if (bits == 64) {
450 error(ERR_WARNING,
451 "ds segment base ignored in 64-bit mode");
452 }
H. Peter Anvine2c80182005-01-15 22:15:51 +0000453 c = 0x3E;
454 break;
455 case R_ES:
Keith Kaniosfd5d9132007-04-16 15:46:46 +0000456 if (bits == 64) {
457 error(ERR_WARNING,
458 "es segment base ignored in 64-bit mode");
459 }
H. Peter Anvine2c80182005-01-15 22:15:51 +0000460 c = 0x26;
461 break;
462 case R_FS:
463 c = 0x64;
464 break;
465 case R_GS:
466 c = 0x65;
467 break;
468 case R_SS:
Keith Kaniosfd5d9132007-04-16 15:46:46 +0000469 if (bits == 64) {
470 error(ERR_WARNING,
471 "ss segment base ignored in 64-bit mode");
472 }
H. Peter Anvine2c80182005-01-15 22:15:51 +0000473 c = 0x36;
474 break;
475 case R_SEGR6:
476 case R_SEGR7:
477 error(ERR_NONFATAL,
478 "segr6 and segr7 cannot be used as prefixes");
479 break;
480 case P_A16:
Keith Kaniosb7a89542007-04-12 02:40:54 +0000481 if (bits == 64) {
H. Peter Anvin0db11e22007-04-17 20:23:11 +0000482 error(ERR_NONFATAL,
483 "16-bit addressing is not supported "
484 "in 64-bit mode");
Keith Kaniosb7a89542007-04-12 02:40:54 +0000485 break;
486 }
H. Peter Anvine2c80182005-01-15 22:15:51 +0000487 if (bits != 16)
488 c = 0x67;
489 break;
490 case P_A32:
491 if (bits != 32)
492 c = 0x67;
493 break;
494 case P_O16:
495 if (bits != 16)
496 c = 0x66;
497 break;
498 case P_O32:
Keith Kaniosb7a89542007-04-12 02:40:54 +0000499 if (bits == 16)
H. Peter Anvine2c80182005-01-15 22:15:51 +0000500 c = 0x66;
501 break;
502 default:
503 error(ERR_PANIC, "invalid instruction prefix");
504 }
505 if (c != 0) {
506 out(offset, segment, &c, OUT_RAWDATA + 1,
507 NO_SEG, NO_SEG);
508 offset++;
509 }
Keith Kaniosb7a89542007-04-12 02:40:54 +0000510 }
H. Peter Anvine2c80182005-01-15 22:15:51 +0000511 insn_end = offset + insn_size;
512 gencode(segment, offset, bits, instruction, codes,
513 insn_end);
514 offset += insn_size;
515 if (itimes > 0 && itimes == instruction->times - 1) {
516 /*
517 * Dummy call to list->output to give the offset to the
518 * listing module.
519 */
520 list->output(offset, NULL, OUT_RAWDATA);
521 list->uplevel(LIST_TIMES);
522 }
523 }
524 if (instruction->times > 1)
525 list->downlevel(LIST_TIMES);
526 return offset - start;
527 } else if (m > 0 && m > size_prob) {
528 size_prob = m;
529 }
Keith Kaniosb7a89542007-04-12 02:40:54 +0000530// temp++;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000531 }
H. Peter Anvineba20a72002-04-30 20:53:55 +0000532
H. Peter Anvine2c80182005-01-15 22:15:51 +0000533 if (temp->opcode == -1) { /* didn't match any instruction */
H. Peter Anvin34539fb2007-05-30 04:27:58 +0000534 switch (size_prob) {
535 case 1:
536 error(ERR_NONFATAL, "operation size not specified");
537 break;
538 case 2:
H. Peter Anvine2c80182005-01-15 22:15:51 +0000539 error(ERR_NONFATAL, "mismatch in operand sizes");
H. Peter Anvin34539fb2007-05-30 04:27:58 +0000540 break;
541 case 3:
H. Peter Anvine2c80182005-01-15 22:15:51 +0000542 error(ERR_NONFATAL, "no instruction for this cpu level");
H. Peter Anvin34539fb2007-05-30 04:27:58 +0000543 break;
544 case 4:
H. Peter Anvin0db11e22007-04-17 20:23:11 +0000545 error(ERR_NONFATAL, "instruction not supported in 64-bit mode");
H. Peter Anvin34539fb2007-05-30 04:27:58 +0000546 break;
547 default:
H. Peter Anvine2c80182005-01-15 22:15:51 +0000548 error(ERR_NONFATAL,
549 "invalid combination of opcode and operands");
H. Peter Anvin34539fb2007-05-30 04:27:58 +0000550 break;
551 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000552 }
553 return 0;
554}
555
Keith Kaniosb7a89542007-04-12 02:40:54 +0000556int32_t insn_size(int32_t segment, int32_t offset, int bits, uint32_t cp,
H. Peter Anvine2c80182005-01-15 22:15:51 +0000557 insn * instruction, efunc error)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000558{
H. Peter Anvin3360d792007-09-11 04:16:57 +0000559 const struct itemplate *temp;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000560
H. Peter Anvine2c80182005-01-15 22:15:51 +0000561 errfunc = error; /* to pass to other functions */
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000562 cpu = cp;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000563
564 if (instruction->opcode == -1)
H. Peter Anvine2c80182005-01-15 22:15:51 +0000565 return 0;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000566
567 if (instruction->opcode == I_DB ||
H. Peter Anvine2c80182005-01-15 22:15:51 +0000568 instruction->opcode == I_DW ||
569 instruction->opcode == I_DD ||
570 instruction->opcode == I_DQ || instruction->opcode == I_DT) {
571 extop *e;
Keith Kaniosb7a89542007-04-12 02:40:54 +0000572 int32_t isize, osize, wsize = 0; /* placate gcc */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000573
H. Peter Anvine2c80182005-01-15 22:15:51 +0000574 isize = 0;
575 switch (instruction->opcode) {
576 case I_DB:
577 wsize = 1;
578 break;
579 case I_DW:
580 wsize = 2;
581 break;
582 case I_DD:
583 wsize = 4;
584 break;
585 case I_DQ:
586 wsize = 8;
587 break;
588 case I_DT:
589 wsize = 10;
590 break;
H. Peter Anvin16b0a332007-09-12 20:27:41 -0700591 default:
592 break;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000593 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000594
H. Peter Anvine2c80182005-01-15 22:15:51 +0000595 for (e = instruction->eops; e; e = e->next) {
Keith Kaniosb7a89542007-04-12 02:40:54 +0000596 int32_t align;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000597
H. Peter Anvine2c80182005-01-15 22:15:51 +0000598 osize = 0;
599 if (e->type == EOT_DB_NUMBER)
600 osize = 1;
601 else if (e->type == EOT_DB_STRING)
602 osize = e->stringlen;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000603
H. Peter Anvine2c80182005-01-15 22:15:51 +0000604 align = (-osize) % wsize;
605 if (align < 0)
606 align += wsize;
607 isize += osize + align;
608 }
609 return isize * instruction->times;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000610 }
611
H. Peter Anvine2c80182005-01-15 22:15:51 +0000612 if (instruction->opcode == I_INCBIN) {
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000613 char fname[FILENAME_MAX];
H. Peter Anvine2c80182005-01-15 22:15:51 +0000614 FILE *fp;
Keith Kaniosb7a89542007-04-12 02:40:54 +0000615 int32_t len;
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000616 char *prefix = "", *combine;
617 char **pPrevPath = NULL;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000618
H. Peter Anvine2c80182005-01-15 22:15:51 +0000619 len = FILENAME_MAX - 1;
620 if (len > instruction->eops->stringlen)
621 len = instruction->eops->stringlen;
622 strncpy(fname, instruction->eops->stringval, len);
623 fname[len] = '\0';
Frank Kotlerd0ed6fd2003-08-27 11:33:56 +0000624
H. Peter Anvine2c80182005-01-15 22:15:51 +0000625 while (1) { /* added by alexfru: 'incbin' uses include paths */
626 combine = nasm_malloc(strlen(prefix) + len + 1);
627 strcpy(combine, prefix);
628 strcat(combine, fname);
Frank Kotlerd0ed6fd2003-08-27 11:33:56 +0000629
H. Peter Anvine2c80182005-01-15 22:15:51 +0000630 if ((fp = fopen(combine, "rb")) != NULL) {
631 nasm_free(combine);
632 break;
633 }
Frank Kotlerd0ed6fd2003-08-27 11:33:56 +0000634
H. Peter Anvine2c80182005-01-15 22:15:51 +0000635 nasm_free(combine);
636 pPrevPath = pp_get_include_path_ptr(pPrevPath);
637 if (pPrevPath == NULL)
638 break;
639 prefix = *pPrevPath;
Frank Kotlerd0ed6fd2003-08-27 11:33:56 +0000640 }
641
642 if (fp == NULL)
H. Peter Anvine2c80182005-01-15 22:15:51 +0000643 error(ERR_NONFATAL, "`incbin': unable to open file `%s'",
644 fname);
645 else if (fseek(fp, 0L, SEEK_END) < 0)
646 error(ERR_NONFATAL, "`incbin': unable to seek on file `%s'",
647 fname);
648 else {
649 len = ftell(fp);
650 fclose(fp);
651 if (instruction->eops->next) {
652 len -= instruction->eops->next->offset;
653 if (instruction->eops->next->next &&
654 len > instruction->eops->next->next->offset) {
655 len = instruction->eops->next->next->offset;
656 }
657 }
658 return instruction->times * len;
659 }
660 return 0; /* if we're here, there's an error */
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000661 }
662
Keith Kaniosb7a89542007-04-12 02:40:54 +0000663 for (temp = nasm_instructions[instruction->opcode]; temp->opcode != -1; temp++) {
664 int m = matches(temp, instruction, bits);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000665 if (m == 99)
666 m += jmp_match(segment, offset, bits, instruction, temp->code);
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000667
H. Peter Anvine2c80182005-01-15 22:15:51 +0000668 if (m == 100) {
669 /* we've matched an instruction. */
Keith Kaniosb7a89542007-04-12 02:40:54 +0000670 int32_t isize;
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000671 const char *codes = temp->code;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000672 int j;
673
674 isize = calcsize(segment, offset, bits, instruction, codes);
675 if (isize < 0)
676 return -1;
677 for (j = 0; j < instruction->nprefix; j++) {
678 if ((instruction->prefixes[j] != P_A16 &&
679 instruction->prefixes[j] != P_O16 && bits == 16) ||
680 (instruction->prefixes[j] != P_A32 &&
Keith Kaniosfd5d9132007-04-16 15:46:46 +0000681 instruction->prefixes[j] != P_O32 && bits >= 32)) {
H. Peter Anvine2c80182005-01-15 22:15:51 +0000682 isize++;
683 }
684 }
685 return isize * instruction->times;
686 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000687 }
H. Peter Anvine2c80182005-01-15 22:15:51 +0000688 return -1; /* didn't match any instruction */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000689}
690
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000691/* check that opn[op] is a signed byte of size 16 or 32,
692 and return the signed value*/
H. Peter Anvine2c80182005-01-15 22:15:51 +0000693static int is_sbyte(insn * ins, int op, int size)
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000694{
Keith Kaniosb7a89542007-04-12 02:40:54 +0000695 int32_t v;
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000696 int ret;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000697
698 ret = !(ins->forw_ref && ins->oprs[op].opflags) && /* dead in the water on forward reference or External */
699 optimizing >= 0 &&
700 !(ins->oprs[op].type & STRICT) &&
701 ins->oprs[op].wrt == NO_SEG && ins->oprs[op].segment == NO_SEG;
H. Peter Anvin734b1882002-04-30 21:01:08 +0000702
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000703 v = ins->oprs[op].offset;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000704 if (size == 16)
Keith Kaniosb7a89542007-04-12 02:40:54 +0000705 v = (int16_t)v; /* sign extend if 16 bits */
H. Peter Anvine2c80182005-01-15 22:15:51 +0000706
707 return ret && v >= -128L && v <= 127L;
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000708}
709
Keith Kaniosb7a89542007-04-12 02:40:54 +0000710static int32_t calcsize(int32_t segment, int32_t offset, int bits,
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000711 insn * ins, const char *codes)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000712{
Keith Kaniosb7a89542007-04-12 02:40:54 +0000713 int32_t length = 0;
714 uint8_t c;
H. Peter Anvin3df97a72007-05-30 03:25:21 +0000715 int rex_mask = ~0;
H. Peter Anvin8d7316a2007-04-18 02:27:18 +0000716 ins->rex = 0; /* Ensure REX is reset */
H. Peter Anvineba20a72002-04-30 20:53:55 +0000717
H. Peter Anvine2c80182005-01-15 22:15:51 +0000718 (void)segment; /* Don't warn that this parameter is unused */
719 (void)offset; /* Don't warn that this parameter is unused */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000720
H. Peter Anvine2c80182005-01-15 22:15:51 +0000721 while (*codes)
722 switch (c = *codes++) {
723 case 01:
724 case 02:
725 case 03:
726 codes += c, length += c;
727 break;
728 case 04:
729 case 05:
730 case 06:
731 case 07:
732 length++;
733 break;
734 case 010:
735 case 011:
736 case 012:
H. Peter Anvin7eb4a382007-09-17 15:49:30 -0700737 case 013:
H. Peter Anvin3df97a72007-05-30 03:25:21 +0000738 ins->rex |=
739 op_rexflags(&ins->oprs[c - 010], REX_B|REX_H|REX_P|REX_W);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000740 codes++, length++;
741 break;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000742 case 014:
743 case 015:
744 case 016:
H. Peter Anvin7eb4a382007-09-17 15:49:30 -0700745 case 017:
H. Peter Anvine2c80182005-01-15 22:15:51 +0000746 length++;
747 break;
748 case 020:
749 case 021:
750 case 022:
H. Peter Anvin7eb4a382007-09-17 15:49:30 -0700751 case 023:
H. Peter Anvine2c80182005-01-15 22:15:51 +0000752 length++;
753 break;
754 case 024:
755 case 025:
756 case 026:
H. Peter Anvin7eb4a382007-09-17 15:49:30 -0700757 case 027:
H. Peter Anvine2c80182005-01-15 22:15:51 +0000758 length++;
759 break;
760 case 030:
761 case 031:
762 case 032:
H. Peter Anvin7eb4a382007-09-17 15:49:30 -0700763 case 033:
H. Peter Anvine2c80182005-01-15 22:15:51 +0000764 length += 2;
765 break;
766 case 034:
767 case 035:
768 case 036:
H. Peter Anvin7eb4a382007-09-17 15:49:30 -0700769 case 037:
Keith Kaniosb7a89542007-04-12 02:40:54 +0000770 if (ins->oprs[c - 034].type & (BITS16 | BITS32 | BITS64))
H. Peter Anvine2c80182005-01-15 22:15:51 +0000771 length += (ins->oprs[c - 034].type & BITS16) ? 2 : 4;
772 else
773 length += (bits == 16) ? 2 : 4;
774 break;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000775 case 040:
776 case 041:
777 case 042:
H. Peter Anvin7eb4a382007-09-17 15:49:30 -0700778 case 043:
H. Peter Anvine2c80182005-01-15 22:15:51 +0000779 length += 4;
780 break;
781 case 044:
782 case 045:
783 case 046:
H. Peter Anvin7eb4a382007-09-17 15:49:30 -0700784 case 047:
H. Peter Anvine2c80182005-01-15 22:15:51 +0000785 length += ((ins->oprs[c - 044].addr_size ?
Keith Kaniosb7a89542007-04-12 02:40:54 +0000786 ins->oprs[c - 044].addr_size : bits) >> 3);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000787 break;
788 case 050:
789 case 051:
790 case 052:
H. Peter Anvin7eb4a382007-09-17 15:49:30 -0700791 case 053:
H. Peter Anvine2c80182005-01-15 22:15:51 +0000792 length++;
793 break;
Keith Kaniosb7a89542007-04-12 02:40:54 +0000794 case 054:
795 case 055:
796 case 056:
H. Peter Anvin7eb4a382007-09-17 15:49:30 -0700797 case 057:
Keith Kaniosb7a89542007-04-12 02:40:54 +0000798 length += 8; /* MOV reg64/imm */
799 break;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000800 case 060:
801 case 061:
802 case 062:
H. Peter Anvin7eb4a382007-09-17 15:49:30 -0700803 case 063:
H. Peter Anvine2c80182005-01-15 22:15:51 +0000804 length += 2;
805 break;
806 case 064:
807 case 065:
808 case 066:
H. Peter Anvin7eb4a382007-09-17 15:49:30 -0700809 case 067:
Keith Kaniosb7a89542007-04-12 02:40:54 +0000810 if (ins->oprs[c - 064].type & (BITS16 | BITS32 | BITS64))
H. Peter Anvine2c80182005-01-15 22:15:51 +0000811 length += (ins->oprs[c - 064].type & BITS16) ? 2 : 4;
812 else
813 length += (bits == 16) ? 2 : 4;
814 break;
815 case 070:
816 case 071:
817 case 072:
H. Peter Anvin7eb4a382007-09-17 15:49:30 -0700818 case 073:
H. Peter Anvine2c80182005-01-15 22:15:51 +0000819 length += 4;
820 break;
H. Peter Anvin7eb4a382007-09-17 15:49:30 -0700821 case 074:
822 case 075:
823 case 076:
824 case 077:
825 length += 2;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000826 break;
827 case 0140:
828 case 0141:
829 case 0142:
H. Peter Anvin7eb4a382007-09-17 15:49:30 -0700830 case 0143:
831 length += is_sbyte(ins, c - 0140, 16) ? 1 : 2;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000832 break;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000833 case 0144:
834 case 0145:
H. Peter Anvin7eb4a382007-09-17 15:49:30 -0700835 case 0146:
836 case 0147:
H. Peter Anvine2c80182005-01-15 22:15:51 +0000837 codes += 2;
838 length++;
839 break;
H. Peter Anvin7eb4a382007-09-17 15:49:30 -0700840 case 0150:
841 case 0151:
842 case 0152:
843 case 0153:
844 length += is_sbyte(ins, c - 0150, 32) ? 1 : 4;
845 break;
846 case 0154:
847 case 0155:
848 case 0156:
849 case 0157:
850 codes += 2;
851 length++;
852 break;
H. Peter Anvin401c07e2007-09-17 16:55:04 -0700853 case 0160:
854 case 0161:
855 case 0162:
856 case 0163:
857 length++;
858 ins->rex |= REX_D;
H. Peter Anvincf5180a2007-09-17 17:25:27 -0700859 ins->drexdst = regval(&ins->oprs[c & 3]);
H. Peter Anvin401c07e2007-09-17 16:55:04 -0700860 break;
861 case 0164:
862 case 0165:
863 case 0166:
864 case 0167:
865 length++;
866 ins->rex |= REX_D|REX_OC;
H. Peter Anvincf5180a2007-09-17 17:25:27 -0700867 ins->drexdst = regval(&ins->oprs[c & 3]);
H. Peter Anvin401c07e2007-09-17 16:55:04 -0700868 break;
H. Peter Anvin7eb4a382007-09-17 15:49:30 -0700869 case 0170:
870 length++;
871 break;
H. Peter Anvin401c07e2007-09-17 16:55:04 -0700872 case 0171:
873 break;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000874 case 0300:
875 case 0301:
Keith Kaniosb7a89542007-04-12 02:40:54 +0000876 case 0302:
H. Peter Anvin7eb4a382007-09-17 15:49:30 -0700877 case 0303:
H. Peter Anvine2c80182005-01-15 22:15:51 +0000878 length += chsize(&ins->oprs[c - 0300], bits);
879 break;
880 case 0310:
Keith Kaniosb7a89542007-04-12 02:40:54 +0000881 length += (bits != 16);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000882 break;
883 case 0311:
Keith Kaniosb7a89542007-04-12 02:40:54 +0000884 length += (bits != 32);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000885 break;
886 case 0312:
Keith Kaniosb7a89542007-04-12 02:40:54 +0000887 break;
888 case 0313:
H. Peter Anvine2c80182005-01-15 22:15:51 +0000889 break;
890 case 0320:
Keith Kaniosb7a89542007-04-12 02:40:54 +0000891 length += (bits != 16);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000892 break;
893 case 0321:
894 length += (bits == 16);
895 break;
896 case 0322:
897 break;
Keith Kaniosb7a89542007-04-12 02:40:54 +0000898 case 0323:
H. Peter Anvin3df97a72007-05-30 03:25:21 +0000899 rex_mask &= ~REX_W;
Keith Kaniosb7a89542007-04-12 02:40:54 +0000900 break;
901 case 0324:
H. Peter Anvin3df97a72007-05-30 03:25:21 +0000902 ins->rex |= REX_W;
H. Peter Anvin8d7316a2007-04-18 02:27:18 +0000903 break;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000904 case 0330:
905 codes++, length++;
906 break;
907 case 0331:
H. Peter Anvine2c80182005-01-15 22:15:51 +0000908 break;
H. Peter Anvincb9b6902007-09-12 21:58:51 -0700909 case 0332:
H. Peter Anvine2c80182005-01-15 22:15:51 +0000910 case 0333:
911 length++;
912 break;
H. Peter Anvin0db11e22007-04-17 20:23:11 +0000913 case 0334:
914 assert_no_prefix(ins, P_LOCK);
H. Peter Anvin3df97a72007-05-30 03:25:21 +0000915 ins->rex |= REX_L;
H. Peter Anvin0db11e22007-04-17 20:23:11 +0000916 break;
H. Peter Anvincb9b6902007-09-12 21:58:51 -0700917 case 0335:
918 break;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000919 case 0340:
920 case 0341:
921 case 0342:
922 if (ins->oprs[0].segment != NO_SEG)
923 errfunc(ERR_NONFATAL, "attempt to reserve non-constant"
924 " quantity of BSS space");
925 else
926 length += ins->oprs[0].offset << (c - 0340);
927 break;
H. Peter Anvin62cb6062007-09-11 22:44:03 +0000928 case 0364:
929 case 0365:
930 break;
Keith Kanios48af1772007-08-17 07:37:52 +0000931 case 0366:
H. Peter Anvin62cb6062007-09-11 22:44:03 +0000932 case 0367:
933 length++;
934 break;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000935 case 0370:
936 case 0371:
937 case 0372:
938 break;
939 case 0373:
940 length++;
941 break;
942 default: /* can't do it by 'case' statements */
943 if (c >= 0100 && c <= 0277) { /* it's an EA */
944 ea ea_data;
Keith Kaniosb7a89542007-04-12 02:40:54 +0000945 int rfield;
H. Peter Anvin3df97a72007-05-30 03:25:21 +0000946 int32_t rflags;
Keith Kaniosb7a89542007-04-12 02:40:54 +0000947 ea_data.rex = 0; /* Ensure ea.REX is initially 0 */
948
H. Peter Anvin3df97a72007-05-30 03:25:21 +0000949 if (c <= 0177) {
950 /* pick rfield from operand b */
951 rflags = regflag(&ins->oprs[c & 7]);
952 rfield = regvals[ins->oprs[c & 7].basereg];
953 } else {
954 rflags = 0;
H. Peter Anvin0db11e22007-04-17 20:23:11 +0000955 rfield = c & 7;
H. Peter Anvin3df97a72007-05-30 03:25:21 +0000956 }
Keith Kaniosb7a89542007-04-12 02:40:54 +0000957
H. Peter Anvine2c80182005-01-15 22:15:51 +0000958 if (!process_ea
Keith Kaniosb7a89542007-04-12 02:40:54 +0000959 (&ins->oprs[(c >> 3) & 7], &ea_data, bits,
H. Peter Anvin3df97a72007-05-30 03:25:21 +0000960 rfield, rflags, ins->forw_ref)) {
H. Peter Anvine2c80182005-01-15 22:15:51 +0000961 errfunc(ERR_NONFATAL, "invalid effective address");
962 return -1;
Keith Kaniosb7a89542007-04-12 02:40:54 +0000963 } else {
H. Peter Anvin0db11e22007-04-17 20:23:11 +0000964 ins->rex |= ea_data.rex;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000965 length += ea_data.size;
Keith Kaniosb7a89542007-04-12 02:40:54 +0000966 }
H. Peter Anvine2c80182005-01-15 22:15:51 +0000967 } else
968 errfunc(ERR_PANIC, "internal instruction table corrupt"
969 ": instruction code 0x%02X given", c);
970 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000971
H. Peter Anvin0db11e22007-04-17 20:23:11 +0000972 ins->rex &= rex_mask;
H. Peter Anvin401c07e2007-09-17 16:55:04 -0700973
974 if (ins->rex & REX_D) {
975 if (ins->rex & REX_H) {
976 errfunc(ERR_NONFATAL, "cannot use high register in drex instruction");
977 return -1;
978 }
H. Peter Anvincf5180a2007-09-17 17:25:27 -0700979 if (bits != 64 && ((ins->rex & (REX_W|REX_X|REX_B)) ||
980 ins->drexdst > 7)) {
981 errfunc(ERR_NONFATAL, "invalid operands in non-64-bit mode");
982 return -1;
983 }
H. Peter Anvin401c07e2007-09-17 16:55:04 -0700984 length++;
985 } else if (ins->rex & REX_REAL) {
H. Peter Anvin3df97a72007-05-30 03:25:21 +0000986 if (ins->rex & REX_H) {
987 errfunc(ERR_NONFATAL, "cannot use high register in rex instruction");
988 return -1;
989 } else if (bits == 64 ||
990 ((ins->rex & REX_L) &&
991 !(ins->rex & (REX_P|REX_W|REX_X|REX_B)) &&
992 cpu >= IF_X86_64)) {
H. Peter Anvin0db11e22007-04-17 20:23:11 +0000993 length++;
H. Peter Anvin8d7316a2007-04-18 02:27:18 +0000994 } else {
H. Peter Anvincf5180a2007-09-17 17:25:27 -0700995 errfunc(ERR_NONFATAL, "invalid operands in non-64-bit mode");
996 return -1;
H. Peter Anvin8d7316a2007-04-18 02:27:18 +0000997 }
Keith Kaniosb7a89542007-04-12 02:40:54 +0000998 }
999
H. Peter Anvin0db11e22007-04-17 20:23:11 +00001000 return length;
1001}
Keith Kaniosb7a89542007-04-12 02:40:54 +00001002
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001003#define EMIT_REX() \
H. Peter Anvin401c07e2007-09-17 16:55:04 -07001004 if (!(ins->rex & REX_D) && (ins->rex & REX_REAL) && (bits == 64)) { \
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001005 ins->rex = (ins->rex & REX_REAL)|REX_P; \
1006 out(offset, segment, &ins->rex, OUT_RAWDATA+1, NO_SEG, NO_SEG); \
1007 ins->rex = 0; \
1008 offset += 1; \
1009 }
1010
Keith Kaniosb7a89542007-04-12 02:40:54 +00001011static void gencode(int32_t segment, int32_t offset, int bits,
Keith Kaniosa6dfa782007-04-13 16:47:53 +00001012 insn * ins, const char *codes, int32_t insn_end)
H. Peter Anvineba20a72002-04-30 20:53:55 +00001013{
Keith Kaniosa6dfa782007-04-13 16:47:53 +00001014 static char condval[] = { /* conditional opcodes */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001015 0x7, 0x3, 0x2, 0x6, 0x2, 0x4, 0xF, 0xD, 0xC, 0xE, 0x6, 0x2,
1016 0x3, 0x7, 0x3, 0x5, 0xE, 0xC, 0xD, 0xF, 0x1, 0xB, 0x9, 0x5,
1017 0x0, 0xA, 0xA, 0xB, 0x8, 0x4
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001018 };
Keith Kaniosb7a89542007-04-12 02:40:54 +00001019 uint8_t c;
1020 uint8_t bytes[4];
1021 int32_t size;
1022 int64_t data;
1023
H. Peter Anvineba20a72002-04-30 20:53:55 +00001024 while (*codes)
H. Peter Anvine2c80182005-01-15 22:15:51 +00001025 switch (c = *codes++) {
1026 case 01:
1027 case 02:
1028 case 03:
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001029 EMIT_REX();
H. Peter Anvine2c80182005-01-15 22:15:51 +00001030 out(offset, segment, codes, OUT_RAWDATA + c, NO_SEG, NO_SEG);
1031 codes += c;
1032 offset += c;
1033 break;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001034
H. Peter Anvine2c80182005-01-15 22:15:51 +00001035 case 04:
1036 case 06:
1037 switch (ins->oprs[0].basereg) {
1038 case R_CS:
1039 bytes[0] = 0x0E + (c == 0x04 ? 1 : 0);
1040 break;
1041 case R_DS:
1042 bytes[0] = 0x1E + (c == 0x04 ? 1 : 0);
1043 break;
1044 case R_ES:
1045 bytes[0] = 0x06 + (c == 0x04 ? 1 : 0);
1046 break;
1047 case R_SS:
1048 bytes[0] = 0x16 + (c == 0x04 ? 1 : 0);
1049 break;
1050 default:
1051 errfunc(ERR_PANIC,
1052 "bizarre 8086 segment register received");
1053 }
1054 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1055 offset++;
1056 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001057
H. Peter Anvine2c80182005-01-15 22:15:51 +00001058 case 05:
1059 case 07:
1060 switch (ins->oprs[0].basereg) {
1061 case R_FS:
1062 bytes[0] = 0xA0 + (c == 0x05 ? 1 : 0);
1063 break;
1064 case R_GS:
1065 bytes[0] = 0xA8 + (c == 0x05 ? 1 : 0);
1066 break;
1067 default:
1068 errfunc(ERR_PANIC,
1069 "bizarre 386 segment register received");
1070 }
1071 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1072 offset++;
1073 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001074
H. Peter Anvine2c80182005-01-15 22:15:51 +00001075 case 010:
1076 case 011:
1077 case 012:
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001078 case 013:
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001079 EMIT_REX();
Keith Kaniosb7a89542007-04-12 02:40:54 +00001080 bytes[0] = *codes++ + ((regval(&ins->oprs[c - 010])) & 7);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001081 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1082 offset += 1;
1083 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001084
H. Peter Anvine2c80182005-01-15 22:15:51 +00001085 case 014:
1086 case 015:
1087 case 016:
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001088 case 017:
H. Peter Anvine2c80182005-01-15 22:15:51 +00001089 if (ins->oprs[c - 014].offset < -128
1090 || ins->oprs[c - 014].offset > 127) {
1091 errfunc(ERR_WARNING, "signed byte value exceeds bounds");
1092 }
H. Peter Anvineba20a72002-04-30 20:53:55 +00001093
H. Peter Anvine2c80182005-01-15 22:15:51 +00001094 if (ins->oprs[c - 014].segment != NO_SEG) {
1095 data = ins->oprs[c - 014].offset;
1096 out(offset, segment, &data, OUT_ADDRESS + 1,
1097 ins->oprs[c - 014].segment, ins->oprs[c - 014].wrt);
1098 } else {
1099 bytes[0] = ins->oprs[c - 014].offset;
1100 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG,
1101 NO_SEG);
1102 }
1103 offset += 1;
1104 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001105
H. Peter Anvine2c80182005-01-15 22:15:51 +00001106 case 020:
1107 case 021:
1108 case 022:
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001109 case 023:
H. Peter Anvine2c80182005-01-15 22:15:51 +00001110 if (ins->oprs[c - 020].offset < -256
1111 || ins->oprs[c - 020].offset > 255) {
1112 errfunc(ERR_WARNING, "byte value exceeds bounds");
1113 }
1114 if (ins->oprs[c - 020].segment != NO_SEG) {
1115 data = ins->oprs[c - 020].offset;
1116 out(offset, segment, &data, OUT_ADDRESS + 1,
1117 ins->oprs[c - 020].segment, ins->oprs[c - 020].wrt);
1118 } else {
1119 bytes[0] = ins->oprs[c - 020].offset;
1120 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG,
1121 NO_SEG);
1122 }
1123 offset += 1;
1124 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001125
H. Peter Anvine2c80182005-01-15 22:15:51 +00001126 case 024:
1127 case 025:
1128 case 026:
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001129 case 027:
H. Peter Anvine2c80182005-01-15 22:15:51 +00001130 if (ins->oprs[c - 024].offset < 0
1131 || ins->oprs[c - 024].offset > 255)
1132 errfunc(ERR_WARNING, "unsigned byte value exceeds bounds");
1133 if (ins->oprs[c - 024].segment != NO_SEG) {
1134 data = ins->oprs[c - 024].offset;
1135 out(offset, segment, &data, OUT_ADDRESS + 1,
1136 ins->oprs[c - 024].segment, ins->oprs[c - 024].wrt);
1137 } else {
1138 bytes[0] = ins->oprs[c - 024].offset;
1139 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG,
1140 NO_SEG);
1141 }
1142 offset += 1;
1143 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001144
H. Peter Anvine2c80182005-01-15 22:15:51 +00001145 case 030:
1146 case 031:
1147 case 032:
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001148 case 033:
H. Peter Anvine2c80182005-01-15 22:15:51 +00001149 if (ins->oprs[c - 030].segment == NO_SEG &&
1150 ins->oprs[c - 030].wrt == NO_SEG &&
1151 (ins->oprs[c - 030].offset < -65536L ||
1152 ins->oprs[c - 030].offset > 65535L)) {
1153 errfunc(ERR_WARNING, "word value exceeds bounds");
1154 }
1155 data = ins->oprs[c - 030].offset;
1156 out(offset, segment, &data, OUT_ADDRESS + 2,
1157 ins->oprs[c - 030].segment, ins->oprs[c - 030].wrt);
1158 offset += 2;
1159 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001160
H. Peter Anvine2c80182005-01-15 22:15:51 +00001161 case 034:
1162 case 035:
1163 case 036:
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001164 case 037:
H. Peter Anvine2c80182005-01-15 22:15:51 +00001165 if (ins->oprs[c - 034].type & (BITS16 | BITS32))
1166 size = (ins->oprs[c - 034].type & BITS16) ? 2 : 4;
1167 else
1168 size = (bits == 16) ? 2 : 4;
1169 data = ins->oprs[c - 034].offset;
1170 if (size == 2 && (data < -65536L || data > 65535L))
1171 errfunc(ERR_WARNING, "word value exceeds bounds");
1172 out(offset, segment, &data, OUT_ADDRESS + size,
1173 ins->oprs[c - 034].segment, ins->oprs[c - 034].wrt);
1174 offset += size;
1175 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001176
H. Peter Anvine2c80182005-01-15 22:15:51 +00001177 case 040:
1178 case 041:
1179 case 042:
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001180 case 043:
H. Peter Anvine2c80182005-01-15 22:15:51 +00001181 data = ins->oprs[c - 040].offset;
1182 out(offset, segment, &data, OUT_ADDRESS + 4,
1183 ins->oprs[c - 040].segment, ins->oprs[c - 040].wrt);
1184 offset += 4;
1185 break;
H. Peter Anvin3ba46772002-05-27 23:19:35 +00001186
H. Peter Anvine2c80182005-01-15 22:15:51 +00001187 case 044:
1188 case 045:
1189 case 046:
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001190 case 047:
H. Peter Anvine2c80182005-01-15 22:15:51 +00001191 data = ins->oprs[c - 044].offset;
1192 size = ((ins->oprs[c - 044].addr_size ?
Keith Kaniosb7a89542007-04-12 02:40:54 +00001193 ins->oprs[c - 044].addr_size : bits) >> 3);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001194 if (size == 2 && (data < -65536L || data > 65535L))
1195 errfunc(ERR_WARNING, "word value exceeds bounds");
1196 out(offset, segment, &data, OUT_ADDRESS + size,
1197 ins->oprs[c - 044].segment, ins->oprs[c - 044].wrt);
1198 offset += size;
1199 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001200
H. Peter Anvine2c80182005-01-15 22:15:51 +00001201 case 050:
1202 case 051:
1203 case 052:
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001204 case 053:
H. Peter Anvine2c80182005-01-15 22:15:51 +00001205 if (ins->oprs[c - 050].segment != segment)
1206 errfunc(ERR_NONFATAL,
1207 "short relative jump outside segment");
1208 data = ins->oprs[c - 050].offset - insn_end;
1209 if (data > 127 || data < -128)
1210 errfunc(ERR_NONFATAL, "short jump is out of range");
1211 bytes[0] = data;
1212 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1213 offset += 1;
1214 break;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001215
1216 case 054:
1217 case 055:
1218 case 056:
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001219 case 057:
Keith Kaniosb7a89542007-04-12 02:40:54 +00001220 data = (int64_t)ins->oprs[c - 054].offset;
1221 out(offset, segment, &data, OUT_ADDRESS + 8,
1222 ins->oprs[c - 054].segment, ins->oprs[c - 054].wrt);
1223 offset += 8;
1224 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001225
H. Peter Anvine2c80182005-01-15 22:15:51 +00001226 case 060:
1227 case 061:
1228 case 062:
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001229 case 063:
H. Peter Anvine2c80182005-01-15 22:15:51 +00001230 if (ins->oprs[c - 060].segment != segment) {
1231 data = ins->oprs[c - 060].offset;
1232 out(offset, segment, &data,
1233 OUT_REL2ADR + insn_end - offset,
1234 ins->oprs[c - 060].segment, ins->oprs[c - 060].wrt);
1235 } else {
1236 data = ins->oprs[c - 060].offset - insn_end;
1237 out(offset, segment, &data,
1238 OUT_ADDRESS + 2, NO_SEG, NO_SEG);
1239 }
1240 offset += 2;
1241 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001242
H. Peter Anvine2c80182005-01-15 22:15:51 +00001243 case 064:
1244 case 065:
1245 case 066:
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001246 case 067:
Keith Kaniosb7a89542007-04-12 02:40:54 +00001247 if (ins->oprs[c - 064].type & (BITS16 | BITS32 | BITS64))
H. Peter Anvine2c80182005-01-15 22:15:51 +00001248 size = (ins->oprs[c - 064].type & BITS16) ? 2 : 4;
1249 else
1250 size = (bits == 16) ? 2 : 4;
1251 if (ins->oprs[c - 064].segment != segment) {
Keith Kaniosb7a89542007-04-12 02:40:54 +00001252 int32_t reltype = (size == 2 ? OUT_REL2ADR : OUT_REL4ADR);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001253 data = ins->oprs[c - 064].offset;
1254 out(offset, segment, &data, reltype + insn_end - offset,
1255 ins->oprs[c - 064].segment, ins->oprs[c - 064].wrt);
1256 } else {
1257 data = ins->oprs[c - 064].offset - insn_end;
1258 out(offset, segment, &data,
1259 OUT_ADDRESS + size, NO_SEG, NO_SEG);
1260 }
1261 offset += size;
1262 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001263
H. Peter Anvine2c80182005-01-15 22:15:51 +00001264 case 070:
1265 case 071:
1266 case 072:
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001267 case 073:
H. Peter Anvine2c80182005-01-15 22:15:51 +00001268 if (ins->oprs[c - 070].segment != segment) {
1269 data = ins->oprs[c - 070].offset;
1270 out(offset, segment, &data,
1271 OUT_REL4ADR + insn_end - offset,
1272 ins->oprs[c - 070].segment, ins->oprs[c - 070].wrt);
1273 } else {
1274 data = ins->oprs[c - 070].offset - insn_end;
1275 out(offset, segment, &data,
1276 OUT_ADDRESS + 4, NO_SEG, NO_SEG);
1277 }
1278 offset += 4;
1279 break;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001280
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001281 case 074:
1282 case 075:
1283 case 076:
1284 case 077:
1285 if (ins->oprs[c - 074].segment == NO_SEG)
1286 errfunc(ERR_NONFATAL, "value referenced by FAR is not"
1287 " relocatable");
1288 data = 0L;
1289 out(offset, segment, &data, OUT_ADDRESS + 2,
1290 outfmt->segbase(1 + ins->oprs[c - 074].segment),
1291 ins->oprs[c - 074].wrt);
1292 offset += 2;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001293 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001294
H. Peter Anvine2c80182005-01-15 22:15:51 +00001295 case 0140:
1296 case 0141:
1297 case 0142:
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001298 case 0143:
H. Peter Anvine2c80182005-01-15 22:15:51 +00001299 data = ins->oprs[c - 0140].offset;
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001300 if (is_sbyte(ins, c - 0140, 16)) {
1301 bytes[0] = data;
1302 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG,
1303 NO_SEG);
1304 offset++;
1305 } else {
1306 if (ins->oprs[c - 0140].segment == NO_SEG &&
1307 ins->oprs[c - 0140].wrt == NO_SEG &&
1308 (data < -65536L || data > 65535L)) {
1309 errfunc(ERR_WARNING, "word value exceeds bounds");
1310 }
1311 out(offset, segment, &data, OUT_ADDRESS + 2,
H. Peter Anvin8f94f982007-09-17 16:31:33 -07001312 ins->oprs[c - 0140].segment, ins->oprs[c - 0140].wrt);
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001313 offset += 2;
1314 }
1315 break;
1316
1317 case 0144:
1318 case 0145:
1319 case 0146:
1320 case 0147:
1321 EMIT_REX();
1322 codes++;
1323 bytes[0] = *codes++;
1324 if (is_sbyte(ins, c - 0144, 16))
1325 bytes[0] |= 2; /* s-bit */
1326 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1327 offset++;
1328 break;
1329
1330 case 0150:
1331 case 0151:
1332 case 0152:
1333 case 0153:
1334 data = ins->oprs[c - 0150].offset;
1335 if (is_sbyte(ins, c - 0150, 32)) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001336 bytes[0] = data;
1337 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG,
1338 NO_SEG);
1339 offset++;
1340 } else {
1341 out(offset, segment, &data, OUT_ADDRESS + 4,
H. Peter Anvin8f94f982007-09-17 16:31:33 -07001342 ins->oprs[c - 0150].segment, ins->oprs[c - 0150].wrt);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001343 offset += 4;
1344 }
1345 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001346
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001347 case 0154:
1348 case 0155:
1349 case 0156:
1350 case 0157:
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001351 EMIT_REX();
H. Peter Anvine2c80182005-01-15 22:15:51 +00001352 codes++;
1353 bytes[0] = *codes++;
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001354 if (is_sbyte(ins, c - 0154, 32))
H. Peter Anvine2c80182005-01-15 22:15:51 +00001355 bytes[0] |= 2; /* s-bit */
1356 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1357 offset++;
1358 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001359
H. Peter Anvin401c07e2007-09-17 16:55:04 -07001360 case 0160:
1361 case 0161:
1362 case 0162:
1363 case 0163:
1364 case 0164:
1365 case 0165:
1366 case 0166:
1367 case 0167:
H. Peter Anvin401c07e2007-09-17 16:55:04 -07001368 break;
1369
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001370 case 0170:
1371 bytes[0] = 0;
1372 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1373 offset += 1;
1374 break;
1375
H. Peter Anvin401c07e2007-09-17 16:55:04 -07001376 case 0171:
1377 bytes[0] =
1378 (ins->drexdst << 4) |
1379 (ins->rex & REX_OC ? 0x08 : 0) |
1380 (ins->rex & (REX_R|REX_X|REX_B));
1381 ins->rex = 0;
1382 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1383 offset++;
1384 break;
1385
H. Peter Anvine2c80182005-01-15 22:15:51 +00001386 case 0300:
1387 case 0301:
1388 case 0302:
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001389 case 0303:
H. Peter Anvine2c80182005-01-15 22:15:51 +00001390 if (chsize(&ins->oprs[c - 0300], bits)) {
1391 *bytes = 0x67;
1392 out(offset, segment, bytes,
1393 OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1394 offset += 1;
1395 } else
1396 offset += 0;
1397 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001398
H. Peter Anvine2c80182005-01-15 22:15:51 +00001399 case 0310:
Keith Kaniosb7a89542007-04-12 02:40:54 +00001400 if (bits != 16) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001401 *bytes = 0x67;
1402 out(offset, segment, bytes,
1403 OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1404 offset += 1;
1405 } else
1406 offset += 0;
1407 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001408
H. Peter Anvine2c80182005-01-15 22:15:51 +00001409 case 0311:
Keith Kaniosb7a89542007-04-12 02:40:54 +00001410 if (bits != 32) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001411 *bytes = 0x67;
1412 out(offset, segment, bytes,
1413 OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1414 offset += 1;
1415 } else
1416 offset += 0;
1417 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001418
H. Peter Anvine2c80182005-01-15 22:15:51 +00001419 case 0312:
1420 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001421
Keith Kaniosb7a89542007-04-12 02:40:54 +00001422 case 0313:
1423 ins->rex = 0;
1424 break;
1425
H. Peter Anvine2c80182005-01-15 22:15:51 +00001426 case 0320:
Keith Kaniosb7a89542007-04-12 02:40:54 +00001427 if (bits != 16) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001428 *bytes = 0x66;
1429 out(offset, segment, bytes,
1430 OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1431 offset += 1;
1432 } else
1433 offset += 0;
1434 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001435
H. Peter Anvine2c80182005-01-15 22:15:51 +00001436 case 0321:
1437 if (bits == 16) {
1438 *bytes = 0x66;
1439 out(offset, segment, bytes,
1440 OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1441 offset += 1;
1442 } else
1443 offset += 0;
1444 break;
H. Peter Anvinef7468f2002-04-30 20:57:59 +00001445
H. Peter Anvine2c80182005-01-15 22:15:51 +00001446 case 0322:
Keith Kaniosb7a89542007-04-12 02:40:54 +00001447 case 0323:
1448 break;
1449
1450 case 0324:
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001451 ins->rex |= REX_W;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001452 break;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001453
H. Peter Anvine2c80182005-01-15 22:15:51 +00001454 case 0330:
1455 *bytes = *codes++ ^ condval[ins->condition];
1456 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1457 offset += 1;
1458 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001459
H. Peter Anvine2c80182005-01-15 22:15:51 +00001460 case 0331:
H. Peter Anvine2c80182005-01-15 22:15:51 +00001461 break;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001462
H. Peter Anvincb9b6902007-09-12 21:58:51 -07001463 case 0332:
H. Peter Anvine2c80182005-01-15 22:15:51 +00001464 case 0333:
H. Peter Anvincb9b6902007-09-12 21:58:51 -07001465 *bytes = c - 0332 + 0xF2;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001466 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1467 offset += 1;
1468 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001469
Keith Kanios48af1772007-08-17 07:37:52 +00001470 case 0334:
1471 if (ins->rex & REX_R) {
1472 *bytes = 0xF0;
1473 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1474 offset += 1;
1475 }
1476 ins->rex &= ~(REX_L|REX_R);
1477 break;
H. Peter Anvin0db11e22007-04-17 20:23:11 +00001478
H. Peter Anvincb9b6902007-09-12 21:58:51 -07001479 case 0335:
1480 break;
1481
H. Peter Anvine2c80182005-01-15 22:15:51 +00001482 case 0340:
1483 case 0341:
1484 case 0342:
1485 if (ins->oprs[0].segment != NO_SEG)
1486 errfunc(ERR_PANIC, "non-constant BSS size in pass two");
1487 else {
Keith Kaniosb7a89542007-04-12 02:40:54 +00001488 int32_t size = ins->oprs[0].offset << (c - 0340);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001489 if (size > 0)
1490 out(offset, segment, NULL,
1491 OUT_RESERVE + size, NO_SEG, NO_SEG);
1492 offset += size;
1493 }
1494 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001495
H. Peter Anvin62cb6062007-09-11 22:44:03 +00001496 case 0364:
1497 case 0365:
1498 break;
1499
Keith Kanios48af1772007-08-17 07:37:52 +00001500 case 0366:
H. Peter Anvin62cb6062007-09-11 22:44:03 +00001501 case 0367:
1502 *bytes = c - 0366 + 0x66;
Keith Kanios48af1772007-08-17 07:37:52 +00001503 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1504 offset += 1;
1505 break;
H. Peter Anvin62cb6062007-09-11 22:44:03 +00001506
H. Peter Anvine2c80182005-01-15 22:15:51 +00001507 case 0370:
1508 case 0371:
1509 case 0372:
1510 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001511
H. Peter Anvine2c80182005-01-15 22:15:51 +00001512 case 0373:
1513 *bytes = bits == 16 ? 3 : 5;
1514 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1515 offset += 1;
1516 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001517
H. Peter Anvine2c80182005-01-15 22:15:51 +00001518 default: /* can't do it by 'case' statements */
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001519 if (c >= 0100 && c <= 0277) { /* it's an EA */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001520 ea ea_data;
1521 int rfield;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001522 int32_t rflags;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001523 uint8_t *p;
1524 int32_t s;
1525
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001526 if (c <= 0177) {
1527 /* pick rfield from operand b */
1528 rflags = regflag(&ins->oprs[c & 7]);
1529 rfield = regvals[ins->oprs[c & 7].basereg];
1530 } else {
1531 /* rfield is constant */
1532 rflags = 0;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001533 rfield = c & 7;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001534 }
H. Peter Anvine2c80182005-01-15 22:15:51 +00001535
1536 if (!process_ea
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001537 (&ins->oprs[(c >> 3) & 7], &ea_data, bits,
1538 rfield, rflags, ins->forw_ref)) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001539 errfunc(ERR_NONFATAL, "invalid effective address");
1540 }
Keith Kaniosb7a89542007-04-12 02:40:54 +00001541
H. Peter Anvine2c80182005-01-15 22:15:51 +00001542 p = bytes;
1543 *p++ = ea_data.modrm;
1544 if (ea_data.sib_present)
1545 *p++ = ea_data.sib;
1546
H. Peter Anvin401c07e2007-09-17 16:55:04 -07001547 /* DREX suffixes come between the SIB and the displacement */
1548 if (ins->rex & REX_D) {
1549 *p++ =
1550 (ins->drexdst << 4) |
1551 (ins->rex & REX_OC ? 0x08 : 0) |
1552 (ins->rex & (REX_R|REX_X|REX_B));
1553 ins->rex = 0;
1554 }
1555
H. Peter Anvine2c80182005-01-15 22:15:51 +00001556 s = p - bytes;
1557 out(offset, segment, bytes, OUT_RAWDATA + s,
1558 NO_SEG, NO_SEG);
1559
1560 switch (ea_data.bytes) {
1561 case 0:
1562 break;
1563 case 1:
1564 if (ins->oprs[(c >> 3) & 7].segment != NO_SEG) {
1565 data = ins->oprs[(c >> 3) & 7].offset;
1566 out(offset, segment, &data, OUT_ADDRESS + 1,
1567 ins->oprs[(c >> 3) & 7].segment,
1568 ins->oprs[(c >> 3) & 7].wrt);
1569 } else {
1570 *bytes = ins->oprs[(c >> 3) & 7].offset;
1571 out(offset, segment, bytes, OUT_RAWDATA + 1,
1572 NO_SEG, NO_SEG);
1573 }
1574 s++;
1575 break;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001576 case 8:
H. Peter Anvine2c80182005-01-15 22:15:51 +00001577 case 2:
1578 case 4:
1579 data = ins->oprs[(c >> 3) & 7].offset;
Keith Kaniose83b3182007-04-16 14:31:54 +00001580 if (ea_data.rip && (ins->oprs[(c >> 3) & 7].segment == 0xFFFFFFFF))
1581 ea_data.rip = 0; /* Make distinction between Symbols and Immediates */
Keith Kaniosb7a89542007-04-12 02:40:54 +00001582 out(offset, segment, &data, /* RIP = Relative, not Absolute */
1583 (ea_data.rip ? OUT_REL4ADR : OUT_ADDRESS) + ea_data.bytes,
H. Peter Anvine2c80182005-01-15 22:15:51 +00001584 ins->oprs[(c >> 3) & 7].segment,
1585 ins->oprs[(c >> 3) & 7].wrt);
1586 s += ea_data.bytes;
1587 break;
1588 }
1589 offset += s;
1590 } else
1591 errfunc(ERR_PANIC, "internal instruction table corrupt"
1592 ": instruction code 0x%02X given", c);
1593 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001594}
1595
H. Peter Anvin0ec60e62007-07-07 01:59:52 +00001596static int32_t regflag(const operand * o)
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001597{
1598 if (o->basereg < EXPR_REG_START || o->basereg >= REG_ENUM_LIMIT) {
1599 errfunc(ERR_PANIC, "invalid operand passed to regflag()");
1600 }
1601 return reg_flags[o->basereg];
1602}
1603
H. Peter Anvin5b0e3ec2007-07-07 02:01:08 +00001604static int32_t regval(const operand * o)
H. Peter Anvineba20a72002-04-30 20:53:55 +00001605{
H. Peter Anvine2c80182005-01-15 22:15:51 +00001606 if (o->basereg < EXPR_REG_START || o->basereg >= REG_ENUM_LIMIT) {
1607 errfunc(ERR_PANIC, "invalid operand passed to regval()");
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001608 }
H. Peter Anvin232badb2002-06-06 02:41:20 +00001609 return regvals[o->basereg];
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001610}
1611
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001612static int op_rexflags(const operand * o, int mask)
1613{
1614 int32_t flags;
1615 int val;
1616
1617 if (o->basereg < EXPR_REG_START || o->basereg >= REG_ENUM_LIMIT) {
1618 errfunc(ERR_PANIC, "invalid operand passed to op_rexflags()");
1619 }
1620
1621 flags = reg_flags[o->basereg];
1622 val = regvals[o->basereg];
1623
1624 return rexflags(val, flags, mask);
1625}
1626
1627static int rexflags(int val, int32_t flags, int mask)
1628{
1629 int rex = 0;
1630
1631 if (val >= 8)
1632 rex |= REX_B|REX_X|REX_R;
1633 if (flags & BITS64)
1634 rex |= REX_W;
1635 if (!(REG_HIGH & ~flags)) /* AH, CH, DH, BH */
1636 rex |= REX_H;
1637 else if (!(REG8 & ~flags) && val >= 4) /* SPL, BPL, SIL, DIL */
1638 rex |= REX_P;
1639
1640 return rex & mask;
1641}
1642
H. Peter Anvin3360d792007-09-11 04:16:57 +00001643static int matches(const struct itemplate *itemp, insn * instruction, int bits)
H. Peter Anvineba20a72002-04-30 20:53:55 +00001644{
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001645 int i, size[MAX_OPERANDS], asize, oprs, ret;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001646
1647 ret = 100;
1648
1649 /*
1650 * Check the opcode
1651 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001652 if (itemp->opcode != instruction->opcode)
1653 return 0;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001654
1655 /*
1656 * Count the operands
1657 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001658 if (itemp->operands != instruction->operands)
1659 return 0;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001660
1661 /*
1662 * Check that no spurious colons or TOs are present
1663 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001664 for (i = 0; i < itemp->operands; i++)
1665 if (instruction->oprs[i].type & ~itemp->opd[i] & (COLON | TO))
1666 return 0;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001667
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001668 /*
1669 * Check that the operand flags all match up
1670 */
H. Peter Anvin16b0a332007-09-12 20:27:41 -07001671 for (i = 0; i < itemp->operands; i++) {
H. Peter Anvincf5180a2007-09-17 17:25:27 -07001672 if (itemp->opd[i] & SAME_AS) {
1673 int j = itemp->opd[i] & ~SAME_AS;
1674 if (instruction->oprs[i].type != instruction->oprs[j].type ||
1675 instruction->oprs[i].basereg != instruction->oprs[j].basereg)
1676 return 0;
1677 } else if (itemp->opd[i] & ~instruction->oprs[i].type ||
H. Peter Anvine2c80182005-01-15 22:15:51 +00001678 ((itemp->opd[i] & SIZE_MASK) &&
1679 ((itemp->opd[i] ^ instruction->oprs[i].type) & SIZE_MASK))) {
H. Peter Anvin5a640e12007-05-29 23:57:12 +00001680 if ((itemp->opd[i] & ~instruction->oprs[i].type & ~SIZE_MASK) ||
H. Peter Anvine2c80182005-01-15 22:15:51 +00001681 (instruction->oprs[i].type & SIZE_MASK))
1682 return 0;
1683 else
H. Peter Anvine2c80182005-01-15 22:15:51 +00001684 return 1;
1685 }
H. Peter Anvin16b0a332007-09-12 20:27:41 -07001686 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001687
1688 /*
1689 * Check operand sizes
1690 */
H. Peter Anvinef7468f2002-04-30 20:57:59 +00001691 if (itemp->flags & IF_ARMASK) {
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001692 memset(size, 0, sizeof size);
H. Peter Anvinef7468f2002-04-30 20:57:59 +00001693
H. Peter Anvine2c80182005-01-15 22:15:51 +00001694 switch (itemp->flags & IF_ARMASK) {
1695 case IF_AR0:
1696 i = 0;
1697 break;
1698 case IF_AR1:
1699 i = 1;
1700 break;
1701 case IF_AR2:
1702 i = 2;
1703 break;
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001704 case IF_AR3:
1705 i = 3;
1706 break;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001707 default:
1708 break; /* Shouldn't happen */
1709 }
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001710 switch (itemp->flags & IF_SMASK) {
1711 case IF_SB:
H. Peter Anvine2c80182005-01-15 22:15:51 +00001712 size[i] = BITS8;
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001713 break;
1714 case IF_SW:
H. Peter Anvine2c80182005-01-15 22:15:51 +00001715 size[i] = BITS16;
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001716 break;
1717 case IF_SD:
H. Peter Anvine2c80182005-01-15 22:15:51 +00001718 size[i] = BITS32;
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001719 break;
1720 case IF_SQ:
Keith Kaniosb7a89542007-04-12 02:40:54 +00001721 size[i] = BITS64;
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001722 break;
H. Peter Anvin41c9f6f2007-09-18 13:01:32 -07001723 case IF_SO:
1724 size[i] = BITS128;
1725 break;
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001726 default:
1727 break;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001728 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001729 } else {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001730 asize = 0;
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001731 switch (itemp->flags & IF_SMASK) {
1732 case IF_SB:
H. Peter Anvine2c80182005-01-15 22:15:51 +00001733 asize = BITS8;
1734 oprs = itemp->operands;
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001735 break;
1736 case IF_SW:
H. Peter Anvine2c80182005-01-15 22:15:51 +00001737 asize = BITS16;
1738 oprs = itemp->operands;
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001739 break;
1740 case IF_SD:
H. Peter Anvine2c80182005-01-15 22:15:51 +00001741 asize = BITS32;
1742 oprs = itemp->operands;
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001743 break;
1744 case IF_SQ:
Keith Kaniosb7a89542007-04-12 02:40:54 +00001745 asize = BITS64;
1746 oprs = itemp->operands;
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001747 break;
H. Peter Anvin41c9f6f2007-09-18 13:01:32 -07001748 case IF_SO:
1749 asize = BITS128;
1750 oprs = itemp->operands;
1751 break;
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001752 default:
1753 break;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001754 }
H. Peter Anvin7eb4a382007-09-17 15:49:30 -07001755 for (i = 0; i < MAX_OPERANDS; i++)
1756 size[i] = asize;
H. Peter Anvinef7468f2002-04-30 20:57:59 +00001757 }
Keith Kaniosb7a89542007-04-12 02:40:54 +00001758
H. Peter Anvinef7468f2002-04-30 20:57:59 +00001759 if (itemp->flags & (IF_SM | IF_SM2)) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001760 oprs = (itemp->flags & IF_SM2 ? 2 : itemp->operands);
1761 asize = 0;
1762 for (i = 0; i < oprs; i++) {
1763 if ((asize = itemp->opd[i] & SIZE_MASK) != 0) {
1764 int j;
1765 for (j = 0; j < oprs; j++)
1766 size[j] = asize;
1767 break;
1768 }
1769 }
H. Peter Anvinef7468f2002-04-30 20:57:59 +00001770 } else {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001771 oprs = itemp->operands;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001772 }
1773
Keith Kaniosb7a89542007-04-12 02:40:54 +00001774 for (i = 0; i < itemp->operands; i++) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001775 if (!(itemp->opd[i] & SIZE_MASK) &&
1776 (instruction->oprs[i].type & SIZE_MASK & ~size[i]))
H. Peter Anvine2c80182005-01-15 22:15:51 +00001777 return 2;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001778 }
1779
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001780 /*
1781 * Check template is okay at the set cpu level
1782 */
Keith Kaniosb7a89542007-04-12 02:40:54 +00001783 if (((itemp->flags & IF_PLEVEL) > cpu))
H. Peter Anvine2c80182005-01-15 22:15:51 +00001784 return 3;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001785
1786 /*
1787 * Check if instruction is available in long mode
1788 */
1789 if ((itemp->flags & IF_NOLONG) && (bits == 64))
1790 return 4;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001791
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001792 /*
1793 * Check if special handling needed for Jumps
1794 */
Keith Kaniosb7a89542007-04-12 02:40:54 +00001795 if ((uint8_t)(itemp->code[0]) >= 0370)
H. Peter Anvine2c80182005-01-15 22:15:51 +00001796 return 99;
1797
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001798 return ret;
1799}
1800
H. Peter Anvine2c80182005-01-15 22:15:51 +00001801static ea *process_ea(operand * input, ea * output, int addrbits,
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001802 int rfield, int32_t rflags, int forw_ref)
H. Peter Anvineba20a72002-04-30 20:53:55 +00001803{
H. Peter Anvin99c4ecd2007-08-28 23:06:00 +00001804 output->rip = FALSE;
1805
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001806 /* REX flags for the rfield operand */
1807 output->rex |= rexflags(rfield, rflags, REX_R|REX_P|REX_W|REX_H);
1808
Keith Kaniosb7a89542007-04-12 02:40:54 +00001809 if (!(REGISTER & ~input->type)) { /* register direct */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001810 int i;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001811 int32_t f;
1812
1813 if (input->basereg < EXPR_REG_START /* Verify as Register */
Keith Kaniosb7a89542007-04-12 02:40:54 +00001814 || input->basereg >= REG_ENUM_LIMIT)
H. Peter Anvine2c80182005-01-15 22:15:51 +00001815 return NULL;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001816 f = regflag(input);
Keith Kaniosb7a89542007-04-12 02:40:54 +00001817 i = regvals[input->basereg];
Keith Kaniosb7a89542007-04-12 02:40:54 +00001818
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001819 if (REG_EA & ~f)
1820 return NULL; /* Invalid EA register */
1821
1822 output->rex |= op_rexflags(input, REX_B|REX_P|REX_W|REX_H);
1823
Keith Kaniosb7a89542007-04-12 02:40:54 +00001824 output->sib_present = FALSE; /* no SIB necessary */
1825 output->bytes = 0; /* no offset necessary either */
1826 output->modrm = 0xC0 | ((rfield & 7) << 3) | (i & 7);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001827 } else { /* it's a memory reference */
1828 if (input->basereg == -1
1829 && (input->indexreg == -1 || input->scale == 0)) {
1830 /* it's a pure offset */
1831 if (input->addr_size)
1832 addrbits = input->addr_size;
H. Peter Anvin99c4ecd2007-08-28 23:06:00 +00001833
1834 if (globalbits == 64 && (~input->type & IP_REL)) {
Chuck Crayne42fe6ce2007-06-03 02:42:41 +00001835 int scale, index, base;
1836 output->sib_present = TRUE;
1837 scale = 0;
1838 index = 4;
1839 base = 5;
1840 output->sib = (scale << 6) | (index << 3) | base;
1841 output->bytes = 4;
1842 output->modrm = 4 | ((rfield & 7) << 3);
H. Peter Anvin99c4ecd2007-08-28 23:06:00 +00001843 output->rip = FALSE;
Chuck Crayne42fe6ce2007-06-03 02:42:41 +00001844 } else {
1845 output->sib_present = FALSE;
1846 output->bytes = (addrbits != 16 ? 4 : 2);
1847 output->modrm = (addrbits != 16 ? 5 : 6) | ((rfield & 7) << 3);
H. Peter Anvin99c4ecd2007-08-28 23:06:00 +00001848 output->rip = globalbits == 64;
Chuck Crayne42fe6ce2007-06-03 02:42:41 +00001849 }
H. Peter Anvine2c80182005-01-15 22:15:51 +00001850 } else { /* it's an indirection */
1851 int i = input->indexreg, b = input->basereg, s = input->scale;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001852 int32_t o = input->offset, seg = input->segment;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001853 int hb = input->hintbase, ht = input->hinttype;
1854 int t;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001855 int it, bt;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001856 int32_t ix, bx; /* register flags */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001857
H. Peter Anvine2c80182005-01-15 22:15:51 +00001858 if (s == 0)
1859 i = -1; /* make this easy, at least */
Keith Kaniosb7a89542007-04-12 02:40:54 +00001860
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001861 if (i >= EXPR_REG_START && i < REG_ENUM_LIMIT) {
Keith Kaniosb7a89542007-04-12 02:40:54 +00001862 it = regvals[i];
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001863 ix = reg_flags[i];
1864 } else {
Keith Kaniosb7a89542007-04-12 02:40:54 +00001865 it = -1;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001866 ix = 0;
1867 }
Keith Kaniosb7a89542007-04-12 02:40:54 +00001868
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001869 if (b != -1 && b >= EXPR_REG_START && b < REG_ENUM_LIMIT) {
Keith Kaniosb7a89542007-04-12 02:40:54 +00001870 bt = regvals[b];
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001871 bx = reg_flags[b];
1872 } else {
Keith Kaniosb7a89542007-04-12 02:40:54 +00001873 bt = -1;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001874 bx = 0;
1875 }
Keith Kaniosb7a89542007-04-12 02:40:54 +00001876
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001877 /* check for a 32/64-bit memory reference... */
1878 if ((ix|bx) & (BITS32|BITS64)) {
Keith Kaniosb7a89542007-04-12 02:40:54 +00001879 /* it must be a 32/64-bit memory reference. Firstly we have
1880 * to check that all registers involved are type E/Rxx. */
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001881 int32_t sok = BITS32|BITS64;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001882
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001883 if (it != -1) {
1884 if (!(REG64 & ~ix) || !(REG32 & ~ix))
1885 sok &= ix;
1886 else
1887 return NULL;
1888 }
1889
1890 if (bt != -1) {
H. Peter Anvin99c4ecd2007-08-28 23:06:00 +00001891 if (REG_GPR & ~bx)
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001892 return NULL; /* Invalid register */
H. Peter Anvina57e8d42007-05-30 03:44:02 +00001893 if (~sok & bx & SIZE_MASK)
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001894 return NULL; /* Invalid size */
1895 sok &= ~bx;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001896 }
Keith Kaniosb7a89542007-04-12 02:40:54 +00001897
H. Peter Anvine2c80182005-01-15 22:15:51 +00001898 /* While we're here, ensure the user didn't specify WORD. */
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001899 if (input->addr_size == 16 ||
1900 (input->addr_size == 32 && !(sok & BITS32)) ||
1901 (input->addr_size == 64 && !(sok & BITS64)))
H. Peter Anvine2c80182005-01-15 22:15:51 +00001902 return NULL;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001903
Keith Kaniosb7a89542007-04-12 02:40:54 +00001904 /* now reorganize base/index */
1905 if (s == 1 && bt != it && bt != -1 && it != -1 &&
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001906 ((hb == b && ht == EAH_NOTBASE)
1907 || (hb == i && ht == EAH_MAKEBASE))) {
1908 /* swap if hints say so */
1909 t = bt, bt = it, it = t;
1910 t = bx, bx = ix, ix = t;
1911 }
Keith Kaniosb7a89542007-04-12 02:40:54 +00001912 if (bt == it) /* convert EAX+2*EAX to 3*EAX */
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001913 bt = -1, bx = 0, s++;
1914 if (bt == -1 && s == 1 && !(hb == it && ht == EAH_NOTBASE)) {
1915 /* make single reg base, unless hint */
1916 bt = it, bx = ix, it = -1, ix = 0;
1917 }
H. Peter Anvinf5843c62007-09-10 18:59:26 +00001918 if (((s == 2 && it != REG_NUM_ESP
H. Peter Anvine2c80182005-01-15 22:15:51 +00001919 && !(input->eaflags & EAF_TIMESTWO)) || s == 3
Keith Kaniosb7a89542007-04-12 02:40:54 +00001920 || s == 5 || s == 9) && bt == -1)
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001921 bt = it, bx = ix, s--; /* convert 3*EAX to EAX+2*EAX */
Keith Kanios48af1772007-08-17 07:37:52 +00001922 if (it == -1 && (bt & 7) != REG_NUM_ESP
H. Peter Anvine2c80182005-01-15 22:15:51 +00001923 && (input->eaflags & EAF_TIMESTWO))
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001924 it = bt, ix = bx, bt = -1, bx = 0, s = 1;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001925 /* convert [NOSPLIT EAX] to sib format with 0x0 displacement */
Keith Kanios48af1772007-08-17 07:37:52 +00001926 if (s == 1 && it == REG_NUM_ESP) {
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001927 /* swap ESP into base if scale is 1 */
Keith Kaniosb7a89542007-04-12 02:40:54 +00001928 t = it, it = bt, bt = t;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001929 t = ix, ix = bx, bx = t;
1930 }
Keith Kanios48af1772007-08-17 07:37:52 +00001931 if (it == REG_NUM_ESP
Keith Kaniosb7a89542007-04-12 02:40:54 +00001932 || (s != 1 && s != 2 && s != 4 && s != 8 && it != -1))
H. Peter Anvine2c80182005-01-15 22:15:51 +00001933 return NULL; /* wrong, for various reasons */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001934
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001935 output->rex |= rexflags(it, ix, REX_X);
1936 output->rex |= rexflags(bt, bx, REX_B);
Keith Kaniosb7a89542007-04-12 02:40:54 +00001937
Keith Kanios48af1772007-08-17 07:37:52 +00001938 if (it == -1 && (bt & 7) != REG_NUM_ESP) {
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001939 /* no SIB needed */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001940 int mod, rm;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001941
1942 if (bt == -1) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001943 rm = 5;
H. Peter Anvine2c80182005-01-15 22:15:51 +00001944 mod = 0;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001945 } else {
1946 rm = (bt & 7);
Keith Kanios48af1772007-08-17 07:37:52 +00001947 if (rm != REG_NUM_EBP && o == 0 &&
Keith Kaniosb7a89542007-04-12 02:40:54 +00001948 seg == NO_SEG && !forw_ref &&
1949 !(input->eaflags &
1950 (EAF_BYTEOFFS | EAF_WORDOFFS)))
1951 mod = 0;
1952 else if (input->eaflags & EAF_BYTEOFFS ||
1953 (o >= -128 && o <= 127 && seg == NO_SEG
1954 && !forw_ref
1955 && !(input->eaflags & EAF_WORDOFFS)))
1956 mod = 1;
1957 else
1958 mod = 2;
1959 }
H. Peter Anvinea838272002-04-30 20:51:53 +00001960
H. Peter Anvine2c80182005-01-15 22:15:51 +00001961 output->sib_present = FALSE;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001962 output->bytes = (bt == -1 || mod == 2 ? 4 : mod);
1963 output->modrm = (mod << 6) | ((rfield & 7) << 3) | rm;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00001964 } else {
1965 /* we need a SIB */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001966 int mod, scale, index, base;
Keith Kaniosb7a89542007-04-12 02:40:54 +00001967
1968 if (it == -1)
1969 index = 4, s = 1;
1970 else
1971 index = (it & 7);
1972
H. Peter Anvine2c80182005-01-15 22:15:51 +00001973 switch (s) {
1974 case 1:
1975 scale = 0;
1976 break;
1977 case 2:
1978 scale = 1;
1979 break;
1980 case 4:
1981 scale = 2;
1982 break;
1983 case 8:
1984 scale = 3;
1985 break;
1986 default: /* then what the smeg is it? */
1987 return NULL; /* panic */
1988 }
Keith Kaniosb7a89542007-04-12 02:40:54 +00001989
1990 if (bt == -1) {
1991 base = 5;
1992 mod = 0;
1993 } else {
1994 base = (bt & 7);
Keith Kanios48af1772007-08-17 07:37:52 +00001995 if (base != REG_NUM_EBP && o == 0 &&
H. Peter Anvine2c80182005-01-15 22:15:51 +00001996 seg == NO_SEG && !forw_ref &&
1997 !(input->eaflags &
Keith Kaniosb7a89542007-04-12 02:40:54 +00001998 (EAF_BYTEOFFS | EAF_WORDOFFS)))
1999 mod = 0;
2000 else if (input->eaflags & EAF_BYTEOFFS ||
2001 (o >= -128 && o <= 127 && seg == NO_SEG
2002 && !forw_ref
2003 && !(input->eaflags & EAF_WORDOFFS)))
2004 mod = 1;
2005 else
2006 mod = 2;
2007 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00002008
H. Peter Anvine2c80182005-01-15 22:15:51 +00002009 output->sib_present = TRUE;
Keith Kaniosb7a89542007-04-12 02:40:54 +00002010 output->bytes = (bt == -1 || mod == 2 ? 4 : mod);
2011 output->modrm = (mod << 6) | ((rfield & 7) << 3) | 4;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002012 output->sib = (scale << 6) | (index << 3) | base;
2013 }
2014 } else { /* it's 16-bit */
2015 int mod, rm;
Keith Kaniosb7a89542007-04-12 02:40:54 +00002016
2017 /* check for 64-bit long mode */
2018 if (addrbits == 64)
2019 return NULL;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00002020
H. Peter Anvine2c80182005-01-15 22:15:51 +00002021 /* check all registers are BX, BP, SI or DI */
2022 if ((b != -1 && b != R_BP && b != R_BX && b != R_SI
2023 && b != R_DI) || (i != -1 && i != R_BP && i != R_BX
2024 && i != R_SI && i != R_DI))
2025 return NULL;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00002026
Keith Kaniosb7a89542007-04-12 02:40:54 +00002027 /* ensure the user didn't specify DWORD/QWORD */
2028 if (input->addr_size == 32 || input->addr_size == 64)
H. Peter Anvine2c80182005-01-15 22:15:51 +00002029 return NULL;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00002030
H. Peter Anvine2c80182005-01-15 22:15:51 +00002031 if (s != 1 && i != -1)
2032 return NULL; /* no can do, in 16-bit EA */
2033 if (b == -1 && i != -1) {
2034 int tmp = b;
2035 b = i;
2036 i = tmp;
2037 } /* swap */
2038 if ((b == R_SI || b == R_DI) && i != -1) {
2039 int tmp = b;
2040 b = i;
2041 i = tmp;
2042 }
2043 /* have BX/BP as base, SI/DI index */
2044 if (b == i)
2045 return NULL; /* shouldn't ever happen, in theory */
2046 if (i != -1 && b != -1 &&
2047 (i == R_BP || i == R_BX || b == R_SI || b == R_DI))
2048 return NULL; /* invalid combinations */
2049 if (b == -1) /* pure offset: handled above */
2050 return NULL; /* so if it gets to here, panic! */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00002051
H. Peter Anvine2c80182005-01-15 22:15:51 +00002052 rm = -1;
2053 if (i != -1)
2054 switch (i * 256 + b) {
2055 case R_SI * 256 + R_BX:
2056 rm = 0;
2057 break;
2058 case R_DI * 256 + R_BX:
2059 rm = 1;
2060 break;
2061 case R_SI * 256 + R_BP:
2062 rm = 2;
2063 break;
2064 case R_DI * 256 + R_BP:
2065 rm = 3;
2066 break;
2067 } else
2068 switch (b) {
2069 case R_SI:
2070 rm = 4;
2071 break;
2072 case R_DI:
2073 rm = 5;
2074 break;
2075 case R_BP:
2076 rm = 6;
2077 break;
2078 case R_BX:
2079 rm = 7;
2080 break;
2081 }
2082 if (rm == -1) /* can't happen, in theory */
2083 return NULL; /* so panic if it does */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00002084
H. Peter Anvine2c80182005-01-15 22:15:51 +00002085 if (o == 0 && seg == NO_SEG && !forw_ref && rm != 6 &&
2086 !(input->eaflags & (EAF_BYTEOFFS | EAF_WORDOFFS)))
2087 mod = 0;
2088 else if (input->eaflags & EAF_BYTEOFFS ||
2089 (o >= -128 && o <= 127 && seg == NO_SEG
2090 && !forw_ref
2091 && !(input->eaflags & EAF_WORDOFFS)))
2092 mod = 1;
2093 else
2094 mod = 2;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00002095
H. Peter Anvine2c80182005-01-15 22:15:51 +00002096 output->sib_present = FALSE; /* no SIB - it's 16-bit */
2097 output->bytes = mod; /* bytes of offset needed */
Keith Kaniosb7a89542007-04-12 02:40:54 +00002098 output->modrm = (mod << 6) | ((rfield & 7) << 3) | rm;
H. Peter Anvine2c80182005-01-15 22:15:51 +00002099 }
2100 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00002101 }
Keith Kaniosb7a89542007-04-12 02:40:54 +00002102
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00002103 output->size = 1 + output->sib_present + output->bytes;
2104 return output;
2105}
2106
H. Peter Anvine2c80182005-01-15 22:15:51 +00002107static int chsize(operand * input, int addrbits)
H. Peter Anvineba20a72002-04-30 20:53:55 +00002108{
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00002109 if (!(MEMORY & ~input->type)) {
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002110 int32_t i, b;
Keith Kaniosb7a89542007-04-12 02:40:54 +00002111
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002112 if (input->indexreg < EXPR_REG_START /* Verify as Register */
Keith Kaniosb7a89542007-04-12 02:40:54 +00002113 || input->indexreg >= REG_ENUM_LIMIT)
H. Peter Anvinc6be66f2007-05-30 20:30:15 +00002114 i = 0;
Keith Kaniosb7a89542007-04-12 02:40:54 +00002115 else
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002116 i = reg_flags[input->indexreg];
Keith Kaniosb7a89542007-04-12 02:40:54 +00002117
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002118 if (input->basereg < EXPR_REG_START /* Verify as Register */
Keith Kaniosb7a89542007-04-12 02:40:54 +00002119 || input->basereg >= REG_ENUM_LIMIT)
H. Peter Anvinc6be66f2007-05-30 20:30:15 +00002120 b = 0;
Keith Kaniosb7a89542007-04-12 02:40:54 +00002121 else
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002122 b = reg_flags[input->basereg];
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00002123
H. Peter Anvine2c80182005-01-15 22:15:51 +00002124 if (input->scale == 0)
H. Peter Anvinc6be66f2007-05-30 20:30:15 +00002125 i = 0;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00002126
H. Peter Anvinc6be66f2007-05-30 20:30:15 +00002127 if (!i && !b) /* pure offset */
H. Peter Anvine2c80182005-01-15 22:15:51 +00002128 return (input->addr_size != 0 && input->addr_size != addrbits);
Keith Kaniosb7a89542007-04-12 02:40:54 +00002129
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002130 if (!(REG32 & ~i) || !(REG32 & ~b))
Keith Kaniosb7a89542007-04-12 02:40:54 +00002131 return (addrbits != 32);
H. Peter Anvine2c80182005-01-15 22:15:51 +00002132 else
2133 return (addrbits == 32);
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002134 } else {
H. Peter Anvine2c80182005-01-15 22:15:51 +00002135 return 0;
H. Peter Anvin3df97a72007-05-30 03:25:21 +00002136 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00002137}