blob: 5cfc9457316f1d52b3c502abf360b87bf3d360a2 [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 Anvin9eb185b2002-04-30 21:02:47 +0000158 if (lnfname) nasm_free(lnfname);
H. Peter Anvince616072002-04-30 21:02:23 +0000159 }
H. Peter Anvineba20a72002-04-30 20:53:55 +0000160
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000161 outfmt->output (segto, data, type, segment, wrt);
162}
163
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000164static int jmp_match (long segment, long offset, int bits,
H. Peter Anvinbfebdb02002-09-12 02:23:54 +0000165 insn *ins, const char *code)
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000166{ long isize;
167 unsigned char c = code[0];
168
169
H. Peter Anvin788e6c12002-04-30 21:02:01 +0000170 if (c != 0370 && c != 0371) return 0;
171 if (ins->oprs[0].opflags & OPFLAG_FORWARD) {
H. Peter Anvin01377d82002-05-21 03:16:33 +0000172 if ((optimizing<0 || (ins->oprs[0].type & STRICT))
173 && c==0370) return 1;
H. Peter Anvin788e6c12002-04-30 21:02:01 +0000174 else return (pass0==0); /* match a forward reference */
175 }
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000176 isize = calcsize (segment, offset, bits, ins, code);
177 if (ins->oprs[0].segment != segment) return 0;
178 isize = ins->oprs[0].offset - offset - isize; /* isize is now the delta */
179 if (isize >= -128L && isize <= 127L) return 1; /* it is byte size */
180
181 return 0;
182}
183
184
185long assemble (long segment, long offset, int bits, unsigned long cp,
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000186 insn *instruction, struct ofmt *output, efunc error,
H. Peter Anvineba20a72002-04-30 20:53:55 +0000187 ListGen *listgen)
188{
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000189 struct itemplate *temp;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000190 int j;
191 int size_prob;
192 long insn_end;
193 long itimes;
194 long start = offset;
195 long wsize = 0; /* size for DB etc. */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000196
197 errfunc = error; /* to pass to other functions */
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000198 cpu = cp;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000199 outfmt = output; /* likewise */
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000200 list = listgen; /* and again */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000201
H. Peter Anvineba20a72002-04-30 20:53:55 +0000202 switch (instruction->opcode)
203 {
204 case -1: return 0;
205 case I_DB: wsize = 1; break;
206 case I_DW: wsize = 2; break;
207 case I_DD: wsize = 4; break;
208 case I_DQ: wsize = 8; break;
209 case I_DT: wsize = 10; break;
210 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000211
H. Peter Anvineba20a72002-04-30 20:53:55 +0000212 if (wsize) {
213 extop * e;
214 long t = instruction->times;
215 if (t < 0)
216 errfunc(ERR_PANIC, "instruction->times < 0 (%ld) in assemble()",t);
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000217
H. Peter Anvineba20a72002-04-30 20:53:55 +0000218 while (t--) /* repeat TIMES times */
219 {
220 for (e = instruction->eops; e; e = e->next)
221 {
222 if (e->type == EOT_DB_NUMBER)
223 {
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000224 if (wsize == 1) {
225 if (e->segment != NO_SEG)
226 errfunc (ERR_NONFATAL,
227 "one-byte relocation attempted");
228 else {
H. Peter Anvin41bf8002002-04-30 20:58:18 +0000229 unsigned char out_byte = e->offset;
230 out (offset, segment, &out_byte, OUT_RAWDATA+1,
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000231 NO_SEG, NO_SEG);
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000232 }
H. Peter Anvineba20a72002-04-30 20:53:55 +0000233 }
234 else if (wsize > 5) {
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000235 errfunc (ERR_NONFATAL, "integer supplied to a D%c"
236 " instruction", wsize==8 ? 'Q' : 'T');
H. Peter Anvineba20a72002-04-30 20:53:55 +0000237 }
238 else
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000239 out (offset, segment, &e->offset,
240 OUT_ADDRESS+wsize, e->segment,
241 e->wrt);
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000242 offset += wsize;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000243 }
244 else if (e->type == EOT_DB_STRING)
245 {
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000246 int align;
247
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000248 out (offset, segment, e->stringval,
249 OUT_RAWDATA+e->stringlen, NO_SEG, NO_SEG);
H. Peter Anvineba20a72002-04-30 20:53:55 +0000250 align = e->stringlen % wsize;
251
252 if (align) {
253 align = wsize - align;
254 out (offset, segment, "\0\0\0\0\0\0\0\0",
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000255 OUT_RAWDATA+align, NO_SEG, NO_SEG);
H. Peter Anvineba20a72002-04-30 20:53:55 +0000256 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000257 offset += e->stringlen + align;
258 }
259 }
H. Peter Anvineba20a72002-04-30 20:53:55 +0000260 if (t > 0 && t == instruction->times-1)
261 {
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000262 /*
263 * Dummy call to list->output to give the offset to the
264 * listing module.
265 */
266 list->output (offset, NULL, OUT_RAWDATA);
267 list->uplevel (LIST_TIMES);
268 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000269 }
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000270 if (instruction->times > 1)
271 list->downlevel (LIST_TIMES);
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000272 return offset - start;
273 }
274
H. Peter Anvineba20a72002-04-30 20:53:55 +0000275 if (instruction->opcode == I_INCBIN)
276 {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000277 static char fname[FILENAME_MAX];
H. Peter Anvineba20a72002-04-30 20:53:55 +0000278 FILE * fp;
279 long len;
Frank Kotlerd0ed6fd2003-08-27 11:33:56 +0000280 char *prefix = "", *combine;
281 char** pPrevPath = NULL;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000282
283 len = FILENAME_MAX-1;
284 if (len > instruction->eops->stringlen)
285 len = instruction->eops->stringlen;
286 strncpy (fname, instruction->eops->stringval, len);
287 fname[len] = '\0';
H. Peter Anvineba20a72002-04-30 20:53:55 +0000288
Frank Kotlerd0ed6fd2003-08-27 11:33:56 +0000289 while (1) /* added by alexfru: 'incbin' uses include paths */
290 {
291 combine = nasm_malloc(strlen(prefix) + len + 1);
292 strcpy(combine, prefix);
293 strcat(combine, fname);
294
295 if ( (fp = fopen(combine, "rb")) != NULL)
296 {
297 nasm_free(combine);
298 break;
299 }
300
301 nasm_free(combine);
302 pPrevPath = pp_get_include_path_ptr (pPrevPath);
303 if (pPrevPath == NULL)
304 break;
305 prefix = *pPrevPath;
306 }
307
308 if (fp == NULL)
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000309 error (ERR_NONFATAL, "`incbin': unable to open file `%s'", fname);
310 else if (fseek(fp, 0L, SEEK_END) < 0)
311 error (ERR_NONFATAL, "`incbin': unable to seek on file `%s'",
312 fname);
H. Peter Anvineba20a72002-04-30 20:53:55 +0000313 else
314 {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000315 static char buf[2048];
316 long t = instruction->times;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000317 long base = 0;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000318
319 len = ftell (fp);
320 if (instruction->eops->next) {
H. Peter Anvineba20a72002-04-30 20:53:55 +0000321 base = instruction->eops->next->offset;
322 len -= base;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000323 if (instruction->eops->next->next &&
324 len > instruction->eops->next->next->offset)
325 len = instruction->eops->next->next->offset;
326 }
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000327 /*
328 * Dummy call to list->output to give the offset to the
329 * listing module.
330 */
331 list->output (offset, NULL, OUT_RAWDATA);
332 list->uplevel(LIST_INCBIN);
H. Peter Anvineba20a72002-04-30 20:53:55 +0000333 while (t--)
334 {
335 long l;
336
337 fseek (fp, base, SEEK_SET);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000338 l = len;
339 while (l > 0) {
340 long m = fread (buf, 1, (l>sizeof(buf)?sizeof(buf):l),
341 fp);
342 if (!m) {
343 /*
344 * This shouldn't happen unless the file
345 * actually changes while we are reading
346 * it.
347 */
348 error (ERR_NONFATAL, "`incbin': unexpected EOF while"
349 " reading file `%s'", fname);
H. Peter Anvineba20a72002-04-30 20:53:55 +0000350 t=0; /* Try to exit cleanly */
351 break;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000352 }
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000353 out (offset, segment, buf, OUT_RAWDATA+m,
354 NO_SEG, NO_SEG);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000355 l -= m;
356 }
357 }
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000358 list->downlevel(LIST_INCBIN);
359 if (instruction->times > 1) {
360 /*
361 * Dummy call to list->output to give the offset to the
362 * listing module.
363 */
364 list->output (offset, NULL, OUT_RAWDATA);
365 list->uplevel(LIST_TIMES);
366 list->downlevel(LIST_TIMES);
367 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000368 fclose (fp);
369 return instruction->times * len;
370 }
371 return 0; /* if we're here, there's an error */
372 }
373
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000374 size_prob = FALSE;
375 temp = nasm_instructions[instruction->opcode];
376 while (temp->opcode != -1) {
377 int m = matches (temp, instruction);
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000378 if (m == 99)
379 m += jmp_match(segment, offset, bits, instruction, temp->code);
H. Peter Anvineba20a72002-04-30 20:53:55 +0000380
381 if (m == 100) /* matches! */
382 {
H. Peter Anvinbfebdb02002-09-12 02:23:54 +0000383 const char *codes = temp->code;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000384 long insn_size = calcsize(segment, offset, bits,
385 instruction, codes);
386 itimes = instruction->times;
387 if (insn_size < 0) /* shouldn't be, on pass two */
388 error (ERR_PANIC, "errors made it through from pass one");
389 else while (itimes--) {
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000390 for (j=0; j<instruction->nprefix; j++) {
H. Peter Anvineba20a72002-04-30 20:53:55 +0000391 unsigned char c=0;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000392 switch (instruction->prefixes[j]) {
393 case P_LOCK:
394 c = 0xF0; break;
395 case P_REPNE: case P_REPNZ:
396 c = 0xF2; break;
397 case P_REPE: case P_REPZ: case P_REP:
398 c = 0xF3; break;
399 case R_CS: c = 0x2E; break;
400 case R_DS: c = 0x3E; break;
401 case R_ES: c = 0x26; break;
402 case R_FS: c = 0x64; break;
403 case R_GS: c = 0x65; break;
404 case R_SS: c = 0x36; break;
H. Peter Anvin232badb2002-06-06 02:41:20 +0000405 case R_SEGR6:
406 case R_SEGR7:
407 error (ERR_NONFATAL, "segr6 and segr7 cannot be used as prefixes");
408 break;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000409 case P_A16:
H. Peter Anvineba20a72002-04-30 20:53:55 +0000410 if (bits != 16)
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000411 c = 0x67;
412 break;
413 case P_A32:
H. Peter Anvineba20a72002-04-30 20:53:55 +0000414 if (bits != 32)
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000415 c = 0x67;
416 break;
417 case P_O16:
H. Peter Anvineba20a72002-04-30 20:53:55 +0000418 if (bits != 16)
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000419 c = 0x66;
420 break;
421 case P_O32:
H. Peter Anvineba20a72002-04-30 20:53:55 +0000422 if (bits != 32)
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000423 c = 0x66;
424 break;
425 default:
426 error (ERR_PANIC,
427 "invalid instruction prefix");
428 }
H. Peter Anvineba20a72002-04-30 20:53:55 +0000429 if (c != 0) {
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000430 out (offset, segment, &c, OUT_RAWDATA+1,
431 NO_SEG, NO_SEG);
H. Peter Anvineba20a72002-04-30 20:53:55 +0000432 offset++;
433 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000434 }
H. Peter Anvin3198bee2003-07-16 19:53:51 +0000435 insn_end = offset + insn_size;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000436 gencode (segment, offset, bits, instruction, codes, insn_end);
437 offset += insn_size;
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000438 if (itimes > 0 && itimes == instruction->times-1) {
439 /*
440 * Dummy call to list->output to give the offset to the
441 * listing module.
442 */
443 list->output (offset, NULL, OUT_RAWDATA);
444 list->uplevel (LIST_TIMES);
445 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000446 }
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000447 if (instruction->times > 1)
448 list->downlevel (LIST_TIMES);
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000449 return offset - start;
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000450 } else if (m > 0 && m > size_prob) {
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000451 size_prob = m;
452 }
453 temp++;
454 }
H. Peter Anvineba20a72002-04-30 20:53:55 +0000455
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000456 if (temp->opcode == -1) { /* didn't match any instruction */
457 if (size_prob == 1) /* would have matched, but for size */
458 error (ERR_NONFATAL, "operation size not specified");
459 else if (size_prob == 2)
460 error (ERR_NONFATAL, "mismatch in operand sizes");
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000461 else if (size_prob == 3)
462 error (ERR_NONFATAL, "no instruction for this cpu level");
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000463 else
464 error (ERR_NONFATAL,
465 "invalid combination of opcode and operands");
466 }
467 return 0;
468}
469
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000470long insn_size (long segment, long offset, int bits, unsigned long cp,
H. Peter Anvineba20a72002-04-30 20:53:55 +0000471 insn *instruction, efunc error)
472{
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000473 struct itemplate *temp;
474
475 errfunc = error; /* to pass to other functions */
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000476 cpu = cp;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000477
478 if (instruction->opcode == -1)
479 return 0;
480
481 if (instruction->opcode == I_DB ||
482 instruction->opcode == I_DW ||
483 instruction->opcode == I_DD ||
484 instruction->opcode == I_DQ ||
H. Peter Anvineba20a72002-04-30 20:53:55 +0000485 instruction->opcode == I_DT)
486 {
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000487 extop *e;
488 long isize, osize, wsize = 0; /* placate gcc */
489
490 isize = 0;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000491 switch (instruction->opcode)
492 {
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000493 case I_DB: wsize = 1; break;
494 case I_DW: wsize = 2; break;
495 case I_DD: wsize = 4; break;
496 case I_DQ: wsize = 8; break;
497 case I_DT: wsize = 10; break;
498 }
499
H. Peter Anvineba20a72002-04-30 20:53:55 +0000500 for (e = instruction->eops; e; e = e->next)
501 {
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000502 long align;
503
504 osize = 0;
505 if (e->type == EOT_DB_NUMBER)
506 osize = 1;
507 else if (e->type == EOT_DB_STRING)
508 osize = e->stringlen;
509
510 align = (-osize) % wsize;
511 if (align < 0)
512 align += wsize;
513 isize += osize + align;
514 }
515 return isize * instruction->times;
516 }
517
H. Peter Anvineba20a72002-04-30 20:53:55 +0000518 if (instruction->opcode == I_INCBIN)
519 {
520 char fname[FILENAME_MAX];
521 FILE * fp;
522 long len;
Frank Kotlerd0ed6fd2003-08-27 11:33:56 +0000523 char *prefix = "", *combine;
524 char** pPrevPath = NULL;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000525
526 len = FILENAME_MAX-1;
527 if (len > instruction->eops->stringlen)
528 len = instruction->eops->stringlen;
529 strncpy (fname, instruction->eops->stringval, len);
530 fname[len] = '\0';
Frank Kotlerd0ed6fd2003-08-27 11:33:56 +0000531
532 while (1) /* added by alexfru: 'incbin' uses include paths */
533 {
534 combine = nasm_malloc(strlen(prefix) + len + 1);
535 strcpy(combine, prefix);
536 strcat(combine, fname);
537
538 if ( (fp = fopen(combine, "rb")) != NULL)
539 {
540 nasm_free(combine);
541 break;
542 }
543
544 nasm_free(combine);
545 pPrevPath = pp_get_include_path_ptr (pPrevPath);
546 if (pPrevPath == NULL)
547 break;
548 prefix = *pPrevPath;
549 }
550
551 if (fp == NULL)
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000552 error (ERR_NONFATAL, "`incbin': unable to open file `%s'", fname);
553 else if (fseek(fp, 0L, SEEK_END) < 0)
554 error (ERR_NONFATAL, "`incbin': unable to seek on file `%s'",
555 fname);
H. Peter Anvineba20a72002-04-30 20:53:55 +0000556 else
557 {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000558 len = ftell (fp);
559 fclose (fp);
H. Peter Anvineba20a72002-04-30 20:53:55 +0000560 if (instruction->eops->next)
561 {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000562 len -= instruction->eops->next->offset;
563 if (instruction->eops->next->next &&
564 len > instruction->eops->next->next->offset)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000565 {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000566 len = instruction->eops->next->next->offset;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000567 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000568 }
569 return instruction->times * len;
570 }
571 return 0; /* if we're here, there's an error */
572 }
573
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000574 temp = nasm_instructions[instruction->opcode];
575 while (temp->opcode != -1) {
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000576 int m = matches(temp, instruction);
577 if (m == 99)
578 m += jmp_match(segment, offset, bits, instruction, temp->code);
579
580 if (m == 100) {
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000581 /* we've matched an instruction. */
H. Peter Anvineba20a72002-04-30 20:53:55 +0000582 long isize;
H. Peter Anvinbfebdb02002-09-12 02:23:54 +0000583 const char * codes = temp->code;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000584 int j;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000585
586 isize = calcsize(segment, offset, bits, instruction, codes);
587 if (isize < 0)
588 return -1;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000589 for (j = 0; j < instruction->nprefix; j++)
590 {
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000591 if ((instruction->prefixes[j] != P_A16 &&
592 instruction->prefixes[j] != P_O16 && bits==16) ||
593 (instruction->prefixes[j] != P_A32 &&
594 instruction->prefixes[j] != P_O32 && bits==32))
H. Peter Anvineba20a72002-04-30 20:53:55 +0000595 {
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000596 isize++;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000597 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000598 }
599 return isize * instruction->times;
600 }
601 temp++;
602 }
603 return -1; /* didn't match any instruction */
604}
605
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000606
607/* check that opn[op] is a signed byte of size 16 or 32,
608 and return the signed value*/
609static int is_sbyte (insn *ins, int op, int size)
610{
611 signed long v;
612 int ret;
613
614 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 +0000615 optimizing>=0 &&
616 !(ins->oprs[op].type & STRICT) &&
617 ins->oprs[op].wrt==NO_SEG && ins->oprs[op].segment==NO_SEG;
H. Peter Anvin734b1882002-04-30 21:01:08 +0000618
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000619 v = ins->oprs[op].offset;
620 if (size==16) v = (signed short)v; /* sign extend if 16 bits */
621
622 return ret && v>=-128L && v<=127L;
623}
624
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000625static long calcsize (long segment, long offset, int bits,
H. Peter Anvinbfebdb02002-09-12 02:23:54 +0000626 insn *ins, const char *codes)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000627{
628 long length = 0;
629 unsigned char c;
630
631 (void) segment; /* Don't warn that this parameter is unused */
632 (void) offset; /* Don't warn that this parameter is unused */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000633
634 while (*codes) switch (c = *codes++) {
635 case 01: case 02: case 03:
636 codes += c, length += c; break;
637 case 04: case 05: case 06: case 07:
638 length++; break;
639 case 010: case 011: case 012:
640 codes++, length++; break;
641 case 017:
642 length++; break;
643 case 014: case 015: case 016:
644 length++; break;
645 case 020: case 021: case 022:
646 length++; break;
647 case 024: case 025: case 026:
648 length++; break;
649 case 030: case 031: case 032:
650 length += 2; break;
651 case 034: case 035: case 036:
H. Peter Anvin3ba46772002-05-27 23:19:35 +0000652 if ( ins->oprs[c-034].type & (BITS16|BITS32) )
653 length += (ins->oprs[c-034].type & BITS16) ? 2 : 4;
654 else
655 length += (bits == 16) ? 2 : 4;
656 break;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000657 case 037:
658 length += 2; break;
659 case 040: case 041: case 042:
660 length += 4; break;
H. Peter Anvin3ba46772002-05-27 23:19:35 +0000661 case 044: case 045: case 046:
662 length += ((ins->oprs[c-044].addr_size ?
663 ins->oprs[c-044].addr_size : bits) == 16 ? 2 : 4); break;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000664 case 050: case 051: case 052:
665 length++; break;
666 case 060: case 061: case 062:
667 length += 2; break;
668 case 064: case 065: case 066:
H. Peter Anvin17799b42002-05-21 03:31:21 +0000669 if ( ins->oprs[c-064].type & (BITS16|BITS32) )
670 length += (ins->oprs[c-064].type & BITS16) ? 2 : 4;
671 else
672 length += (bits == 16) ? 2 : 4;
673 break;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000674 case 070: case 071: case 072:
675 length += 4; break;
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000676 case 0130: case 0131: case 0132:
677 length += is_sbyte(ins, c-0130, 16) ? 1 : 2; break;
678 case 0133: case 0134: case 0135:
679 codes+=2; length++; break;
680 case 0140: case 0141: case 0142:
681 length += is_sbyte(ins, c-0140, 32) ? 1 : 4; break;
682 case 0143: case 0144: case 0145:
683 codes+=2; length++; break;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000684 case 0300: case 0301: case 0302:
685 length += chsize (&ins->oprs[c-0300], bits);
686 break;
687 case 0310:
688 length += (bits==32);
689 break;
690 case 0311:
691 length += (bits==16);
692 break;
693 case 0312:
694 break;
695 case 0320:
696 length += (bits==32);
697 break;
698 case 0321:
699 length += (bits==16);
700 break;
701 case 0322:
702 break;
703 case 0330:
704 codes++, length++; break;
H. Peter Anvinef7468f2002-04-30 20:57:59 +0000705 case 0331:
706 case 0332:
707 break;
708 case 0333:
709 length++; break;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000710 case 0340: case 0341: case 0342:
711 if (ins->oprs[0].segment != NO_SEG)
712 errfunc (ERR_NONFATAL, "attempt to reserve non-constant"
713 " quantity of BSS space");
714 else
715 length += ins->oprs[0].offset << (c-0340);
716 break;
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000717 case 0370: case 0371: case 0372:
718 break;
719 case 0373:
720 length++; break;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000721 default: /* can't do it by 'case' statements */
722 if (c>=0100 && c<=0277) { /* it's an EA */
723 ea ea_data;
H. Peter Anvinea838272002-04-30 20:51:53 +0000724 if (!process_ea (&ins->oprs[(c>>3)&7], &ea_data, bits, 0,
725 ins->forw_ref)) {
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000726 errfunc (ERR_NONFATAL, "invalid effective address");
727 return -1;
728 } else
729 length += ea_data.size;
730 } else
731 errfunc (ERR_PANIC, "internal instruction table corrupt"
732 ": instruction code 0x%02X given", c);
733 }
734 return length;
735}
736
737static void gencode (long segment, long offset, int bits,
H. Peter Anvinbfebdb02002-09-12 02:23:54 +0000738 insn *ins, const char *codes, long insn_end)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000739{
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000740 static char condval[] = { /* conditional opcodes */
741 0x7, 0x3, 0x2, 0x6, 0x2, 0x4, 0xF, 0xD, 0xC, 0xE, 0x6, 0x2,
742 0x3, 0x7, 0x3, 0x5, 0xE, 0xC, 0xD, 0xF, 0x1, 0xB, 0x9, 0x5,
743 0x0, 0xA, 0xA, 0xB, 0x8, 0x4
744 };
H. Peter Anvineba20a72002-04-30 20:53:55 +0000745 unsigned char c;
746 unsigned char bytes[4];
747 long data, size;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000748
H. Peter Anvineba20a72002-04-30 20:53:55 +0000749 while (*codes)
750 switch (c = *codes++)
751 {
752 case 01: case 02: case 03:
753 out (offset, segment, codes, OUT_RAWDATA+c, NO_SEG, NO_SEG);
754 codes += c;
755 offset += c;
756 break;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000757
H. Peter Anvineba20a72002-04-30 20:53:55 +0000758 case 04: case 06:
759 switch (ins->oprs[0].basereg)
760 {
761 case R_CS:
762 bytes[0] = 0x0E + (c == 0x04 ? 1 : 0); break;
763 case R_DS:
764 bytes[0] = 0x1E + (c == 0x04 ? 1 : 0); break;
765 case R_ES:
766 bytes[0] = 0x06 + (c == 0x04 ? 1 : 0); break;
767 case R_SS:
768 bytes[0] = 0x16 + (c == 0x04 ? 1 : 0); break;
769 default:
H. Peter Anvin4836e332002-04-30 20:56:43 +0000770 errfunc (ERR_PANIC, "bizarre 8086 segment register received");
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000771 }
H. Peter Anvineba20a72002-04-30 20:53:55 +0000772 out (offset, segment, bytes, OUT_RAWDATA+1, NO_SEG, NO_SEG);
773 offset++;
774 break;
775
776 case 05: case 07:
777 switch (ins->oprs[0].basereg) {
778 case R_FS: bytes[0] = 0xA0 + (c == 0x05 ? 1 : 0); break;
779 case R_GS: bytes[0] = 0xA8 + (c == 0x05 ? 1 : 0); break;
780 default:
H. Peter Anvin4836e332002-04-30 20:56:43 +0000781 errfunc (ERR_PANIC, "bizarre 386 segment register received");
H. Peter Anvineba20a72002-04-30 20:53:55 +0000782 }
783 out (offset, segment, bytes, OUT_RAWDATA+1, NO_SEG, NO_SEG);
784 offset++;
785 break;
786
787 case 010: case 011: case 012:
788 bytes[0] = *codes++ + regval(&ins->oprs[c-010]);
789 out (offset, segment, bytes, OUT_RAWDATA+1, NO_SEG, NO_SEG);
790 offset += 1;
791 break;
792
793 case 017:
794 bytes[0] = 0;
795 out (offset, segment, bytes, OUT_RAWDATA+1, NO_SEG, NO_SEG);
796 offset += 1;
797 break;
798
799 case 014: case 015: case 016:
800 if (ins->oprs[c-014].offset < -128
801 || ins->oprs[c-014].offset > 127)
802 {
803 errfunc (ERR_WARNING, "signed byte value exceeds bounds");
804 }
805
806 if (ins->oprs[c-014].segment != NO_SEG)
807 {
808 data = ins->oprs[c-014].offset;
809 out (offset, segment, &data, OUT_ADDRESS+1,
810 ins->oprs[c-014].segment, ins->oprs[c-014].wrt);
811 }
812 else {
813 bytes[0] = ins->oprs[c-014].offset;
814 out (offset, segment, bytes, OUT_RAWDATA+1, NO_SEG, NO_SEG);
815 }
816 offset += 1;
817 break;
818
819 case 020: case 021: case 022:
820 if (ins->oprs[c-020].offset < -256
821 || ins->oprs[c-020].offset > 255)
822 {
823 errfunc (ERR_WARNING, "byte value exceeds bounds");
824 }
825 if (ins->oprs[c-020].segment != NO_SEG) {
826 data = ins->oprs[c-020].offset;
827 out (offset, segment, &data, OUT_ADDRESS+1,
828 ins->oprs[c-020].segment, ins->oprs[c-020].wrt);
829 }
830 else {
831 bytes[0] = ins->oprs[c-020].offset;
832 out (offset, segment, bytes, OUT_RAWDATA+1, NO_SEG, NO_SEG);
833 }
834 offset += 1;
835 break;
836
837 case 024: case 025: case 026:
838 if (ins->oprs[c-024].offset < 0 || ins->oprs[c-024].offset > 255)
839 errfunc (ERR_WARNING, "unsigned byte value exceeds bounds");
840 if (ins->oprs[c-024].segment != NO_SEG) {
841 data = ins->oprs[c-024].offset;
842 out (offset, segment, &data, OUT_ADDRESS+1,
843 ins->oprs[c-024].segment, ins->oprs[c-024].wrt);
844 }
845 else {
846 bytes[0] = ins->oprs[c-024].offset;
847 out (offset, segment, bytes, OUT_RAWDATA+1, NO_SEG, NO_SEG);
848 }
849 offset += 1;
850 break;
851
852 case 030: case 031: case 032:
853 if (ins->oprs[c-030].segment == NO_SEG &&
854 ins->oprs[c-030].wrt == NO_SEG &&
855 (ins->oprs[c-030].offset < -65536L ||
856 ins->oprs[c-030].offset > 65535L))
857 {
858 errfunc (ERR_WARNING, "word value exceeds bounds");
859 }
860 data = ins->oprs[c-030].offset;
861 out (offset, segment, &data, OUT_ADDRESS+2,
862 ins->oprs[c-030].segment, ins->oprs[c-030].wrt);
863 offset += 2;
864 break;
865
866 case 034: case 035: case 036:
H. Peter Anvin3ba46772002-05-27 23:19:35 +0000867 if ( ins->oprs[c-034].type & (BITS16|BITS32) )
868 size = (ins->oprs[c-034].type & BITS16) ? 2 : 4;
869 else
870 size = (bits == 16) ? 2 : 4;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000871 data = ins->oprs[c-034].offset;
H. Peter Anvin4cf17482002-04-30 21:01:38 +0000872 if (size==2 && (data < -65536L || data > 65535L))
H. Peter Anvineba20a72002-04-30 20:53:55 +0000873 errfunc (ERR_WARNING, "word value exceeds bounds");
874 out (offset, segment, &data, OUT_ADDRESS+size,
875 ins->oprs[c-034].segment, ins->oprs[c-034].wrt);
876 offset += size;
877 break;
878
879 case 037:
880 if (ins->oprs[0].segment == NO_SEG)
881 errfunc (ERR_NONFATAL, "value referenced by FAR is not"
882 " relocatable");
883 data = 0L;
884 out (offset, segment, &data, OUT_ADDRESS+2,
885 outfmt->segbase(1+ins->oprs[0].segment),
886 ins->oprs[0].wrt);
887 offset += 2;
888 break;
889
890 case 040: case 041: case 042:
891 data = ins->oprs[c-040].offset;
892 out (offset, segment, &data, OUT_ADDRESS+4,
893 ins->oprs[c-040].segment, ins->oprs[c-040].wrt);
894 offset += 4;
895 break;
896
H. Peter Anvin3ba46772002-05-27 23:19:35 +0000897 case 044: case 045: case 046:
898 data = ins->oprs[c-044].offset;
899 size = ((ins->oprs[c-044].addr_size ?
900 ins->oprs[c-044].addr_size : bits) == 16 ? 2 : 4);
901 if (size==2 && (data < -65536L || data > 65535L))
902 errfunc (ERR_WARNING, "word value exceeds bounds");
903 out (offset, segment, &data, OUT_ADDRESS+size,
904 ins->oprs[c-044].segment, ins->oprs[c-044].wrt);
905 offset += size;
906 break;
907
H. Peter Anvineba20a72002-04-30 20:53:55 +0000908 case 050: case 051: case 052:
909 if (ins->oprs[c-050].segment != segment)
910 errfunc (ERR_NONFATAL, "short relative jump outside segment");
911 data = ins->oprs[c-050].offset - insn_end;
912 if (data > 127 || data < -128)
913 errfunc (ERR_NONFATAL, "short jump is out of range");
914 bytes[0] = data;
915 out (offset, segment, bytes, OUT_RAWDATA+1, NO_SEG, NO_SEG);
916 offset += 1;
917 break;
918
919 case 060: case 061: case 062:
920 if (ins->oprs[c-060].segment != segment) {
921 data = ins->oprs[c-060].offset;
922 out (offset, segment, &data, OUT_REL2ADR+insn_end-offset,
923 ins->oprs[c-060].segment, ins->oprs[c-060].wrt);
924 } else {
925 data = ins->oprs[c-060].offset - insn_end;
926 out (offset, segment, &data,
927 OUT_ADDRESS+2, NO_SEG, NO_SEG);
928 }
929 offset += 2;
930 break;
931
932 case 064: case 065: case 066:
H. Peter Anvin17799b42002-05-21 03:31:21 +0000933 if ( ins->oprs[c-064].type & (BITS16|BITS32) )
934 size = (ins->oprs[c-064].type & BITS16) ? 2 : 4;
935 else
936 size = (bits == 16) ? 2 : 4;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000937 if (ins->oprs[c-064].segment != segment) {
H. Peter Anvin17799b42002-05-21 03:31:21 +0000938 long reltype = (size == 2 ? OUT_REL2ADR : OUT_REL4ADR);
H. Peter Anvineba20a72002-04-30 20:53:55 +0000939 data = ins->oprs[c-064].offset;
H. Peter Anvin17799b42002-05-21 03:31:21 +0000940 out (offset, segment, &data, reltype+insn_end-offset,
H. Peter Anvineba20a72002-04-30 20:53:55 +0000941 ins->oprs[c-064].segment, ins->oprs[c-064].wrt);
H. Peter Anvineba20a72002-04-30 20:53:55 +0000942 } else {
943 data = ins->oprs[c-064].offset - insn_end;
944 out (offset, segment, &data,
945 OUT_ADDRESS+size, NO_SEG, NO_SEG);
946 }
947 offset += size;
948 break;
949
950 case 070: case 071: case 072:
951 if (ins->oprs[c-070].segment != segment) {
952 data = ins->oprs[c-070].offset;
953 out (offset, segment, &data, OUT_REL4ADR+insn_end-offset,
954 ins->oprs[c-070].segment, ins->oprs[c-070].wrt);
955 } else {
956 data = ins->oprs[c-070].offset - insn_end;
957 out (offset, segment, &data,
958 OUT_ADDRESS+4, NO_SEG, NO_SEG);
959 }
960 offset += 4;
961 break;
962
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000963 case 0130: case 0131: case 0132:
964 data = ins->oprs[c-0130].offset;
965 if (is_sbyte(ins, c-0130, 16)) {
H. Peter Anvin0bfed6c2002-11-10 06:29:23 +0000966 bytes[0] = data;
967 out (offset, segment, bytes, OUT_RAWDATA+1, NO_SEG, NO_SEG);
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000968 offset++;
969 } else {
970 if (ins->oprs[c-0130].segment == NO_SEG &&
971 ins->oprs[c-0130].wrt == NO_SEG &&
972 (data < -65536L || data > 65535L)) {
973 errfunc (ERR_WARNING, "word value exceeds bounds");
974 }
975 out (offset, segment, &data, OUT_ADDRESS+2,
976 ins->oprs[c-0130].segment, ins->oprs[c-0130].wrt);
977 offset += 2;
978 }
979 break;
980
981 case 0133: case 0134: case 0135:
982 codes++;
983 bytes[0] = *codes++;
984 if (is_sbyte(ins, c-0133, 16)) bytes[0] |= 2; /* s-bit */
985 out (offset, segment, bytes, OUT_RAWDATA+1, NO_SEG, NO_SEG);
986 offset++;
987 break;
988
989 case 0140: case 0141: case 0142:
990 data = ins->oprs[c-0140].offset;
991 if (is_sbyte(ins, c-0140, 32)) {
H. Peter Anvin0bfed6c2002-11-10 06:29:23 +0000992 bytes[0] = data;
993 out (offset, segment, bytes, OUT_RAWDATA+1, NO_SEG, NO_SEG);
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000994 offset++;
995 } else {
996 out (offset, segment, &data, OUT_ADDRESS+4,
997 ins->oprs[c-0140].segment, ins->oprs[c-0140].wrt);
998 offset += 4;
999 }
1000 break;
1001
1002 case 0143: case 0144: case 0145:
1003 codes++;
1004 bytes[0] = *codes++;
1005 if (is_sbyte(ins, c-0143, 32)) bytes[0] |= 2; /* s-bit */
1006 out (offset, segment, bytes, OUT_RAWDATA+1, NO_SEG, NO_SEG);
1007 offset++;
1008 break;
1009
H. Peter Anvineba20a72002-04-30 20:53:55 +00001010 case 0300: case 0301: case 0302:
1011 if (chsize (&ins->oprs[c-0300], bits)) {
1012 *bytes = 0x67;
1013 out (offset, segment, bytes,
1014 OUT_RAWDATA+1, NO_SEG, NO_SEG);
1015 offset += 1;
1016 } else
1017 offset += 0;
1018 break;
1019
1020 case 0310:
1021 if (bits==32) {
1022 *bytes = 0x67;
1023 out (offset, segment, bytes,
1024 OUT_RAWDATA+1, NO_SEG, NO_SEG);
1025 offset += 1;
1026 } else
1027 offset += 0;
1028 break;
1029
1030 case 0311:
1031 if (bits==16) {
1032 *bytes = 0x67;
1033 out (offset, segment, bytes,
1034 OUT_RAWDATA+1, NO_SEG, NO_SEG);
1035 offset += 1;
1036 } else
1037 offset += 0;
1038 break;
1039
1040 case 0312:
1041 break;
1042
1043 case 0320:
1044 if (bits==32) {
1045 *bytes = 0x66;
1046 out (offset, segment, bytes,
1047 OUT_RAWDATA+1, NO_SEG, NO_SEG);
1048 offset += 1;
1049 } else
1050 offset += 0;
1051 break;
1052
1053 case 0321:
1054 if (bits==16) {
1055 *bytes = 0x66;
1056 out (offset, segment, bytes,
1057 OUT_RAWDATA+1, NO_SEG, NO_SEG);
1058 offset += 1;
1059 } else
1060 offset += 0;
1061 break;
1062
1063 case 0322:
1064 break;
1065
1066 case 0330:
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001067 *bytes = *codes++ ^ condval[ins->condition];
H. Peter Anvineba20a72002-04-30 20:53:55 +00001068 out (offset, segment, bytes,
1069 OUT_RAWDATA+1, NO_SEG, NO_SEG);
1070 offset += 1;
1071 break;
1072
H. Peter Anvinef7468f2002-04-30 20:57:59 +00001073 case 0331:
1074 case 0332:
1075 break;
1076
1077 case 0333:
1078 *bytes = 0xF3;
1079 out (offset, segment, bytes,
1080 OUT_RAWDATA+1, NO_SEG, NO_SEG);
1081 offset += 1;
1082 break;
1083
H. Peter Anvineba20a72002-04-30 20:53:55 +00001084 case 0340: case 0341: case 0342:
1085 if (ins->oprs[0].segment != NO_SEG)
1086 errfunc (ERR_PANIC, "non-constant BSS size in pass two");
1087 else {
1088 long size = ins->oprs[0].offset << (c-0340);
1089 if (size > 0)
1090 out (offset, segment, NULL,
1091 OUT_RESERVE+size, NO_SEG, NO_SEG);
1092 offset += size;
1093 }
1094 break;
1095
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001096 case 0370: case 0371: case 0372:
1097 break;
1098
1099 case 0373:
1100 *bytes = bits==16 ? 3 : 5;
1101 out (offset, segment, bytes,
1102 OUT_RAWDATA+1, NO_SEG, NO_SEG);
1103 offset += 1;
1104 break;
1105
H. Peter Anvineba20a72002-04-30 20:53:55 +00001106 default: /* can't do it by 'case' statements */
1107 if (c>=0100 && c<=0277) { /* it's an EA */
1108 ea ea_data;
1109 int rfield;
1110 unsigned char *p;
1111 long s;
1112
1113 if (c<=0177) /* pick rfield from operand b */
1114 rfield = regval (&ins->oprs[c&7]);
1115 else /* rfield is constant */
1116 rfield = c & 7;
1117
1118 if (!process_ea (&ins->oprs[(c>>3)&7], &ea_data, bits, rfield,
1119 ins->forw_ref))
1120 {
1121 errfunc (ERR_NONFATAL, "invalid effective address");
1122 }
1123
1124 p = bytes;
1125 *p++ = ea_data.modrm;
1126 if (ea_data.sib_present)
1127 *p++ = ea_data.sib;
1128
1129 s = p-bytes;
1130 out (offset, segment, bytes, OUT_RAWDATA + s,
1131 NO_SEG, NO_SEG);
1132
1133 switch (ea_data.bytes) {
1134 case 0:
1135 break;
1136 case 1:
1137 if (ins->oprs[(c>>3)&7].segment != NO_SEG) {
1138 data = ins->oprs[(c>>3)&7].offset;
1139 out (offset, segment, &data, OUT_ADDRESS+1,
1140 ins->oprs[(c>>3)&7].segment,
1141 ins->oprs[(c>>3)&7].wrt);
1142 } else {
1143 *bytes = ins->oprs[(c>>3)&7].offset;
1144 out (offset, segment, bytes, OUT_RAWDATA+1,
1145 NO_SEG, NO_SEG);
1146 }
1147 s++;
1148 break;
1149 case 2:
1150 case 4:
1151 data = ins->oprs[(c>>3)&7].offset;
1152 out (offset, segment, &data,
1153 OUT_ADDRESS+ea_data.bytes,
1154 ins->oprs[(c>>3)&7].segment, ins->oprs[(c>>3)&7].wrt);
1155 s += ea_data.bytes;
1156 break;
1157 }
1158 offset += s;
1159 } else
1160 errfunc (ERR_PANIC, "internal instruction table corrupt"
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001161 ": instruction code 0x%02X given", c);
H. Peter Anvineba20a72002-04-30 20:53:55 +00001162 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001163}
1164
H. Peter Anvin232badb2002-06-06 02:41:20 +00001165#include "regvals.c"
1166
H. Peter Anvineba20a72002-04-30 20:53:55 +00001167static int regval (operand *o)
1168{
H. Peter Anvin232badb2002-06-06 02:41:20 +00001169 if ( o->basereg < EXPR_REG_START || o->basereg >= REG_ENUM_LIMIT ) {
1170 errfunc (ERR_PANIC, "invalid operand passed to regval()");
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001171 }
H. Peter Anvin232badb2002-06-06 02:41:20 +00001172 return regvals[o->basereg];
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001173}
1174
H. Peter Anvineba20a72002-04-30 20:53:55 +00001175static int matches (struct itemplate *itemp, insn *instruction)
1176{
H. Peter Anvinef7468f2002-04-30 20:57:59 +00001177 int i, size[3], asize, oprs, ret;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001178
1179 ret = 100;
1180
1181 /*
1182 * Check the opcode
1183 */
1184 if (itemp->opcode != instruction->opcode) return 0;
1185
1186 /*
1187 * Count the operands
1188 */
1189 if (itemp->operands != instruction->operands) return 0;
1190
1191 /*
1192 * Check that no spurious colons or TOs are present
1193 */
1194 for (i=0; i<itemp->operands; i++)
1195 if (instruction->oprs[i].type & ~itemp->opd[i] & (COLON|TO))
1196 return 0;
1197
1198 /*
1199 * Check that the operand flags all match up
1200 */
1201 for (i=0; i<itemp->operands; i++)
1202 if (itemp->opd[i] & ~instruction->oprs[i].type ||
1203 ((itemp->opd[i] & SIZE_MASK) &&
H. Peter Anvineba20a72002-04-30 20:53:55 +00001204 ((itemp->opd[i] ^ instruction->oprs[i].type) & SIZE_MASK)))
1205 {
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001206 if ((itemp->opd[i] & ~instruction->oprs[i].type & NON_SIZE) ||
1207 (instruction->oprs[i].type & SIZE_MASK))
1208 return 0;
1209 else
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001210/* ret = 1; */
1211 return 1;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001212 }
1213
1214 /*
1215 * Check operand sizes
1216 */
H. Peter Anvinef7468f2002-04-30 20:57:59 +00001217 if (itemp->flags & IF_ARMASK) {
1218 size[0] = size[1] = size[2] = 0;
1219
1220 switch (itemp->flags & IF_ARMASK) {
1221 case IF_AR0: i = 0; break;
1222 case IF_AR1: i = 1; break;
1223 case IF_AR2: i = 2; break;
1224 default: break; /* Shouldn't happen */
1225 }
1226 if (itemp->flags & IF_SB) {
1227 size[i] = BITS8;
1228 } else if (itemp->flags & IF_SW) {
1229 size[i] = BITS16;
1230 } else if (itemp->flags & IF_SD) {
1231 size[i] = BITS32;
1232 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001233 } else {
H. Peter Anvinef7468f2002-04-30 20:57:59 +00001234 asize = 0;
1235 if (itemp->flags & IF_SB) {
1236 asize = BITS8;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001237 oprs = itemp->operands;
H. Peter Anvinef7468f2002-04-30 20:57:59 +00001238 } else if (itemp->flags & IF_SW) {
1239 asize = BITS16;
1240 oprs = itemp->operands;
1241 } else if (itemp->flags & IF_SD) {
1242 asize = BITS32;
1243 oprs = itemp->operands;
1244 }
1245 size[0] = size[1] = size[2] = asize;
1246 }
1247
1248 if (itemp->flags & (IF_SM | IF_SM2)) {
1249 oprs = (itemp->flags & IF_SM2 ? 2 : itemp->operands);
1250 asize = 0;
1251 for (i=0; i<oprs; i++) {
1252 if ( (asize = itemp->opd[i] & SIZE_MASK) != 0) {
1253 int j;
1254 for (j=0; j<oprs; j++)
1255 size[j] = asize;
1256 break;
1257 }
1258 }
1259 } else {
1260 oprs = itemp->operands;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001261 }
1262
1263 for (i=0; i<itemp->operands; i++)
1264 if (!(itemp->opd[i] & SIZE_MASK) &&
H. Peter Anvinef7468f2002-04-30 20:57:59 +00001265 (instruction->oprs[i].type & SIZE_MASK & ~size[i]))
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001266/* ret = 2; */
1267 return 2;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001268
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001269 /*
1270 * Check template is okay at the set cpu level
1271 */
1272 if ((itemp->flags & IF_PLEVEL) > cpu) return 3;
1273
1274 /*
1275 * Check if special handling needed for Jumps
1276 */
1277 if ((unsigned char)(itemp->code[0]) >= 0370) return 99;
1278
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001279 return ret;
1280}
1281
H. Peter Anvinea838272002-04-30 20:51:53 +00001282static ea *process_ea (operand *input, ea *output, int addrbits, int rfield,
H. Peter Anvineba20a72002-04-30 20:53:55 +00001283 int forw_ref)
1284{
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001285 if (!(REGISTER & ~input->type)) { /* it's a single register */
1286 static int regs[] = {
H. Peter Anvin4836e332002-04-30 20:56:43 +00001287 R_AL, R_CL, R_DL, R_BL, R_AH, R_CH, R_DH, R_BH,
1288 R_AX, R_CX, R_DX, R_BX, R_SP, R_BP, R_SI, R_DI,
1289 R_EAX, R_ECX, R_EDX, R_EBX, R_ESP, R_EBP, R_ESI, R_EDI,
1290 R_MM0, R_MM1, R_MM2, R_MM3, R_MM4, R_MM5, R_MM6, R_MM7,
1291 R_XMM0, R_XMM1, R_XMM2, R_XMM3, R_XMM4, R_XMM5, R_XMM6, R_XMM7
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001292 };
1293 int i;
1294
1295 for (i=0; i<elements(regs); i++)
1296 if (input->basereg == regs[i]) break;
1297 if (i<elements(regs)) {
1298 output->sib_present = FALSE;/* no SIB necessary */
1299 output->bytes = 0; /* no offset necessary either */
H. Peter Anvin4836e332002-04-30 20:56:43 +00001300 output->modrm = 0xC0 | (rfield << 3) | (i & 7);
H. Peter Anvineba20a72002-04-30 20:53:55 +00001301 }
1302 else
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001303 return NULL;
1304 } else { /* it's a memory reference */
1305 if (input->basereg==-1 && (input->indexreg==-1 || input->scale==0)) {
1306 /* it's a pure offset */
1307 if (input->addr_size)
1308 addrbits = input->addr_size;
1309 output->sib_present = FALSE;
1310 output->bytes = (addrbits==32 ? 4 : 2);
1311 output->modrm = (addrbits==32 ? 5 : 6) | (rfield << 3);
H. Peter Anvineba20a72002-04-30 20:53:55 +00001312 }
1313 else { /* it's an indirection */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001314 int i=input->indexreg, b=input->basereg, s=input->scale;
1315 long o=input->offset, seg=input->segment;
H. Peter Anvin76690a12002-04-30 20:52:49 +00001316 int hb=input->hintbase, ht=input->hinttype;
1317 int t;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001318
1319 if (s==0) i = -1; /* make this easy, at least */
1320
1321 if (i==R_EAX || i==R_EBX || i==R_ECX || i==R_EDX
1322 || i==R_EBP || i==R_ESP || i==R_ESI || i==R_EDI
1323 || b==R_EAX || b==R_EBX || b==R_ECX || b==R_EDX
1324 || b==R_EBP || b==R_ESP || b==R_ESI || b==R_EDI) {
1325 /* it must be a 32-bit memory reference. Firstly we have
1326 * to check that all registers involved are type Exx. */
1327 if (i!=-1 && i!=R_EAX && i!=R_EBX && i!=R_ECX && i!=R_EDX
1328 && i!=R_EBP && i!=R_ESP && i!=R_ESI && i!=R_EDI)
1329 return NULL;
1330 if (b!=-1 && b!=R_EAX && b!=R_EBX && b!=R_ECX && b!=R_EDX
1331 && b!=R_EBP && b!=R_ESP && b!=R_ESI && b!=R_EDI)
1332 return NULL;
1333
1334 /* While we're here, ensure the user didn't specify WORD. */
1335 if (input->addr_size == 16)
1336 return NULL;
1337
1338 /* now reorganise base/index */
H. Peter Anvin76690a12002-04-30 20:52:49 +00001339 if (s == 1 && b != i && b != -1 && i != -1 &&
1340 ((hb==b&&ht==EAH_NOTBASE) || (hb==i&&ht==EAH_MAKEBASE)))
1341 t = b, b = i, i = t; /* swap if hints say so */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001342 if (b==i) /* convert EAX+2*EAX to 3*EAX */
1343 b = -1, s++;
H. Peter Anvin76690a12002-04-30 20:52:49 +00001344 if (b==-1 && s==1 && !(hb == i && ht == EAH_NOTBASE))
1345 b = i, i = -1; /* make single reg base, unless hint */
1346 if (((s==2 && i!=R_ESP && !(input->eaflags & EAF_TIMESTWO)) ||
1347 s==3 || s==5 || s==9) && b==-1)
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001348 b = i, s--; /* convert 3*EAX to EAX+2*EAX */
Debbie Wiles0f65f882002-06-08 19:30:14 +00001349 if (i==-1 && b!=R_ESP && (input->eaflags & EAF_TIMESTWO))
1350 i = b, b = -1, s = 1;
1351 /* convert [NOSPLIT EAX] to sib format with 0x0 displacement */
H. Peter Anvinea838272002-04-30 20:51:53 +00001352 if (s==1 && i==R_ESP) /* swap ESP into base if scale is 1 */
1353 i = b, b = R_ESP;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001354 if (i==R_ESP || (s!=1 && s!=2 && s!=4 && s!=8 && i!=-1))
1355 return NULL; /* wrong, for various reasons */
1356
1357 if (i==-1 && b!=R_ESP) {/* no SIB needed */
1358 int mod, rm;
1359 switch(b) {
1360 case R_EAX: rm = 0; break;
1361 case R_ECX: rm = 1; break;
1362 case R_EDX: rm = 2; break;
1363 case R_EBX: rm = 3; break;
1364 case R_EBP: rm = 5; break;
1365 case R_ESI: rm = 6; break;
1366 case R_EDI: rm = 7; break;
1367 case -1: rm = 5; break;
1368 default: /* should never happen */
1369 return NULL;
1370 }
H. Peter Anvinea838272002-04-30 20:51:53 +00001371 if (b==-1 || (b!=R_EBP && o==0 &&
H. Peter Anvin76690a12002-04-30 20:52:49 +00001372 seg==NO_SEG && !forw_ref &&
1373 !(input->eaflags &
1374 (EAF_BYTEOFFS|EAF_WORDOFFS))))
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001375 mod = 0;
H. Peter Anvin76690a12002-04-30 20:52:49 +00001376 else if (input->eaflags & EAF_BYTEOFFS ||
1377 (o>=-128 && o<=127 && seg==NO_SEG && !forw_ref &&
1378 !(input->eaflags & EAF_WORDOFFS))) {
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001379 mod = 1;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001380 }
1381 else
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001382 mod = 2;
H. Peter Anvinea838272002-04-30 20:51:53 +00001383
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001384 output->sib_present = FALSE;
1385 output->bytes = (b==-1 || mod==2 ? 4 : mod);
1386 output->modrm = (mod<<6) | (rfield<<3) | rm;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001387 }
1388 else { /* we need a SIB */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001389 int mod, scale, index, base;
1390
1391 switch (b) {
1392 case R_EAX: base = 0; break;
1393 case R_ECX: base = 1; break;
1394 case R_EDX: base = 2; break;
1395 case R_EBX: base = 3; break;
1396 case R_ESP: base = 4; break;
1397 case R_EBP: case -1: base = 5; break;
1398 case R_ESI: base = 6; break;
1399 case R_EDI: base = 7; break;
1400 default: /* then what the smeg is it? */
1401 return NULL; /* panic */
1402 }
1403
1404 switch (i) {
1405 case R_EAX: index = 0; break;
1406 case R_ECX: index = 1; break;
1407 case R_EDX: index = 2; break;
1408 case R_EBX: index = 3; break;
1409 case -1: index = 4; break;
1410 case R_EBP: index = 5; break;
1411 case R_ESI: index = 6; break;
1412 case R_EDI: index = 7; break;
1413 default: /* then what the smeg is it? */
1414 return NULL; /* panic */
1415 }
1416
1417 if (i==-1) s = 1;
1418 switch (s) {
1419 case 1: scale = 0; break;
1420 case 2: scale = 1; break;
1421 case 4: scale = 2; break;
1422 case 8: scale = 3; break;
1423 default: /* then what the smeg is it? */
1424 return NULL; /* panic */
1425 }
1426
H. Peter Anvinea838272002-04-30 20:51:53 +00001427 if (b==-1 || (b!=R_EBP && o==0 &&
H. Peter Anvin76690a12002-04-30 20:52:49 +00001428 seg==NO_SEG && !forw_ref &&
1429 !(input->eaflags &
1430 (EAF_BYTEOFFS|EAF_WORDOFFS))))
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001431 mod = 0;
H. Peter Anvin76690a12002-04-30 20:52:49 +00001432 else if (input->eaflags & EAF_BYTEOFFS ||
1433 (o>=-128 && o<=127 && seg==NO_SEG && !forw_ref &&
1434 !(input->eaflags & EAF_WORDOFFS)))
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001435 mod = 1;
1436 else
1437 mod = 2;
1438
1439 output->sib_present = TRUE;
1440 output->bytes = (b==-1 || mod==2 ? 4 : mod);
1441 output->modrm = (mod<<6) | (rfield<<3) | 4;
1442 output->sib = (scale<<6) | (index<<3) | base;
1443 }
H. Peter Anvineba20a72002-04-30 20:53:55 +00001444 }
1445 else { /* it's 16-bit */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001446 int mod, rm;
1447
1448 /* check all registers are BX, BP, SI or DI */
1449 if ((b!=-1 && b!=R_BP && b!=R_BX && b!=R_SI && b!=R_DI) ||
1450 (i!=-1 && i!=R_BP && i!=R_BX && i!=R_SI && i!=R_DI))
1451 return NULL;
1452
1453 /* ensure the user didn't specify DWORD */
1454 if (input->addr_size == 32)
1455 return NULL;
1456
1457 if (s!=1 && i!=-1) return NULL;/* no can do, in 16-bit EA */
H. Peter Anvin87e1fcd2002-05-11 04:01:26 +00001458 if (b==-1 && i!=-1) { int tmp = b; b = i; i = tmp; } /* swap */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001459 if ((b==R_SI || b==R_DI) && i!=-1)
H. Peter Anvin87e1fcd2002-05-11 04:01:26 +00001460 { int tmp = b; b = i; i = tmp; }
1461 /* have BX/BP as base, SI/DI index */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001462 if (b==i) return NULL;/* shouldn't ever happen, in theory */
1463 if (i!=-1 && b!=-1 &&
1464 (i==R_BP || i==R_BX || b==R_SI || b==R_DI))
1465 return NULL; /* invalid combinations */
H. Peter Anvin87e1fcd2002-05-11 04:01:26 +00001466 if (b==-1) /* pure offset: handled above */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001467 return NULL; /* so if it gets to here, panic! */
1468
1469 rm = -1;
1470 if (i!=-1)
1471 switch (i*256 + b) {
1472 case R_SI*256+R_BX: rm=0; break;
1473 case R_DI*256+R_BX: rm=1; break;
1474 case R_SI*256+R_BP: rm=2; break;
1475 case R_DI*256+R_BP: rm=3; break;
1476 }
1477 else
1478 switch (b) {
1479 case R_SI: rm=4; break;
1480 case R_DI: rm=5; break;
1481 case R_BP: rm=6; break;
1482 case R_BX: rm=7; break;
1483 }
1484 if (rm==-1) /* can't happen, in theory */
1485 return NULL; /* so panic if it does */
1486
H. Peter Anvin76690a12002-04-30 20:52:49 +00001487 if (o==0 && seg==NO_SEG && !forw_ref && rm!=6 &&
1488 !(input->eaflags & (EAF_BYTEOFFS|EAF_WORDOFFS)))
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001489 mod = 0;
H. Peter Anvin76690a12002-04-30 20:52:49 +00001490 else if (input->eaflags & EAF_BYTEOFFS ||
1491 (o>=-128 && o<=127 && seg==NO_SEG && !forw_ref &&
1492 !(input->eaflags & EAF_WORDOFFS)))
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001493 mod = 1;
1494 else
1495 mod = 2;
1496
1497 output->sib_present = FALSE; /* no SIB - it's 16-bit */
1498 output->bytes = mod; /* bytes of offset needed */
1499 output->modrm = (mod<<6) | (rfield<<3) | rm;
1500 }
1501 }
1502 }
1503 output->size = 1 + output->sib_present + output->bytes;
1504 return output;
1505}
1506
H. Peter Anvineba20a72002-04-30 20:53:55 +00001507static int chsize (operand *input, int addrbits)
1508{
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001509 if (!(MEMORY & ~input->type)) {
1510 int i=input->indexreg, b=input->basereg;
1511
1512 if (input->scale==0) i = -1;
1513
1514 if (i == -1 && b == -1) /* pure offset */
1515 return (input->addr_size != 0 && input->addr_size != addrbits);
1516
1517 if (i==R_EAX || i==R_EBX || i==R_ECX || i==R_EDX
1518 || i==R_EBP || i==R_ESP || i==R_ESI || i==R_EDI
1519 || b==R_EAX || b==R_EBX || b==R_ECX || b==R_EDX
1520 || b==R_EBP || b==R_ESP || b==R_ESI || b==R_EDI)
1521 return (addrbits==16);
1522 else
1523 return (addrbits==32);
H. Peter Anvineba20a72002-04-30 20:53:55 +00001524 }
1525 else
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001526 return 0;
1527}