blob: 8a6bd0d26e075a19016fc6787e2877323e3a943c [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 {
82 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 */
86} ea;
87
H. Peter Anvinaf535c12002-04-30 20:59:21 +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 Anvinbfebdb02002-09-12 02:23:54 +000093static long calcsize (long, long, int, insn *, const char *);
94static void gencode (long, long, int, insn *, const char *, long);
H. Peter Anvineba20a72002-04-30 20:53:55 +000095static 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 Anvinbfebdb02002-09-12 02:23:54 +0000105static void out (long offset, long segto, const void *data, unsigned long type,
H. Peter Anvineba20a72002-04-30 20:53:55 +0000106 long segment, long wrt)
107{
Frank Kotlerabebb082003-09-06 04:45:37 +0000108 static long lineno = 0; /* static!!! */
109 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) {
112 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);
H. Peter Anvineba20a72002-04-30 20:53:55 +0000118 }
119 else {
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000120 unsigned char p[4], *q = p;
121 /*
122 * This is a non-relocated address, and we're going to
123 * convert it into RAWDATA format.
124 */
125 if ((type & OUT_SIZMASK) == 4) {
126 WRITELONG (q, * (long *) data);
127 list->output (offset, p, OUT_RAWDATA+4);
H. Peter Anvineba20a72002-04-30 20:53:55 +0000128 }
129 else {
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000130 WRITESHORT (q, * (long *) data);
131 list->output (offset, p, OUT_RAWDATA+2);
132 }
133 }
H. Peter Anvineba20a72002-04-30 20:53:55 +0000134 }
135 else if ((type & OUT_TYPMASK) == OUT_RAWDATA) {
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000136 list->output (offset, data, type);
H. Peter Anvineba20a72002-04-30 20:53:55 +0000137 }
138 else if ((type & OUT_TYPMASK) == OUT_RESERVE) {
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000139 list->output (offset, NULL, type);
H. Peter Anvineba20a72002-04-30 20:53:55 +0000140 }
141 else if ((type & OUT_TYPMASK) == OUT_REL2ADR ||
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000142 (type & OUT_TYPMASK) == OUT_REL4ADR) {
143 list->output (offset, data, type);
144 }
145
Frank Kotlerabebb082003-09-06 04:45:37 +0000146 /*
147 * this call to src_get determines when we call the
148 * debug-format-specific "linenum" function
149 * it updates lineno and lnfname to the current values
150 * returning 0 if "same as last time", -2 if lnfname
151 * changed, and the amount by which lineno changed,
152 * if it did. thus, these variables must be static
153 */
154
H. Peter Anvineba20a72002-04-30 20:53:55 +0000155 if (src_get(&lineno,&lnfname))
H. Peter Anvince616072002-04-30 21:02:23 +0000156 {
H. Peter Anvineba20a72002-04-30 20:53:55 +0000157 outfmt->current_dfmt->linenum(lnfname,lineno,segto);
H. Peter Anvince616072002-04-30 21:02:23 +0000158 }
H. Peter Anvineba20a72002-04-30 20:53:55 +0000159
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000160 outfmt->output (segto, data, type, segment, wrt);
161}
162
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000163static int jmp_match (long segment, long offset, int bits,
H. Peter Anvinbfebdb02002-09-12 02:23:54 +0000164 insn *ins, const char *code)
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000165{ long isize;
166 unsigned char c = code[0];
167
168
H. Peter Anvin788e6c12002-04-30 21:02:01 +0000169 if (c != 0370 && c != 0371) return 0;
170 if (ins->oprs[0].opflags & OPFLAG_FORWARD) {
H. Peter Anvin01377d82002-05-21 03:16:33 +0000171 if ((optimizing<0 || (ins->oprs[0].type & STRICT))
172 && c==0370) return 1;
H. Peter Anvin788e6c12002-04-30 21:02:01 +0000173 else return (pass0==0); /* match a forward reference */
174 }
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000175 isize = calcsize (segment, offset, bits, ins, code);
176 if (ins->oprs[0].segment != segment) return 0;
177 isize = ins->oprs[0].offset - offset - isize; /* isize is now the delta */
178 if (isize >= -128L && isize <= 127L) return 1; /* it is byte size */
179
180 return 0;
181}
182
183
184long assemble (long segment, long offset, int bits, unsigned long cp,
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000185 insn *instruction, struct ofmt *output, efunc error,
H. Peter Anvineba20a72002-04-30 20:53:55 +0000186 ListGen *listgen)
187{
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000188 struct itemplate *temp;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000189 int j;
190 int size_prob;
191 long insn_end;
192 long itimes;
193 long start = offset;
194 long wsize = 0; /* size for DB etc. */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000195
196 errfunc = error; /* to pass to other functions */
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000197 cpu = cp;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000198 outfmt = output; /* likewise */
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000199 list = listgen; /* and again */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000200
H. Peter Anvineba20a72002-04-30 20:53:55 +0000201 switch (instruction->opcode)
202 {
203 case -1: return 0;
204 case I_DB: wsize = 1; break;
205 case I_DW: wsize = 2; break;
206 case I_DD: wsize = 4; break;
207 case I_DQ: wsize = 8; break;
208 case I_DT: wsize = 10; break;
209 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000210
H. Peter Anvineba20a72002-04-30 20:53:55 +0000211 if (wsize) {
212 extop * e;
213 long t = instruction->times;
214 if (t < 0)
215 errfunc(ERR_PANIC, "instruction->times < 0 (%ld) in assemble()",t);
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000216
H. Peter Anvineba20a72002-04-30 20:53:55 +0000217 while (t--) /* repeat TIMES times */
218 {
219 for (e = instruction->eops; e; e = e->next)
220 {
221 if (e->type == EOT_DB_NUMBER)
222 {
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000223 if (wsize == 1) {
224 if (e->segment != NO_SEG)
225 errfunc (ERR_NONFATAL,
226 "one-byte relocation attempted");
227 else {
H. Peter Anvin41bf8002002-04-30 20:58:18 +0000228 unsigned char out_byte = e->offset;
229 out (offset, segment, &out_byte, OUT_RAWDATA+1,
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000230 NO_SEG, NO_SEG);
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000231 }
H. Peter Anvineba20a72002-04-30 20:53:55 +0000232 }
233 else if (wsize > 5) {
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000234 errfunc (ERR_NONFATAL, "integer supplied to a D%c"
235 " instruction", wsize==8 ? 'Q' : 'T');
H. Peter Anvineba20a72002-04-30 20:53:55 +0000236 }
237 else
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000238 out (offset, segment, &e->offset,
239 OUT_ADDRESS+wsize, e->segment,
240 e->wrt);
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000241 offset += wsize;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000242 }
243 else if (e->type == EOT_DB_STRING)
244 {
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000245 int align;
246
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000247 out (offset, segment, e->stringval,
248 OUT_RAWDATA+e->stringlen, NO_SEG, NO_SEG);
H. Peter Anvineba20a72002-04-30 20:53:55 +0000249 align = e->stringlen % wsize;
250
251 if (align) {
252 align = wsize - align;
253 out (offset, segment, "\0\0\0\0\0\0\0\0",
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000254 OUT_RAWDATA+align, NO_SEG, NO_SEG);
H. Peter Anvineba20a72002-04-30 20:53:55 +0000255 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000256 offset += e->stringlen + align;
257 }
258 }
H. Peter Anvineba20a72002-04-30 20:53:55 +0000259 if (t > 0 && t == instruction->times-1)
260 {
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000261 /*
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 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000268 }
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000269 if (instruction->times > 1)
270 list->downlevel (LIST_TIMES);
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000271 return offset - start;
272 }
273
H. Peter Anvineba20a72002-04-30 20:53:55 +0000274 if (instruction->opcode == I_INCBIN)
275 {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000276 static char fname[FILENAME_MAX];
H. Peter Anvineba20a72002-04-30 20:53:55 +0000277 FILE * fp;
278 long len;
Frank Kotlerd0ed6fd2003-08-27 11:33:56 +0000279 char *prefix = "", *combine;
280 char** pPrevPath = NULL;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000281
282 len = FILENAME_MAX-1;
283 if (len > instruction->eops->stringlen)
284 len = instruction->eops->stringlen;
285 strncpy (fname, instruction->eops->stringval, len);
286 fname[len] = '\0';
H. Peter Anvineba20a72002-04-30 20:53:55 +0000287
Frank Kotlerd0ed6fd2003-08-27 11:33:56 +0000288 while (1) /* added by alexfru: 'incbin' uses include paths */
289 {
290 combine = nasm_malloc(strlen(prefix) + len + 1);
291 strcpy(combine, prefix);
292 strcat(combine, fname);
293
294 if ( (fp = fopen(combine, "rb")) != NULL)
295 {
296 nasm_free(combine);
297 break;
298 }
299
300 nasm_free(combine);
301 pPrevPath = pp_get_include_path_ptr (pPrevPath);
302 if (pPrevPath == NULL)
303 break;
304 prefix = *pPrevPath;
305 }
306
307 if (fp == NULL)
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000308 error (ERR_NONFATAL, "`incbin': unable to open file `%s'", fname);
309 else if (fseek(fp, 0L, SEEK_END) < 0)
310 error (ERR_NONFATAL, "`incbin': unable to seek on file `%s'",
311 fname);
H. Peter Anvineba20a72002-04-30 20:53:55 +0000312 else
313 {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000314 static char buf[2048];
315 long t = instruction->times;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000316 long base = 0;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000317
318 len = ftell (fp);
319 if (instruction->eops->next) {
H. Peter Anvineba20a72002-04-30 20:53:55 +0000320 base = instruction->eops->next->offset;
321 len -= base;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000322 if (instruction->eops->next->next &&
323 len > instruction->eops->next->next->offset)
324 len = instruction->eops->next->next->offset;
325 }
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000326 /*
327 * Dummy call to list->output to give the offset to the
328 * listing module.
329 */
330 list->output (offset, NULL, OUT_RAWDATA);
331 list->uplevel(LIST_INCBIN);
H. Peter Anvineba20a72002-04-30 20:53:55 +0000332 while (t--)
333 {
334 long l;
335
336 fseek (fp, base, SEEK_SET);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000337 l = len;
338 while (l > 0) {
339 long m = fread (buf, 1, (l>sizeof(buf)?sizeof(buf):l),
340 fp);
341 if (!m) {
342 /*
343 * This shouldn't happen unless the file
344 * actually changes while we are reading
345 * it.
346 */
347 error (ERR_NONFATAL, "`incbin': unexpected EOF while"
348 " reading file `%s'", fname);
H. Peter Anvineba20a72002-04-30 20:53:55 +0000349 t=0; /* Try to exit cleanly */
350 break;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000351 }
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000352 out (offset, segment, buf, OUT_RAWDATA+m,
353 NO_SEG, NO_SEG);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000354 l -= m;
355 }
356 }
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000357 list->downlevel(LIST_INCBIN);
358 if (instruction->times > 1) {
359 /*
360 * Dummy call to list->output to give the offset to the
361 * listing module.
362 */
363 list->output (offset, NULL, OUT_RAWDATA);
364 list->uplevel(LIST_TIMES);
365 list->downlevel(LIST_TIMES);
366 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000367 fclose (fp);
368 return instruction->times * len;
369 }
370 return 0; /* if we're here, there's an error */
371 }
372
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000373 size_prob = FALSE;
374 temp = nasm_instructions[instruction->opcode];
375 while (temp->opcode != -1) {
376 int m = matches (temp, instruction);
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000377 if (m == 99)
378 m += jmp_match(segment, offset, bits, instruction, temp->code);
H. Peter Anvineba20a72002-04-30 20:53:55 +0000379
380 if (m == 100) /* matches! */
381 {
H. Peter Anvinbfebdb02002-09-12 02:23:54 +0000382 const char *codes = temp->code;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000383 long insn_size = calcsize(segment, offset, bits,
384 instruction, codes);
385 itimes = instruction->times;
386 if (insn_size < 0) /* shouldn't be, on pass two */
387 error (ERR_PANIC, "errors made it through from pass one");
388 else while (itimes--) {
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000389 for (j=0; j<instruction->nprefix; j++) {
H. Peter Anvineba20a72002-04-30 20:53:55 +0000390 unsigned char c=0;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000391 switch (instruction->prefixes[j]) {
392 case P_LOCK:
393 c = 0xF0; break;
394 case P_REPNE: case P_REPNZ:
395 c = 0xF2; break;
396 case P_REPE: case P_REPZ: case P_REP:
397 c = 0xF3; break;
398 case R_CS: c = 0x2E; break;
399 case R_DS: c = 0x3E; break;
400 case R_ES: c = 0x26; break;
401 case R_FS: c = 0x64; break;
402 case R_GS: c = 0x65; break;
403 case R_SS: c = 0x36; break;
H. Peter Anvin232badb2002-06-06 02:41:20 +0000404 case R_SEGR6:
405 case R_SEGR7:
406 error (ERR_NONFATAL, "segr6 and segr7 cannot be used as prefixes");
407 break;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000408 case P_A16:
H. Peter Anvineba20a72002-04-30 20:53:55 +0000409 if (bits != 16)
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000410 c = 0x67;
411 break;
412 case P_A32:
H. Peter Anvineba20a72002-04-30 20:53:55 +0000413 if (bits != 32)
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000414 c = 0x67;
415 break;
416 case P_O16:
H. Peter Anvineba20a72002-04-30 20:53:55 +0000417 if (bits != 16)
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000418 c = 0x66;
419 break;
420 case P_O32:
H. Peter Anvineba20a72002-04-30 20:53:55 +0000421 if (bits != 32)
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000422 c = 0x66;
423 break;
424 default:
425 error (ERR_PANIC,
426 "invalid instruction prefix");
427 }
H. Peter Anvineba20a72002-04-30 20:53:55 +0000428 if (c != 0) {
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000429 out (offset, segment, &c, OUT_RAWDATA+1,
430 NO_SEG, NO_SEG);
H. Peter Anvineba20a72002-04-30 20:53:55 +0000431 offset++;
432 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000433 }
H. Peter Anvin3198bee2003-07-16 19:53:51 +0000434 insn_end = offset + insn_size;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000435 gencode (segment, offset, bits, instruction, codes, insn_end);
436 offset += insn_size;
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000437 if (itimes > 0 && itimes == instruction->times-1) {
438 /*
439 * Dummy call to list->output to give the offset to the
440 * listing module.
441 */
442 list->output (offset, NULL, OUT_RAWDATA);
443 list->uplevel (LIST_TIMES);
444 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000445 }
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000446 if (instruction->times > 1)
447 list->downlevel (LIST_TIMES);
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000448 return offset - start;
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000449 } else if (m > 0 && m > size_prob) {
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000450 size_prob = m;
451 }
452 temp++;
453 }
H. Peter Anvineba20a72002-04-30 20:53:55 +0000454
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000455 if (temp->opcode == -1) { /* didn't match any instruction */
456 if (size_prob == 1) /* would have matched, but for size */
457 error (ERR_NONFATAL, "operation size not specified");
458 else if (size_prob == 2)
459 error (ERR_NONFATAL, "mismatch in operand sizes");
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000460 else if (size_prob == 3)
461 error (ERR_NONFATAL, "no instruction for this cpu level");
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000462 else
463 error (ERR_NONFATAL,
464 "invalid combination of opcode and operands");
465 }
466 return 0;
467}
468
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000469long insn_size (long segment, long offset, int bits, unsigned long cp,
H. Peter Anvineba20a72002-04-30 20:53:55 +0000470 insn *instruction, efunc error)
471{
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000472 struct itemplate *temp;
473
474 errfunc = error; /* to pass to other functions */
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000475 cpu = cp;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000476
477 if (instruction->opcode == -1)
478 return 0;
479
480 if (instruction->opcode == I_DB ||
481 instruction->opcode == I_DW ||
482 instruction->opcode == I_DD ||
483 instruction->opcode == I_DQ ||
H. Peter Anvineba20a72002-04-30 20:53:55 +0000484 instruction->opcode == I_DT)
485 {
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000486 extop *e;
487 long isize, osize, wsize = 0; /* placate gcc */
488
489 isize = 0;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000490 switch (instruction->opcode)
491 {
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000492 case I_DB: wsize = 1; break;
493 case I_DW: wsize = 2; break;
494 case I_DD: wsize = 4; break;
495 case I_DQ: wsize = 8; break;
496 case I_DT: wsize = 10; break;
497 }
498
H. Peter Anvineba20a72002-04-30 20:53:55 +0000499 for (e = instruction->eops; e; e = e->next)
500 {
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000501 long align;
502
503 osize = 0;
504 if (e->type == EOT_DB_NUMBER)
505 osize = 1;
506 else if (e->type == EOT_DB_STRING)
507 osize = e->stringlen;
508
509 align = (-osize) % wsize;
510 if (align < 0)
511 align += wsize;
512 isize += osize + align;
513 }
514 return isize * instruction->times;
515 }
516
H. Peter Anvineba20a72002-04-30 20:53:55 +0000517 if (instruction->opcode == I_INCBIN)
518 {
519 char fname[FILENAME_MAX];
520 FILE * fp;
521 long len;
Frank Kotlerd0ed6fd2003-08-27 11:33:56 +0000522 char *prefix = "", *combine;
523 char** pPrevPath = NULL;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000524
525 len = FILENAME_MAX-1;
526 if (len > instruction->eops->stringlen)
527 len = instruction->eops->stringlen;
528 strncpy (fname, instruction->eops->stringval, len);
529 fname[len] = '\0';
Frank Kotlerd0ed6fd2003-08-27 11:33:56 +0000530
531 while (1) /* added by alexfru: 'incbin' uses include paths */
532 {
533 combine = nasm_malloc(strlen(prefix) + len + 1);
534 strcpy(combine, prefix);
535 strcat(combine, fname);
536
537 if ( (fp = fopen(combine, "rb")) != NULL)
538 {
539 nasm_free(combine);
540 break;
541 }
542
543 nasm_free(combine);
544 pPrevPath = pp_get_include_path_ptr (pPrevPath);
545 if (pPrevPath == NULL)
546 break;
547 prefix = *pPrevPath;
548 }
549
550 if (fp == NULL)
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000551 error (ERR_NONFATAL, "`incbin': unable to open file `%s'", fname);
552 else if (fseek(fp, 0L, SEEK_END) < 0)
553 error (ERR_NONFATAL, "`incbin': unable to seek on file `%s'",
554 fname);
H. Peter Anvineba20a72002-04-30 20:53:55 +0000555 else
556 {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000557 len = ftell (fp);
558 fclose (fp);
H. Peter Anvineba20a72002-04-30 20:53:55 +0000559 if (instruction->eops->next)
560 {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000561 len -= instruction->eops->next->offset;
562 if (instruction->eops->next->next &&
563 len > instruction->eops->next->next->offset)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000564 {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000565 len = instruction->eops->next->next->offset;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000566 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000567 }
568 return instruction->times * len;
569 }
570 return 0; /* if we're here, there's an error */
571 }
572
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000573 temp = nasm_instructions[instruction->opcode];
574 while (temp->opcode != -1) {
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000575 int m = matches(temp, instruction);
576 if (m == 99)
577 m += jmp_match(segment, offset, bits, instruction, temp->code);
578
579 if (m == 100) {
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000580 /* we've matched an instruction. */
H. Peter Anvineba20a72002-04-30 20:53:55 +0000581 long isize;
H. Peter Anvinbfebdb02002-09-12 02:23:54 +0000582 const char * codes = temp->code;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000583 int j;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000584
585 isize = calcsize(segment, offset, bits, instruction, codes);
586 if (isize < 0)
587 return -1;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000588 for (j = 0; j < instruction->nprefix; j++)
589 {
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000590 if ((instruction->prefixes[j] != P_A16 &&
591 instruction->prefixes[j] != P_O16 && bits==16) ||
592 (instruction->prefixes[j] != P_A32 &&
593 instruction->prefixes[j] != P_O32 && bits==32))
H. Peter Anvineba20a72002-04-30 20:53:55 +0000594 {
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000595 isize++;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000596 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000597 }
598 return isize * instruction->times;
599 }
600 temp++;
601 }
602 return -1; /* didn't match any instruction */
603}
604
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000605
606/* check that opn[op] is a signed byte of size 16 or 32,
607 and return the signed value*/
608static int is_sbyte (insn *ins, int op, int size)
609{
610 signed long v;
611 int ret;
612
613 ret = !(ins->forw_ref && ins->oprs[op].opflags ) && /* dead in the water on forward reference or External */
H. Peter Anvin01377d82002-05-21 03:16:33 +0000614 optimizing>=0 &&
615 !(ins->oprs[op].type & STRICT) &&
616 ins->oprs[op].wrt==NO_SEG && ins->oprs[op].segment==NO_SEG;
H. Peter Anvin734b1882002-04-30 21:01:08 +0000617
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000618 v = ins->oprs[op].offset;
619 if (size==16) v = (signed short)v; /* sign extend if 16 bits */
620
621 return ret && v>=-128L && v<=127L;
622}
623
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000624static long calcsize (long segment, long offset, int bits,
H. Peter Anvinbfebdb02002-09-12 02:23:54 +0000625 insn *ins, const char *codes)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000626{
627 long length = 0;
628 unsigned char c;
629
630 (void) segment; /* Don't warn that this parameter is unused */
631 (void) offset; /* Don't warn that this parameter is unused */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000632
633 while (*codes) switch (c = *codes++) {
634 case 01: case 02: case 03:
635 codes += c, length += c; break;
636 case 04: case 05: case 06: case 07:
637 length++; break;
638 case 010: case 011: case 012:
639 codes++, length++; break;
640 case 017:
641 length++; break;
642 case 014: case 015: case 016:
643 length++; break;
644 case 020: case 021: case 022:
645 length++; break;
646 case 024: case 025: case 026:
647 length++; break;
648 case 030: case 031: case 032:
649 length += 2; break;
650 case 034: case 035: case 036:
H. Peter Anvin3ba46772002-05-27 23:19:35 +0000651 if ( ins->oprs[c-034].type & (BITS16|BITS32) )
652 length += (ins->oprs[c-034].type & BITS16) ? 2 : 4;
653 else
654 length += (bits == 16) ? 2 : 4;
655 break;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000656 case 037:
657 length += 2; break;
658 case 040: case 041: case 042:
659 length += 4; break;
H. Peter Anvin3ba46772002-05-27 23:19:35 +0000660 case 044: case 045: case 046:
661 length += ((ins->oprs[c-044].addr_size ?
662 ins->oprs[c-044].addr_size : bits) == 16 ? 2 : 4); break;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000663 case 050: case 051: case 052:
664 length++; break;
665 case 060: case 061: case 062:
666 length += 2; break;
667 case 064: case 065: case 066:
H. Peter Anvin17799b42002-05-21 03:31:21 +0000668 if ( ins->oprs[c-064].type & (BITS16|BITS32) )
669 length += (ins->oprs[c-064].type & BITS16) ? 2 : 4;
670 else
671 length += (bits == 16) ? 2 : 4;
672 break;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000673 case 070: case 071: case 072:
674 length += 4; break;
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000675 case 0130: case 0131: case 0132:
676 length += is_sbyte(ins, c-0130, 16) ? 1 : 2; break;
677 case 0133: case 0134: case 0135:
678 codes+=2; length++; break;
679 case 0140: case 0141: case 0142:
680 length += is_sbyte(ins, c-0140, 32) ? 1 : 4; break;
681 case 0143: case 0144: case 0145:
682 codes+=2; length++; break;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000683 case 0300: case 0301: case 0302:
684 length += chsize (&ins->oprs[c-0300], bits);
685 break;
686 case 0310:
687 length += (bits==32);
688 break;
689 case 0311:
690 length += (bits==16);
691 break;
692 case 0312:
693 break;
694 case 0320:
695 length += (bits==32);
696 break;
697 case 0321:
698 length += (bits==16);
699 break;
700 case 0322:
701 break;
702 case 0330:
703 codes++, length++; break;
H. Peter Anvinef7468f2002-04-30 20:57:59 +0000704 case 0331:
705 case 0332:
706 break;
707 case 0333:
708 length++; break;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000709 case 0340: case 0341: case 0342:
710 if (ins->oprs[0].segment != NO_SEG)
711 errfunc (ERR_NONFATAL, "attempt to reserve non-constant"
712 " quantity of BSS space");
713 else
714 length += ins->oprs[0].offset << (c-0340);
715 break;
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000716 case 0370: case 0371: case 0372:
717 break;
718 case 0373:
719 length++; break;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000720 default: /* can't do it by 'case' statements */
721 if (c>=0100 && c<=0277) { /* it's an EA */
722 ea ea_data;
H. Peter Anvinea838272002-04-30 20:51:53 +0000723 if (!process_ea (&ins->oprs[(c>>3)&7], &ea_data, bits, 0,
724 ins->forw_ref)) {
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000725 errfunc (ERR_NONFATAL, "invalid effective address");
726 return -1;
727 } else
728 length += ea_data.size;
729 } else
730 errfunc (ERR_PANIC, "internal instruction table corrupt"
731 ": instruction code 0x%02X given", c);
732 }
733 return length;
734}
735
736static void gencode (long segment, long offset, int bits,
H. Peter Anvinbfebdb02002-09-12 02:23:54 +0000737 insn *ins, const char *codes, long insn_end)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000738{
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000739 static char condval[] = { /* conditional opcodes */
740 0x7, 0x3, 0x2, 0x6, 0x2, 0x4, 0xF, 0xD, 0xC, 0xE, 0x6, 0x2,
741 0x3, 0x7, 0x3, 0x5, 0xE, 0xC, 0xD, 0xF, 0x1, 0xB, 0x9, 0x5,
742 0x0, 0xA, 0xA, 0xB, 0x8, 0x4
743 };
H. Peter Anvineba20a72002-04-30 20:53:55 +0000744 unsigned char c;
745 unsigned char bytes[4];
746 long data, size;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000747
H. Peter Anvineba20a72002-04-30 20:53:55 +0000748 while (*codes)
749 switch (c = *codes++)
750 {
751 case 01: case 02: case 03:
752 out (offset, segment, codes, OUT_RAWDATA+c, NO_SEG, NO_SEG);
753 codes += c;
754 offset += c;
755 break;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000756
H. Peter Anvineba20a72002-04-30 20:53:55 +0000757 case 04: case 06:
758 switch (ins->oprs[0].basereg)
759 {
760 case R_CS:
761 bytes[0] = 0x0E + (c == 0x04 ? 1 : 0); break;
762 case R_DS:
763 bytes[0] = 0x1E + (c == 0x04 ? 1 : 0); break;
764 case R_ES:
765 bytes[0] = 0x06 + (c == 0x04 ? 1 : 0); break;
766 case R_SS:
767 bytes[0] = 0x16 + (c == 0x04 ? 1 : 0); break;
768 default:
H. Peter Anvin4836e332002-04-30 20:56:43 +0000769 errfunc (ERR_PANIC, "bizarre 8086 segment register received");
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000770 }
H. Peter Anvineba20a72002-04-30 20:53:55 +0000771 out (offset, segment, bytes, OUT_RAWDATA+1, NO_SEG, NO_SEG);
772 offset++;
773 break;
774
775 case 05: case 07:
776 switch (ins->oprs[0].basereg) {
777 case R_FS: bytes[0] = 0xA0 + (c == 0x05 ? 1 : 0); break;
778 case R_GS: bytes[0] = 0xA8 + (c == 0x05 ? 1 : 0); break;
779 default:
H. Peter Anvin4836e332002-04-30 20:56:43 +0000780 errfunc (ERR_PANIC, "bizarre 386 segment register received");
H. Peter Anvineba20a72002-04-30 20:53:55 +0000781 }
782 out (offset, segment, bytes, OUT_RAWDATA+1, NO_SEG, NO_SEG);
783 offset++;
784 break;
785
786 case 010: case 011: case 012:
787 bytes[0] = *codes++ + regval(&ins->oprs[c-010]);
788 out (offset, segment, bytes, OUT_RAWDATA+1, NO_SEG, NO_SEG);
789 offset += 1;
790 break;
791
792 case 017:
793 bytes[0] = 0;
794 out (offset, segment, bytes, OUT_RAWDATA+1, NO_SEG, NO_SEG);
795 offset += 1;
796 break;
797
798 case 014: case 015: case 016:
799 if (ins->oprs[c-014].offset < -128
800 || ins->oprs[c-014].offset > 127)
801 {
802 errfunc (ERR_WARNING, "signed byte value exceeds bounds");
803 }
804
805 if (ins->oprs[c-014].segment != NO_SEG)
806 {
807 data = ins->oprs[c-014].offset;
808 out (offset, segment, &data, OUT_ADDRESS+1,
809 ins->oprs[c-014].segment, ins->oprs[c-014].wrt);
810 }
811 else {
812 bytes[0] = ins->oprs[c-014].offset;
813 out (offset, segment, bytes, OUT_RAWDATA+1, NO_SEG, NO_SEG);
814 }
815 offset += 1;
816 break;
817
818 case 020: case 021: case 022:
819 if (ins->oprs[c-020].offset < -256
820 || ins->oprs[c-020].offset > 255)
821 {
822 errfunc (ERR_WARNING, "byte value exceeds bounds");
823 }
824 if (ins->oprs[c-020].segment != NO_SEG) {
825 data = ins->oprs[c-020].offset;
826 out (offset, segment, &data, OUT_ADDRESS+1,
827 ins->oprs[c-020].segment, ins->oprs[c-020].wrt);
828 }
829 else {
830 bytes[0] = ins->oprs[c-020].offset;
831 out (offset, segment, bytes, OUT_RAWDATA+1, NO_SEG, NO_SEG);
832 }
833 offset += 1;
834 break;
835
836 case 024: case 025: case 026:
837 if (ins->oprs[c-024].offset < 0 || ins->oprs[c-024].offset > 255)
838 errfunc (ERR_WARNING, "unsigned byte value exceeds bounds");
839 if (ins->oprs[c-024].segment != NO_SEG) {
840 data = ins->oprs[c-024].offset;
841 out (offset, segment, &data, OUT_ADDRESS+1,
842 ins->oprs[c-024].segment, ins->oprs[c-024].wrt);
843 }
844 else {
845 bytes[0] = ins->oprs[c-024].offset;
846 out (offset, segment, bytes, OUT_RAWDATA+1, NO_SEG, NO_SEG);
847 }
848 offset += 1;
849 break;
850
851 case 030: case 031: case 032:
852 if (ins->oprs[c-030].segment == NO_SEG &&
853 ins->oprs[c-030].wrt == NO_SEG &&
854 (ins->oprs[c-030].offset < -65536L ||
855 ins->oprs[c-030].offset > 65535L))
856 {
857 errfunc (ERR_WARNING, "word value exceeds bounds");
858 }
859 data = ins->oprs[c-030].offset;
860 out (offset, segment, &data, OUT_ADDRESS+2,
861 ins->oprs[c-030].segment, ins->oprs[c-030].wrt);
862 offset += 2;
863 break;
864
865 case 034: case 035: case 036:
H. Peter Anvin3ba46772002-05-27 23:19:35 +0000866 if ( ins->oprs[c-034].type & (BITS16|BITS32) )
867 size = (ins->oprs[c-034].type & BITS16) ? 2 : 4;
868 else
869 size = (bits == 16) ? 2 : 4;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000870 data = ins->oprs[c-034].offset;
H. Peter Anvin4cf17482002-04-30 21:01:38 +0000871 if (size==2 && (data < -65536L || data > 65535L))
H. Peter Anvineba20a72002-04-30 20:53:55 +0000872 errfunc (ERR_WARNING, "word value exceeds bounds");
873 out (offset, segment, &data, OUT_ADDRESS+size,
874 ins->oprs[c-034].segment, ins->oprs[c-034].wrt);
875 offset += size;
876 break;
877
878 case 037:
879 if (ins->oprs[0].segment == NO_SEG)
880 errfunc (ERR_NONFATAL, "value referenced by FAR is not"
881 " relocatable");
882 data = 0L;
883 out (offset, segment, &data, OUT_ADDRESS+2,
884 outfmt->segbase(1+ins->oprs[0].segment),
885 ins->oprs[0].wrt);
886 offset += 2;
887 break;
888
889 case 040: case 041: case 042:
890 data = ins->oprs[c-040].offset;
891 out (offset, segment, &data, OUT_ADDRESS+4,
892 ins->oprs[c-040].segment, ins->oprs[c-040].wrt);
893 offset += 4;
894 break;
895
H. Peter Anvin3ba46772002-05-27 23:19:35 +0000896 case 044: case 045: case 046:
897 data = ins->oprs[c-044].offset;
898 size = ((ins->oprs[c-044].addr_size ?
899 ins->oprs[c-044].addr_size : bits) == 16 ? 2 : 4);
900 if (size==2 && (data < -65536L || data > 65535L))
901 errfunc (ERR_WARNING, "word value exceeds bounds");
902 out (offset, segment, &data, OUT_ADDRESS+size,
903 ins->oprs[c-044].segment, ins->oprs[c-044].wrt);
904 offset += size;
905 break;
906
H. Peter Anvineba20a72002-04-30 20:53:55 +0000907 case 050: case 051: case 052:
908 if (ins->oprs[c-050].segment != segment)
909 errfunc (ERR_NONFATAL, "short relative jump outside segment");
910 data = ins->oprs[c-050].offset - insn_end;
911 if (data > 127 || data < -128)
912 errfunc (ERR_NONFATAL, "short jump is out of range");
913 bytes[0] = data;
914 out (offset, segment, bytes, OUT_RAWDATA+1, NO_SEG, NO_SEG);
915 offset += 1;
916 break;
917
918 case 060: case 061: case 062:
919 if (ins->oprs[c-060].segment != segment) {
920 data = ins->oprs[c-060].offset;
921 out (offset, segment, &data, OUT_REL2ADR+insn_end-offset,
922 ins->oprs[c-060].segment, ins->oprs[c-060].wrt);
923 } else {
924 data = ins->oprs[c-060].offset - insn_end;
925 out (offset, segment, &data,
926 OUT_ADDRESS+2, NO_SEG, NO_SEG);
927 }
928 offset += 2;
929 break;
930
931 case 064: case 065: case 066:
H. Peter Anvin17799b42002-05-21 03:31:21 +0000932 if ( ins->oprs[c-064].type & (BITS16|BITS32) )
933 size = (ins->oprs[c-064].type & BITS16) ? 2 : 4;
934 else
935 size = (bits == 16) ? 2 : 4;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000936 if (ins->oprs[c-064].segment != segment) {
H. Peter Anvin17799b42002-05-21 03:31:21 +0000937 long reltype = (size == 2 ? OUT_REL2ADR : OUT_REL4ADR);
H. Peter Anvineba20a72002-04-30 20:53:55 +0000938 data = ins->oprs[c-064].offset;
H. Peter Anvin17799b42002-05-21 03:31:21 +0000939 out (offset, segment, &data, reltype+insn_end-offset,
H. Peter Anvineba20a72002-04-30 20:53:55 +0000940 ins->oprs[c-064].segment, ins->oprs[c-064].wrt);
H. Peter Anvineba20a72002-04-30 20:53:55 +0000941 } else {
942 data = ins->oprs[c-064].offset - insn_end;
943 out (offset, segment, &data,
944 OUT_ADDRESS+size, NO_SEG, NO_SEG);
945 }
946 offset += size;
947 break;
948
949 case 070: case 071: case 072:
950 if (ins->oprs[c-070].segment != segment) {
951 data = ins->oprs[c-070].offset;
952 out (offset, segment, &data, OUT_REL4ADR+insn_end-offset,
953 ins->oprs[c-070].segment, ins->oprs[c-070].wrt);
954 } else {
955 data = ins->oprs[c-070].offset - insn_end;
956 out (offset, segment, &data,
957 OUT_ADDRESS+4, NO_SEG, NO_SEG);
958 }
959 offset += 4;
960 break;
961
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000962 case 0130: case 0131: case 0132:
963 data = ins->oprs[c-0130].offset;
964 if (is_sbyte(ins, c-0130, 16)) {
H. Peter Anvin0bfed6c2002-11-10 06:29:23 +0000965 bytes[0] = data;
966 out (offset, segment, bytes, OUT_RAWDATA+1, NO_SEG, NO_SEG);
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000967 offset++;
968 } else {
969 if (ins->oprs[c-0130].segment == NO_SEG &&
970 ins->oprs[c-0130].wrt == NO_SEG &&
971 (data < -65536L || data > 65535L)) {
972 errfunc (ERR_WARNING, "word value exceeds bounds");
973 }
974 out (offset, segment, &data, OUT_ADDRESS+2,
975 ins->oprs[c-0130].segment, ins->oprs[c-0130].wrt);
976 offset += 2;
977 }
978 break;
979
980 case 0133: case 0134: case 0135:
981 codes++;
982 bytes[0] = *codes++;
983 if (is_sbyte(ins, c-0133, 16)) bytes[0] |= 2; /* s-bit */
984 out (offset, segment, bytes, OUT_RAWDATA+1, NO_SEG, NO_SEG);
985 offset++;
986 break;
987
988 case 0140: case 0141: case 0142:
989 data = ins->oprs[c-0140].offset;
990 if (is_sbyte(ins, c-0140, 32)) {
H. Peter Anvin0bfed6c2002-11-10 06:29:23 +0000991 bytes[0] = data;
992 out (offset, segment, bytes, OUT_RAWDATA+1, NO_SEG, NO_SEG);
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000993 offset++;
994 } else {
995 out (offset, segment, &data, OUT_ADDRESS+4,
996 ins->oprs[c-0140].segment, ins->oprs[c-0140].wrt);
997 offset += 4;
998 }
999 break;
1000
1001 case 0143: case 0144: case 0145:
1002 codes++;
1003 bytes[0] = *codes++;
1004 if (is_sbyte(ins, c-0143, 32)) bytes[0] |= 2; /* s-bit */
1005 out (offset, segment, bytes, OUT_RAWDATA+1, NO_SEG, NO_SEG);
1006 offset++;
1007 break;
1008
H. Peter Anvineba20a72002-04-30 20:53:55 +00001009 case 0300: case 0301: case 0302:
1010 if (chsize (&ins->oprs[c-0300], bits)) {
1011 *bytes = 0x67;
1012 out (offset, segment, bytes,
1013 OUT_RAWDATA+1, NO_SEG, NO_SEG);
1014 offset += 1;
1015 } else
1016 offset += 0;
1017 break;
1018
1019 case 0310:
1020 if (bits==32) {
1021 *bytes = 0x67;
1022 out (offset, segment, bytes,
1023 OUT_RAWDATA+1, NO_SEG, NO_SEG);
1024 offset += 1;
1025 } else
1026 offset += 0;
1027 break;
1028
1029 case 0311:
1030 if (bits==16) {
1031 *bytes = 0x67;
1032 out (offset, segment, bytes,
1033 OUT_RAWDATA+1, NO_SEG, NO_SEG);
1034 offset += 1;
1035 } else
1036 offset += 0;
1037 break;
1038
1039 case 0312:
1040 break;
1041
1042 case 0320:
1043 if (bits==32) {
1044 *bytes = 0x66;
1045 out (offset, segment, bytes,
1046 OUT_RAWDATA+1, NO_SEG, NO_SEG);
1047 offset += 1;
1048 } else
1049 offset += 0;
1050 break;
1051
1052 case 0321:
1053 if (bits==16) {
1054 *bytes = 0x66;
1055 out (offset, segment, bytes,
1056 OUT_RAWDATA+1, NO_SEG, NO_SEG);
1057 offset += 1;
1058 } else
1059 offset += 0;
1060 break;
1061
1062 case 0322:
1063 break;
1064
1065 case 0330:
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001066 *bytes = *codes++ ^ condval[ins->condition];
H. Peter Anvineba20a72002-04-30 20:53:55 +00001067 out (offset, segment, bytes,
1068 OUT_RAWDATA+1, NO_SEG, NO_SEG);
1069 offset += 1;
1070 break;
1071
H. Peter Anvinef7468f2002-04-30 20:57:59 +00001072 case 0331:
1073 case 0332:
1074 break;
1075
1076 case 0333:
1077 *bytes = 0xF3;
1078 out (offset, segment, bytes,
1079 OUT_RAWDATA+1, NO_SEG, NO_SEG);
1080 offset += 1;
1081 break;
1082
H. Peter Anvineba20a72002-04-30 20:53:55 +00001083 case 0340: case 0341: case 0342:
1084 if (ins->oprs[0].segment != NO_SEG)
1085 errfunc (ERR_PANIC, "non-constant BSS size in pass two");
1086 else {
1087 long size = ins->oprs[0].offset << (c-0340);
1088 if (size > 0)
1089 out (offset, segment, NULL,
1090 OUT_RESERVE+size, NO_SEG, NO_SEG);
1091 offset += size;
1092 }
1093 break;
1094
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001095 case 0370: case 0371: case 0372:
1096 break;
1097
1098 case 0373:
1099 *bytes = bits==16 ? 3 : 5;
1100 out (offset, segment, bytes,
1101 OUT_RAWDATA+1, NO_SEG, NO_SEG);
1102 offset += 1;
1103 break;
1104
H. Peter Anvineba20a72002-04-30 20:53:55 +00001105 default: /* can't do it by 'case' statements */
1106 if (c>=0100 && c<=0277) { /* it's an EA */
1107 ea ea_data;
1108 int rfield;
1109 unsigned char *p;
1110 long s;
1111
1112 if (c<=0177) /* pick rfield from operand b */
1113 rfield = regval (&ins->oprs[c&7]);
1114 else /* rfield is constant */
1115 rfield = c & 7;
1116
1117 if (!process_ea (&ins->oprs[(c>>3)&7], &ea_data, bits, rfield,
1118 ins->forw_ref))
1119 {
1120 errfunc (ERR_NONFATAL, "invalid effective address");
1121 }
1122
1123 p = bytes;
1124 *p++ = ea_data.modrm;
1125 if (ea_data.sib_present)
1126 *p++ = ea_data.sib;
1127
1128 s = p-bytes;
1129 out (offset, segment, bytes, OUT_RAWDATA + s,
1130 NO_SEG, NO_SEG);
1131
1132 switch (ea_data.bytes) {
1133 case 0:
1134 break;
1135 case 1:
1136 if (ins->oprs[(c>>3)&7].segment != NO_SEG) {
1137 data = ins->oprs[(c>>3)&7].offset;
1138 out (offset, segment, &data, OUT_ADDRESS+1,
1139 ins->oprs[(c>>3)&7].segment,
1140 ins->oprs[(c>>3)&7].wrt);
1141 } else {
1142 *bytes = ins->oprs[(c>>3)&7].offset;
1143 out (offset, segment, bytes, OUT_RAWDATA+1,
1144 NO_SEG, NO_SEG);
1145 }
1146 s++;
1147 break;
1148 case 2:
1149 case 4:
1150 data = ins->oprs[(c>>3)&7].offset;
1151 out (offset, segment, &data,
1152 OUT_ADDRESS+ea_data.bytes,
1153 ins->oprs[(c>>3)&7].segment, ins->oprs[(c>>3)&7].wrt);
1154 s += ea_data.bytes;
1155 break;
1156 }
1157 offset += s;
1158 } else
1159 errfunc (ERR_PANIC, "internal instruction table corrupt"
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001160 ": instruction code 0x%02X given", c);
H. Peter Anvineba20a72002-04-30 20:53:55 +00001161 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001162}
1163
H. Peter Anvin232badb2002-06-06 02:41:20 +00001164#include "regvals.c"
1165
H. Peter Anvineba20a72002-04-30 20:53:55 +00001166static int regval (operand *o)
1167{
H. Peter Anvin232badb2002-06-06 02:41:20 +00001168 if ( o->basereg < EXPR_REG_START || o->basereg >= REG_ENUM_LIMIT ) {
1169 errfunc (ERR_PANIC, "invalid operand passed to regval()");
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001170 }
H. Peter Anvin232badb2002-06-06 02:41:20 +00001171 return regvals[o->basereg];
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001172}
1173
H. Peter Anvineba20a72002-04-30 20:53:55 +00001174static int matches (struct itemplate *itemp, insn *instruction)
1175{
H. Peter Anvinef7468f2002-04-30 20:57:59 +00001176 int i, size[3], asize, oprs, ret;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001177
1178 ret = 100;
1179
1180 /*
1181 * Check the opcode
1182 */
1183 if (itemp->opcode != instruction->opcode) return 0;
1184
1185 /*
1186 * Count the operands
1187 */
1188 if (itemp->operands != instruction->operands) return 0;
1189
1190 /*
1191 * Check that no spurious colons or TOs are present
1192 */
1193 for (i=0; i<itemp->operands; i++)
1194 if (instruction->oprs[i].type & ~itemp->opd[i] & (COLON|TO))
1195 return 0;
1196
1197 /*
1198 * Check that the operand flags all match up
1199 */
1200 for (i=0; i<itemp->operands; i++)
1201 if (itemp->opd[i] & ~instruction->oprs[i].type ||
1202 ((itemp->opd[i] & SIZE_MASK) &&
H. Peter Anvineba20a72002-04-30 20:53:55 +00001203 ((itemp->opd[i] ^ instruction->oprs[i].type) & SIZE_MASK)))
1204 {
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001205 if ((itemp->opd[i] & ~instruction->oprs[i].type & NON_SIZE) ||
1206 (instruction->oprs[i].type & SIZE_MASK))
1207 return 0;
1208 else
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001209/* ret = 1; */
1210 return 1;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001211 }
1212
1213 /*
1214 * Check operand sizes
1215 */
H. Peter Anvinef7468f2002-04-30 20:57:59 +00001216 if (itemp->flags & IF_ARMASK) {
1217 size[0] = size[1] = size[2] = 0;
1218
1219 switch (itemp->flags & IF_ARMASK) {
1220 case IF_AR0: i = 0; break;
1221 case IF_AR1: i = 1; break;
1222 case IF_AR2: i = 2; break;
1223 default: break; /* Shouldn't happen */
1224 }
1225 if (itemp->flags & IF_SB) {
1226 size[i] = BITS8;
1227 } else if (itemp->flags & IF_SW) {
1228 size[i] = BITS16;
1229 } else if (itemp->flags & IF_SD) {
1230 size[i] = BITS32;
1231 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001232 } else {
H. Peter Anvinef7468f2002-04-30 20:57:59 +00001233 asize = 0;
1234 if (itemp->flags & IF_SB) {
1235 asize = BITS8;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001236 oprs = itemp->operands;
H. Peter Anvinef7468f2002-04-30 20:57:59 +00001237 } else if (itemp->flags & IF_SW) {
1238 asize = BITS16;
1239 oprs = itemp->operands;
1240 } else if (itemp->flags & IF_SD) {
1241 asize = BITS32;
1242 oprs = itemp->operands;
1243 }
1244 size[0] = size[1] = size[2] = asize;
1245 }
1246
1247 if (itemp->flags & (IF_SM | IF_SM2)) {
1248 oprs = (itemp->flags & IF_SM2 ? 2 : itemp->operands);
1249 asize = 0;
1250 for (i=0; i<oprs; i++) {
1251 if ( (asize = itemp->opd[i] & SIZE_MASK) != 0) {
1252 int j;
1253 for (j=0; j<oprs; j++)
1254 size[j] = asize;
1255 break;
1256 }
1257 }
1258 } else {
1259 oprs = itemp->operands;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001260 }
1261
1262 for (i=0; i<itemp->operands; i++)
1263 if (!(itemp->opd[i] & SIZE_MASK) &&
H. Peter Anvinef7468f2002-04-30 20:57:59 +00001264 (instruction->oprs[i].type & SIZE_MASK & ~size[i]))
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001265/* ret = 2; */
1266 return 2;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001267
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001268 /*
1269 * Check template is okay at the set cpu level
1270 */
1271 if ((itemp->flags & IF_PLEVEL) > cpu) return 3;
1272
1273 /*
1274 * Check if special handling needed for Jumps
1275 */
1276 if ((unsigned char)(itemp->code[0]) >= 0370) return 99;
1277
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001278 return ret;
1279}
1280
H. Peter Anvinea838272002-04-30 20:51:53 +00001281static ea *process_ea (operand *input, ea *output, int addrbits, int rfield,
H. Peter Anvineba20a72002-04-30 20:53:55 +00001282 int forw_ref)
1283{
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001284 if (!(REGISTER & ~input->type)) { /* it's a single register */
1285 static int regs[] = {
H. Peter Anvin4836e332002-04-30 20:56:43 +00001286 R_AL, R_CL, R_DL, R_BL, R_AH, R_CH, R_DH, R_BH,
1287 R_AX, R_CX, R_DX, R_BX, R_SP, R_BP, R_SI, R_DI,
1288 R_EAX, R_ECX, R_EDX, R_EBX, R_ESP, R_EBP, R_ESI, R_EDI,
1289 R_MM0, R_MM1, R_MM2, R_MM3, R_MM4, R_MM5, R_MM6, R_MM7,
1290 R_XMM0, R_XMM1, R_XMM2, R_XMM3, R_XMM4, R_XMM5, R_XMM6, R_XMM7
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001291 };
1292 int i;
1293
1294 for (i=0; i<elements(regs); i++)
1295 if (input->basereg == regs[i]) break;
1296 if (i<elements(regs)) {
1297 output->sib_present = FALSE;/* no SIB necessary */
1298 output->bytes = 0; /* no offset necessary either */
H. Peter Anvin4836e332002-04-30 20:56:43 +00001299 output->modrm = 0xC0 | (rfield << 3) | (i & 7);
H. Peter Anvineba20a72002-04-30 20:53:55 +00001300 }
1301 else
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001302 return NULL;
1303 } else { /* it's a memory reference */
1304 if (input->basereg==-1 && (input->indexreg==-1 || input->scale==0)) {
1305 /* it's a pure offset */
1306 if (input->addr_size)
1307 addrbits = input->addr_size;
1308 output->sib_present = FALSE;
1309 output->bytes = (addrbits==32 ? 4 : 2);
1310 output->modrm = (addrbits==32 ? 5 : 6) | (rfield << 3);
H. Peter Anvineba20a72002-04-30 20:53:55 +00001311 }
1312 else { /* it's an indirection */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001313 int i=input->indexreg, b=input->basereg, s=input->scale;
1314 long o=input->offset, seg=input->segment;
H. Peter Anvin76690a12002-04-30 20:52:49 +00001315 int hb=input->hintbase, ht=input->hinttype;
1316 int t;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001317
1318 if (s==0) i = -1; /* make this easy, at least */
1319
1320 if (i==R_EAX || i==R_EBX || i==R_ECX || i==R_EDX
1321 || i==R_EBP || i==R_ESP || i==R_ESI || i==R_EDI
1322 || b==R_EAX || b==R_EBX || b==R_ECX || b==R_EDX
1323 || b==R_EBP || b==R_ESP || b==R_ESI || b==R_EDI) {
1324 /* it must be a 32-bit memory reference. Firstly we have
1325 * to check that all registers involved are type Exx. */
1326 if (i!=-1 && i!=R_EAX && i!=R_EBX && i!=R_ECX && i!=R_EDX
1327 && i!=R_EBP && i!=R_ESP && i!=R_ESI && i!=R_EDI)
1328 return NULL;
1329 if (b!=-1 && b!=R_EAX && b!=R_EBX && b!=R_ECX && b!=R_EDX
1330 && b!=R_EBP && b!=R_ESP && b!=R_ESI && b!=R_EDI)
1331 return NULL;
1332
1333 /* While we're here, ensure the user didn't specify WORD. */
1334 if (input->addr_size == 16)
1335 return NULL;
1336
1337 /* now reorganise base/index */
H. Peter Anvin76690a12002-04-30 20:52:49 +00001338 if (s == 1 && b != i && b != -1 && i != -1 &&
1339 ((hb==b&&ht==EAH_NOTBASE) || (hb==i&&ht==EAH_MAKEBASE)))
1340 t = b, b = i, i = t; /* swap if hints say so */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001341 if (b==i) /* convert EAX+2*EAX to 3*EAX */
1342 b = -1, s++;
H. Peter Anvin76690a12002-04-30 20:52:49 +00001343 if (b==-1 && s==1 && !(hb == i && ht == EAH_NOTBASE))
1344 b = i, i = -1; /* make single reg base, unless hint */
1345 if (((s==2 && i!=R_ESP && !(input->eaflags & EAF_TIMESTWO)) ||
1346 s==3 || s==5 || s==9) && b==-1)
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001347 b = i, s--; /* convert 3*EAX to EAX+2*EAX */
Debbie Wiles0f65f882002-06-08 19:30:14 +00001348 if (i==-1 && b!=R_ESP && (input->eaflags & EAF_TIMESTWO))
1349 i = b, b = -1, s = 1;
1350 /* convert [NOSPLIT EAX] to sib format with 0x0 displacement */
H. Peter Anvinea838272002-04-30 20:51:53 +00001351 if (s==1 && i==R_ESP) /* swap ESP into base if scale is 1 */
1352 i = b, b = R_ESP;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001353 if (i==R_ESP || (s!=1 && s!=2 && s!=4 && s!=8 && i!=-1))
1354 return NULL; /* wrong, for various reasons */
1355
1356 if (i==-1 && b!=R_ESP) {/* no SIB needed */
1357 int mod, rm;
1358 switch(b) {
1359 case R_EAX: rm = 0; break;
1360 case R_ECX: rm = 1; break;
1361 case R_EDX: rm = 2; break;
1362 case R_EBX: rm = 3; break;
1363 case R_EBP: rm = 5; break;
1364 case R_ESI: rm = 6; break;
1365 case R_EDI: rm = 7; break;
1366 case -1: rm = 5; break;
1367 default: /* should never happen */
1368 return NULL;
1369 }
H. Peter Anvinea838272002-04-30 20:51:53 +00001370 if (b==-1 || (b!=R_EBP && o==0 &&
H. Peter Anvin76690a12002-04-30 20:52:49 +00001371 seg==NO_SEG && !forw_ref &&
1372 !(input->eaflags &
1373 (EAF_BYTEOFFS|EAF_WORDOFFS))))
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001374 mod = 0;
H. Peter Anvin76690a12002-04-30 20:52:49 +00001375 else if (input->eaflags & EAF_BYTEOFFS ||
1376 (o>=-128 && o<=127 && seg==NO_SEG && !forw_ref &&
1377 !(input->eaflags & EAF_WORDOFFS))) {
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001378 mod = 1;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001379 }
1380 else
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001381 mod = 2;
H. Peter Anvinea838272002-04-30 20:51:53 +00001382
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001383 output->sib_present = FALSE;
1384 output->bytes = (b==-1 || mod==2 ? 4 : mod);
1385 output->modrm = (mod<<6) | (rfield<<3) | rm;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001386 }
1387 else { /* we need a SIB */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001388 int mod, scale, index, base;
1389
1390 switch (b) {
1391 case R_EAX: base = 0; break;
1392 case R_ECX: base = 1; break;
1393 case R_EDX: base = 2; break;
1394 case R_EBX: base = 3; break;
1395 case R_ESP: base = 4; break;
1396 case R_EBP: case -1: base = 5; break;
1397 case R_ESI: base = 6; break;
1398 case R_EDI: base = 7; break;
1399 default: /* then what the smeg is it? */
1400 return NULL; /* panic */
1401 }
1402
1403 switch (i) {
1404 case R_EAX: index = 0; break;
1405 case R_ECX: index = 1; break;
1406 case R_EDX: index = 2; break;
1407 case R_EBX: index = 3; break;
1408 case -1: index = 4; break;
1409 case R_EBP: index = 5; break;
1410 case R_ESI: index = 6; break;
1411 case R_EDI: index = 7; break;
1412 default: /* then what the smeg is it? */
1413 return NULL; /* panic */
1414 }
1415
1416 if (i==-1) s = 1;
1417 switch (s) {
1418 case 1: scale = 0; break;
1419 case 2: scale = 1; break;
1420 case 4: scale = 2; break;
1421 case 8: scale = 3; break;
1422 default: /* then what the smeg is it? */
1423 return NULL; /* panic */
1424 }
1425
H. Peter Anvinea838272002-04-30 20:51:53 +00001426 if (b==-1 || (b!=R_EBP && o==0 &&
H. Peter Anvin76690a12002-04-30 20:52:49 +00001427 seg==NO_SEG && !forw_ref &&
1428 !(input->eaflags &
1429 (EAF_BYTEOFFS|EAF_WORDOFFS))))
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001430 mod = 0;
H. Peter Anvin76690a12002-04-30 20:52:49 +00001431 else if (input->eaflags & EAF_BYTEOFFS ||
1432 (o>=-128 && o<=127 && seg==NO_SEG && !forw_ref &&
1433 !(input->eaflags & EAF_WORDOFFS)))
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001434 mod = 1;
1435 else
1436 mod = 2;
1437
1438 output->sib_present = TRUE;
1439 output->bytes = (b==-1 || mod==2 ? 4 : mod);
1440 output->modrm = (mod<<6) | (rfield<<3) | 4;
1441 output->sib = (scale<<6) | (index<<3) | base;
1442 }
H. Peter Anvineba20a72002-04-30 20:53:55 +00001443 }
1444 else { /* it's 16-bit */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001445 int mod, rm;
1446
1447 /* check all registers are BX, BP, SI or DI */
1448 if ((b!=-1 && b!=R_BP && b!=R_BX && b!=R_SI && b!=R_DI) ||
1449 (i!=-1 && i!=R_BP && i!=R_BX && i!=R_SI && i!=R_DI))
1450 return NULL;
1451
1452 /* ensure the user didn't specify DWORD */
1453 if (input->addr_size == 32)
1454 return NULL;
1455
1456 if (s!=1 && i!=-1) return NULL;/* no can do, in 16-bit EA */
H. Peter Anvin87e1fcd2002-05-11 04:01:26 +00001457 if (b==-1 && i!=-1) { int tmp = b; b = i; i = tmp; } /* swap */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001458 if ((b==R_SI || b==R_DI) && i!=-1)
H. Peter Anvin87e1fcd2002-05-11 04:01:26 +00001459 { int tmp = b; b = i; i = tmp; }
1460 /* have BX/BP as base, SI/DI index */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001461 if (b==i) return NULL;/* shouldn't ever happen, in theory */
1462 if (i!=-1 && b!=-1 &&
1463 (i==R_BP || i==R_BX || b==R_SI || b==R_DI))
1464 return NULL; /* invalid combinations */
H. Peter Anvin87e1fcd2002-05-11 04:01:26 +00001465 if (b==-1) /* pure offset: handled above */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001466 return NULL; /* so if it gets to here, panic! */
1467
1468 rm = -1;
1469 if (i!=-1)
1470 switch (i*256 + b) {
1471 case R_SI*256+R_BX: rm=0; break;
1472 case R_DI*256+R_BX: rm=1; break;
1473 case R_SI*256+R_BP: rm=2; break;
1474 case R_DI*256+R_BP: rm=3; break;
1475 }
1476 else
1477 switch (b) {
1478 case R_SI: rm=4; break;
1479 case R_DI: rm=5; break;
1480 case R_BP: rm=6; break;
1481 case R_BX: rm=7; break;
1482 }
1483 if (rm==-1) /* can't happen, in theory */
1484 return NULL; /* so panic if it does */
1485
H. Peter Anvin76690a12002-04-30 20:52:49 +00001486 if (o==0 && seg==NO_SEG && !forw_ref && rm!=6 &&
1487 !(input->eaflags & (EAF_BYTEOFFS|EAF_WORDOFFS)))
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001488 mod = 0;
H. Peter Anvin76690a12002-04-30 20:52:49 +00001489 else if (input->eaflags & EAF_BYTEOFFS ||
1490 (o>=-128 && o<=127 && seg==NO_SEG && !forw_ref &&
1491 !(input->eaflags & EAF_WORDOFFS)))
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001492 mod = 1;
1493 else
1494 mod = 2;
1495
1496 output->sib_present = FALSE; /* no SIB - it's 16-bit */
1497 output->bytes = mod; /* bytes of offset needed */
1498 output->modrm = (mod<<6) | (rfield<<3) | rm;
1499 }
1500 }
1501 }
1502 output->size = 1 + output->sib_present + output->bytes;
1503 return output;
1504}
1505
H. Peter Anvineba20a72002-04-30 20:53:55 +00001506static int chsize (operand *input, int addrbits)
1507{
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001508 if (!(MEMORY & ~input->type)) {
1509 int i=input->indexreg, b=input->basereg;
1510
1511 if (input->scale==0) i = -1;
1512
1513 if (i == -1 && b == -1) /* pure offset */
1514 return (input->addr_size != 0 && input->addr_size != addrbits);
1515
1516 if (i==R_EAX || i==R_EBX || i==R_ECX || i==R_EDX
1517 || i==R_EBP || i==R_ESP || i==R_ESI || i==R_EDI
1518 || b==R_EAX || b==R_EBX || b==R_ECX || b==R_EDX
1519 || b==R_EBP || b==R_ESP || b==R_ESI || b==R_EDI)
1520 return (addrbits==16);
1521 else
1522 return (addrbits==32);
H. Peter Anvineba20a72002-04-30 20:53:55 +00001523 }
1524 else
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001525 return 0;
1526}