blob: 426bae23731b9acbf30e52e7ca9cd1d6bae27289 [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
25 * assembly mode or the address-size override on the operand
26 * \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
28 * \50, \51, \52 - a byte relative operand, from operand 0, 1 or 2
29 * \60, \61, \62 - a word relative operand, from operand 0, 1 or 2
30 * \64, \65, \66 - select between \6[012] and \7[012] depending on 16/32 bit
31 * assembly mode or the address-size override on the operand
32 * \70, \71, \72 - a long relative operand, from operand 0, 1 or 2
33 * \1ab - a ModRM, calculated on EA in operand a, with the spare
34 * field the register value of operand b.
35 * \2ab - a ModRM, calculated on EA in operand a, with the spare
36 * field equal to digit b.
37 * \30x - might be an 0x67 byte, depending on the address size of
38 * the memory reference in operand x.
39 * \310 - indicates fixed 16-bit address size, i.e. optional 0x67.
40 * \311 - indicates fixed 32-bit address size, i.e. optional 0x67.
41 * \320 - indicates fixed 16-bit operand size, i.e. optional 0x66.
42 * \321 - indicates fixed 32-bit operand size, i.e. optional 0x66.
43 * \322 - indicates that this instruction is only valid when the
44 * operand size is the default (instruction to disassembler,
45 * generates no code in the assembler)
46 * \330 - a literal byte follows in the code stream, to be added
47 * to the condition code value of the instruction.
H. Peter Anvinef7468f2002-04-30 20:57:59 +000048 * \331 - instruction not valid with REP prefix. Hint for
49 * disassembler only; for SSE instructions.
50 * \332 - disassemble a rep (0xF3 byte) prefix as repe not rep.
51 * \333 - REP prefix (0xF3 byte); for SSE instructions. Not encoded
52 * as a literal byte in order to aid the disassembler.
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000053 * \340 - reserve <operand 0> bytes of uninitialised storage.
54 * Operand 0 had better be a segmentless constant.
55 */
56
57#include <stdio.h>
58#include <string.h>
59
60#include "nasm.h"
H. Peter Anvin6768eb72002-04-30 20:52:26 +000061#include "nasmlib.h"
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000062#include "assemble.h"
63#include "insns.h"
64
65extern struct itemplate *nasm_instructions[];
66
67typedef struct {
68 int sib_present; /* is a SIB byte necessary? */
69 int bytes; /* # of bytes of offset needed */
70 int size; /* lazy - this is sib+bytes+1 */
71 unsigned char modrm, sib; /* the bytes themselves */
72} ea;
73
74static efunc errfunc;
75static struct ofmt *outfmt;
H. Peter Anvin6768eb72002-04-30 20:52:26 +000076static ListGen *list;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000077
78static long calcsize (long, long, int, insn *, char *);
79static void gencode (long, long, int, insn *, char *, long);
H. Peter Anvineba20a72002-04-30 20:53:55 +000080static int regval (operand *o);
81static int matches (struct itemplate *, insn *);
82static ea * process_ea (operand *, ea *, int, int, int);
83static int chsize (operand *, int);
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000084
H. Peter Anvin6768eb72002-04-30 20:52:26 +000085/*
86 * This routine wrappers the real output format's output routine,
87 * in order to pass a copy of the data off to the listing file
88 * generator at the same time.
89 */
90static void out (long offset, long segto, void *data, unsigned long type,
H. Peter Anvineba20a72002-04-30 20:53:55 +000091 long segment, long wrt)
92{
93 static long lineno;
94 static char *lnfname;
95
H. Peter Anvin6768eb72002-04-30 20:52:26 +000096 if ((type & OUT_TYPMASK) == OUT_ADDRESS) {
97 if (segment != NO_SEG || wrt != NO_SEG) {
98 /*
99 * This address is relocated. We must write it as
100 * OUT_ADDRESS, so there's no work to be done here.
101 */
102 list->output (offset, data, type);
H. Peter Anvineba20a72002-04-30 20:53:55 +0000103 }
104 else {
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000105 unsigned char p[4], *q = p;
106 /*
107 * This is a non-relocated address, and we're going to
108 * convert it into RAWDATA format.
109 */
110 if ((type & OUT_SIZMASK) == 4) {
111 WRITELONG (q, * (long *) data);
112 list->output (offset, p, OUT_RAWDATA+4);
H. Peter Anvineba20a72002-04-30 20:53:55 +0000113 }
114 else {
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000115 WRITESHORT (q, * (long *) data);
116 list->output (offset, p, OUT_RAWDATA+2);
117 }
118 }
H. Peter Anvineba20a72002-04-30 20:53:55 +0000119 }
120 else if ((type & OUT_TYPMASK) == OUT_RAWDATA) {
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000121 list->output (offset, data, type);
H. Peter Anvineba20a72002-04-30 20:53:55 +0000122 }
123 else if ((type & OUT_TYPMASK) == OUT_RESERVE) {
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000124 list->output (offset, NULL, type);
H. Peter Anvineba20a72002-04-30 20:53:55 +0000125 }
126 else if ((type & OUT_TYPMASK) == OUT_REL2ADR ||
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000127 (type & OUT_TYPMASK) == OUT_REL4ADR) {
128 list->output (offset, data, type);
129 }
130
H. Peter Anvineba20a72002-04-30 20:53:55 +0000131 if (src_get(&lineno,&lnfname))
132 outfmt->current_dfmt->linenum(lnfname,lineno,segto);
133
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000134 outfmt->output (segto, data, type, segment, wrt);
135}
136
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000137long assemble (long segment, long offset, int bits,
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000138 insn *instruction, struct ofmt *output, efunc error,
H. Peter Anvineba20a72002-04-30 20:53:55 +0000139 ListGen *listgen)
140{
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000141 struct itemplate *temp;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000142 int j;
143 int size_prob;
144 long insn_end;
145 long itimes;
146 long start = offset;
147 long wsize = 0; /* size for DB etc. */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000148
149 errfunc = error; /* to pass to other functions */
150 outfmt = output; /* likewise */
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000151 list = listgen; /* and again */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000152
H. Peter Anvineba20a72002-04-30 20:53:55 +0000153 switch (instruction->opcode)
154 {
155 case -1: return 0;
156 case I_DB: wsize = 1; break;
157 case I_DW: wsize = 2; break;
158 case I_DD: wsize = 4; break;
159 case I_DQ: wsize = 8; break;
160 case I_DT: wsize = 10; break;
161 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000162
H. Peter Anvineba20a72002-04-30 20:53:55 +0000163 if (wsize) {
164 extop * e;
165 long t = instruction->times;
166 if (t < 0)
167 errfunc(ERR_PANIC, "instruction->times < 0 (%ld) in assemble()",t);
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000168
H. Peter Anvineba20a72002-04-30 20:53:55 +0000169 while (t--) /* repeat TIMES times */
170 {
171 for (e = instruction->eops; e; e = e->next)
172 {
173 if (e->type == EOT_DB_NUMBER)
174 {
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000175 if (wsize == 1) {
176 if (e->segment != NO_SEG)
177 errfunc (ERR_NONFATAL,
178 "one-byte relocation attempted");
179 else {
H. Peter Anvineba20a72002-04-30 20:53:55 +0000180 out (offset, segment, &e->offset, OUT_RAWDATA+1,
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000181 NO_SEG, NO_SEG);
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000182 }
H. Peter Anvineba20a72002-04-30 20:53:55 +0000183 }
184 else if (wsize > 5) {
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000185 errfunc (ERR_NONFATAL, "integer supplied to a D%c"
186 " instruction", wsize==8 ? 'Q' : 'T');
H. Peter Anvineba20a72002-04-30 20:53:55 +0000187 }
188 else
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000189 out (offset, segment, &e->offset,
190 OUT_ADDRESS+wsize, e->segment,
191 e->wrt);
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000192 offset += wsize;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000193 }
194 else if (e->type == EOT_DB_STRING)
195 {
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000196 int align;
197
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000198 out (offset, segment, e->stringval,
199 OUT_RAWDATA+e->stringlen, NO_SEG, NO_SEG);
H. Peter Anvineba20a72002-04-30 20:53:55 +0000200 align = e->stringlen % wsize;
201
202 if (align) {
203 align = wsize - align;
204 out (offset, segment, "\0\0\0\0\0\0\0\0",
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000205 OUT_RAWDATA+align, NO_SEG, NO_SEG);
H. Peter Anvineba20a72002-04-30 20:53:55 +0000206 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000207 offset += e->stringlen + align;
208 }
209 }
H. Peter Anvineba20a72002-04-30 20:53:55 +0000210 if (t > 0 && t == instruction->times-1)
211 {
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000212 /*
213 * Dummy call to list->output to give the offset to the
214 * listing module.
215 */
216 list->output (offset, NULL, OUT_RAWDATA);
217 list->uplevel (LIST_TIMES);
218 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000219 }
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000220 if (instruction->times > 1)
221 list->downlevel (LIST_TIMES);
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000222 return offset - start;
223 }
224
H. Peter Anvineba20a72002-04-30 20:53:55 +0000225 if (instruction->opcode == I_INCBIN)
226 {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000227 static char fname[FILENAME_MAX];
H. Peter Anvineba20a72002-04-30 20:53:55 +0000228 FILE * fp;
229 long len;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000230
231 len = FILENAME_MAX-1;
232 if (len > instruction->eops->stringlen)
233 len = instruction->eops->stringlen;
234 strncpy (fname, instruction->eops->stringval, len);
235 fname[len] = '\0';
H. Peter Anvineba20a72002-04-30 20:53:55 +0000236
237 if ( (fp = fopen(fname, "rb")) == NULL)
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000238 error (ERR_NONFATAL, "`incbin': unable to open file `%s'", fname);
239 else if (fseek(fp, 0L, SEEK_END) < 0)
240 error (ERR_NONFATAL, "`incbin': unable to seek on file `%s'",
241 fname);
H. Peter Anvineba20a72002-04-30 20:53:55 +0000242 else
243 {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000244 static char buf[2048];
245 long t = instruction->times;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000246 long base = 0;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000247
248 len = ftell (fp);
249 if (instruction->eops->next) {
H. Peter Anvineba20a72002-04-30 20:53:55 +0000250 base = instruction->eops->next->offset;
251 len -= base;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000252 if (instruction->eops->next->next &&
253 len > instruction->eops->next->next->offset)
254 len = instruction->eops->next->next->offset;
255 }
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000256 /*
257 * Dummy call to list->output to give the offset to the
258 * listing module.
259 */
260 list->output (offset, NULL, OUT_RAWDATA);
261 list->uplevel(LIST_INCBIN);
H. Peter Anvineba20a72002-04-30 20:53:55 +0000262 while (t--)
263 {
264 long l;
265
266 fseek (fp, base, SEEK_SET);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000267 l = len;
268 while (l > 0) {
269 long m = fread (buf, 1, (l>sizeof(buf)?sizeof(buf):l),
270 fp);
271 if (!m) {
272 /*
273 * This shouldn't happen unless the file
274 * actually changes while we are reading
275 * it.
276 */
277 error (ERR_NONFATAL, "`incbin': unexpected EOF while"
278 " reading file `%s'", fname);
H. Peter Anvineba20a72002-04-30 20:53:55 +0000279 t=0; /* Try to exit cleanly */
280 break;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000281 }
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000282 out (offset, segment, buf, OUT_RAWDATA+m,
283 NO_SEG, NO_SEG);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000284 l -= m;
285 }
286 }
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000287 list->downlevel(LIST_INCBIN);
288 if (instruction->times > 1) {
289 /*
290 * Dummy call to list->output to give the offset to the
291 * listing module.
292 */
293 list->output (offset, NULL, OUT_RAWDATA);
294 list->uplevel(LIST_TIMES);
295 list->downlevel(LIST_TIMES);
296 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000297 fclose (fp);
298 return instruction->times * len;
299 }
300 return 0; /* if we're here, there's an error */
301 }
302
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000303 size_prob = FALSE;
304 temp = nasm_instructions[instruction->opcode];
305 while (temp->opcode != -1) {
306 int m = matches (temp, instruction);
H. Peter Anvineba20a72002-04-30 20:53:55 +0000307
308 if (m == 100) /* matches! */
309 {
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000310 char *codes = temp->code;
311 long insn_size = calcsize(segment, offset, bits,
312 instruction, codes);
313 itimes = instruction->times;
314 if (insn_size < 0) /* shouldn't be, on pass two */
315 error (ERR_PANIC, "errors made it through from pass one");
316 else while (itimes--) {
317 insn_end = offset + insn_size;
318 for (j=0; j<instruction->nprefix; j++) {
H. Peter Anvineba20a72002-04-30 20:53:55 +0000319 unsigned char c=0;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000320 switch (instruction->prefixes[j]) {
321 case P_LOCK:
322 c = 0xF0; break;
323 case P_REPNE: case P_REPNZ:
324 c = 0xF2; break;
325 case P_REPE: case P_REPZ: case P_REP:
326 c = 0xF3; break;
327 case R_CS: c = 0x2E; break;
328 case R_DS: c = 0x3E; break;
329 case R_ES: c = 0x26; break;
330 case R_FS: c = 0x64; break;
331 case R_GS: c = 0x65; break;
332 case R_SS: c = 0x36; break;
333 case P_A16:
H. Peter Anvineba20a72002-04-30 20:53:55 +0000334 if (bits != 16)
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000335 c = 0x67;
336 break;
337 case P_A32:
H. Peter Anvineba20a72002-04-30 20:53:55 +0000338 if (bits != 32)
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000339 c = 0x67;
340 break;
341 case P_O16:
H. Peter Anvineba20a72002-04-30 20:53:55 +0000342 if (bits != 16)
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000343 c = 0x66;
344 break;
345 case P_O32:
H. Peter Anvineba20a72002-04-30 20:53:55 +0000346 if (bits != 32)
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000347 c = 0x66;
348 break;
349 default:
350 error (ERR_PANIC,
351 "invalid instruction prefix");
352 }
H. Peter Anvineba20a72002-04-30 20:53:55 +0000353 if (c != 0) {
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000354 out (offset, segment, &c, OUT_RAWDATA+1,
355 NO_SEG, NO_SEG);
H. Peter Anvineba20a72002-04-30 20:53:55 +0000356 offset++;
357 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000358 }
359 gencode (segment, offset, bits, instruction, codes, insn_end);
360 offset += insn_size;
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000361 if (itimes > 0 && itimes == instruction->times-1) {
362 /*
363 * Dummy call to list->output to give the offset to the
364 * listing module.
365 */
366 list->output (offset, NULL, OUT_RAWDATA);
367 list->uplevel (LIST_TIMES);
368 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000369 }
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000370 if (instruction->times > 1)
371 list->downlevel (LIST_TIMES);
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000372 return offset - start;
373 } else if (m > 0) {
374 size_prob = m;
375 }
376 temp++;
377 }
H. Peter Anvineba20a72002-04-30 20:53:55 +0000378
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000379 if (temp->opcode == -1) { /* didn't match any instruction */
380 if (size_prob == 1) /* would have matched, but for size */
381 error (ERR_NONFATAL, "operation size not specified");
382 else if (size_prob == 2)
383 error (ERR_NONFATAL, "mismatch in operand sizes");
384 else
385 error (ERR_NONFATAL,
386 "invalid combination of opcode and operands");
387 }
388 return 0;
389}
390
391long insn_size (long segment, long offset, int bits,
H. Peter Anvineba20a72002-04-30 20:53:55 +0000392 insn *instruction, efunc error)
393{
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000394 struct itemplate *temp;
395
396 errfunc = error; /* to pass to other functions */
397
398 if (instruction->opcode == -1)
399 return 0;
400
401 if (instruction->opcode == I_DB ||
402 instruction->opcode == I_DW ||
403 instruction->opcode == I_DD ||
404 instruction->opcode == I_DQ ||
H. Peter Anvineba20a72002-04-30 20:53:55 +0000405 instruction->opcode == I_DT)
406 {
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000407 extop *e;
408 long isize, osize, wsize = 0; /* placate gcc */
409
410 isize = 0;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000411 switch (instruction->opcode)
412 {
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000413 case I_DB: wsize = 1; break;
414 case I_DW: wsize = 2; break;
415 case I_DD: wsize = 4; break;
416 case I_DQ: wsize = 8; break;
417 case I_DT: wsize = 10; break;
418 }
419
H. Peter Anvineba20a72002-04-30 20:53:55 +0000420 for (e = instruction->eops; e; e = e->next)
421 {
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000422 long align;
423
424 osize = 0;
425 if (e->type == EOT_DB_NUMBER)
426 osize = 1;
427 else if (e->type == EOT_DB_STRING)
428 osize = e->stringlen;
429
430 align = (-osize) % wsize;
431 if (align < 0)
432 align += wsize;
433 isize += osize + align;
434 }
435 return isize * instruction->times;
436 }
437
H. Peter Anvineba20a72002-04-30 20:53:55 +0000438 if (instruction->opcode == I_INCBIN)
439 {
440 char fname[FILENAME_MAX];
441 FILE * fp;
442 long len;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000443
444 len = FILENAME_MAX-1;
445 if (len > instruction->eops->stringlen)
446 len = instruction->eops->stringlen;
447 strncpy (fname, instruction->eops->stringval, len);
448 fname[len] = '\0';
H. Peter Anvineba20a72002-04-30 20:53:55 +0000449 if ( (fp = fopen(fname, "rb")) == NULL )
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000450 error (ERR_NONFATAL, "`incbin': unable to open file `%s'", fname);
451 else if (fseek(fp, 0L, SEEK_END) < 0)
452 error (ERR_NONFATAL, "`incbin': unable to seek on file `%s'",
453 fname);
H. Peter Anvineba20a72002-04-30 20:53:55 +0000454 else
455 {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000456 len = ftell (fp);
457 fclose (fp);
H. Peter Anvineba20a72002-04-30 20:53:55 +0000458 if (instruction->eops->next)
459 {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000460 len -= instruction->eops->next->offset;
461 if (instruction->eops->next->next &&
462 len > instruction->eops->next->next->offset)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000463 {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000464 len = instruction->eops->next->next->offset;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000465 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000466 }
467 return instruction->times * len;
468 }
469 return 0; /* if we're here, there's an error */
470 }
471
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000472 temp = nasm_instructions[instruction->opcode];
473 while (temp->opcode != -1) {
474 if (matches(temp, instruction) == 100) {
475 /* we've matched an instruction. */
H. Peter Anvineba20a72002-04-30 20:53:55 +0000476 long isize;
477 char * codes = temp->code;
478 int j;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000479
480 isize = calcsize(segment, offset, bits, instruction, codes);
481 if (isize < 0)
482 return -1;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000483 for (j = 0; j < instruction->nprefix; j++)
484 {
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000485 if ((instruction->prefixes[j] != P_A16 &&
486 instruction->prefixes[j] != P_O16 && bits==16) ||
487 (instruction->prefixes[j] != P_A32 &&
488 instruction->prefixes[j] != P_O32 && bits==32))
H. Peter Anvineba20a72002-04-30 20:53:55 +0000489 {
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000490 isize++;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000491 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000492 }
493 return isize * instruction->times;
494 }
495 temp++;
496 }
497 return -1; /* didn't match any instruction */
498}
499
500static long calcsize (long segment, long offset, int bits,
H. Peter Anvineba20a72002-04-30 20:53:55 +0000501 insn *ins, char *codes)
502{
503 long length = 0;
504 unsigned char c;
505
506 (void) segment; /* Don't warn that this parameter is unused */
507 (void) offset; /* Don't warn that this parameter is unused */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000508
509 while (*codes) switch (c = *codes++) {
510 case 01: case 02: case 03:
511 codes += c, length += c; break;
512 case 04: case 05: case 06: case 07:
513 length++; break;
514 case 010: case 011: case 012:
515 codes++, length++; break;
516 case 017:
517 length++; break;
518 case 014: case 015: case 016:
519 length++; break;
520 case 020: case 021: case 022:
521 length++; break;
522 case 024: case 025: case 026:
523 length++; break;
524 case 030: case 031: case 032:
525 length += 2; break;
526 case 034: case 035: case 036:
527 length += ((ins->oprs[c-034].addr_size ?
528 ins->oprs[c-034].addr_size : bits) == 16 ? 2 : 4); break;
529 case 037:
530 length += 2; break;
531 case 040: case 041: case 042:
532 length += 4; break;
533 case 050: case 051: case 052:
534 length++; break;
535 case 060: case 061: case 062:
536 length += 2; break;
537 case 064: case 065: case 066:
538 length += ((ins->oprs[c-064].addr_size ?
539 ins->oprs[c-064].addr_size : bits) == 16 ? 2 : 4); break;
540 case 070: case 071: case 072:
541 length += 4; break;
542 case 0300: case 0301: case 0302:
543 length += chsize (&ins->oprs[c-0300], bits);
544 break;
545 case 0310:
546 length += (bits==32);
547 break;
548 case 0311:
549 length += (bits==16);
550 break;
551 case 0312:
552 break;
553 case 0320:
554 length += (bits==32);
555 break;
556 case 0321:
557 length += (bits==16);
558 break;
559 case 0322:
560 break;
561 case 0330:
562 codes++, length++; break;
H. Peter Anvinef7468f2002-04-30 20:57:59 +0000563 case 0331:
564 case 0332:
565 break;
566 case 0333:
567 length++; break;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000568 case 0340: case 0341: case 0342:
569 if (ins->oprs[0].segment != NO_SEG)
570 errfunc (ERR_NONFATAL, "attempt to reserve non-constant"
571 " quantity of BSS space");
572 else
573 length += ins->oprs[0].offset << (c-0340);
574 break;
575 default: /* can't do it by 'case' statements */
576 if (c>=0100 && c<=0277) { /* it's an EA */
577 ea ea_data;
H. Peter Anvinea838272002-04-30 20:51:53 +0000578 if (!process_ea (&ins->oprs[(c>>3)&7], &ea_data, bits, 0,
579 ins->forw_ref)) {
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000580 errfunc (ERR_NONFATAL, "invalid effective address");
581 return -1;
582 } else
583 length += ea_data.size;
584 } else
585 errfunc (ERR_PANIC, "internal instruction table corrupt"
586 ": instruction code 0x%02X given", c);
587 }
588 return length;
589}
590
591static void gencode (long segment, long offset, int bits,
H. Peter Anvineba20a72002-04-30 20:53:55 +0000592 insn *ins, char *codes, long insn_end)
593{
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000594 static char condval[] = { /* conditional opcodes */
595 0x7, 0x3, 0x2, 0x6, 0x2, 0x4, 0xF, 0xD, 0xC, 0xE, 0x6, 0x2,
596 0x3, 0x7, 0x3, 0x5, 0xE, 0xC, 0xD, 0xF, 0x1, 0xB, 0x9, 0x5,
597 0x0, 0xA, 0xA, 0xB, 0x8, 0x4
598 };
H. Peter Anvineba20a72002-04-30 20:53:55 +0000599 unsigned char c;
600 unsigned char bytes[4];
601 long data, size;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000602
H. Peter Anvineba20a72002-04-30 20:53:55 +0000603 while (*codes)
604 switch (c = *codes++)
605 {
606 case 01: case 02: case 03:
607 out (offset, segment, codes, OUT_RAWDATA+c, NO_SEG, NO_SEG);
608 codes += c;
609 offset += c;
610 break;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000611
H. Peter Anvineba20a72002-04-30 20:53:55 +0000612 case 04: case 06:
613 switch (ins->oprs[0].basereg)
614 {
615 case R_CS:
616 bytes[0] = 0x0E + (c == 0x04 ? 1 : 0); break;
617 case R_DS:
618 bytes[0] = 0x1E + (c == 0x04 ? 1 : 0); break;
619 case R_ES:
620 bytes[0] = 0x06 + (c == 0x04 ? 1 : 0); break;
621 case R_SS:
622 bytes[0] = 0x16 + (c == 0x04 ? 1 : 0); break;
623 default:
H. Peter Anvin4836e332002-04-30 20:56:43 +0000624 errfunc (ERR_PANIC, "bizarre 8086 segment register received");
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000625 }
H. Peter Anvineba20a72002-04-30 20:53:55 +0000626 out (offset, segment, bytes, OUT_RAWDATA+1, NO_SEG, NO_SEG);
627 offset++;
628 break;
629
630 case 05: case 07:
631 switch (ins->oprs[0].basereg) {
632 case R_FS: bytes[0] = 0xA0 + (c == 0x05 ? 1 : 0); break;
633 case R_GS: bytes[0] = 0xA8 + (c == 0x05 ? 1 : 0); break;
634 default:
H. Peter Anvin4836e332002-04-30 20:56:43 +0000635 errfunc (ERR_PANIC, "bizarre 386 segment register received");
H. Peter Anvineba20a72002-04-30 20:53:55 +0000636 }
637 out (offset, segment, bytes, OUT_RAWDATA+1, NO_SEG, NO_SEG);
638 offset++;
639 break;
640
641 case 010: case 011: case 012:
642 bytes[0] = *codes++ + regval(&ins->oprs[c-010]);
643 out (offset, segment, bytes, OUT_RAWDATA+1, NO_SEG, NO_SEG);
644 offset += 1;
645 break;
646
647 case 017:
648 bytes[0] = 0;
649 out (offset, segment, bytes, OUT_RAWDATA+1, NO_SEG, NO_SEG);
650 offset += 1;
651 break;
652
653 case 014: case 015: case 016:
654 if (ins->oprs[c-014].offset < -128
655 || ins->oprs[c-014].offset > 127)
656 {
657 errfunc (ERR_WARNING, "signed byte value exceeds bounds");
658 }
659
660 if (ins->oprs[c-014].segment != NO_SEG)
661 {
662 data = ins->oprs[c-014].offset;
663 out (offset, segment, &data, OUT_ADDRESS+1,
664 ins->oprs[c-014].segment, ins->oprs[c-014].wrt);
665 }
666 else {
667 bytes[0] = ins->oprs[c-014].offset;
668 out (offset, segment, bytes, OUT_RAWDATA+1, NO_SEG, NO_SEG);
669 }
670 offset += 1;
671 break;
672
673 case 020: case 021: case 022:
674 if (ins->oprs[c-020].offset < -256
675 || ins->oprs[c-020].offset > 255)
676 {
677 errfunc (ERR_WARNING, "byte value exceeds bounds");
678 }
679 if (ins->oprs[c-020].segment != NO_SEG) {
680 data = ins->oprs[c-020].offset;
681 out (offset, segment, &data, OUT_ADDRESS+1,
682 ins->oprs[c-020].segment, ins->oprs[c-020].wrt);
683 }
684 else {
685 bytes[0] = ins->oprs[c-020].offset;
686 out (offset, segment, bytes, OUT_RAWDATA+1, NO_SEG, NO_SEG);
687 }
688 offset += 1;
689 break;
690
691 case 024: case 025: case 026:
692 if (ins->oprs[c-024].offset < 0 || ins->oprs[c-024].offset > 255)
693 errfunc (ERR_WARNING, "unsigned byte value exceeds bounds");
694 if (ins->oprs[c-024].segment != NO_SEG) {
695 data = ins->oprs[c-024].offset;
696 out (offset, segment, &data, OUT_ADDRESS+1,
697 ins->oprs[c-024].segment, ins->oprs[c-024].wrt);
698 }
699 else {
700 bytes[0] = ins->oprs[c-024].offset;
701 out (offset, segment, bytes, OUT_RAWDATA+1, NO_SEG, NO_SEG);
702 }
703 offset += 1;
704 break;
705
706 case 030: case 031: case 032:
707 if (ins->oprs[c-030].segment == NO_SEG &&
708 ins->oprs[c-030].wrt == NO_SEG &&
709 (ins->oprs[c-030].offset < -65536L ||
710 ins->oprs[c-030].offset > 65535L))
711 {
712 errfunc (ERR_WARNING, "word value exceeds bounds");
713 }
714 data = ins->oprs[c-030].offset;
715 out (offset, segment, &data, OUT_ADDRESS+2,
716 ins->oprs[c-030].segment, ins->oprs[c-030].wrt);
717 offset += 2;
718 break;
719
720 case 034: case 035: case 036:
721 data = ins->oprs[c-034].offset;
722 size = ((ins->oprs[c-034].addr_size ?
723 ins->oprs[c-034].addr_size : bits) == 16 ? 2 : 4);
724 if (size==16 && (data < -65536L || data > 65535L))
725 errfunc (ERR_WARNING, "word value exceeds bounds");
726 out (offset, segment, &data, OUT_ADDRESS+size,
727 ins->oprs[c-034].segment, ins->oprs[c-034].wrt);
728 offset += size;
729 break;
730
731 case 037:
732 if (ins->oprs[0].segment == NO_SEG)
733 errfunc (ERR_NONFATAL, "value referenced by FAR is not"
734 " relocatable");
735 data = 0L;
736 out (offset, segment, &data, OUT_ADDRESS+2,
737 outfmt->segbase(1+ins->oprs[0].segment),
738 ins->oprs[0].wrt);
739 offset += 2;
740 break;
741
742 case 040: case 041: case 042:
743 data = ins->oprs[c-040].offset;
744 out (offset, segment, &data, OUT_ADDRESS+4,
745 ins->oprs[c-040].segment, ins->oprs[c-040].wrt);
746 offset += 4;
747 break;
748
749 case 050: case 051: case 052:
750 if (ins->oprs[c-050].segment != segment)
751 errfunc (ERR_NONFATAL, "short relative jump outside segment");
752 data = ins->oprs[c-050].offset - insn_end;
753 if (data > 127 || data < -128)
754 errfunc (ERR_NONFATAL, "short jump is out of range");
755 bytes[0] = data;
756 out (offset, segment, bytes, OUT_RAWDATA+1, NO_SEG, NO_SEG);
757 offset += 1;
758 break;
759
760 case 060: case 061: case 062:
761 if (ins->oprs[c-060].segment != segment) {
762 data = ins->oprs[c-060].offset;
763 out (offset, segment, &data, OUT_REL2ADR+insn_end-offset,
764 ins->oprs[c-060].segment, ins->oprs[c-060].wrt);
765 } else {
766 data = ins->oprs[c-060].offset - insn_end;
767 out (offset, segment, &data,
768 OUT_ADDRESS+2, NO_SEG, NO_SEG);
769 }
770 offset += 2;
771 break;
772
773 case 064: case 065: case 066:
774 size = ((ins->oprs[c-064].addr_size ?
775 ins->oprs[c-064].addr_size : bits) == 16 ? 2 : 4);
776 if (ins->oprs[c-064].segment != segment) {
777 data = ins->oprs[c-064].offset;
778 size = (bits == 16 ? OUT_REL2ADR : OUT_REL4ADR);
779 out (offset, segment, &data, size+insn_end-offset,
780 ins->oprs[c-064].segment, ins->oprs[c-064].wrt);
781 size = (bits == 16 ? 2 : 4);
782 } else {
783 data = ins->oprs[c-064].offset - insn_end;
784 out (offset, segment, &data,
785 OUT_ADDRESS+size, NO_SEG, NO_SEG);
786 }
787 offset += size;
788 break;
789
790 case 070: case 071: case 072:
791 if (ins->oprs[c-070].segment != segment) {
792 data = ins->oprs[c-070].offset;
793 out (offset, segment, &data, OUT_REL4ADR+insn_end-offset,
794 ins->oprs[c-070].segment, ins->oprs[c-070].wrt);
795 } else {
796 data = ins->oprs[c-070].offset - insn_end;
797 out (offset, segment, &data,
798 OUT_ADDRESS+4, NO_SEG, NO_SEG);
799 }
800 offset += 4;
801 break;
802
803 case 0300: case 0301: case 0302:
804 if (chsize (&ins->oprs[c-0300], bits)) {
805 *bytes = 0x67;
806 out (offset, segment, bytes,
807 OUT_RAWDATA+1, NO_SEG, NO_SEG);
808 offset += 1;
809 } else
810 offset += 0;
811 break;
812
813 case 0310:
814 if (bits==32) {
815 *bytes = 0x67;
816 out (offset, segment, bytes,
817 OUT_RAWDATA+1, NO_SEG, NO_SEG);
818 offset += 1;
819 } else
820 offset += 0;
821 break;
822
823 case 0311:
824 if (bits==16) {
825 *bytes = 0x67;
826 out (offset, segment, bytes,
827 OUT_RAWDATA+1, NO_SEG, NO_SEG);
828 offset += 1;
829 } else
830 offset += 0;
831 break;
832
833 case 0312:
834 break;
835
836 case 0320:
837 if (bits==32) {
838 *bytes = 0x66;
839 out (offset, segment, bytes,
840 OUT_RAWDATA+1, NO_SEG, NO_SEG);
841 offset += 1;
842 } else
843 offset += 0;
844 break;
845
846 case 0321:
847 if (bits==16) {
848 *bytes = 0x66;
849 out (offset, segment, bytes,
850 OUT_RAWDATA+1, NO_SEG, NO_SEG);
851 offset += 1;
852 } else
853 offset += 0;
854 break;
855
856 case 0322:
857 break;
858
859 case 0330:
860 *bytes = *codes++ + condval[ins->condition];
861 out (offset, segment, bytes,
862 OUT_RAWDATA+1, NO_SEG, NO_SEG);
863 offset += 1;
864 break;
865
H. Peter Anvinef7468f2002-04-30 20:57:59 +0000866 case 0331:
867 case 0332:
868 break;
869
870 case 0333:
871 *bytes = 0xF3;
872 out (offset, segment, bytes,
873 OUT_RAWDATA+1, NO_SEG, NO_SEG);
874 offset += 1;
875 break;
876
H. Peter Anvineba20a72002-04-30 20:53:55 +0000877 case 0340: case 0341: case 0342:
878 if (ins->oprs[0].segment != NO_SEG)
879 errfunc (ERR_PANIC, "non-constant BSS size in pass two");
880 else {
881 long size = ins->oprs[0].offset << (c-0340);
882 if (size > 0)
883 out (offset, segment, NULL,
884 OUT_RESERVE+size, NO_SEG, NO_SEG);
885 offset += size;
886 }
887 break;
888
889 default: /* can't do it by 'case' statements */
890 if (c>=0100 && c<=0277) { /* it's an EA */
891 ea ea_data;
892 int rfield;
893 unsigned char *p;
894 long s;
895
896 if (c<=0177) /* pick rfield from operand b */
897 rfield = regval (&ins->oprs[c&7]);
898 else /* rfield is constant */
899 rfield = c & 7;
900
901 if (!process_ea (&ins->oprs[(c>>3)&7], &ea_data, bits, rfield,
902 ins->forw_ref))
903 {
904 errfunc (ERR_NONFATAL, "invalid effective address");
905 }
906
907 p = bytes;
908 *p++ = ea_data.modrm;
909 if (ea_data.sib_present)
910 *p++ = ea_data.sib;
911
912 s = p-bytes;
913 out (offset, segment, bytes, OUT_RAWDATA + s,
914 NO_SEG, NO_SEG);
915
916 switch (ea_data.bytes) {
917 case 0:
918 break;
919 case 1:
920 if (ins->oprs[(c>>3)&7].segment != NO_SEG) {
921 data = ins->oprs[(c>>3)&7].offset;
922 out (offset, segment, &data, OUT_ADDRESS+1,
923 ins->oprs[(c>>3)&7].segment,
924 ins->oprs[(c>>3)&7].wrt);
925 } else {
926 *bytes = ins->oprs[(c>>3)&7].offset;
927 out (offset, segment, bytes, OUT_RAWDATA+1,
928 NO_SEG, NO_SEG);
929 }
930 s++;
931 break;
932 case 2:
933 case 4:
934 data = ins->oprs[(c>>3)&7].offset;
935 out (offset, segment, &data,
936 OUT_ADDRESS+ea_data.bytes,
937 ins->oprs[(c>>3)&7].segment, ins->oprs[(c>>3)&7].wrt);
938 s += ea_data.bytes;
939 break;
940 }
941 offset += s;
942 } else
943 errfunc (ERR_PANIC, "internal instruction table corrupt"
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000944 ": instruction code 0x%02X given", c);
H. Peter Anvineba20a72002-04-30 20:53:55 +0000945 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000946}
947
H. Peter Anvineba20a72002-04-30 20:53:55 +0000948static int regval (operand *o)
949{
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000950 switch (o->basereg) {
951 case R_EAX: case R_AX: case R_AL: case R_ES: case R_CR0: case R_DR0:
H. Peter Anvin4836e332002-04-30 20:56:43 +0000952 case R_ST0: case R_MM0: case R_XMM0:
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000953 return 0;
954 case R_ECX: case R_CX: case R_CL: case R_CS: case R_DR1: case R_ST1:
H. Peter Anvin4836e332002-04-30 20:56:43 +0000955 case R_MM1: case R_XMM1:
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000956 return 1;
957 case R_EDX: case R_DX: case R_DL: case R_SS: case R_CR2: case R_DR2:
H. Peter Anvin4836e332002-04-30 20:56:43 +0000958 case R_ST2: case R_MM2: case R_XMM2:
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000959 return 2;
960 case R_EBX: case R_BX: case R_BL: case R_DS: case R_CR3: case R_DR3:
H. Peter Anvin4836e332002-04-30 20:56:43 +0000961 case R_TR3: case R_ST3: case R_MM3: case R_XMM3:
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000962 return 3;
963 case R_ESP: case R_SP: case R_AH: case R_FS: case R_CR4: case R_TR4:
H. Peter Anvin4836e332002-04-30 20:56:43 +0000964 case R_ST4: case R_MM4: case R_XMM4:
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000965 return 4;
966 case R_EBP: case R_BP: case R_CH: case R_GS: case R_TR5: case R_ST5:
H. Peter Anvin4836e332002-04-30 20:56:43 +0000967 case R_MM5: case R_XMM5:
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000968 return 5;
969 case R_ESI: case R_SI: case R_DH: case R_DR6: case R_TR6: case R_ST6:
H. Peter Anvin4836e332002-04-30 20:56:43 +0000970 case R_MM6: case R_XMM6:
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000971 return 6;
972 case R_EDI: case R_DI: case R_BH: case R_DR7: case R_TR7: case R_ST7:
H. Peter Anvin4836e332002-04-30 20:56:43 +0000973 case R_MM7: case R_XMM7:
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000974 return 7;
975 default: /* panic */
H. Peter Anvin4836e332002-04-30 20:56:43 +0000976 errfunc (ERR_PANIC, "invalid register operand given to regval()");
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000977 return 0;
978 }
979}
980
H. Peter Anvineba20a72002-04-30 20:53:55 +0000981static int matches (struct itemplate *itemp, insn *instruction)
982{
H. Peter Anvinef7468f2002-04-30 20:57:59 +0000983 int i, size[3], asize, oprs, ret;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000984
985 ret = 100;
986
987 /*
988 * Check the opcode
989 */
990 if (itemp->opcode != instruction->opcode) return 0;
991
992 /*
993 * Count the operands
994 */
995 if (itemp->operands != instruction->operands) return 0;
996
997 /*
998 * Check that no spurious colons or TOs are present
999 */
1000 for (i=0; i<itemp->operands; i++)
1001 if (instruction->oprs[i].type & ~itemp->opd[i] & (COLON|TO))
1002 return 0;
1003
1004 /*
1005 * Check that the operand flags all match up
1006 */
1007 for (i=0; i<itemp->operands; i++)
1008 if (itemp->opd[i] & ~instruction->oprs[i].type ||
1009 ((itemp->opd[i] & SIZE_MASK) &&
H. Peter Anvineba20a72002-04-30 20:53:55 +00001010 ((itemp->opd[i] ^ instruction->oprs[i].type) & SIZE_MASK)))
1011 {
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001012 if ((itemp->opd[i] & ~instruction->oprs[i].type & NON_SIZE) ||
1013 (instruction->oprs[i].type & SIZE_MASK))
1014 return 0;
1015 else
1016 ret = 1;
1017 }
1018
1019 /*
1020 * Check operand sizes
1021 */
H. Peter Anvinef7468f2002-04-30 20:57:59 +00001022 if (itemp->flags & IF_ARMASK) {
1023 size[0] = size[1] = size[2] = 0;
1024
1025 switch (itemp->flags & IF_ARMASK) {
1026 case IF_AR0: i = 0; break;
1027 case IF_AR1: i = 1; break;
1028 case IF_AR2: i = 2; break;
1029 default: break; /* Shouldn't happen */
1030 }
1031 if (itemp->flags & IF_SB) {
1032 size[i] = BITS8;
1033 } else if (itemp->flags & IF_SW) {
1034 size[i] = BITS16;
1035 } else if (itemp->flags & IF_SD) {
1036 size[i] = BITS32;
1037 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001038 } else {
H. Peter Anvinef7468f2002-04-30 20:57:59 +00001039 asize = 0;
1040 if (itemp->flags & IF_SB) {
1041 asize = BITS8;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001042 oprs = itemp->operands;
H. Peter Anvinef7468f2002-04-30 20:57:59 +00001043 } else if (itemp->flags & IF_SW) {
1044 asize = BITS16;
1045 oprs = itemp->operands;
1046 } else if (itemp->flags & IF_SD) {
1047 asize = BITS32;
1048 oprs = itemp->operands;
1049 }
1050 size[0] = size[1] = size[2] = asize;
1051 }
1052
1053 if (itemp->flags & (IF_SM | IF_SM2)) {
1054 oprs = (itemp->flags & IF_SM2 ? 2 : itemp->operands);
1055 asize = 0;
1056 for (i=0; i<oprs; i++) {
1057 if ( (asize = itemp->opd[i] & SIZE_MASK) != 0) {
1058 int j;
1059 for (j=0; j<oprs; j++)
1060 size[j] = asize;
1061 break;
1062 }
1063 }
1064 } else {
1065 oprs = itemp->operands;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001066 }
1067
1068 for (i=0; i<itemp->operands; i++)
1069 if (!(itemp->opd[i] & SIZE_MASK) &&
H. Peter Anvinef7468f2002-04-30 20:57:59 +00001070 (instruction->oprs[i].type & SIZE_MASK & ~size[i]))
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001071 ret = 2;
1072
1073 return ret;
1074}
1075
H. Peter Anvinea838272002-04-30 20:51:53 +00001076static ea *process_ea (operand *input, ea *output, int addrbits, int rfield,
H. Peter Anvineba20a72002-04-30 20:53:55 +00001077 int forw_ref)
1078{
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001079 if (!(REGISTER & ~input->type)) { /* it's a single register */
1080 static int regs[] = {
H. Peter Anvin4836e332002-04-30 20:56:43 +00001081 R_AL, R_CL, R_DL, R_BL, R_AH, R_CH, R_DH, R_BH,
1082 R_AX, R_CX, R_DX, R_BX, R_SP, R_BP, R_SI, R_DI,
1083 R_EAX, R_ECX, R_EDX, R_EBX, R_ESP, R_EBP, R_ESI, R_EDI,
1084 R_MM0, R_MM1, R_MM2, R_MM3, R_MM4, R_MM5, R_MM6, R_MM7,
1085 R_XMM0, R_XMM1, R_XMM2, R_XMM3, R_XMM4, R_XMM5, R_XMM6, R_XMM7
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001086 };
1087 int i;
1088
1089 for (i=0; i<elements(regs); i++)
1090 if (input->basereg == regs[i]) break;
1091 if (i<elements(regs)) {
1092 output->sib_present = FALSE;/* no SIB necessary */
1093 output->bytes = 0; /* no offset necessary either */
H. Peter Anvin4836e332002-04-30 20:56:43 +00001094 output->modrm = 0xC0 | (rfield << 3) | (i & 7);
H. Peter Anvineba20a72002-04-30 20:53:55 +00001095 }
1096 else
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001097 return NULL;
1098 } else { /* it's a memory reference */
1099 if (input->basereg==-1 && (input->indexreg==-1 || input->scale==0)) {
1100 /* it's a pure offset */
1101 if (input->addr_size)
1102 addrbits = input->addr_size;
1103 output->sib_present = FALSE;
1104 output->bytes = (addrbits==32 ? 4 : 2);
1105 output->modrm = (addrbits==32 ? 5 : 6) | (rfield << 3);
H. Peter Anvineba20a72002-04-30 20:53:55 +00001106 }
1107 else { /* it's an indirection */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001108 int i=input->indexreg, b=input->basereg, s=input->scale;
1109 long o=input->offset, seg=input->segment;
H. Peter Anvin76690a12002-04-30 20:52:49 +00001110 int hb=input->hintbase, ht=input->hinttype;
1111 int t;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001112
1113 if (s==0) i = -1; /* make this easy, at least */
1114
1115 if (i==R_EAX || i==R_EBX || i==R_ECX || i==R_EDX
1116 || i==R_EBP || i==R_ESP || i==R_ESI || i==R_EDI
1117 || b==R_EAX || b==R_EBX || b==R_ECX || b==R_EDX
1118 || b==R_EBP || b==R_ESP || b==R_ESI || b==R_EDI) {
1119 /* it must be a 32-bit memory reference. Firstly we have
1120 * to check that all registers involved are type Exx. */
1121 if (i!=-1 && i!=R_EAX && i!=R_EBX && i!=R_ECX && i!=R_EDX
1122 && i!=R_EBP && i!=R_ESP && i!=R_ESI && i!=R_EDI)
1123 return NULL;
1124 if (b!=-1 && b!=R_EAX && b!=R_EBX && b!=R_ECX && b!=R_EDX
1125 && b!=R_EBP && b!=R_ESP && b!=R_ESI && b!=R_EDI)
1126 return NULL;
1127
1128 /* While we're here, ensure the user didn't specify WORD. */
1129 if (input->addr_size == 16)
1130 return NULL;
1131
1132 /* now reorganise base/index */
H. Peter Anvin76690a12002-04-30 20:52:49 +00001133 if (s == 1 && b != i && b != -1 && i != -1 &&
1134 ((hb==b&&ht==EAH_NOTBASE) || (hb==i&&ht==EAH_MAKEBASE)))
1135 t = b, b = i, i = t; /* swap if hints say so */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001136 if (b==i) /* convert EAX+2*EAX to 3*EAX */
1137 b = -1, s++;
H. Peter Anvin76690a12002-04-30 20:52:49 +00001138 if (b==-1 && s==1 && !(hb == i && ht == EAH_NOTBASE))
1139 b = i, i = -1; /* make single reg base, unless hint */
1140 if (((s==2 && i!=R_ESP && !(input->eaflags & EAF_TIMESTWO)) ||
1141 s==3 || s==5 || s==9) && b==-1)
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001142 b = i, s--; /* convert 3*EAX to EAX+2*EAX */
H. Peter Anvinea838272002-04-30 20:51:53 +00001143 if (s==1 && i==R_ESP) /* swap ESP into base if scale is 1 */
1144 i = b, b = R_ESP;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001145 if (i==R_ESP || (s!=1 && s!=2 && s!=4 && s!=8 && i!=-1))
1146 return NULL; /* wrong, for various reasons */
1147
1148 if (i==-1 && b!=R_ESP) {/* no SIB needed */
1149 int mod, rm;
1150 switch(b) {
1151 case R_EAX: rm = 0; break;
1152 case R_ECX: rm = 1; break;
1153 case R_EDX: rm = 2; break;
1154 case R_EBX: rm = 3; break;
1155 case R_EBP: rm = 5; break;
1156 case R_ESI: rm = 6; break;
1157 case R_EDI: rm = 7; break;
1158 case -1: rm = 5; break;
1159 default: /* should never happen */
1160 return NULL;
1161 }
H. Peter Anvinea838272002-04-30 20:51:53 +00001162 if (b==-1 || (b!=R_EBP && o==0 &&
H. Peter Anvin76690a12002-04-30 20:52:49 +00001163 seg==NO_SEG && !forw_ref &&
1164 !(input->eaflags &
1165 (EAF_BYTEOFFS|EAF_WORDOFFS))))
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001166 mod = 0;
H. Peter Anvin76690a12002-04-30 20:52:49 +00001167 else if (input->eaflags & EAF_BYTEOFFS ||
1168 (o>=-128 && o<=127 && seg==NO_SEG && !forw_ref &&
1169 !(input->eaflags & EAF_WORDOFFS))) {
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001170 mod = 1;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001171 }
1172 else
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001173 mod = 2;
H. Peter Anvinea838272002-04-30 20:51:53 +00001174
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001175 output->sib_present = FALSE;
1176 output->bytes = (b==-1 || mod==2 ? 4 : mod);
1177 output->modrm = (mod<<6) | (rfield<<3) | rm;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001178 }
1179 else { /* we need a SIB */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001180 int mod, scale, index, base;
1181
1182 switch (b) {
1183 case R_EAX: base = 0; break;
1184 case R_ECX: base = 1; break;
1185 case R_EDX: base = 2; break;
1186 case R_EBX: base = 3; break;
1187 case R_ESP: base = 4; break;
1188 case R_EBP: case -1: base = 5; break;
1189 case R_ESI: base = 6; break;
1190 case R_EDI: base = 7; break;
1191 default: /* then what the smeg is it? */
1192 return NULL; /* panic */
1193 }
1194
1195 switch (i) {
1196 case R_EAX: index = 0; break;
1197 case R_ECX: index = 1; break;
1198 case R_EDX: index = 2; break;
1199 case R_EBX: index = 3; break;
1200 case -1: index = 4; break;
1201 case R_EBP: index = 5; break;
1202 case R_ESI: index = 6; break;
1203 case R_EDI: index = 7; break;
1204 default: /* then what the smeg is it? */
1205 return NULL; /* panic */
1206 }
1207
1208 if (i==-1) s = 1;
1209 switch (s) {
1210 case 1: scale = 0; break;
1211 case 2: scale = 1; break;
1212 case 4: scale = 2; break;
1213 case 8: scale = 3; break;
1214 default: /* then what the smeg is it? */
1215 return NULL; /* panic */
1216 }
1217
H. Peter Anvinea838272002-04-30 20:51:53 +00001218 if (b==-1 || (b!=R_EBP && o==0 &&
H. Peter Anvin76690a12002-04-30 20:52:49 +00001219 seg==NO_SEG && !forw_ref &&
1220 !(input->eaflags &
1221 (EAF_BYTEOFFS|EAF_WORDOFFS))))
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001222 mod = 0;
H. Peter Anvin76690a12002-04-30 20:52:49 +00001223 else if (input->eaflags & EAF_BYTEOFFS ||
1224 (o>=-128 && o<=127 && seg==NO_SEG && !forw_ref &&
1225 !(input->eaflags & EAF_WORDOFFS)))
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001226 mod = 1;
1227 else
1228 mod = 2;
1229
1230 output->sib_present = TRUE;
1231 output->bytes = (b==-1 || mod==2 ? 4 : mod);
1232 output->modrm = (mod<<6) | (rfield<<3) | 4;
1233 output->sib = (scale<<6) | (index<<3) | base;
1234 }
H. Peter Anvineba20a72002-04-30 20:53:55 +00001235 }
1236 else { /* it's 16-bit */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001237 int mod, rm;
1238
1239 /* check all registers are BX, BP, SI or DI */
1240 if ((b!=-1 && b!=R_BP && b!=R_BX && b!=R_SI && b!=R_DI) ||
1241 (i!=-1 && i!=R_BP && i!=R_BX && i!=R_SI && i!=R_DI))
1242 return NULL;
1243
1244 /* ensure the user didn't specify DWORD */
1245 if (input->addr_size == 32)
1246 return NULL;
1247
1248 if (s!=1 && i!=-1) return NULL;/* no can do, in 16-bit EA */
1249 if (b==-1 && i!=-1) b ^= i ^= b ^= i; /* swap them round */
1250 if ((b==R_SI || b==R_DI) && i!=-1)
1251 b ^= i ^= b ^= i; /* have BX/BP as base, SI/DI index */
1252 if (b==i) return NULL;/* shouldn't ever happen, in theory */
1253 if (i!=-1 && b!=-1 &&
1254 (i==R_BP || i==R_BX || b==R_SI || b==R_DI))
1255 return NULL; /* invalid combinations */
1256 if (b==-1) /* pure offset: handled above */
1257 return NULL; /* so if it gets to here, panic! */
1258
1259 rm = -1;
1260 if (i!=-1)
1261 switch (i*256 + b) {
1262 case R_SI*256+R_BX: rm=0; break;
1263 case R_DI*256+R_BX: rm=1; break;
1264 case R_SI*256+R_BP: rm=2; break;
1265 case R_DI*256+R_BP: rm=3; break;
1266 }
1267 else
1268 switch (b) {
1269 case R_SI: rm=4; break;
1270 case R_DI: rm=5; break;
1271 case R_BP: rm=6; break;
1272 case R_BX: rm=7; break;
1273 }
1274 if (rm==-1) /* can't happen, in theory */
1275 return NULL; /* so panic if it does */
1276
H. Peter Anvin76690a12002-04-30 20:52:49 +00001277 if (o==0 && seg==NO_SEG && !forw_ref && rm!=6 &&
1278 !(input->eaflags & (EAF_BYTEOFFS|EAF_WORDOFFS)))
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001279 mod = 0;
H. Peter Anvin76690a12002-04-30 20:52:49 +00001280 else if (input->eaflags & EAF_BYTEOFFS ||
1281 (o>=-128 && o<=127 && seg==NO_SEG && !forw_ref &&
1282 !(input->eaflags & EAF_WORDOFFS)))
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001283 mod = 1;
1284 else
1285 mod = 2;
1286
1287 output->sib_present = FALSE; /* no SIB - it's 16-bit */
1288 output->bytes = mod; /* bytes of offset needed */
1289 output->modrm = (mod<<6) | (rfield<<3) | rm;
1290 }
1291 }
1292 }
1293 output->size = 1 + output->sib_present + output->bytes;
1294 return output;
1295}
1296
H. Peter Anvineba20a72002-04-30 20:53:55 +00001297static int chsize (operand *input, int addrbits)
1298{
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001299 if (!(MEMORY & ~input->type)) {
1300 int i=input->indexreg, b=input->basereg;
1301
1302 if (input->scale==0) i = -1;
1303
1304 if (i == -1 && b == -1) /* pure offset */
1305 return (input->addr_size != 0 && input->addr_size != addrbits);
1306
1307 if (i==R_EAX || i==R_EBX || i==R_ECX || i==R_EDX
1308 || i==R_EBP || i==R_ESP || i==R_ESI || i==R_EDI
1309 || b==R_EAX || b==R_EBX || b==R_ECX || b==R_EDX
1310 || b==R_EBP || b==R_ESP || b==R_ESI || b==R_EDI)
1311 return (addrbits==16);
1312 else
1313 return (addrbits==32);
H. Peter Anvineba20a72002-04-30 20:53:55 +00001314 }
1315 else
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001316 return 0;
1317}