blob: 3a610411507a5f9f403d921b8c78c88cfe1b8036 [file] [log] [blame]
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001/* assemble.c code generation for the Netwide Assembler
2 *
3 * The Netwide Assembler is copyright (C) 1996 Simon Tatham and
4 * Julian Hall. All rights reserved. The software is
5 * redistributable under the licence given in the file "Licence"
6 * distributed in the NASM archive.
7 *
8 * the actual codes (C syntax, i.e. octal):
9 * \0 - terminates the code. (Unless it's a literal of course.)
10 * \1, \2, \3 - that many literal bytes follow in the code stream
11 * \4, \6 - the POP/PUSH (respectively) codes for CS, DS, ES, SS
12 * (POP is never used for CS) depending on operand 0
13 * \5, \7 - the second byte of POP/PUSH codes for FS, GS, depending
14 * on operand 0
15 * \10, \11, \12 - a literal byte follows in the code stream, to be added
16 * to the register value of operand 0, 1 or 2
17 * \17 - encodes the literal byte 0. (Some compilers don't take
18 * kindly to a zero byte in the _middle_ of a compile time
19 * string constant, so I had to put this hack in.)
20 * \14, \15, \16 - a signed byte immediate operand, from operand 0, 1 or 2
21 * \20, \21, \22 - a byte immediate operand, from operand 0, 1 or 2
22 * \24, \25, \26 - an unsigned byte immediate operand, from operand 0, 1 or 2
23 * \30, \31, \32 - a word immediate operand, from operand 0, 1 or 2
24 * \34, \35, \36 - select between \3[012] and \4[012] depending on 16/32 bit
H. Peter Anvin3ba46772002-05-27 23:19:35 +000025 * assembly mode or the operand-size override on the operand
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000026 * \37 - a word constant, from the _segment_ part of operand 0
27 * \40, \41, \42 - a long immediate operand, from operand 0, 1 or 2
H. Peter Anvin3ba46772002-05-27 23:19:35 +000028 * \44, \45, \46 - select between \3[012] and \4[012] depending on 16/32 bit
29 * assembly mode or the address-size override on the operand
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000030 * \50, \51, \52 - a byte relative operand, from operand 0, 1 or 2
31 * \60, \61, \62 - a word relative operand, from operand 0, 1 or 2
32 * \64, \65, \66 - select between \6[012] and \7[012] depending on 16/32 bit
H. Peter Anvin17799b42002-05-21 03:31:21 +000033 * assembly mode or the operand-size override on the operand
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000034 * \70, \71, \72 - a long relative operand, from operand 0, 1 or 2
35 * \1ab - a ModRM, calculated on EA in operand a, with the spare
36 * field the register value of operand b.
H. Peter Anvinaf535c12002-04-30 20:59:21 +000037 * \130,\131,\132 - an immediate word or signed byte for operand 0, 1, or 2
38 * \133,\134,\135 - or 2 (s-field) into next opcode byte if operand 0, 1, or 2
39 * is a signed byte rather than a word.
40 * \140,\141,\142 - an immediate dword or signed byte for operand 0, 1, or 2
41 * \143,\144,\145 - or 2 (s-field) into next opcode byte if operand 0, 1, or 2
42 * is a signed byte rather than a dword.
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000043 * \2ab - a ModRM, calculated on EA in operand a, with the spare
44 * field equal to digit b.
45 * \30x - might be an 0x67 byte, depending on the address size of
46 * the memory reference in operand x.
47 * \310 - indicates fixed 16-bit address size, i.e. optional 0x67.
48 * \311 - indicates fixed 32-bit address size, i.e. optional 0x67.
H. Peter Anvinaf535c12002-04-30 20:59:21 +000049 * \312 - (disassembler only) marker on LOOP, LOOPxx instructions.
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000050 * \320 - indicates fixed 16-bit operand size, i.e. optional 0x66.
51 * \321 - indicates fixed 32-bit operand size, i.e. optional 0x66.
52 * \322 - indicates that this instruction is only valid when the
53 * operand size is the default (instruction to disassembler,
54 * generates no code in the assembler)
55 * \330 - a literal byte follows in the code stream, to be added
56 * to the condition code value of the instruction.
H. Peter Anvinef7468f2002-04-30 20:57:59 +000057 * \331 - instruction not valid with REP prefix. Hint for
58 * disassembler only; for SSE instructions.
59 * \332 - disassemble a rep (0xF3 byte) prefix as repe not rep.
60 * \333 - REP prefix (0xF3 byte); for SSE instructions. Not encoded
61 * as a literal byte in order to aid the disassembler.
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000062 * \340 - reserve <operand 0> bytes of uninitialised storage.
63 * Operand 0 had better be a segmentless constant.
H. Peter Anvin788e6c12002-04-30 21:02:01 +000064 * \370,\371,\372 - match only if operand 0 meets byte jump criteria.
65 * 370 is used for Jcc, 371 is used for JMP.
H. Peter Anvinaf535c12002-04-30 20:59:21 +000066 * \373 - assemble 0x03 if bits==16, 0x05 if bits==32;
67 * used for conditional jump over longer jump
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000068 */
69
70#include <stdio.h>
71#include <string.h>
72
73#include "nasm.h"
H. Peter Anvin6768eb72002-04-30 20:52:26 +000074#include "nasmlib.h"
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000075#include "assemble.h"
76#include "insns.h"
Frank Kotlerd0ed6fd2003-08-27 11:33:56 +000077#include "preproc.h"
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000078
79extern struct itemplate *nasm_instructions[];
80
81typedef struct {
H. Peter Anvine2c80182005-01-15 22:15:51 +000082 int sib_present; /* is a SIB byte necessary? */
83 int bytes; /* # of bytes of offset needed */
84 int size; /* lazy - this is sib+bytes+1 */
85 unsigned char modrm, sib; /* the bytes themselves */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000086} ea;
87
H. Peter Anvine2c80182005-01-15 22:15:51 +000088static unsigned long cpu; /* cpu level received from nasm.c */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000089static efunc errfunc;
90static struct ofmt *outfmt;
H. Peter Anvin6768eb72002-04-30 20:52:26 +000091static ListGen *list;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000092
H. Peter Anvine2c80182005-01-15 22:15:51 +000093static long calcsize(long, long, int, insn *, const char *);
94static void gencode(long, long, int, insn *, const char *, long);
95static int regval(operand * o);
96static int matches(struct itemplate *, insn *);
97static ea *process_ea(operand *, ea *, int, int, int);
98static int chsize(operand *, int);
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000099
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000100/*
101 * This routine wrappers the real output format's output routine,
102 * in order to pass a copy of the data off to the listing file
103 * generator at the same time.
104 */
H. Peter Anvine2c80182005-01-15 22:15:51 +0000105static void out(long offset, long segto, const void *data,
106 unsigned long type, long segment, long wrt)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000107{
H. Peter Anvine2c80182005-01-15 22:15:51 +0000108 static long lineno = 0; /* static!!! */
Frank Kotlerabebb082003-09-06 04:45:37 +0000109 static char *lnfname = NULL;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000110
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000111 if ((type & OUT_TYPMASK) == OUT_ADDRESS) {
H. Peter Anvine2c80182005-01-15 22:15:51 +0000112 if (segment != NO_SEG || wrt != NO_SEG) {
113 /*
114 * This address is relocated. We must write it as
115 * OUT_ADDRESS, so there's no work to be done here.
116 */
117 list->output(offset, data, type);
118 } else {
119 unsigned char p[4], *q = p;
120 /*
121 * This is a non-relocated address, and we're going to
122 * convert it into RAWDATA format.
123 */
124 if ((type & OUT_SIZMASK) == 4) {
125 WRITELONG(q, *(long *)data);
126 list->output(offset, p, OUT_RAWDATA + 4);
127 } else {
128 WRITESHORT(q, *(long *)data);
129 list->output(offset, p, OUT_RAWDATA + 2);
130 }
131 }
132 } else if ((type & OUT_TYPMASK) == OUT_RAWDATA) {
133 list->output(offset, data, type);
134 } else if ((type & OUT_TYPMASK) == OUT_RESERVE) {
135 list->output(offset, NULL, type);
136 } else if ((type & OUT_TYPMASK) == OUT_REL2ADR ||
137 (type & OUT_TYPMASK) == OUT_REL4ADR) {
138 list->output(offset, data, type);
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000139 }
140
Frank Kotlerabebb082003-09-06 04:45:37 +0000141 /*
142 * this call to src_get determines when we call the
143 * debug-format-specific "linenum" function
144 * it updates lineno and lnfname to the current values
145 * returning 0 if "same as last time", -2 if lnfname
146 * changed, and the amount by which lineno changed,
147 * if it did. thus, these variables must be static
148 */
149
H. Peter Anvine2c80182005-01-15 22:15:51 +0000150 if (src_get(&lineno, &lnfname)) {
151 outfmt->current_dfmt->linenum(lnfname, lineno, segto);
H. Peter Anvince616072002-04-30 21:02:23 +0000152 }
H. Peter Anvineba20a72002-04-30 20:53:55 +0000153
H. Peter Anvine2c80182005-01-15 22:15:51 +0000154 outfmt->output(segto, data, type, segment, wrt);
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000155}
156
H. Peter Anvine2c80182005-01-15 22:15:51 +0000157static int jmp_match(long segment, long offset, int bits,
158 insn * ins, const char *code)
159{
160 long isize;
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000161 unsigned char c = code[0];
162
H. Peter Anvine2c80182005-01-15 22:15:51 +0000163 if (c != 0370 && c != 0371)
164 return 0;
H. Peter Anvin788e6c12002-04-30 21:02:01 +0000165 if (ins->oprs[0].opflags & OPFLAG_FORWARD) {
H. Peter Anvine2c80182005-01-15 22:15:51 +0000166 if ((optimizing < 0 || (ins->oprs[0].type & STRICT))
167 && c == 0370)
168 return 1;
169 else
170 return (pass0 == 0); /* match a forward reference */
H. Peter Anvin788e6c12002-04-30 21:02:01 +0000171 }
H. Peter Anvine2c80182005-01-15 22:15:51 +0000172 isize = calcsize(segment, offset, bits, ins, code);
173 if (ins->oprs[0].segment != segment)
174 return 0;
175 isize = ins->oprs[0].offset - offset - isize; /* isize is now the delta */
176 if (isize >= -128L && isize <= 127L)
177 return 1; /* it is byte size */
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000178
179 return 0;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000180}
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000181
H. Peter Anvine2c80182005-01-15 22:15:51 +0000182long assemble(long segment, long offset, int bits, unsigned long cp,
183 insn * instruction, struct ofmt *output, efunc error,
184 ListGen * listgen)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000185{
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000186 struct itemplate *temp;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000187 int j;
188 int size_prob;
189 long insn_end;
190 long itimes;
191 long start = offset;
192 long wsize = 0; /* size for DB etc. */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000193
H. Peter Anvine2c80182005-01-15 22:15:51 +0000194 errfunc = error; /* to pass to other functions */
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000195 cpu = cp;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000196 outfmt = output; /* likewise */
197 list = listgen; /* and again */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000198
H. Peter Anvine2c80182005-01-15 22:15:51 +0000199 switch (instruction->opcode) {
200 case -1:
201 return 0;
202 case I_DB:
203 wsize = 1;
204 break;
205 case I_DW:
206 wsize = 2;
207 break;
208 case I_DD:
209 wsize = 4;
210 break;
211 case I_DQ:
212 wsize = 8;
213 break;
214 case I_DT:
215 wsize = 10;
216 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000217 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000218
H. Peter Anvineba20a72002-04-30 20:53:55 +0000219 if (wsize) {
H. Peter Anvine2c80182005-01-15 22:15:51 +0000220 extop *e;
221 long t = instruction->times;
222 if (t < 0)
223 errfunc(ERR_PANIC,
224 "instruction->times < 0 (%ld) in assemble()", t);
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000225
H. Peter Anvine2c80182005-01-15 22:15:51 +0000226 while (t--) { /* repeat TIMES times */
227 for (e = instruction->eops; e; e = e->next) {
228 if (e->type == EOT_DB_NUMBER) {
229 if (wsize == 1) {
230 if (e->segment != NO_SEG)
231 errfunc(ERR_NONFATAL,
232 "one-byte relocation attempted");
233 else {
234 unsigned char out_byte = e->offset;
235 out(offset, segment, &out_byte,
236 OUT_RAWDATA + 1, NO_SEG, NO_SEG);
237 }
238 } else if (wsize > 5) {
239 errfunc(ERR_NONFATAL, "integer supplied to a D%c"
240 " instruction", wsize == 8 ? 'Q' : 'T');
241 } else
242 out(offset, segment, &e->offset,
243 OUT_ADDRESS + wsize, e->segment, e->wrt);
244 offset += wsize;
245 } else if (e->type == EOT_DB_STRING) {
246 int align;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000247
H. Peter Anvine2c80182005-01-15 22:15:51 +0000248 out(offset, segment, e->stringval,
249 OUT_RAWDATA + e->stringlen, NO_SEG, NO_SEG);
250 align = e->stringlen % wsize;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000251
H. Peter Anvine2c80182005-01-15 22:15:51 +0000252 if (align) {
253 align = wsize - align;
254 out(offset, segment, "\0\0\0\0\0\0\0\0",
255 OUT_RAWDATA + align, NO_SEG, NO_SEG);
256 }
257 offset += e->stringlen + align;
258 }
259 }
260 if (t > 0 && t == instruction->times - 1) {
261 /*
262 * Dummy call to list->output to give the offset to the
263 * listing module.
264 */
265 list->output(offset, NULL, OUT_RAWDATA);
266 list->uplevel(LIST_TIMES);
267 }
268 }
269 if (instruction->times > 1)
270 list->downlevel(LIST_TIMES);
271 return offset - start;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000272 }
273
H. Peter Anvine2c80182005-01-15 22:15:51 +0000274 if (instruction->opcode == I_INCBIN) {
275 static char fname[FILENAME_MAX];
276 FILE *fp;
277 long len;
Frank Kotlerd0ed6fd2003-08-27 11:33:56 +0000278 char *prefix = "", *combine;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000279 char **pPrevPath = NULL;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000280
H. Peter Anvine2c80182005-01-15 22:15:51 +0000281 len = FILENAME_MAX - 1;
282 if (len > instruction->eops->stringlen)
283 len = instruction->eops->stringlen;
284 strncpy(fname, instruction->eops->stringval, len);
285 fname[len] = '\0';
H. Peter Anvineba20a72002-04-30 20:53:55 +0000286
H. Peter Anvine2c80182005-01-15 22:15:51 +0000287 while (1) { /* added by alexfru: 'incbin' uses include paths */
288 combine = nasm_malloc(strlen(prefix) + len + 1);
289 strcpy(combine, prefix);
290 strcat(combine, fname);
Frank Kotlerd0ed6fd2003-08-27 11:33:56 +0000291
H. Peter Anvine2c80182005-01-15 22:15:51 +0000292 if ((fp = fopen(combine, "rb")) != NULL) {
293 nasm_free(combine);
294 break;
295 }
Frank Kotlerd0ed6fd2003-08-27 11:33:56 +0000296
H. Peter Anvine2c80182005-01-15 22:15:51 +0000297 nasm_free(combine);
298 pPrevPath = pp_get_include_path_ptr(pPrevPath);
299 if (pPrevPath == NULL)
300 break;
301 prefix = *pPrevPath;
Frank Kotlerd0ed6fd2003-08-27 11:33:56 +0000302 }
303
304 if (fp == NULL)
H. Peter Anvine2c80182005-01-15 22:15:51 +0000305 error(ERR_NONFATAL, "`incbin': unable to open file `%s'",
306 fname);
307 else if (fseek(fp, 0L, SEEK_END) < 0)
308 error(ERR_NONFATAL, "`incbin': unable to seek on file `%s'",
309 fname);
310 else {
311 static char buf[2048];
312 long t = instruction->times;
313 long base = 0;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000314
H. Peter Anvine2c80182005-01-15 22:15:51 +0000315 len = ftell(fp);
316 if (instruction->eops->next) {
317 base = instruction->eops->next->offset;
318 len -= base;
319 if (instruction->eops->next->next &&
320 len > instruction->eops->next->next->offset)
321 len = instruction->eops->next->next->offset;
322 }
323 /*
324 * Dummy call to list->output to give the offset to the
325 * listing module.
326 */
327 list->output(offset, NULL, OUT_RAWDATA);
328 list->uplevel(LIST_INCBIN);
329 while (t--) {
330 long l;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000331
H. Peter Anvine2c80182005-01-15 22:15:51 +0000332 fseek(fp, base, SEEK_SET);
333 l = len;
334 while (l > 0) {
335 long m =
336 fread(buf, 1, (l > sizeof(buf) ? sizeof(buf) : l),
337 fp);
338 if (!m) {
339 /*
340 * This shouldn't happen unless the file
341 * actually changes while we are reading
342 * it.
343 */
344 error(ERR_NONFATAL,
345 "`incbin': unexpected EOF while"
346 " reading file `%s'", fname);
347 t = 0; /* Try to exit cleanly */
348 break;
349 }
350 out(offset, segment, buf, OUT_RAWDATA + m,
351 NO_SEG, NO_SEG);
352 l -= m;
353 }
354 }
355 list->downlevel(LIST_INCBIN);
356 if (instruction->times > 1) {
357 /*
358 * Dummy call to list->output to give the offset to the
359 * listing module.
360 */
361 list->output(offset, NULL, OUT_RAWDATA);
362 list->uplevel(LIST_TIMES);
363 list->downlevel(LIST_TIMES);
364 }
365 fclose(fp);
366 return instruction->times * len;
367 }
368 return 0; /* if we're here, there's an error */
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000369 }
370
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000371 size_prob = FALSE;
372 temp = nasm_instructions[instruction->opcode];
373 while (temp->opcode != -1) {
H. Peter Anvine2c80182005-01-15 22:15:51 +0000374 int m = matches(temp, instruction);
375 if (m == 99)
376 m += jmp_match(segment, offset, bits, instruction, temp->code);
H. Peter Anvineba20a72002-04-30 20:53:55 +0000377
H. Peter Anvine2c80182005-01-15 22:15:51 +0000378 if (m == 100) { /* matches! */
379 const char *codes = temp->code;
380 long insn_size = calcsize(segment, offset, bits,
381 instruction, codes);
382 itimes = instruction->times;
383 if (insn_size < 0) /* shouldn't be, on pass two */
384 error(ERR_PANIC, "errors made it through from pass one");
385 else
386 while (itimes--) {
387 for (j = 0; j < instruction->nprefix; j++) {
388 unsigned char c = 0;
389 switch (instruction->prefixes[j]) {
390 case P_LOCK:
391 c = 0xF0;
392 break;
393 case P_REPNE:
394 case P_REPNZ:
395 c = 0xF2;
396 break;
397 case P_REPE:
398 case P_REPZ:
399 case P_REP:
400 c = 0xF3;
401 break;
402 case R_CS:
403 c = 0x2E;
404 break;
405 case R_DS:
406 c = 0x3E;
407 break;
408 case R_ES:
409 c = 0x26;
410 break;
411 case R_FS:
412 c = 0x64;
413 break;
414 case R_GS:
415 c = 0x65;
416 break;
417 case R_SS:
418 c = 0x36;
419 break;
420 case R_SEGR6:
421 case R_SEGR7:
422 error(ERR_NONFATAL,
423 "segr6 and segr7 cannot be used as prefixes");
424 break;
425 case P_A16:
426 if (bits != 16)
427 c = 0x67;
428 break;
429 case P_A32:
430 if (bits != 32)
431 c = 0x67;
432 break;
433 case P_O16:
434 if (bits != 16)
435 c = 0x66;
436 break;
437 case P_O32:
438 if (bits != 32)
439 c = 0x66;
440 break;
441 default:
442 error(ERR_PANIC, "invalid instruction prefix");
443 }
444 if (c != 0) {
445 out(offset, segment, &c, OUT_RAWDATA + 1,
446 NO_SEG, NO_SEG);
447 offset++;
448 }
449 }
450 insn_end = offset + insn_size;
451 gencode(segment, offset, bits, instruction, codes,
452 insn_end);
453 offset += insn_size;
454 if (itimes > 0 && itimes == instruction->times - 1) {
455 /*
456 * Dummy call to list->output to give the offset to the
457 * listing module.
458 */
459 list->output(offset, NULL, OUT_RAWDATA);
460 list->uplevel(LIST_TIMES);
461 }
462 }
463 if (instruction->times > 1)
464 list->downlevel(LIST_TIMES);
465 return offset - start;
466 } else if (m > 0 && m > size_prob) {
467 size_prob = m;
468 }
469 temp++;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000470 }
H. Peter Anvineba20a72002-04-30 20:53:55 +0000471
H. Peter Anvine2c80182005-01-15 22:15:51 +0000472 if (temp->opcode == -1) { /* didn't match any instruction */
473 if (size_prob == 1) /* would have matched, but for size */
474 error(ERR_NONFATAL, "operation size not specified");
475 else if (size_prob == 2)
476 error(ERR_NONFATAL, "mismatch in operand sizes");
477 else if (size_prob == 3)
478 error(ERR_NONFATAL, "no instruction for this cpu level");
479 else
480 error(ERR_NONFATAL,
481 "invalid combination of opcode and operands");
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000482 }
483 return 0;
484}
485
H. Peter Anvine2c80182005-01-15 22:15:51 +0000486long insn_size(long segment, long offset, int bits, unsigned long cp,
487 insn * instruction, efunc error)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000488{
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000489 struct itemplate *temp;
490
H. Peter Anvine2c80182005-01-15 22:15:51 +0000491 errfunc = error; /* to pass to other functions */
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000492 cpu = cp;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000493
494 if (instruction->opcode == -1)
H. Peter Anvine2c80182005-01-15 22:15:51 +0000495 return 0;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000496
497 if (instruction->opcode == I_DB ||
H. Peter Anvine2c80182005-01-15 22:15:51 +0000498 instruction->opcode == I_DW ||
499 instruction->opcode == I_DD ||
500 instruction->opcode == I_DQ || instruction->opcode == I_DT) {
501 extop *e;
502 long isize, osize, wsize = 0; /* placate gcc */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000503
H. Peter Anvine2c80182005-01-15 22:15:51 +0000504 isize = 0;
505 switch (instruction->opcode) {
506 case I_DB:
507 wsize = 1;
508 break;
509 case I_DW:
510 wsize = 2;
511 break;
512 case I_DD:
513 wsize = 4;
514 break;
515 case I_DQ:
516 wsize = 8;
517 break;
518 case I_DT:
519 wsize = 10;
520 break;
521 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000522
H. Peter Anvine2c80182005-01-15 22:15:51 +0000523 for (e = instruction->eops; e; e = e->next) {
524 long align;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000525
H. Peter Anvine2c80182005-01-15 22:15:51 +0000526 osize = 0;
527 if (e->type == EOT_DB_NUMBER)
528 osize = 1;
529 else if (e->type == EOT_DB_STRING)
530 osize = e->stringlen;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000531
H. Peter Anvine2c80182005-01-15 22:15:51 +0000532 align = (-osize) % wsize;
533 if (align < 0)
534 align += wsize;
535 isize += osize + align;
536 }
537 return isize * instruction->times;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000538 }
539
H. Peter Anvine2c80182005-01-15 22:15:51 +0000540 if (instruction->opcode == I_INCBIN) {
541 char fname[FILENAME_MAX];
542 FILE *fp;
543 long len;
Frank Kotlerd0ed6fd2003-08-27 11:33:56 +0000544 char *prefix = "", *combine;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000545 char **pPrevPath = NULL;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000546
H. Peter Anvine2c80182005-01-15 22:15:51 +0000547 len = FILENAME_MAX - 1;
548 if (len > instruction->eops->stringlen)
549 len = instruction->eops->stringlen;
550 strncpy(fname, instruction->eops->stringval, len);
551 fname[len] = '\0';
Frank Kotlerd0ed6fd2003-08-27 11:33:56 +0000552
H. Peter Anvine2c80182005-01-15 22:15:51 +0000553 while (1) { /* added by alexfru: 'incbin' uses include paths */
554 combine = nasm_malloc(strlen(prefix) + len + 1);
555 strcpy(combine, prefix);
556 strcat(combine, fname);
Frank Kotlerd0ed6fd2003-08-27 11:33:56 +0000557
H. Peter Anvine2c80182005-01-15 22:15:51 +0000558 if ((fp = fopen(combine, "rb")) != NULL) {
559 nasm_free(combine);
560 break;
561 }
Frank Kotlerd0ed6fd2003-08-27 11:33:56 +0000562
H. Peter Anvine2c80182005-01-15 22:15:51 +0000563 nasm_free(combine);
564 pPrevPath = pp_get_include_path_ptr(pPrevPath);
565 if (pPrevPath == NULL)
566 break;
567 prefix = *pPrevPath;
Frank Kotlerd0ed6fd2003-08-27 11:33:56 +0000568 }
569
570 if (fp == NULL)
H. Peter Anvine2c80182005-01-15 22:15:51 +0000571 error(ERR_NONFATAL, "`incbin': unable to open file `%s'",
572 fname);
573 else if (fseek(fp, 0L, SEEK_END) < 0)
574 error(ERR_NONFATAL, "`incbin': unable to seek on file `%s'",
575 fname);
576 else {
577 len = ftell(fp);
578 fclose(fp);
579 if (instruction->eops->next) {
580 len -= instruction->eops->next->offset;
581 if (instruction->eops->next->next &&
582 len > instruction->eops->next->next->offset) {
583 len = instruction->eops->next->next->offset;
584 }
585 }
586 return instruction->times * len;
587 }
588 return 0; /* if we're here, there's an error */
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000589 }
590
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000591 temp = nasm_instructions[instruction->opcode];
592 while (temp->opcode != -1) {
H. Peter Anvine2c80182005-01-15 22:15:51 +0000593 int m = matches(temp, instruction);
594 if (m == 99)
595 m += jmp_match(segment, offset, bits, instruction, temp->code);
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000596
H. Peter Anvine2c80182005-01-15 22:15:51 +0000597 if (m == 100) {
598 /* we've matched an instruction. */
599 long isize;
600 const char *codes = temp->code;
601 int j;
602
603 isize = calcsize(segment, offset, bits, instruction, codes);
604 if (isize < 0)
605 return -1;
606 for (j = 0; j < instruction->nprefix; j++) {
607 if ((instruction->prefixes[j] != P_A16 &&
608 instruction->prefixes[j] != P_O16 && bits == 16) ||
609 (instruction->prefixes[j] != P_A32 &&
610 instruction->prefixes[j] != P_O32 && bits == 32)) {
611 isize++;
612 }
613 }
614 return isize * instruction->times;
615 }
616 temp++;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000617 }
H. Peter Anvine2c80182005-01-15 22:15:51 +0000618 return -1; /* didn't match any instruction */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000619}
620
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000621/* check that opn[op] is a signed byte of size 16 or 32,
622 and return the signed value*/
H. Peter Anvine2c80182005-01-15 22:15:51 +0000623static int is_sbyte(insn * ins, int op, int size)
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000624{
625 signed long v;
626 int ret;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000627
628 ret = !(ins->forw_ref && ins->oprs[op].opflags) && /* dead in the water on forward reference or External */
629 optimizing >= 0 &&
630 !(ins->oprs[op].type & STRICT) &&
631 ins->oprs[op].wrt == NO_SEG && ins->oprs[op].segment == NO_SEG;
H. Peter Anvin734b1882002-04-30 21:01:08 +0000632
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000633 v = ins->oprs[op].offset;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000634 if (size == 16)
635 v = (signed short)v; /* sign extend if 16 bits */
636
637 return ret && v >= -128L && v <= 127L;
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000638}
639
H. Peter Anvine2c80182005-01-15 22:15:51 +0000640static long calcsize(long segment, long offset, int bits,
641 insn * ins, const char *codes)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000642{
H. Peter Anvine2c80182005-01-15 22:15:51 +0000643 long length = 0;
644 unsigned char c;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000645
H. Peter Anvine2c80182005-01-15 22:15:51 +0000646 (void)segment; /* Don't warn that this parameter is unused */
647 (void)offset; /* Don't warn that this parameter is unused */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000648
H. Peter Anvine2c80182005-01-15 22:15:51 +0000649 while (*codes)
650 switch (c = *codes++) {
651 case 01:
652 case 02:
653 case 03:
654 codes += c, length += c;
655 break;
656 case 04:
657 case 05:
658 case 06:
659 case 07:
660 length++;
661 break;
662 case 010:
663 case 011:
664 case 012:
665 codes++, length++;
666 break;
667 case 017:
668 length++;
669 break;
670 case 014:
671 case 015:
672 case 016:
673 length++;
674 break;
675 case 020:
676 case 021:
677 case 022:
678 length++;
679 break;
680 case 024:
681 case 025:
682 case 026:
683 length++;
684 break;
685 case 030:
686 case 031:
687 case 032:
688 length += 2;
689 break;
690 case 034:
691 case 035:
692 case 036:
693 if (ins->oprs[c - 034].type & (BITS16 | BITS32))
694 length += (ins->oprs[c - 034].type & BITS16) ? 2 : 4;
695 else
696 length += (bits == 16) ? 2 : 4;
697 break;
698 case 037:
699 length += 2;
700 break;
701 case 040:
702 case 041:
703 case 042:
704 length += 4;
705 break;
706 case 044:
707 case 045:
708 case 046:
709 length += ((ins->oprs[c - 044].addr_size ?
710 ins->oprs[c - 044].addr_size : bits) ==
711 16 ? 2 : 4);
712 break;
713 case 050:
714 case 051:
715 case 052:
716 length++;
717 break;
718 case 060:
719 case 061:
720 case 062:
721 length += 2;
722 break;
723 case 064:
724 case 065:
725 case 066:
726 if (ins->oprs[c - 064].type & (BITS16 | BITS32))
727 length += (ins->oprs[c - 064].type & BITS16) ? 2 : 4;
728 else
729 length += (bits == 16) ? 2 : 4;
730 break;
731 case 070:
732 case 071:
733 case 072:
734 length += 4;
735 break;
736 case 0130:
737 case 0131:
738 case 0132:
739 length += is_sbyte(ins, c - 0130, 16) ? 1 : 2;
740 break;
741 case 0133:
742 case 0134:
743 case 0135:
744 codes += 2;
745 length++;
746 break;
747 case 0140:
748 case 0141:
749 case 0142:
750 length += is_sbyte(ins, c - 0140, 32) ? 1 : 4;
751 break;
752 case 0143:
753 case 0144:
754 case 0145:
755 codes += 2;
756 length++;
757 break;
758 case 0300:
759 case 0301:
760 case 0302:
761 length += chsize(&ins->oprs[c - 0300], bits);
762 break;
763 case 0310:
764 length += (bits == 32);
765 break;
766 case 0311:
767 length += (bits == 16);
768 break;
769 case 0312:
770 break;
771 case 0320:
772 length += (bits == 32);
773 break;
774 case 0321:
775 length += (bits == 16);
776 break;
777 case 0322:
778 break;
779 case 0330:
780 codes++, length++;
781 break;
782 case 0331:
783 case 0332:
784 break;
785 case 0333:
786 length++;
787 break;
788 case 0340:
789 case 0341:
790 case 0342:
791 if (ins->oprs[0].segment != NO_SEG)
792 errfunc(ERR_NONFATAL, "attempt to reserve non-constant"
793 " quantity of BSS space");
794 else
795 length += ins->oprs[0].offset << (c - 0340);
796 break;
797 case 0370:
798 case 0371:
799 case 0372:
800 break;
801 case 0373:
802 length++;
803 break;
804 default: /* can't do it by 'case' statements */
805 if (c >= 0100 && c <= 0277) { /* it's an EA */
806 ea ea_data;
807 if (!process_ea
808 (&ins->oprs[(c >> 3) & 7], &ea_data, bits, 0,
809 ins->forw_ref)) {
810 errfunc(ERR_NONFATAL, "invalid effective address");
811 return -1;
812 } else
813 length += ea_data.size;
814 } else
815 errfunc(ERR_PANIC, "internal instruction table corrupt"
816 ": instruction code 0x%02X given", c);
817 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000818 return length;
819}
820
H. Peter Anvine2c80182005-01-15 22:15:51 +0000821static void gencode(long segment, long offset, int bits,
822 insn * ins, const char *codes, long insn_end)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000823{
H. Peter Anvine2c80182005-01-15 22:15:51 +0000824 static char condval[] = { /* conditional opcodes */
825 0x7, 0x3, 0x2, 0x6, 0x2, 0x4, 0xF, 0xD, 0xC, 0xE, 0x6, 0x2,
826 0x3, 0x7, 0x3, 0x5, 0xE, 0xC, 0xD, 0xF, 0x1, 0xB, 0x9, 0x5,
827 0x0, 0xA, 0xA, 0xB, 0x8, 0x4
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000828 };
H. Peter Anvineba20a72002-04-30 20:53:55 +0000829 unsigned char c;
830 unsigned char bytes[4];
H. Peter Anvine2c80182005-01-15 22:15:51 +0000831 long data, size;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000832
H. Peter Anvineba20a72002-04-30 20:53:55 +0000833 while (*codes)
H. Peter Anvine2c80182005-01-15 22:15:51 +0000834 switch (c = *codes++) {
835 case 01:
836 case 02:
837 case 03:
838 out(offset, segment, codes, OUT_RAWDATA + c, NO_SEG, NO_SEG);
839 codes += c;
840 offset += c;
841 break;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000842
H. Peter Anvine2c80182005-01-15 22:15:51 +0000843 case 04:
844 case 06:
845 switch (ins->oprs[0].basereg) {
846 case R_CS:
847 bytes[0] = 0x0E + (c == 0x04 ? 1 : 0);
848 break;
849 case R_DS:
850 bytes[0] = 0x1E + (c == 0x04 ? 1 : 0);
851 break;
852 case R_ES:
853 bytes[0] = 0x06 + (c == 0x04 ? 1 : 0);
854 break;
855 case R_SS:
856 bytes[0] = 0x16 + (c == 0x04 ? 1 : 0);
857 break;
858 default:
859 errfunc(ERR_PANIC,
860 "bizarre 8086 segment register received");
861 }
862 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
863 offset++;
864 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000865
H. Peter Anvine2c80182005-01-15 22:15:51 +0000866 case 05:
867 case 07:
868 switch (ins->oprs[0].basereg) {
869 case R_FS:
870 bytes[0] = 0xA0 + (c == 0x05 ? 1 : 0);
871 break;
872 case R_GS:
873 bytes[0] = 0xA8 + (c == 0x05 ? 1 : 0);
874 break;
875 default:
876 errfunc(ERR_PANIC,
877 "bizarre 386 segment register received");
878 }
879 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
880 offset++;
881 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000882
H. Peter Anvine2c80182005-01-15 22:15:51 +0000883 case 010:
884 case 011:
885 case 012:
886 bytes[0] = *codes++ + regval(&ins->oprs[c - 010]);
887 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
888 offset += 1;
889 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000890
H. Peter Anvine2c80182005-01-15 22:15:51 +0000891 case 017:
892 bytes[0] = 0;
893 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
894 offset += 1;
895 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000896
H. Peter Anvine2c80182005-01-15 22:15:51 +0000897 case 014:
898 case 015:
899 case 016:
900 if (ins->oprs[c - 014].offset < -128
901 || ins->oprs[c - 014].offset > 127) {
902 errfunc(ERR_WARNING, "signed byte value exceeds bounds");
903 }
H. Peter Anvineba20a72002-04-30 20:53:55 +0000904
H. Peter Anvine2c80182005-01-15 22:15:51 +0000905 if (ins->oprs[c - 014].segment != NO_SEG) {
906 data = ins->oprs[c - 014].offset;
907 out(offset, segment, &data, OUT_ADDRESS + 1,
908 ins->oprs[c - 014].segment, ins->oprs[c - 014].wrt);
909 } else {
910 bytes[0] = ins->oprs[c - 014].offset;
911 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG,
912 NO_SEG);
913 }
914 offset += 1;
915 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000916
H. Peter Anvine2c80182005-01-15 22:15:51 +0000917 case 020:
918 case 021:
919 case 022:
920 if (ins->oprs[c - 020].offset < -256
921 || ins->oprs[c - 020].offset > 255) {
922 errfunc(ERR_WARNING, "byte value exceeds bounds");
923 }
924 if (ins->oprs[c - 020].segment != NO_SEG) {
925 data = ins->oprs[c - 020].offset;
926 out(offset, segment, &data, OUT_ADDRESS + 1,
927 ins->oprs[c - 020].segment, ins->oprs[c - 020].wrt);
928 } else {
929 bytes[0] = ins->oprs[c - 020].offset;
930 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG,
931 NO_SEG);
932 }
933 offset += 1;
934 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000935
H. Peter Anvine2c80182005-01-15 22:15:51 +0000936 case 024:
937 case 025:
938 case 026:
939 if (ins->oprs[c - 024].offset < 0
940 || ins->oprs[c - 024].offset > 255)
941 errfunc(ERR_WARNING, "unsigned byte value exceeds bounds");
942 if (ins->oprs[c - 024].segment != NO_SEG) {
943 data = ins->oprs[c - 024].offset;
944 out(offset, segment, &data, OUT_ADDRESS + 1,
945 ins->oprs[c - 024].segment, ins->oprs[c - 024].wrt);
946 } else {
947 bytes[0] = ins->oprs[c - 024].offset;
948 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG,
949 NO_SEG);
950 }
951 offset += 1;
952 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000953
H. Peter Anvine2c80182005-01-15 22:15:51 +0000954 case 030:
955 case 031:
956 case 032:
957 if (ins->oprs[c - 030].segment == NO_SEG &&
958 ins->oprs[c - 030].wrt == NO_SEG &&
959 (ins->oprs[c - 030].offset < -65536L ||
960 ins->oprs[c - 030].offset > 65535L)) {
961 errfunc(ERR_WARNING, "word value exceeds bounds");
962 }
963 data = ins->oprs[c - 030].offset;
964 out(offset, segment, &data, OUT_ADDRESS + 2,
965 ins->oprs[c - 030].segment, ins->oprs[c - 030].wrt);
966 offset += 2;
967 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000968
H. Peter Anvine2c80182005-01-15 22:15:51 +0000969 case 034:
970 case 035:
971 case 036:
972 if (ins->oprs[c - 034].type & (BITS16 | BITS32))
973 size = (ins->oprs[c - 034].type & BITS16) ? 2 : 4;
974 else
975 size = (bits == 16) ? 2 : 4;
976 data = ins->oprs[c - 034].offset;
977 if (size == 2 && (data < -65536L || data > 65535L))
978 errfunc(ERR_WARNING, "word value exceeds bounds");
979 out(offset, segment, &data, OUT_ADDRESS + size,
980 ins->oprs[c - 034].segment, ins->oprs[c - 034].wrt);
981 offset += size;
982 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000983
H. Peter Anvine2c80182005-01-15 22:15:51 +0000984 case 037:
985 if (ins->oprs[0].segment == NO_SEG)
986 errfunc(ERR_NONFATAL, "value referenced by FAR is not"
987 " relocatable");
988 data = 0L;
989 out(offset, segment, &data, OUT_ADDRESS + 2,
990 outfmt->segbase(1 + ins->oprs[0].segment),
991 ins->oprs[0].wrt);
992 offset += 2;
993 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000994
H. Peter Anvine2c80182005-01-15 22:15:51 +0000995 case 040:
996 case 041:
997 case 042:
998 data = ins->oprs[c - 040].offset;
999 out(offset, segment, &data, OUT_ADDRESS + 4,
1000 ins->oprs[c - 040].segment, ins->oprs[c - 040].wrt);
1001 offset += 4;
1002 break;
H. Peter Anvin3ba46772002-05-27 23:19:35 +00001003
H. Peter Anvine2c80182005-01-15 22:15:51 +00001004 case 044:
1005 case 045:
1006 case 046:
1007 data = ins->oprs[c - 044].offset;
1008 size = ((ins->oprs[c - 044].addr_size ?
1009 ins->oprs[c - 044].addr_size : bits) == 16 ? 2 : 4);
1010 if (size == 2 && (data < -65536L || data > 65535L))
1011 errfunc(ERR_WARNING, "word value exceeds bounds");
1012 out(offset, segment, &data, OUT_ADDRESS + size,
1013 ins->oprs[c - 044].segment, ins->oprs[c - 044].wrt);
1014 offset += size;
1015 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001016
H. Peter Anvine2c80182005-01-15 22:15:51 +00001017 case 050:
1018 case 051:
1019 case 052:
1020 if (ins->oprs[c - 050].segment != segment)
1021 errfunc(ERR_NONFATAL,
1022 "short relative jump outside segment");
1023 data = ins->oprs[c - 050].offset - insn_end;
1024 if (data > 127 || data < -128)
1025 errfunc(ERR_NONFATAL, "short jump is out of range");
1026 bytes[0] = data;
1027 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1028 offset += 1;
1029 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001030
H. Peter Anvine2c80182005-01-15 22:15:51 +00001031 case 060:
1032 case 061:
1033 case 062:
1034 if (ins->oprs[c - 060].segment != segment) {
1035 data = ins->oprs[c - 060].offset;
1036 out(offset, segment, &data,
1037 OUT_REL2ADR + insn_end - offset,
1038 ins->oprs[c - 060].segment, ins->oprs[c - 060].wrt);
1039 } else {
1040 data = ins->oprs[c - 060].offset - insn_end;
1041 out(offset, segment, &data,
1042 OUT_ADDRESS + 2, NO_SEG, NO_SEG);
1043 }
1044 offset += 2;
1045 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001046
H. Peter Anvine2c80182005-01-15 22:15:51 +00001047 case 064:
1048 case 065:
1049 case 066:
1050 if (ins->oprs[c - 064].type & (BITS16 | BITS32))
1051 size = (ins->oprs[c - 064].type & BITS16) ? 2 : 4;
1052 else
1053 size = (bits == 16) ? 2 : 4;
1054 if (ins->oprs[c - 064].segment != segment) {
1055 long reltype = (size == 2 ? OUT_REL2ADR : OUT_REL4ADR);
1056 data = ins->oprs[c - 064].offset;
1057 out(offset, segment, &data, reltype + insn_end - offset,
1058 ins->oprs[c - 064].segment, ins->oprs[c - 064].wrt);
1059 } else {
1060 data = ins->oprs[c - 064].offset - insn_end;
1061 out(offset, segment, &data,
1062 OUT_ADDRESS + size, NO_SEG, NO_SEG);
1063 }
1064 offset += size;
1065 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001066
H. Peter Anvine2c80182005-01-15 22:15:51 +00001067 case 070:
1068 case 071:
1069 case 072:
1070 if (ins->oprs[c - 070].segment != segment) {
1071 data = ins->oprs[c - 070].offset;
1072 out(offset, segment, &data,
1073 OUT_REL4ADR + insn_end - offset,
1074 ins->oprs[c - 070].segment, ins->oprs[c - 070].wrt);
1075 } else {
1076 data = ins->oprs[c - 070].offset - insn_end;
1077 out(offset, segment, &data,
1078 OUT_ADDRESS + 4, NO_SEG, NO_SEG);
1079 }
1080 offset += 4;
1081 break;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001082
H. Peter Anvine2c80182005-01-15 22:15:51 +00001083 case 0130:
1084 case 0131:
1085 case 0132:
1086 data = ins->oprs[c - 0130].offset;
1087 if (is_sbyte(ins, c - 0130, 16)) {
1088 bytes[0] = data;
1089 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG,
1090 NO_SEG);
1091 offset++;
1092 } else {
1093 if (ins->oprs[c - 0130].segment == NO_SEG &&
1094 ins->oprs[c - 0130].wrt == NO_SEG &&
1095 (data < -65536L || data > 65535L)) {
1096 errfunc(ERR_WARNING, "word value exceeds bounds");
1097 }
1098 out(offset, segment, &data, OUT_ADDRESS + 2,
1099 ins->oprs[c - 0130].segment, ins->oprs[c - 0130].wrt);
1100 offset += 2;
1101 }
1102 break;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001103
H. Peter Anvine2c80182005-01-15 22:15:51 +00001104 case 0133:
1105 case 0134:
1106 case 0135:
1107 codes++;
1108 bytes[0] = *codes++;
1109 if (is_sbyte(ins, c - 0133, 16))
1110 bytes[0] |= 2; /* s-bit */
1111 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1112 offset++;
1113 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001114
H. Peter Anvine2c80182005-01-15 22:15:51 +00001115 case 0140:
1116 case 0141:
1117 case 0142:
1118 data = ins->oprs[c - 0140].offset;
1119 if (is_sbyte(ins, c - 0140, 32)) {
1120 bytes[0] = data;
1121 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG,
1122 NO_SEG);
1123 offset++;
1124 } else {
1125 out(offset, segment, &data, OUT_ADDRESS + 4,
1126 ins->oprs[c - 0140].segment, ins->oprs[c - 0140].wrt);
1127 offset += 4;
1128 }
1129 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001130
H. Peter Anvine2c80182005-01-15 22:15:51 +00001131 case 0143:
1132 case 0144:
1133 case 0145:
1134 codes++;
1135 bytes[0] = *codes++;
1136 if (is_sbyte(ins, c - 0143, 32))
1137 bytes[0] |= 2; /* s-bit */
1138 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1139 offset++;
1140 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001141
H. Peter Anvine2c80182005-01-15 22:15:51 +00001142 case 0300:
1143 case 0301:
1144 case 0302:
1145 if (chsize(&ins->oprs[c - 0300], bits)) {
1146 *bytes = 0x67;
1147 out(offset, segment, bytes,
1148 OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1149 offset += 1;
1150 } else
1151 offset += 0;
1152 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001153
H. Peter Anvine2c80182005-01-15 22:15:51 +00001154 case 0310:
1155 if (bits == 32) {
1156 *bytes = 0x67;
1157 out(offset, segment, bytes,
1158 OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1159 offset += 1;
1160 } else
1161 offset += 0;
1162 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001163
H. Peter Anvine2c80182005-01-15 22:15:51 +00001164 case 0311:
1165 if (bits == 16) {
1166 *bytes = 0x67;
1167 out(offset, segment, bytes,
1168 OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1169 offset += 1;
1170 } else
1171 offset += 0;
1172 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001173
H. Peter Anvine2c80182005-01-15 22:15:51 +00001174 case 0312:
1175 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001176
H. Peter Anvine2c80182005-01-15 22:15:51 +00001177 case 0320:
1178 if (bits == 32) {
1179 *bytes = 0x66;
1180 out(offset, segment, bytes,
1181 OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1182 offset += 1;
1183 } else
1184 offset += 0;
1185 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001186
H. Peter Anvine2c80182005-01-15 22:15:51 +00001187 case 0321:
1188 if (bits == 16) {
1189 *bytes = 0x66;
1190 out(offset, segment, bytes,
1191 OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1192 offset += 1;
1193 } else
1194 offset += 0;
1195 break;
H. Peter Anvinef7468f2002-04-30 20:57:59 +00001196
H. Peter Anvine2c80182005-01-15 22:15:51 +00001197 case 0322:
1198 break;
H. Peter Anvinef7468f2002-04-30 20:57:59 +00001199
H. Peter Anvine2c80182005-01-15 22:15:51 +00001200 case 0330:
1201 *bytes = *codes++ ^ condval[ins->condition];
1202 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1203 offset += 1;
1204 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001205
H. Peter Anvine2c80182005-01-15 22:15:51 +00001206 case 0331:
1207 case 0332:
1208 break;
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001209
H. Peter Anvine2c80182005-01-15 22:15:51 +00001210 case 0333:
1211 *bytes = 0xF3;
1212 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1213 offset += 1;
1214 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001215
H. Peter Anvine2c80182005-01-15 22:15:51 +00001216 case 0340:
1217 case 0341:
1218 case 0342:
1219 if (ins->oprs[0].segment != NO_SEG)
1220 errfunc(ERR_PANIC, "non-constant BSS size in pass two");
1221 else {
1222 long size = ins->oprs[0].offset << (c - 0340);
1223 if (size > 0)
1224 out(offset, segment, NULL,
1225 OUT_RESERVE + size, NO_SEG, NO_SEG);
1226 offset += size;
1227 }
1228 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001229
H. Peter Anvine2c80182005-01-15 22:15:51 +00001230 case 0370:
1231 case 0371:
1232 case 0372:
1233 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001234
H. Peter Anvine2c80182005-01-15 22:15:51 +00001235 case 0373:
1236 *bytes = bits == 16 ? 3 : 5;
1237 out(offset, segment, bytes, OUT_RAWDATA + 1, NO_SEG, NO_SEG);
1238 offset += 1;
1239 break;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001240
H. Peter Anvine2c80182005-01-15 22:15:51 +00001241 default: /* can't do it by 'case' statements */
1242 if (c >= 0100 && c <= 0277) { /* it's an EA */
1243 ea ea_data;
1244 int rfield;
1245 unsigned char *p;
1246 long s;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001247
H. Peter Anvine2c80182005-01-15 22:15:51 +00001248 if (c <= 0177) /* pick rfield from operand b */
1249 rfield = regval(&ins->oprs[c & 7]);
1250 else /* rfield is constant */
1251 rfield = c & 7;
1252
1253 if (!process_ea
1254 (&ins->oprs[(c >> 3) & 7], &ea_data, bits, rfield,
1255 ins->forw_ref)) {
1256 errfunc(ERR_NONFATAL, "invalid effective address");
1257 }
1258
1259 p = bytes;
1260 *p++ = ea_data.modrm;
1261 if (ea_data.sib_present)
1262 *p++ = ea_data.sib;
1263
1264 s = p - bytes;
1265 out(offset, segment, bytes, OUT_RAWDATA + s,
1266 NO_SEG, NO_SEG);
1267
1268 switch (ea_data.bytes) {
1269 case 0:
1270 break;
1271 case 1:
1272 if (ins->oprs[(c >> 3) & 7].segment != NO_SEG) {
1273 data = ins->oprs[(c >> 3) & 7].offset;
1274 out(offset, segment, &data, OUT_ADDRESS + 1,
1275 ins->oprs[(c >> 3) & 7].segment,
1276 ins->oprs[(c >> 3) & 7].wrt);
1277 } else {
1278 *bytes = ins->oprs[(c >> 3) & 7].offset;
1279 out(offset, segment, bytes, OUT_RAWDATA + 1,
1280 NO_SEG, NO_SEG);
1281 }
1282 s++;
1283 break;
1284 case 2:
1285 case 4:
1286 data = ins->oprs[(c >> 3) & 7].offset;
1287 out(offset, segment, &data,
1288 OUT_ADDRESS + ea_data.bytes,
1289 ins->oprs[(c >> 3) & 7].segment,
1290 ins->oprs[(c >> 3) & 7].wrt);
1291 s += ea_data.bytes;
1292 break;
1293 }
1294 offset += s;
1295 } else
1296 errfunc(ERR_PANIC, "internal instruction table corrupt"
1297 ": instruction code 0x%02X given", c);
1298 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001299}
1300
H. Peter Anvin232badb2002-06-06 02:41:20 +00001301#include "regvals.c"
1302
H. Peter Anvine2c80182005-01-15 22:15:51 +00001303static int regval(operand * o)
H. Peter Anvineba20a72002-04-30 20:53:55 +00001304{
H. Peter Anvine2c80182005-01-15 22:15:51 +00001305 if (o->basereg < EXPR_REG_START || o->basereg >= REG_ENUM_LIMIT) {
1306 errfunc(ERR_PANIC, "invalid operand passed to regval()");
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001307 }
H. Peter Anvin232badb2002-06-06 02:41:20 +00001308 return regvals[o->basereg];
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001309}
1310
H. Peter Anvine2c80182005-01-15 22:15:51 +00001311static int matches(struct itemplate *itemp, insn * instruction)
H. Peter Anvineba20a72002-04-30 20:53:55 +00001312{
H. Peter Anvinef7468f2002-04-30 20:57:59 +00001313 int i, size[3], asize, oprs, ret;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001314
1315 ret = 100;
1316
1317 /*
1318 * Check the opcode
1319 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001320 if (itemp->opcode != instruction->opcode)
1321 return 0;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001322
1323 /*
1324 * Count the operands
1325 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001326 if (itemp->operands != instruction->operands)
1327 return 0;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001328
1329 /*
1330 * Check that no spurious colons or TOs are present
1331 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001332 for (i = 0; i < itemp->operands; i++)
1333 if (instruction->oprs[i].type & ~itemp->opd[i] & (COLON | TO))
1334 return 0;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001335
1336 /*
1337 * Check that the operand flags all match up
1338 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001339 for (i = 0; i < itemp->operands; i++)
1340 if (itemp->opd[i] & ~instruction->oprs[i].type ||
1341 ((itemp->opd[i] & SIZE_MASK) &&
1342 ((itemp->opd[i] ^ instruction->oprs[i].type) & SIZE_MASK))) {
1343 if ((itemp->opd[i] & ~instruction->oprs[i].type & NON_SIZE) ||
1344 (instruction->oprs[i].type & SIZE_MASK))
1345 return 0;
1346 else
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001347/* ret = 1; */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001348 return 1;
1349 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001350
1351 /*
1352 * Check operand sizes
1353 */
H. Peter Anvinef7468f2002-04-30 20:57:59 +00001354 if (itemp->flags & IF_ARMASK) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001355 size[0] = size[1] = size[2] = 0;
H. Peter Anvinef7468f2002-04-30 20:57:59 +00001356
H. Peter Anvine2c80182005-01-15 22:15:51 +00001357 switch (itemp->flags & IF_ARMASK) {
1358 case IF_AR0:
1359 i = 0;
1360 break;
1361 case IF_AR1:
1362 i = 1;
1363 break;
1364 case IF_AR2:
1365 i = 2;
1366 break;
1367 default:
1368 break; /* Shouldn't happen */
1369 }
1370 if (itemp->flags & IF_SB) {
1371 size[i] = BITS8;
1372 } else if (itemp->flags & IF_SW) {
1373 size[i] = BITS16;
1374 } else if (itemp->flags & IF_SD) {
1375 size[i] = BITS32;
1376 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001377 } else {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001378 asize = 0;
1379 if (itemp->flags & IF_SB) {
1380 asize = BITS8;
1381 oprs = itemp->operands;
1382 } else if (itemp->flags & IF_SW) {
1383 asize = BITS16;
1384 oprs = itemp->operands;
1385 } else if (itemp->flags & IF_SD) {
1386 asize = BITS32;
1387 oprs = itemp->operands;
1388 }
1389 size[0] = size[1] = size[2] = asize;
H. Peter Anvinef7468f2002-04-30 20:57:59 +00001390 }
1391
1392 if (itemp->flags & (IF_SM | IF_SM2)) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001393 oprs = (itemp->flags & IF_SM2 ? 2 : itemp->operands);
1394 asize = 0;
1395 for (i = 0; i < oprs; i++) {
1396 if ((asize = itemp->opd[i] & SIZE_MASK) != 0) {
1397 int j;
1398 for (j = 0; j < oprs; j++)
1399 size[j] = asize;
1400 break;
1401 }
1402 }
H. Peter Anvinef7468f2002-04-30 20:57:59 +00001403 } else {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001404 oprs = itemp->operands;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001405 }
1406
H. Peter Anvine2c80182005-01-15 22:15:51 +00001407 for (i = 0; i < itemp->operands; i++)
1408 if (!(itemp->opd[i] & SIZE_MASK) &&
1409 (instruction->oprs[i].type & SIZE_MASK & ~size[i]))
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001410/* ret = 2; */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001411 return 2;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001412
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001413 /*
1414 * Check template is okay at the set cpu level
1415 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001416 if ((itemp->flags & IF_PLEVEL) > cpu)
1417 return 3;
1418
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001419 /*
1420 * Check if special handling needed for Jumps
1421 */
H. Peter Anvine2c80182005-01-15 22:15:51 +00001422 if ((unsigned char)(itemp->code[0]) >= 0370)
1423 return 99;
1424
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001425 return ret;
1426}
1427
H. Peter Anvine2c80182005-01-15 22:15:51 +00001428static ea *process_ea(operand * input, ea * output, int addrbits,
1429 int rfield, int forw_ref)
H. Peter Anvineba20a72002-04-30 20:53:55 +00001430{
H. Peter Anvine2c80182005-01-15 22:15:51 +00001431 if (!(REGISTER & ~input->type)) { /* it's a single register */
1432 static int regs[] = {
1433 R_AL, R_CL, R_DL, R_BL, R_AH, R_CH, R_DH, R_BH,
1434 R_AX, R_CX, R_DX, R_BX, R_SP, R_BP, R_SI, R_DI,
1435 R_EAX, R_ECX, R_EDX, R_EBX, R_ESP, R_EBP, R_ESI, R_EDI,
1436 R_MM0, R_MM1, R_MM2, R_MM3, R_MM4, R_MM5, R_MM6, R_MM7,
1437 R_XMM0, R_XMM1, R_XMM2, R_XMM3, R_XMM4, R_XMM5, R_XMM6, R_XMM7
1438 };
1439 int i;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001440
H. Peter Anvine2c80182005-01-15 22:15:51 +00001441 for (i = 0; i < elements(regs); i++)
1442 if (input->basereg == regs[i])
1443 break;
1444 if (i < elements(regs)) {
1445 output->sib_present = FALSE; /* no SIB necessary */
1446 output->bytes = 0; /* no offset necessary either */
H. Peter Anvin4836e332002-04-30 20:56:43 +00001447 output->modrm = 0xC0 | (rfield << 3) | (i & 7);
H. Peter Anvine2c80182005-01-15 22:15:51 +00001448 } else
1449 return NULL;
1450 } else { /* it's a memory reference */
1451 if (input->basereg == -1
1452 && (input->indexreg == -1 || input->scale == 0)) {
1453 /* it's a pure offset */
1454 if (input->addr_size)
1455 addrbits = input->addr_size;
1456 output->sib_present = FALSE;
1457 output->bytes = (addrbits == 32 ? 4 : 2);
1458 output->modrm = (addrbits == 32 ? 5 : 6) | (rfield << 3);
1459 } else { /* it's an indirection */
1460 int i = input->indexreg, b = input->basereg, s = input->scale;
1461 long o = input->offset, seg = input->segment;
1462 int hb = input->hintbase, ht = input->hinttype;
1463 int t;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001464
H. Peter Anvine2c80182005-01-15 22:15:51 +00001465 if (s == 0)
1466 i = -1; /* make this easy, at least */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001467
H. Peter Anvine2c80182005-01-15 22:15:51 +00001468 if (i == R_EAX || i == R_EBX || i == R_ECX || i == R_EDX
1469 || i == R_EBP || i == R_ESP || i == R_ESI || i == R_EDI
1470 || b == R_EAX || b == R_EBX || b == R_ECX || b == R_EDX
1471 || b == R_EBP || b == R_ESP || b == R_ESI || b == R_EDI) {
1472 /* it must be a 32-bit memory reference. Firstly we have
1473 * to check that all registers involved are type Exx. */
1474 if (i != -1 && i != R_EAX && i != R_EBX && i != R_ECX
1475 && i != R_EDX && i != R_EBP && i != R_ESP && i != R_ESI
1476 && i != R_EDI)
1477 return NULL;
1478 if (b != -1 && b != R_EAX && b != R_EBX && b != R_ECX
1479 && b != R_EDX && b != R_EBP && b != R_ESP && b != R_ESI
1480 && b != R_EDI)
1481 return NULL;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001482
H. Peter Anvine2c80182005-01-15 22:15:51 +00001483 /* While we're here, ensure the user didn't specify WORD. */
1484 if (input->addr_size == 16)
1485 return NULL;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001486
H. Peter Anvine2c80182005-01-15 22:15:51 +00001487 /* now reorganise base/index */
1488 if (s == 1 && b != i && b != -1 && i != -1 &&
1489 ((hb == b && ht == EAH_NOTBASE)
1490 || (hb == i && ht == EAH_MAKEBASE)))
1491 t = b, b = i, i = t; /* swap if hints say so */
1492 if (b == i) /* convert EAX+2*EAX to 3*EAX */
1493 b = -1, s++;
1494 if (b == -1 && s == 1 && !(hb == i && ht == EAH_NOTBASE))
1495 b = i, i = -1; /* make single reg base, unless hint */
1496 if (((s == 2 && i != R_ESP
1497 && !(input->eaflags & EAF_TIMESTWO)) || s == 3
1498 || s == 5 || s == 9) && b == -1)
1499 b = i, s--; /* convert 3*EAX to EAX+2*EAX */
1500 if (i == -1 && b != R_ESP
1501 && (input->eaflags & EAF_TIMESTWO))
1502 i = b, b = -1, s = 1;
1503 /* convert [NOSPLIT EAX] to sib format with 0x0 displacement */
1504 if (s == 1 && i == R_ESP) /* swap ESP into base if scale is 1 */
1505 i = b, b = R_ESP;
1506 if (i == R_ESP
1507 || (s != 1 && s != 2 && s != 4 && s != 8 && i != -1))
1508 return NULL; /* wrong, for various reasons */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001509
H. Peter Anvine2c80182005-01-15 22:15:51 +00001510 if (i == -1 && b != R_ESP) { /* no SIB needed */
1511 int mod, rm;
1512 switch (b) {
1513 case R_EAX:
1514 rm = 0;
1515 break;
1516 case R_ECX:
1517 rm = 1;
1518 break;
1519 case R_EDX:
1520 rm = 2;
1521 break;
1522 case R_EBX:
1523 rm = 3;
1524 break;
1525 case R_EBP:
1526 rm = 5;
1527 break;
1528 case R_ESI:
1529 rm = 6;
1530 break;
1531 case R_EDI:
1532 rm = 7;
1533 break;
1534 case -1:
1535 rm = 5;
1536 break;
1537 default: /* should never happen */
1538 return NULL;
1539 }
1540 if (b == -1 || (b != R_EBP && o == 0 &&
1541 seg == NO_SEG && !forw_ref &&
1542 !(input->eaflags &
1543 (EAF_BYTEOFFS | EAF_WORDOFFS))))
1544 mod = 0;
1545 else if (input->eaflags & EAF_BYTEOFFS ||
1546 (o >= -128 && o <= 127 && seg == NO_SEG
1547 && !forw_ref
1548 && !(input->eaflags & EAF_WORDOFFS))) {
1549 mod = 1;
1550 } else
1551 mod = 2;
H. Peter Anvinea838272002-04-30 20:51:53 +00001552
H. Peter Anvine2c80182005-01-15 22:15:51 +00001553 output->sib_present = FALSE;
1554 output->bytes = (b == -1 || mod == 2 ? 4 : mod);
1555 output->modrm = (mod << 6) | (rfield << 3) | rm;
1556 } else { /* we need a SIB */
1557 int mod, scale, index, base;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001558
H. Peter Anvine2c80182005-01-15 22:15:51 +00001559 switch (b) {
1560 case R_EAX:
1561 base = 0;
1562 break;
1563 case R_ECX:
1564 base = 1;
1565 break;
1566 case R_EDX:
1567 base = 2;
1568 break;
1569 case R_EBX:
1570 base = 3;
1571 break;
1572 case R_ESP:
1573 base = 4;
1574 break;
1575 case R_EBP:
1576 case -1:
1577 base = 5;
1578 break;
1579 case R_ESI:
1580 base = 6;
1581 break;
1582 case R_EDI:
1583 base = 7;
1584 break;
1585 default: /* then what the smeg is it? */
1586 return NULL; /* panic */
1587 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001588
H. Peter Anvine2c80182005-01-15 22:15:51 +00001589 switch (i) {
1590 case R_EAX:
1591 index = 0;
1592 break;
1593 case R_ECX:
1594 index = 1;
1595 break;
1596 case R_EDX:
1597 index = 2;
1598 break;
1599 case R_EBX:
1600 index = 3;
1601 break;
1602 case -1:
1603 index = 4;
1604 break;
1605 case R_EBP:
1606 index = 5;
1607 break;
1608 case R_ESI:
1609 index = 6;
1610 break;
1611 case R_EDI:
1612 index = 7;
1613 break;
1614 default: /* then what the smeg is it? */
1615 return NULL; /* panic */
1616 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001617
H. Peter Anvine2c80182005-01-15 22:15:51 +00001618 if (i == -1)
1619 s = 1;
1620 switch (s) {
1621 case 1:
1622 scale = 0;
1623 break;
1624 case 2:
1625 scale = 1;
1626 break;
1627 case 4:
1628 scale = 2;
1629 break;
1630 case 8:
1631 scale = 3;
1632 break;
1633 default: /* then what the smeg is it? */
1634 return NULL; /* panic */
1635 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001636
H. Peter Anvine2c80182005-01-15 22:15:51 +00001637 if (b == -1 || (b != R_EBP && o == 0 &&
1638 seg == NO_SEG && !forw_ref &&
1639 !(input->eaflags &
1640 (EAF_BYTEOFFS | EAF_WORDOFFS))))
1641 mod = 0;
1642 else if (input->eaflags & EAF_BYTEOFFS ||
1643 (o >= -128 && o <= 127 && seg == NO_SEG
1644 && !forw_ref
1645 && !(input->eaflags & EAF_WORDOFFS)))
1646 mod = 1;
1647 else
1648 mod = 2;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001649
H. Peter Anvine2c80182005-01-15 22:15:51 +00001650 output->sib_present = TRUE;
1651 output->bytes = (b == -1 || mod == 2 ? 4 : mod);
1652 output->modrm = (mod << 6) | (rfield << 3) | 4;
1653 output->sib = (scale << 6) | (index << 3) | base;
1654 }
1655 } else { /* it's 16-bit */
1656 int mod, rm;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001657
H. Peter Anvine2c80182005-01-15 22:15:51 +00001658 /* check all registers are BX, BP, SI or DI */
1659 if ((b != -1 && b != R_BP && b != R_BX && b != R_SI
1660 && b != R_DI) || (i != -1 && i != R_BP && i != R_BX
1661 && i != R_SI && i != R_DI))
1662 return NULL;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001663
H. Peter Anvine2c80182005-01-15 22:15:51 +00001664 /* ensure the user didn't specify DWORD */
1665 if (input->addr_size == 32)
1666 return NULL;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001667
H. Peter Anvine2c80182005-01-15 22:15:51 +00001668 if (s != 1 && i != -1)
1669 return NULL; /* no can do, in 16-bit EA */
1670 if (b == -1 && i != -1) {
1671 int tmp = b;
1672 b = i;
1673 i = tmp;
1674 } /* swap */
1675 if ((b == R_SI || b == R_DI) && i != -1) {
1676 int tmp = b;
1677 b = i;
1678 i = tmp;
1679 }
1680 /* have BX/BP as base, SI/DI index */
1681 if (b == i)
1682 return NULL; /* shouldn't ever happen, in theory */
1683 if (i != -1 && b != -1 &&
1684 (i == R_BP || i == R_BX || b == R_SI || b == R_DI))
1685 return NULL; /* invalid combinations */
1686 if (b == -1) /* pure offset: handled above */
1687 return NULL; /* so if it gets to here, panic! */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001688
H. Peter Anvine2c80182005-01-15 22:15:51 +00001689 rm = -1;
1690 if (i != -1)
1691 switch (i * 256 + b) {
1692 case R_SI * 256 + R_BX:
1693 rm = 0;
1694 break;
1695 case R_DI * 256 + R_BX:
1696 rm = 1;
1697 break;
1698 case R_SI * 256 + R_BP:
1699 rm = 2;
1700 break;
1701 case R_DI * 256 + R_BP:
1702 rm = 3;
1703 break;
1704 } else
1705 switch (b) {
1706 case R_SI:
1707 rm = 4;
1708 break;
1709 case R_DI:
1710 rm = 5;
1711 break;
1712 case R_BP:
1713 rm = 6;
1714 break;
1715 case R_BX:
1716 rm = 7;
1717 break;
1718 }
1719 if (rm == -1) /* can't happen, in theory */
1720 return NULL; /* so panic if it does */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001721
H. Peter Anvine2c80182005-01-15 22:15:51 +00001722 if (o == 0 && seg == NO_SEG && !forw_ref && rm != 6 &&
1723 !(input->eaflags & (EAF_BYTEOFFS | EAF_WORDOFFS)))
1724 mod = 0;
1725 else if (input->eaflags & EAF_BYTEOFFS ||
1726 (o >= -128 && o <= 127 && seg == NO_SEG
1727 && !forw_ref
1728 && !(input->eaflags & EAF_WORDOFFS)))
1729 mod = 1;
1730 else
1731 mod = 2;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001732
H. Peter Anvine2c80182005-01-15 22:15:51 +00001733 output->sib_present = FALSE; /* no SIB - it's 16-bit */
1734 output->bytes = mod; /* bytes of offset needed */
1735 output->modrm = (mod << 6) | (rfield << 3) | rm;
1736 }
1737 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001738 }
1739 output->size = 1 + output->sib_present + output->bytes;
1740 return output;
1741}
1742
H. Peter Anvine2c80182005-01-15 22:15:51 +00001743static int chsize(operand * input, int addrbits)
H. Peter Anvineba20a72002-04-30 20:53:55 +00001744{
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001745 if (!(MEMORY & ~input->type)) {
H. Peter Anvine2c80182005-01-15 22:15:51 +00001746 int i = input->indexreg, b = input->basereg;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001747
H. Peter Anvine2c80182005-01-15 22:15:51 +00001748 if (input->scale == 0)
1749 i = -1;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001750
H. Peter Anvine2c80182005-01-15 22:15:51 +00001751 if (i == -1 && b == -1) /* pure offset */
1752 return (input->addr_size != 0 && input->addr_size != addrbits);
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001753
H. Peter Anvine2c80182005-01-15 22:15:51 +00001754 if (i == R_EAX || i == R_EBX || i == R_ECX || i == R_EDX
1755 || i == R_EBP || i == R_ESP || i == R_ESI || i == R_EDI
1756 || b == R_EAX || b == R_EBX || b == R_ECX || b == R_EDX
1757 || b == R_EBP || b == R_ESP || b == R_ESI || b == R_EDI)
1758 return (addrbits == 16);
1759 else
1760 return (addrbits == 32);
1761 } else
1762 return 0;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001763}