blob: 39ffd46acb6fd2ef1685d1e6543c2a8ff9fd658c [file] [log] [blame]
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001/* assemble.c code generation for the Netwide Assembler
2 *
3 * The Netwide Assembler is copyright (C) 1996 Simon Tatham and
4 * Julian Hall. All rights reserved. The software is
5 * redistributable under the licence given in the file "Licence"
6 * distributed in the NASM archive.
7 *
8 * the actual codes (C syntax, i.e. octal):
9 * \0 - terminates the code. (Unless it's a literal of course.)
10 * \1, \2, \3 - that many literal bytes follow in the code stream
11 * \4, \6 - the POP/PUSH (respectively) codes for CS, DS, ES, SS
12 * (POP is never used for CS) depending on operand 0
13 * \5, \7 - the second byte of POP/PUSH codes for FS, GS, depending
14 * on operand 0
15 * \10, \11, \12 - a literal byte follows in the code stream, to be added
16 * to the register value of operand 0, 1 or 2
17 * \17 - encodes the literal byte 0. (Some compilers don't take
18 * kindly to a zero byte in the _middle_ of a compile time
19 * string constant, so I had to put this hack in.)
20 * \14, \15, \16 - a signed byte immediate operand, from operand 0, 1 or 2
21 * \20, \21, \22 - a byte immediate operand, from operand 0, 1 or 2
22 * \24, \25, \26 - an unsigned byte immediate operand, from operand 0, 1 or 2
23 * \30, \31, \32 - a word immediate operand, from operand 0, 1 or 2
24 * \34, \35, \36 - select between \3[012] and \4[012] depending on 16/32 bit
25 * assembly mode or the address-size override on the operand
26 * \37 - a word constant, from the _segment_ part of operand 0
27 * \40, \41, \42 - a long immediate operand, from operand 0, 1 or 2
28 * \50, \51, \52 - a byte relative operand, from operand 0, 1 or 2
29 * \60, \61, \62 - a word relative operand, from operand 0, 1 or 2
30 * \64, \65, \66 - select between \6[012] and \7[012] depending on 16/32 bit
31 * assembly mode or the address-size override on the operand
32 * \70, \71, \72 - a long relative operand, from operand 0, 1 or 2
33 * \1ab - a ModRM, calculated on EA in operand a, with the spare
34 * field the register value of operand b.
H. Peter Anvinaf535c12002-04-30 20:59:21 +000035 * \130,\131,\132 - an immediate word or signed byte for operand 0, 1, or 2
36 * \133,\134,\135 - or 2 (s-field) into next opcode byte if operand 0, 1, or 2
37 * is a signed byte rather than a word.
38 * \140,\141,\142 - an immediate dword or signed byte for operand 0, 1, or 2
39 * \143,\144,\145 - or 2 (s-field) into next opcode byte if operand 0, 1, or 2
40 * is a signed byte rather than a dword.
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000041 * \2ab - a ModRM, calculated on EA in operand a, with the spare
42 * field equal to digit b.
43 * \30x - might be an 0x67 byte, depending on the address size of
44 * the memory reference in operand x.
45 * \310 - indicates fixed 16-bit address size, i.e. optional 0x67.
46 * \311 - indicates fixed 32-bit address size, i.e. optional 0x67.
H. Peter Anvinaf535c12002-04-30 20:59:21 +000047 * \312 - (disassembler only) marker on LOOP, LOOPxx instructions.
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000048 * \320 - indicates fixed 16-bit operand size, i.e. optional 0x66.
49 * \321 - indicates fixed 32-bit operand size, i.e. optional 0x66.
50 * \322 - indicates that this instruction is only valid when the
51 * operand size is the default (instruction to disassembler,
52 * generates no code in the assembler)
53 * \330 - a literal byte follows in the code stream, to be added
54 * to the condition code value of the instruction.
H. Peter Anvinef7468f2002-04-30 20:57:59 +000055 * \331 - instruction not valid with REP prefix. Hint for
56 * disassembler only; for SSE instructions.
57 * \332 - disassemble a rep (0xF3 byte) prefix as repe not rep.
58 * \333 - REP prefix (0xF3 byte); for SSE instructions. Not encoded
59 * as a literal byte in order to aid the disassembler.
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000060 * \340 - reserve <operand 0> bytes of uninitialised storage.
61 * Operand 0 had better be a segmentless constant.
H. Peter Anvinaf535c12002-04-30 20:59:21 +000062 * \370,\371,\372 - match only if operand 0, 1, 2 meets byte jump criteria.
63 * \373 - assemble 0x03 if bits==16, 0x05 if bits==32;
64 * used for conditional jump over longer jump
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000065 */
66
67#include <stdio.h>
68#include <string.h>
69
70#include "nasm.h"
H. Peter Anvin6768eb72002-04-30 20:52:26 +000071#include "nasmlib.h"
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000072#include "assemble.h"
73#include "insns.h"
74
75extern struct itemplate *nasm_instructions[];
76
77typedef struct {
78 int sib_present; /* is a SIB byte necessary? */
79 int bytes; /* # of bytes of offset needed */
80 int size; /* lazy - this is sib+bytes+1 */
81 unsigned char modrm, sib; /* the bytes themselves */
82} ea;
83
H. Peter Anvinaf535c12002-04-30 20:59:21 +000084static unsigned long cpu; /* cpu level received from nasm.c */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000085static efunc errfunc;
86static struct ofmt *outfmt;
H. Peter Anvin6768eb72002-04-30 20:52:26 +000087static ListGen *list;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000088
89static long calcsize (long, long, int, insn *, char *);
90static void gencode (long, long, int, insn *, char *, long);
H. Peter Anvineba20a72002-04-30 20:53:55 +000091static int regval (operand *o);
92static int matches (struct itemplate *, insn *);
93static ea * process_ea (operand *, ea *, int, int, int);
94static int chsize (operand *, int);
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000095
H. Peter Anvin6768eb72002-04-30 20:52:26 +000096/*
97 * This routine wrappers the real output format's output routine,
98 * in order to pass a copy of the data off to the listing file
99 * generator at the same time.
100 */
101static void out (long offset, long segto, void *data, unsigned long type,
H. Peter Anvineba20a72002-04-30 20:53:55 +0000102 long segment, long wrt)
103{
104 static long lineno;
105 static char *lnfname;
106
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000107 if ((type & OUT_TYPMASK) == OUT_ADDRESS) {
108 if (segment != NO_SEG || wrt != NO_SEG) {
109 /*
110 * This address is relocated. We must write it as
111 * OUT_ADDRESS, so there's no work to be done here.
112 */
113 list->output (offset, data, type);
H. Peter Anvineba20a72002-04-30 20:53:55 +0000114 }
115 else {
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000116 unsigned char p[4], *q = p;
117 /*
118 * This is a non-relocated address, and we're going to
119 * convert it into RAWDATA format.
120 */
121 if ((type & OUT_SIZMASK) == 4) {
122 WRITELONG (q, * (long *) data);
123 list->output (offset, p, OUT_RAWDATA+4);
H. Peter Anvineba20a72002-04-30 20:53:55 +0000124 }
125 else {
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000126 WRITESHORT (q, * (long *) data);
127 list->output (offset, p, OUT_RAWDATA+2);
128 }
129 }
H. Peter Anvineba20a72002-04-30 20:53:55 +0000130 }
131 else if ((type & OUT_TYPMASK) == OUT_RAWDATA) {
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000132 list->output (offset, data, type);
H. Peter Anvineba20a72002-04-30 20:53:55 +0000133 }
134 else if ((type & OUT_TYPMASK) == OUT_RESERVE) {
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000135 list->output (offset, NULL, type);
H. Peter Anvineba20a72002-04-30 20:53:55 +0000136 }
137 else if ((type & OUT_TYPMASK) == OUT_REL2ADR ||
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000138 (type & OUT_TYPMASK) == OUT_REL4ADR) {
139 list->output (offset, data, type);
140 }
141
H. Peter Anvineba20a72002-04-30 20:53:55 +0000142 if (src_get(&lineno,&lnfname))
143 outfmt->current_dfmt->linenum(lnfname,lineno,segto);
144
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000145 outfmt->output (segto, data, type, segment, wrt);
146}
147
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000148static int jmp_match (long segment, long offset, int bits,
149 insn *ins, char *code)
150{ long isize;
151 unsigned char c = code[0];
152
153
154 if (c != 0370) return 0;
H. Peter Anvin4cf17482002-04-30 21:01:38 +0000155 if (ins->oprs[0].opflags & OPFLAG_FORWARD) return (!pass0); /* match a forward reference */
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000156
157 isize = calcsize (segment, offset, bits, ins, code);
158 if (ins->oprs[0].segment != segment) return 0;
159 isize = ins->oprs[0].offset - offset - isize; /* isize is now the delta */
160 if (isize >= -128L && isize <= 127L) return 1; /* it is byte size */
161
162 return 0;
163}
164
165
166long assemble (long segment, long offset, int bits, unsigned long cp,
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000167 insn *instruction, struct ofmt *output, efunc error,
H. Peter Anvineba20a72002-04-30 20:53:55 +0000168 ListGen *listgen)
169{
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000170 struct itemplate *temp;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000171 int j;
172 int size_prob;
173 long insn_end;
174 long itimes;
175 long start = offset;
176 long wsize = 0; /* size for DB etc. */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000177
178 errfunc = error; /* to pass to other functions */
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000179 cpu = cp;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000180 outfmt = output; /* likewise */
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000181 list = listgen; /* and again */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000182
H. Peter Anvineba20a72002-04-30 20:53:55 +0000183 switch (instruction->opcode)
184 {
185 case -1: return 0;
186 case I_DB: wsize = 1; break;
187 case I_DW: wsize = 2; break;
188 case I_DD: wsize = 4; break;
189 case I_DQ: wsize = 8; break;
190 case I_DT: wsize = 10; break;
191 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000192
H. Peter Anvineba20a72002-04-30 20:53:55 +0000193 if (wsize) {
194 extop * e;
195 long t = instruction->times;
196 if (t < 0)
197 errfunc(ERR_PANIC, "instruction->times < 0 (%ld) in assemble()",t);
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000198
H. Peter Anvineba20a72002-04-30 20:53:55 +0000199 while (t--) /* repeat TIMES times */
200 {
201 for (e = instruction->eops; e; e = e->next)
202 {
203 if (e->type == EOT_DB_NUMBER)
204 {
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000205 if (wsize == 1) {
206 if (e->segment != NO_SEG)
207 errfunc (ERR_NONFATAL,
208 "one-byte relocation attempted");
209 else {
H. Peter Anvin41bf8002002-04-30 20:58:18 +0000210 unsigned char out_byte = e->offset;
211 out (offset, segment, &out_byte, OUT_RAWDATA+1,
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000212 NO_SEG, NO_SEG);
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000213 }
H. Peter Anvineba20a72002-04-30 20:53:55 +0000214 }
215 else if (wsize > 5) {
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000216 errfunc (ERR_NONFATAL, "integer supplied to a D%c"
217 " instruction", wsize==8 ? 'Q' : 'T');
H. Peter Anvineba20a72002-04-30 20:53:55 +0000218 }
219 else
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000220 out (offset, segment, &e->offset,
221 OUT_ADDRESS+wsize, e->segment,
222 e->wrt);
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000223 offset += wsize;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000224 }
225 else if (e->type == EOT_DB_STRING)
226 {
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000227 int align;
228
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000229 out (offset, segment, e->stringval,
230 OUT_RAWDATA+e->stringlen, NO_SEG, NO_SEG);
H. Peter Anvineba20a72002-04-30 20:53:55 +0000231 align = e->stringlen % wsize;
232
233 if (align) {
234 align = wsize - align;
235 out (offset, segment, "\0\0\0\0\0\0\0\0",
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000236 OUT_RAWDATA+align, NO_SEG, NO_SEG);
H. Peter Anvineba20a72002-04-30 20:53:55 +0000237 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000238 offset += e->stringlen + align;
239 }
240 }
H. Peter Anvineba20a72002-04-30 20:53:55 +0000241 if (t > 0 && t == instruction->times-1)
242 {
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000243 /*
244 * Dummy call to list->output to give the offset to the
245 * listing module.
246 */
247 list->output (offset, NULL, OUT_RAWDATA);
248 list->uplevel (LIST_TIMES);
249 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000250 }
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000251 if (instruction->times > 1)
252 list->downlevel (LIST_TIMES);
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000253 return offset - start;
254 }
255
H. Peter Anvineba20a72002-04-30 20:53:55 +0000256 if (instruction->opcode == I_INCBIN)
257 {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000258 static char fname[FILENAME_MAX];
H. Peter Anvineba20a72002-04-30 20:53:55 +0000259 FILE * fp;
260 long len;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000261
262 len = FILENAME_MAX-1;
263 if (len > instruction->eops->stringlen)
264 len = instruction->eops->stringlen;
265 strncpy (fname, instruction->eops->stringval, len);
266 fname[len] = '\0';
H. Peter Anvineba20a72002-04-30 20:53:55 +0000267
268 if ( (fp = fopen(fname, "rb")) == NULL)
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000269 error (ERR_NONFATAL, "`incbin': unable to open file `%s'", fname);
270 else if (fseek(fp, 0L, SEEK_END) < 0)
271 error (ERR_NONFATAL, "`incbin': unable to seek on file `%s'",
272 fname);
H. Peter Anvineba20a72002-04-30 20:53:55 +0000273 else
274 {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000275 static char buf[2048];
276 long t = instruction->times;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000277 long base = 0;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000278
279 len = ftell (fp);
280 if (instruction->eops->next) {
H. Peter Anvineba20a72002-04-30 20:53:55 +0000281 base = instruction->eops->next->offset;
282 len -= base;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000283 if (instruction->eops->next->next &&
284 len > instruction->eops->next->next->offset)
285 len = instruction->eops->next->next->offset;
286 }
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000287 /*
288 * Dummy call to list->output to give the offset to the
289 * listing module.
290 */
291 list->output (offset, NULL, OUT_RAWDATA);
292 list->uplevel(LIST_INCBIN);
H. Peter Anvineba20a72002-04-30 20:53:55 +0000293 while (t--)
294 {
295 long l;
296
297 fseek (fp, base, SEEK_SET);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000298 l = len;
299 while (l > 0) {
300 long m = fread (buf, 1, (l>sizeof(buf)?sizeof(buf):l),
301 fp);
302 if (!m) {
303 /*
304 * This shouldn't happen unless the file
305 * actually changes while we are reading
306 * it.
307 */
308 error (ERR_NONFATAL, "`incbin': unexpected EOF while"
309 " reading file `%s'", fname);
H. Peter Anvineba20a72002-04-30 20:53:55 +0000310 t=0; /* Try to exit cleanly */
311 break;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000312 }
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000313 out (offset, segment, buf, OUT_RAWDATA+m,
314 NO_SEG, NO_SEG);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000315 l -= m;
316 }
317 }
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000318 list->downlevel(LIST_INCBIN);
319 if (instruction->times > 1) {
320 /*
321 * Dummy call to list->output to give the offset to the
322 * listing module.
323 */
324 list->output (offset, NULL, OUT_RAWDATA);
325 list->uplevel(LIST_TIMES);
326 list->downlevel(LIST_TIMES);
327 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000328 fclose (fp);
329 return instruction->times * len;
330 }
331 return 0; /* if we're here, there's an error */
332 }
333
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000334 size_prob = FALSE;
335 temp = nasm_instructions[instruction->opcode];
336 while (temp->opcode != -1) {
337 int m = matches (temp, instruction);
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000338 if (m == 99)
339 m += jmp_match(segment, offset, bits, instruction, temp->code);
H. Peter Anvineba20a72002-04-30 20:53:55 +0000340
341 if (m == 100) /* matches! */
342 {
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000343 char *codes = temp->code;
344 long insn_size = calcsize(segment, offset, bits,
345 instruction, codes);
346 itimes = instruction->times;
347 if (insn_size < 0) /* shouldn't be, on pass two */
348 error (ERR_PANIC, "errors made it through from pass one");
349 else while (itimes--) {
350 insn_end = offset + insn_size;
351 for (j=0; j<instruction->nprefix; j++) {
H. Peter Anvineba20a72002-04-30 20:53:55 +0000352 unsigned char c=0;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000353 switch (instruction->prefixes[j]) {
354 case P_LOCK:
355 c = 0xF0; break;
356 case P_REPNE: case P_REPNZ:
357 c = 0xF2; break;
358 case P_REPE: case P_REPZ: case P_REP:
359 c = 0xF3; break;
360 case R_CS: c = 0x2E; break;
361 case R_DS: c = 0x3E; break;
362 case R_ES: c = 0x26; break;
363 case R_FS: c = 0x64; break;
364 case R_GS: c = 0x65; break;
365 case R_SS: c = 0x36; break;
366 case P_A16:
H. Peter Anvineba20a72002-04-30 20:53:55 +0000367 if (bits != 16)
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000368 c = 0x67;
369 break;
370 case P_A32:
H. Peter Anvineba20a72002-04-30 20:53:55 +0000371 if (bits != 32)
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000372 c = 0x67;
373 break;
374 case P_O16:
H. Peter Anvineba20a72002-04-30 20:53:55 +0000375 if (bits != 16)
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000376 c = 0x66;
377 break;
378 case P_O32:
H. Peter Anvineba20a72002-04-30 20:53:55 +0000379 if (bits != 32)
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000380 c = 0x66;
381 break;
382 default:
383 error (ERR_PANIC,
384 "invalid instruction prefix");
385 }
H. Peter Anvineba20a72002-04-30 20:53:55 +0000386 if (c != 0) {
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000387 out (offset, segment, &c, OUT_RAWDATA+1,
388 NO_SEG, NO_SEG);
H. Peter Anvineba20a72002-04-30 20:53:55 +0000389 offset++;
390 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000391 }
392 gencode (segment, offset, bits, instruction, codes, insn_end);
393 offset += insn_size;
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000394 if (itimes > 0 && itimes == instruction->times-1) {
395 /*
396 * Dummy call to list->output to give the offset to the
397 * listing module.
398 */
399 list->output (offset, NULL, OUT_RAWDATA);
400 list->uplevel (LIST_TIMES);
401 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000402 }
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000403 if (instruction->times > 1)
404 list->downlevel (LIST_TIMES);
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000405 return offset - start;
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000406 } else if (m > 0 && m > size_prob) {
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000407 size_prob = m;
408 }
409 temp++;
410 }
H. Peter Anvineba20a72002-04-30 20:53:55 +0000411
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000412 if (temp->opcode == -1) { /* didn't match any instruction */
413 if (size_prob == 1) /* would have matched, but for size */
414 error (ERR_NONFATAL, "operation size not specified");
415 else if (size_prob == 2)
416 error (ERR_NONFATAL, "mismatch in operand sizes");
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000417 else if (size_prob == 3)
418 error (ERR_NONFATAL, "no instruction for this cpu level");
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000419 else
420 error (ERR_NONFATAL,
421 "invalid combination of opcode and operands");
422 }
423 return 0;
424}
425
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000426long insn_size (long segment, long offset, int bits, unsigned long cp,
H. Peter Anvineba20a72002-04-30 20:53:55 +0000427 insn *instruction, efunc error)
428{
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000429 struct itemplate *temp;
430
431 errfunc = error; /* to pass to other functions */
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000432 cpu = cp;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000433
434 if (instruction->opcode == -1)
435 return 0;
436
437 if (instruction->opcode == I_DB ||
438 instruction->opcode == I_DW ||
439 instruction->opcode == I_DD ||
440 instruction->opcode == I_DQ ||
H. Peter Anvineba20a72002-04-30 20:53:55 +0000441 instruction->opcode == I_DT)
442 {
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000443 extop *e;
444 long isize, osize, wsize = 0; /* placate gcc */
445
446 isize = 0;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000447 switch (instruction->opcode)
448 {
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000449 case I_DB: wsize = 1; break;
450 case I_DW: wsize = 2; break;
451 case I_DD: wsize = 4; break;
452 case I_DQ: wsize = 8; break;
453 case I_DT: wsize = 10; break;
454 }
455
H. Peter Anvineba20a72002-04-30 20:53:55 +0000456 for (e = instruction->eops; e; e = e->next)
457 {
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000458 long align;
459
460 osize = 0;
461 if (e->type == EOT_DB_NUMBER)
462 osize = 1;
463 else if (e->type == EOT_DB_STRING)
464 osize = e->stringlen;
465
466 align = (-osize) % wsize;
467 if (align < 0)
468 align += wsize;
469 isize += osize + align;
470 }
471 return isize * instruction->times;
472 }
473
H. Peter Anvineba20a72002-04-30 20:53:55 +0000474 if (instruction->opcode == I_INCBIN)
475 {
476 char fname[FILENAME_MAX];
477 FILE * fp;
478 long len;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000479
480 len = FILENAME_MAX-1;
481 if (len > instruction->eops->stringlen)
482 len = instruction->eops->stringlen;
483 strncpy (fname, instruction->eops->stringval, len);
484 fname[len] = '\0';
H. Peter Anvineba20a72002-04-30 20:53:55 +0000485 if ( (fp = fopen(fname, "rb")) == NULL )
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000486 error (ERR_NONFATAL, "`incbin': unable to open file `%s'", fname);
487 else if (fseek(fp, 0L, SEEK_END) < 0)
488 error (ERR_NONFATAL, "`incbin': unable to seek on file `%s'",
489 fname);
H. Peter Anvineba20a72002-04-30 20:53:55 +0000490 else
491 {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000492 len = ftell (fp);
493 fclose (fp);
H. Peter Anvineba20a72002-04-30 20:53:55 +0000494 if (instruction->eops->next)
495 {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000496 len -= instruction->eops->next->offset;
497 if (instruction->eops->next->next &&
498 len > instruction->eops->next->next->offset)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000499 {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000500 len = instruction->eops->next->next->offset;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000501 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000502 }
503 return instruction->times * len;
504 }
505 return 0; /* if we're here, there's an error */
506 }
507
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000508 temp = nasm_instructions[instruction->opcode];
509 while (temp->opcode != -1) {
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000510 int m = matches(temp, instruction);
511 if (m == 99)
512 m += jmp_match(segment, offset, bits, instruction, temp->code);
513
514 if (m == 100) {
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000515 /* we've matched an instruction. */
H. Peter Anvineba20a72002-04-30 20:53:55 +0000516 long isize;
517 char * codes = temp->code;
518 int j;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000519
520 isize = calcsize(segment, offset, bits, instruction, codes);
521 if (isize < 0)
522 return -1;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000523 for (j = 0; j < instruction->nprefix; j++)
524 {
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000525 if ((instruction->prefixes[j] != P_A16 &&
526 instruction->prefixes[j] != P_O16 && bits==16) ||
527 (instruction->prefixes[j] != P_A32 &&
528 instruction->prefixes[j] != P_O32 && bits==32))
H. Peter Anvineba20a72002-04-30 20:53:55 +0000529 {
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000530 isize++;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000531 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000532 }
533 return isize * instruction->times;
534 }
535 temp++;
536 }
537 return -1; /* didn't match any instruction */
538}
539
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000540
541/* check that opn[op] is a signed byte of size 16 or 32,
542 and return the signed value*/
543static int is_sbyte (insn *ins, int op, int size)
544{
545 signed long v;
546 int ret;
547
548 ret = !(ins->forw_ref && ins->oprs[op].opflags ) && /* dead in the water on forward reference or External */
H. Peter Anvin4cf17482002-04-30 21:01:38 +0000549 (optimizing || !(ins->oprs[op].type & (BITS16|BITS32))) &&
H. Peter Anvin734b1882002-04-30 21:01:08 +0000550 ins->oprs[op].wrt==NO_SEG && ins->oprs[op].segment==NO_SEG;
551
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000552 v = ins->oprs[op].offset;
553 if (size==16) v = (signed short)v; /* sign extend if 16 bits */
554
555 return ret && v>=-128L && v<=127L;
556}
557
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000558static long calcsize (long segment, long offset, int bits,
H. Peter Anvineba20a72002-04-30 20:53:55 +0000559 insn *ins, char *codes)
560{
561 long length = 0;
562 unsigned char c;
563
564 (void) segment; /* Don't warn that this parameter is unused */
565 (void) offset; /* Don't warn that this parameter is unused */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000566
567 while (*codes) switch (c = *codes++) {
568 case 01: case 02: case 03:
569 codes += c, length += c; break;
570 case 04: case 05: case 06: case 07:
571 length++; break;
572 case 010: case 011: case 012:
573 codes++, length++; break;
574 case 017:
575 length++; break;
576 case 014: case 015: case 016:
577 length++; break;
578 case 020: case 021: case 022:
579 length++; break;
580 case 024: case 025: case 026:
581 length++; break;
582 case 030: case 031: case 032:
583 length += 2; break;
584 case 034: case 035: case 036:
585 length += ((ins->oprs[c-034].addr_size ?
586 ins->oprs[c-034].addr_size : bits) == 16 ? 2 : 4); break;
587 case 037:
588 length += 2; break;
589 case 040: case 041: case 042:
590 length += 4; break;
591 case 050: case 051: case 052:
592 length++; break;
593 case 060: case 061: case 062:
594 length += 2; break;
595 case 064: case 065: case 066:
596 length += ((ins->oprs[c-064].addr_size ?
597 ins->oprs[c-064].addr_size : bits) == 16 ? 2 : 4); break;
598 case 070: case 071: case 072:
599 length += 4; break;
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000600 case 0130: case 0131: case 0132:
601 length += is_sbyte(ins, c-0130, 16) ? 1 : 2; break;
602 case 0133: case 0134: case 0135:
603 codes+=2; length++; break;
604 case 0140: case 0141: case 0142:
605 length += is_sbyte(ins, c-0140, 32) ? 1 : 4; break;
606 case 0143: case 0144: case 0145:
607 codes+=2; length++; break;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000608 case 0300: case 0301: case 0302:
609 length += chsize (&ins->oprs[c-0300], bits);
610 break;
611 case 0310:
612 length += (bits==32);
613 break;
614 case 0311:
615 length += (bits==16);
616 break;
617 case 0312:
618 break;
619 case 0320:
620 length += (bits==32);
621 break;
622 case 0321:
623 length += (bits==16);
624 break;
625 case 0322:
626 break;
627 case 0330:
628 codes++, length++; break;
H. Peter Anvinef7468f2002-04-30 20:57:59 +0000629 case 0331:
630 case 0332:
631 break;
632 case 0333:
633 length++; break;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000634 case 0340: case 0341: case 0342:
635 if (ins->oprs[0].segment != NO_SEG)
636 errfunc (ERR_NONFATAL, "attempt to reserve non-constant"
637 " quantity of BSS space");
638 else
639 length += ins->oprs[0].offset << (c-0340);
640 break;
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000641 case 0370: case 0371: case 0372:
642 break;
643 case 0373:
644 length++; break;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000645 default: /* can't do it by 'case' statements */
646 if (c>=0100 && c<=0277) { /* it's an EA */
647 ea ea_data;
H. Peter Anvinea838272002-04-30 20:51:53 +0000648 if (!process_ea (&ins->oprs[(c>>3)&7], &ea_data, bits, 0,
649 ins->forw_ref)) {
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000650 errfunc (ERR_NONFATAL, "invalid effective address");
651 return -1;
652 } else
653 length += ea_data.size;
654 } else
655 errfunc (ERR_PANIC, "internal instruction table corrupt"
656 ": instruction code 0x%02X given", c);
657 }
658 return length;
659}
660
661static void gencode (long segment, long offset, int bits,
H. Peter Anvineba20a72002-04-30 20:53:55 +0000662 insn *ins, char *codes, long insn_end)
663{
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000664 static char condval[] = { /* conditional opcodes */
665 0x7, 0x3, 0x2, 0x6, 0x2, 0x4, 0xF, 0xD, 0xC, 0xE, 0x6, 0x2,
666 0x3, 0x7, 0x3, 0x5, 0xE, 0xC, 0xD, 0xF, 0x1, 0xB, 0x9, 0x5,
667 0x0, 0xA, 0xA, 0xB, 0x8, 0x4
668 };
H. Peter Anvineba20a72002-04-30 20:53:55 +0000669 unsigned char c;
670 unsigned char bytes[4];
671 long data, size;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000672
H. Peter Anvineba20a72002-04-30 20:53:55 +0000673 while (*codes)
674 switch (c = *codes++)
675 {
676 case 01: case 02: case 03:
677 out (offset, segment, codes, OUT_RAWDATA+c, NO_SEG, NO_SEG);
678 codes += c;
679 offset += c;
680 break;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000681
H. Peter Anvineba20a72002-04-30 20:53:55 +0000682 case 04: case 06:
683 switch (ins->oprs[0].basereg)
684 {
685 case R_CS:
686 bytes[0] = 0x0E + (c == 0x04 ? 1 : 0); break;
687 case R_DS:
688 bytes[0] = 0x1E + (c == 0x04 ? 1 : 0); break;
689 case R_ES:
690 bytes[0] = 0x06 + (c == 0x04 ? 1 : 0); break;
691 case R_SS:
692 bytes[0] = 0x16 + (c == 0x04 ? 1 : 0); break;
693 default:
H. Peter Anvin4836e332002-04-30 20:56:43 +0000694 errfunc (ERR_PANIC, "bizarre 8086 segment register received");
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000695 }
H. Peter Anvineba20a72002-04-30 20:53:55 +0000696 out (offset, segment, bytes, OUT_RAWDATA+1, NO_SEG, NO_SEG);
697 offset++;
698 break;
699
700 case 05: case 07:
701 switch (ins->oprs[0].basereg) {
702 case R_FS: bytes[0] = 0xA0 + (c == 0x05 ? 1 : 0); break;
703 case R_GS: bytes[0] = 0xA8 + (c == 0x05 ? 1 : 0); break;
704 default:
H. Peter Anvin4836e332002-04-30 20:56:43 +0000705 errfunc (ERR_PANIC, "bizarre 386 segment register received");
H. Peter Anvineba20a72002-04-30 20:53:55 +0000706 }
707 out (offset, segment, bytes, OUT_RAWDATA+1, NO_SEG, NO_SEG);
708 offset++;
709 break;
710
711 case 010: case 011: case 012:
712 bytes[0] = *codes++ + regval(&ins->oprs[c-010]);
713 out (offset, segment, bytes, OUT_RAWDATA+1, NO_SEG, NO_SEG);
714 offset += 1;
715 break;
716
717 case 017:
718 bytes[0] = 0;
719 out (offset, segment, bytes, OUT_RAWDATA+1, NO_SEG, NO_SEG);
720 offset += 1;
721 break;
722
723 case 014: case 015: case 016:
724 if (ins->oprs[c-014].offset < -128
725 || ins->oprs[c-014].offset > 127)
726 {
727 errfunc (ERR_WARNING, "signed byte value exceeds bounds");
728 }
729
730 if (ins->oprs[c-014].segment != NO_SEG)
731 {
732 data = ins->oprs[c-014].offset;
733 out (offset, segment, &data, OUT_ADDRESS+1,
734 ins->oprs[c-014].segment, ins->oprs[c-014].wrt);
735 }
736 else {
737 bytes[0] = ins->oprs[c-014].offset;
738 out (offset, segment, bytes, OUT_RAWDATA+1, NO_SEG, NO_SEG);
739 }
740 offset += 1;
741 break;
742
743 case 020: case 021: case 022:
744 if (ins->oprs[c-020].offset < -256
745 || ins->oprs[c-020].offset > 255)
746 {
747 errfunc (ERR_WARNING, "byte value exceeds bounds");
748 }
749 if (ins->oprs[c-020].segment != NO_SEG) {
750 data = ins->oprs[c-020].offset;
751 out (offset, segment, &data, OUT_ADDRESS+1,
752 ins->oprs[c-020].segment, ins->oprs[c-020].wrt);
753 }
754 else {
755 bytes[0] = ins->oprs[c-020].offset;
756 out (offset, segment, bytes, OUT_RAWDATA+1, NO_SEG, NO_SEG);
757 }
758 offset += 1;
759 break;
760
761 case 024: case 025: case 026:
762 if (ins->oprs[c-024].offset < 0 || ins->oprs[c-024].offset > 255)
763 errfunc (ERR_WARNING, "unsigned byte value exceeds bounds");
764 if (ins->oprs[c-024].segment != NO_SEG) {
765 data = ins->oprs[c-024].offset;
766 out (offset, segment, &data, OUT_ADDRESS+1,
767 ins->oprs[c-024].segment, ins->oprs[c-024].wrt);
768 }
769 else {
770 bytes[0] = ins->oprs[c-024].offset;
771 out (offset, segment, bytes, OUT_RAWDATA+1, NO_SEG, NO_SEG);
772 }
773 offset += 1;
774 break;
775
776 case 030: case 031: case 032:
777 if (ins->oprs[c-030].segment == NO_SEG &&
778 ins->oprs[c-030].wrt == NO_SEG &&
779 (ins->oprs[c-030].offset < -65536L ||
780 ins->oprs[c-030].offset > 65535L))
781 {
782 errfunc (ERR_WARNING, "word value exceeds bounds");
783 }
784 data = ins->oprs[c-030].offset;
785 out (offset, segment, &data, OUT_ADDRESS+2,
786 ins->oprs[c-030].segment, ins->oprs[c-030].wrt);
787 offset += 2;
788 break;
789
790 case 034: case 035: case 036:
791 data = ins->oprs[c-034].offset;
792 size = ((ins->oprs[c-034].addr_size ?
793 ins->oprs[c-034].addr_size : bits) == 16 ? 2 : 4);
H. Peter Anvin4cf17482002-04-30 21:01:38 +0000794 if (size==2 && (data < -65536L || data > 65535L))
H. Peter Anvineba20a72002-04-30 20:53:55 +0000795 errfunc (ERR_WARNING, "word value exceeds bounds");
796 out (offset, segment, &data, OUT_ADDRESS+size,
797 ins->oprs[c-034].segment, ins->oprs[c-034].wrt);
798 offset += size;
799 break;
800
801 case 037:
802 if (ins->oprs[0].segment == NO_SEG)
803 errfunc (ERR_NONFATAL, "value referenced by FAR is not"
804 " relocatable");
805 data = 0L;
806 out (offset, segment, &data, OUT_ADDRESS+2,
807 outfmt->segbase(1+ins->oprs[0].segment),
808 ins->oprs[0].wrt);
809 offset += 2;
810 break;
811
812 case 040: case 041: case 042:
813 data = ins->oprs[c-040].offset;
814 out (offset, segment, &data, OUT_ADDRESS+4,
815 ins->oprs[c-040].segment, ins->oprs[c-040].wrt);
816 offset += 4;
817 break;
818
819 case 050: case 051: case 052:
820 if (ins->oprs[c-050].segment != segment)
821 errfunc (ERR_NONFATAL, "short relative jump outside segment");
822 data = ins->oprs[c-050].offset - insn_end;
823 if (data > 127 || data < -128)
824 errfunc (ERR_NONFATAL, "short jump is out of range");
825 bytes[0] = data;
826 out (offset, segment, bytes, OUT_RAWDATA+1, NO_SEG, NO_SEG);
827 offset += 1;
828 break;
829
830 case 060: case 061: case 062:
831 if (ins->oprs[c-060].segment != segment) {
832 data = ins->oprs[c-060].offset;
833 out (offset, segment, &data, OUT_REL2ADR+insn_end-offset,
834 ins->oprs[c-060].segment, ins->oprs[c-060].wrt);
835 } else {
836 data = ins->oprs[c-060].offset - insn_end;
837 out (offset, segment, &data,
838 OUT_ADDRESS+2, NO_SEG, NO_SEG);
839 }
840 offset += 2;
841 break;
842
843 case 064: case 065: case 066:
844 size = ((ins->oprs[c-064].addr_size ?
845 ins->oprs[c-064].addr_size : bits) == 16 ? 2 : 4);
846 if (ins->oprs[c-064].segment != segment) {
847 data = ins->oprs[c-064].offset;
848 size = (bits == 16 ? OUT_REL2ADR : OUT_REL4ADR);
849 out (offset, segment, &data, size+insn_end-offset,
850 ins->oprs[c-064].segment, ins->oprs[c-064].wrt);
851 size = (bits == 16 ? 2 : 4);
852 } else {
853 data = ins->oprs[c-064].offset - insn_end;
854 out (offset, segment, &data,
855 OUT_ADDRESS+size, NO_SEG, NO_SEG);
856 }
857 offset += size;
858 break;
859
860 case 070: case 071: case 072:
861 if (ins->oprs[c-070].segment != segment) {
862 data = ins->oprs[c-070].offset;
863 out (offset, segment, &data, OUT_REL4ADR+insn_end-offset,
864 ins->oprs[c-070].segment, ins->oprs[c-070].wrt);
865 } else {
866 data = ins->oprs[c-070].offset - insn_end;
867 out (offset, segment, &data,
868 OUT_ADDRESS+4, NO_SEG, NO_SEG);
869 }
870 offset += 4;
871 break;
872
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000873 case 0130: case 0131: case 0132:
874 data = ins->oprs[c-0130].offset;
875 if (is_sbyte(ins, c-0130, 16)) {
876 out (offset, segment, &data, OUT_RAWDATA+1, NO_SEG, NO_SEG);
877 offset++;
878 } else {
879 if (ins->oprs[c-0130].segment == NO_SEG &&
880 ins->oprs[c-0130].wrt == NO_SEG &&
881 (data < -65536L || data > 65535L)) {
882 errfunc (ERR_WARNING, "word value exceeds bounds");
883 }
884 out (offset, segment, &data, OUT_ADDRESS+2,
885 ins->oprs[c-0130].segment, ins->oprs[c-0130].wrt);
886 offset += 2;
887 }
888 break;
889
890 case 0133: case 0134: case 0135:
891 codes++;
892 bytes[0] = *codes++;
893 if (is_sbyte(ins, c-0133, 16)) bytes[0] |= 2; /* s-bit */
894 out (offset, segment, bytes, OUT_RAWDATA+1, NO_SEG, NO_SEG);
895 offset++;
896 break;
897
898 case 0140: case 0141: case 0142:
899 data = ins->oprs[c-0140].offset;
900 if (is_sbyte(ins, c-0140, 32)) {
901 out (offset, segment, &data, OUT_RAWDATA+1, NO_SEG, NO_SEG);
902 offset++;
903 } else {
904 out (offset, segment, &data, OUT_ADDRESS+4,
905 ins->oprs[c-0140].segment, ins->oprs[c-0140].wrt);
906 offset += 4;
907 }
908 break;
909
910 case 0143: case 0144: case 0145:
911 codes++;
912 bytes[0] = *codes++;
913 if (is_sbyte(ins, c-0143, 32)) bytes[0] |= 2; /* s-bit */
914 out (offset, segment, bytes, OUT_RAWDATA+1, NO_SEG, NO_SEG);
915 offset++;
916 break;
917
H. Peter Anvineba20a72002-04-30 20:53:55 +0000918 case 0300: case 0301: case 0302:
919 if (chsize (&ins->oprs[c-0300], bits)) {
920 *bytes = 0x67;
921 out (offset, segment, bytes,
922 OUT_RAWDATA+1, NO_SEG, NO_SEG);
923 offset += 1;
924 } else
925 offset += 0;
926 break;
927
928 case 0310:
929 if (bits==32) {
930 *bytes = 0x67;
931 out (offset, segment, bytes,
932 OUT_RAWDATA+1, NO_SEG, NO_SEG);
933 offset += 1;
934 } else
935 offset += 0;
936 break;
937
938 case 0311:
939 if (bits==16) {
940 *bytes = 0x67;
941 out (offset, segment, bytes,
942 OUT_RAWDATA+1, NO_SEG, NO_SEG);
943 offset += 1;
944 } else
945 offset += 0;
946 break;
947
948 case 0312:
949 break;
950
951 case 0320:
952 if (bits==32) {
953 *bytes = 0x66;
954 out (offset, segment, bytes,
955 OUT_RAWDATA+1, NO_SEG, NO_SEG);
956 offset += 1;
957 } else
958 offset += 0;
959 break;
960
961 case 0321:
962 if (bits==16) {
963 *bytes = 0x66;
964 out (offset, segment, bytes,
965 OUT_RAWDATA+1, NO_SEG, NO_SEG);
966 offset += 1;
967 } else
968 offset += 0;
969 break;
970
971 case 0322:
972 break;
973
974 case 0330:
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000975 *bytes = *codes++ ^ condval[ins->condition];
H. Peter Anvineba20a72002-04-30 20:53:55 +0000976 out (offset, segment, bytes,
977 OUT_RAWDATA+1, NO_SEG, NO_SEG);
978 offset += 1;
979 break;
980
H. Peter Anvinef7468f2002-04-30 20:57:59 +0000981 case 0331:
982 case 0332:
983 break;
984
985 case 0333:
986 *bytes = 0xF3;
987 out (offset, segment, bytes,
988 OUT_RAWDATA+1, NO_SEG, NO_SEG);
989 offset += 1;
990 break;
991
H. Peter Anvineba20a72002-04-30 20:53:55 +0000992 case 0340: case 0341: case 0342:
993 if (ins->oprs[0].segment != NO_SEG)
994 errfunc (ERR_PANIC, "non-constant BSS size in pass two");
995 else {
996 long size = ins->oprs[0].offset << (c-0340);
997 if (size > 0)
998 out (offset, segment, NULL,
999 OUT_RESERVE+size, NO_SEG, NO_SEG);
1000 offset += size;
1001 }
1002 break;
1003
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001004 case 0370: case 0371: case 0372:
1005 break;
1006
1007 case 0373:
1008 *bytes = bits==16 ? 3 : 5;
1009 out (offset, segment, bytes,
1010 OUT_RAWDATA+1, NO_SEG, NO_SEG);
1011 offset += 1;
1012 break;
1013
H. Peter Anvineba20a72002-04-30 20:53:55 +00001014 default: /* can't do it by 'case' statements */
1015 if (c>=0100 && c<=0277) { /* it's an EA */
1016 ea ea_data;
1017 int rfield;
1018 unsigned char *p;
1019 long s;
1020
1021 if (c<=0177) /* pick rfield from operand b */
1022 rfield = regval (&ins->oprs[c&7]);
1023 else /* rfield is constant */
1024 rfield = c & 7;
1025
1026 if (!process_ea (&ins->oprs[(c>>3)&7], &ea_data, bits, rfield,
1027 ins->forw_ref))
1028 {
1029 errfunc (ERR_NONFATAL, "invalid effective address");
1030 }
1031
1032 p = bytes;
1033 *p++ = ea_data.modrm;
1034 if (ea_data.sib_present)
1035 *p++ = ea_data.sib;
1036
1037 s = p-bytes;
1038 out (offset, segment, bytes, OUT_RAWDATA + s,
1039 NO_SEG, NO_SEG);
1040
1041 switch (ea_data.bytes) {
1042 case 0:
1043 break;
1044 case 1:
1045 if (ins->oprs[(c>>3)&7].segment != NO_SEG) {
1046 data = ins->oprs[(c>>3)&7].offset;
1047 out (offset, segment, &data, OUT_ADDRESS+1,
1048 ins->oprs[(c>>3)&7].segment,
1049 ins->oprs[(c>>3)&7].wrt);
1050 } else {
1051 *bytes = ins->oprs[(c>>3)&7].offset;
1052 out (offset, segment, bytes, OUT_RAWDATA+1,
1053 NO_SEG, NO_SEG);
1054 }
1055 s++;
1056 break;
1057 case 2:
1058 case 4:
1059 data = ins->oprs[(c>>3)&7].offset;
1060 out (offset, segment, &data,
1061 OUT_ADDRESS+ea_data.bytes,
1062 ins->oprs[(c>>3)&7].segment, ins->oprs[(c>>3)&7].wrt);
1063 s += ea_data.bytes;
1064 break;
1065 }
1066 offset += s;
1067 } else
1068 errfunc (ERR_PANIC, "internal instruction table corrupt"
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001069 ": instruction code 0x%02X given", c);
H. Peter Anvineba20a72002-04-30 20:53:55 +00001070 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001071}
1072
H. Peter Anvineba20a72002-04-30 20:53:55 +00001073static int regval (operand *o)
1074{
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001075 switch (o->basereg) {
1076 case R_EAX: case R_AX: case R_AL: case R_ES: case R_CR0: case R_DR0:
H. Peter Anvin4836e332002-04-30 20:56:43 +00001077 case R_ST0: case R_MM0: case R_XMM0:
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001078 return 0;
1079 case R_ECX: case R_CX: case R_CL: case R_CS: case R_DR1: case R_ST1:
H. Peter Anvin4836e332002-04-30 20:56:43 +00001080 case R_MM1: case R_XMM1:
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001081 return 1;
1082 case R_EDX: case R_DX: case R_DL: case R_SS: case R_CR2: case R_DR2:
H. Peter Anvin4836e332002-04-30 20:56:43 +00001083 case R_ST2: case R_MM2: case R_XMM2:
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001084 return 2;
1085 case R_EBX: case R_BX: case R_BL: case R_DS: case R_CR3: case R_DR3:
H. Peter Anvin4836e332002-04-30 20:56:43 +00001086 case R_TR3: case R_ST3: case R_MM3: case R_XMM3:
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001087 return 3;
1088 case R_ESP: case R_SP: case R_AH: case R_FS: case R_CR4: case R_TR4:
H. Peter Anvin4836e332002-04-30 20:56:43 +00001089 case R_ST4: case R_MM4: case R_XMM4:
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001090 return 4;
1091 case R_EBP: case R_BP: case R_CH: case R_GS: case R_TR5: case R_ST5:
H. Peter Anvin4836e332002-04-30 20:56:43 +00001092 case R_MM5: case R_XMM5:
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001093 return 5;
1094 case R_ESI: case R_SI: case R_DH: case R_DR6: case R_TR6: case R_ST6:
H. Peter Anvin4836e332002-04-30 20:56:43 +00001095 case R_MM6: case R_XMM6:
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001096 return 6;
1097 case R_EDI: case R_DI: case R_BH: case R_DR7: case R_TR7: case R_ST7:
H. Peter Anvin4836e332002-04-30 20:56:43 +00001098 case R_MM7: case R_XMM7:
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001099 return 7;
1100 default: /* panic */
H. Peter Anvin4836e332002-04-30 20:56:43 +00001101 errfunc (ERR_PANIC, "invalid register operand given to regval()");
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001102 return 0;
1103 }
1104}
1105
H. Peter Anvineba20a72002-04-30 20:53:55 +00001106static int matches (struct itemplate *itemp, insn *instruction)
1107{
H. Peter Anvinef7468f2002-04-30 20:57:59 +00001108 int i, size[3], asize, oprs, ret;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001109
1110 ret = 100;
1111
1112 /*
1113 * Check the opcode
1114 */
1115 if (itemp->opcode != instruction->opcode) return 0;
1116
1117 /*
1118 * Count the operands
1119 */
1120 if (itemp->operands != instruction->operands) return 0;
1121
1122 /*
1123 * Check that no spurious colons or TOs are present
1124 */
1125 for (i=0; i<itemp->operands; i++)
1126 if (instruction->oprs[i].type & ~itemp->opd[i] & (COLON|TO))
1127 return 0;
1128
1129 /*
1130 * Check that the operand flags all match up
1131 */
1132 for (i=0; i<itemp->operands; i++)
1133 if (itemp->opd[i] & ~instruction->oprs[i].type ||
1134 ((itemp->opd[i] & SIZE_MASK) &&
H. Peter Anvineba20a72002-04-30 20:53:55 +00001135 ((itemp->opd[i] ^ instruction->oprs[i].type) & SIZE_MASK)))
1136 {
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001137 if ((itemp->opd[i] & ~instruction->oprs[i].type & NON_SIZE) ||
1138 (instruction->oprs[i].type & SIZE_MASK))
1139 return 0;
1140 else
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001141/* ret = 1; */
1142 return 1;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001143 }
1144
1145 /*
1146 * Check operand sizes
1147 */
H. Peter Anvinef7468f2002-04-30 20:57:59 +00001148 if (itemp->flags & IF_ARMASK) {
1149 size[0] = size[1] = size[2] = 0;
1150
1151 switch (itemp->flags & IF_ARMASK) {
1152 case IF_AR0: i = 0; break;
1153 case IF_AR1: i = 1; break;
1154 case IF_AR2: i = 2; break;
1155 default: break; /* Shouldn't happen */
1156 }
1157 if (itemp->flags & IF_SB) {
1158 size[i] = BITS8;
1159 } else if (itemp->flags & IF_SW) {
1160 size[i] = BITS16;
1161 } else if (itemp->flags & IF_SD) {
1162 size[i] = BITS32;
1163 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001164 } else {
H. Peter Anvinef7468f2002-04-30 20:57:59 +00001165 asize = 0;
1166 if (itemp->flags & IF_SB) {
1167 asize = BITS8;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001168 oprs = itemp->operands;
H. Peter Anvinef7468f2002-04-30 20:57:59 +00001169 } else if (itemp->flags & IF_SW) {
1170 asize = BITS16;
1171 oprs = itemp->operands;
1172 } else if (itemp->flags & IF_SD) {
1173 asize = BITS32;
1174 oprs = itemp->operands;
1175 }
1176 size[0] = size[1] = size[2] = asize;
1177 }
1178
1179 if (itemp->flags & (IF_SM | IF_SM2)) {
1180 oprs = (itemp->flags & IF_SM2 ? 2 : itemp->operands);
1181 asize = 0;
1182 for (i=0; i<oprs; i++) {
1183 if ( (asize = itemp->opd[i] & SIZE_MASK) != 0) {
1184 int j;
1185 for (j=0; j<oprs; j++)
1186 size[j] = asize;
1187 break;
1188 }
1189 }
1190 } else {
1191 oprs = itemp->operands;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001192 }
1193
1194 for (i=0; i<itemp->operands; i++)
1195 if (!(itemp->opd[i] & SIZE_MASK) &&
H. Peter Anvinef7468f2002-04-30 20:57:59 +00001196 (instruction->oprs[i].type & SIZE_MASK & ~size[i]))
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001197/* ret = 2; */
1198 return 2;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001199
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001200 /*
1201 * Check template is okay at the set cpu level
1202 */
1203 if ((itemp->flags & IF_PLEVEL) > cpu) return 3;
1204
1205 /*
1206 * Check if special handling needed for Jumps
1207 */
1208 if ((unsigned char)(itemp->code[0]) >= 0370) return 99;
1209
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001210 return ret;
1211}
1212
H. Peter Anvinea838272002-04-30 20:51:53 +00001213static ea *process_ea (operand *input, ea *output, int addrbits, int rfield,
H. Peter Anvineba20a72002-04-30 20:53:55 +00001214 int forw_ref)
1215{
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001216 if (!(REGISTER & ~input->type)) { /* it's a single register */
1217 static int regs[] = {
H. Peter Anvin4836e332002-04-30 20:56:43 +00001218 R_AL, R_CL, R_DL, R_BL, R_AH, R_CH, R_DH, R_BH,
1219 R_AX, R_CX, R_DX, R_BX, R_SP, R_BP, R_SI, R_DI,
1220 R_EAX, R_ECX, R_EDX, R_EBX, R_ESP, R_EBP, R_ESI, R_EDI,
1221 R_MM0, R_MM1, R_MM2, R_MM3, R_MM4, R_MM5, R_MM6, R_MM7,
1222 R_XMM0, R_XMM1, R_XMM2, R_XMM3, R_XMM4, R_XMM5, R_XMM6, R_XMM7
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001223 };
1224 int i;
1225
1226 for (i=0; i<elements(regs); i++)
1227 if (input->basereg == regs[i]) break;
1228 if (i<elements(regs)) {
1229 output->sib_present = FALSE;/* no SIB necessary */
1230 output->bytes = 0; /* no offset necessary either */
H. Peter Anvin4836e332002-04-30 20:56:43 +00001231 output->modrm = 0xC0 | (rfield << 3) | (i & 7);
H. Peter Anvineba20a72002-04-30 20:53:55 +00001232 }
1233 else
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001234 return NULL;
1235 } else { /* it's a memory reference */
1236 if (input->basereg==-1 && (input->indexreg==-1 || input->scale==0)) {
1237 /* it's a pure offset */
1238 if (input->addr_size)
1239 addrbits = input->addr_size;
1240 output->sib_present = FALSE;
1241 output->bytes = (addrbits==32 ? 4 : 2);
1242 output->modrm = (addrbits==32 ? 5 : 6) | (rfield << 3);
H. Peter Anvineba20a72002-04-30 20:53:55 +00001243 }
1244 else { /* it's an indirection */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001245 int i=input->indexreg, b=input->basereg, s=input->scale;
1246 long o=input->offset, seg=input->segment;
H. Peter Anvin76690a12002-04-30 20:52:49 +00001247 int hb=input->hintbase, ht=input->hinttype;
1248 int t;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001249
1250 if (s==0) i = -1; /* make this easy, at least */
1251
1252 if (i==R_EAX || i==R_EBX || i==R_ECX || i==R_EDX
1253 || i==R_EBP || i==R_ESP || i==R_ESI || i==R_EDI
1254 || b==R_EAX || b==R_EBX || b==R_ECX || b==R_EDX
1255 || b==R_EBP || b==R_ESP || b==R_ESI || b==R_EDI) {
1256 /* it must be a 32-bit memory reference. Firstly we have
1257 * to check that all registers involved are type Exx. */
1258 if (i!=-1 && i!=R_EAX && i!=R_EBX && i!=R_ECX && i!=R_EDX
1259 && i!=R_EBP && i!=R_ESP && i!=R_ESI && i!=R_EDI)
1260 return NULL;
1261 if (b!=-1 && b!=R_EAX && b!=R_EBX && b!=R_ECX && b!=R_EDX
1262 && b!=R_EBP && b!=R_ESP && b!=R_ESI && b!=R_EDI)
1263 return NULL;
1264
1265 /* While we're here, ensure the user didn't specify WORD. */
1266 if (input->addr_size == 16)
1267 return NULL;
1268
1269 /* now reorganise base/index */
H. Peter Anvin76690a12002-04-30 20:52:49 +00001270 if (s == 1 && b != i && b != -1 && i != -1 &&
1271 ((hb==b&&ht==EAH_NOTBASE) || (hb==i&&ht==EAH_MAKEBASE)))
1272 t = b, b = i, i = t; /* swap if hints say so */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001273 if (b==i) /* convert EAX+2*EAX to 3*EAX */
1274 b = -1, s++;
H. Peter Anvin76690a12002-04-30 20:52:49 +00001275 if (b==-1 && s==1 && !(hb == i && ht == EAH_NOTBASE))
1276 b = i, i = -1; /* make single reg base, unless hint */
1277 if (((s==2 && i!=R_ESP && !(input->eaflags & EAF_TIMESTWO)) ||
1278 s==3 || s==5 || s==9) && b==-1)
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001279 b = i, s--; /* convert 3*EAX to EAX+2*EAX */
H. Peter Anvinea838272002-04-30 20:51:53 +00001280 if (s==1 && i==R_ESP) /* swap ESP into base if scale is 1 */
1281 i = b, b = R_ESP;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001282 if (i==R_ESP || (s!=1 && s!=2 && s!=4 && s!=8 && i!=-1))
1283 return NULL; /* wrong, for various reasons */
1284
1285 if (i==-1 && b!=R_ESP) {/* no SIB needed */
1286 int mod, rm;
1287 switch(b) {
1288 case R_EAX: rm = 0; break;
1289 case R_ECX: rm = 1; break;
1290 case R_EDX: rm = 2; break;
1291 case R_EBX: rm = 3; break;
1292 case R_EBP: rm = 5; break;
1293 case R_ESI: rm = 6; break;
1294 case R_EDI: rm = 7; break;
1295 case -1: rm = 5; break;
1296 default: /* should never happen */
1297 return NULL;
1298 }
H. Peter Anvinea838272002-04-30 20:51:53 +00001299 if (b==-1 || (b!=R_EBP && o==0 &&
H. Peter Anvin76690a12002-04-30 20:52:49 +00001300 seg==NO_SEG && !forw_ref &&
1301 !(input->eaflags &
1302 (EAF_BYTEOFFS|EAF_WORDOFFS))))
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001303 mod = 0;
H. Peter Anvin76690a12002-04-30 20:52:49 +00001304 else if (input->eaflags & EAF_BYTEOFFS ||
1305 (o>=-128 && o<=127 && seg==NO_SEG && !forw_ref &&
1306 !(input->eaflags & EAF_WORDOFFS))) {
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001307 mod = 1;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001308 }
1309 else
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001310 mod = 2;
H. Peter Anvinea838272002-04-30 20:51:53 +00001311
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001312 output->sib_present = FALSE;
1313 output->bytes = (b==-1 || mod==2 ? 4 : mod);
1314 output->modrm = (mod<<6) | (rfield<<3) | rm;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001315 }
1316 else { /* we need a SIB */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001317 int mod, scale, index, base;
1318
1319 switch (b) {
1320 case R_EAX: base = 0; break;
1321 case R_ECX: base = 1; break;
1322 case R_EDX: base = 2; break;
1323 case R_EBX: base = 3; break;
1324 case R_ESP: base = 4; break;
1325 case R_EBP: case -1: base = 5; break;
1326 case R_ESI: base = 6; break;
1327 case R_EDI: base = 7; break;
1328 default: /* then what the smeg is it? */
1329 return NULL; /* panic */
1330 }
1331
1332 switch (i) {
1333 case R_EAX: index = 0; break;
1334 case R_ECX: index = 1; break;
1335 case R_EDX: index = 2; break;
1336 case R_EBX: index = 3; break;
1337 case -1: index = 4; break;
1338 case R_EBP: index = 5; break;
1339 case R_ESI: index = 6; break;
1340 case R_EDI: index = 7; break;
1341 default: /* then what the smeg is it? */
1342 return NULL; /* panic */
1343 }
1344
1345 if (i==-1) s = 1;
1346 switch (s) {
1347 case 1: scale = 0; break;
1348 case 2: scale = 1; break;
1349 case 4: scale = 2; break;
1350 case 8: scale = 3; break;
1351 default: /* then what the smeg is it? */
1352 return NULL; /* panic */
1353 }
1354
H. Peter Anvinea838272002-04-30 20:51:53 +00001355 if (b==-1 || (b!=R_EBP && o==0 &&
H. Peter Anvin76690a12002-04-30 20:52:49 +00001356 seg==NO_SEG && !forw_ref &&
1357 !(input->eaflags &
1358 (EAF_BYTEOFFS|EAF_WORDOFFS))))
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001359 mod = 0;
H. Peter Anvin76690a12002-04-30 20:52:49 +00001360 else if (input->eaflags & EAF_BYTEOFFS ||
1361 (o>=-128 && o<=127 && seg==NO_SEG && !forw_ref &&
1362 !(input->eaflags & EAF_WORDOFFS)))
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001363 mod = 1;
1364 else
1365 mod = 2;
1366
1367 output->sib_present = TRUE;
1368 output->bytes = (b==-1 || mod==2 ? 4 : mod);
1369 output->modrm = (mod<<6) | (rfield<<3) | 4;
1370 output->sib = (scale<<6) | (index<<3) | base;
1371 }
H. Peter Anvineba20a72002-04-30 20:53:55 +00001372 }
1373 else { /* it's 16-bit */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001374 int mod, rm;
1375
1376 /* check all registers are BX, BP, SI or DI */
1377 if ((b!=-1 && b!=R_BP && b!=R_BX && b!=R_SI && b!=R_DI) ||
1378 (i!=-1 && i!=R_BP && i!=R_BX && i!=R_SI && i!=R_DI))
1379 return NULL;
1380
1381 /* ensure the user didn't specify DWORD */
1382 if (input->addr_size == 32)
1383 return NULL;
1384
1385 if (s!=1 && i!=-1) return NULL;/* no can do, in 16-bit EA */
1386 if (b==-1 && i!=-1) b ^= i ^= b ^= i; /* swap them round */
1387 if ((b==R_SI || b==R_DI) && i!=-1)
1388 b ^= i ^= b ^= i; /* have BX/BP as base, SI/DI index */
1389 if (b==i) return NULL;/* shouldn't ever happen, in theory */
1390 if (i!=-1 && b!=-1 &&
1391 (i==R_BP || i==R_BX || b==R_SI || b==R_DI))
1392 return NULL; /* invalid combinations */
1393 if (b==-1) /* pure offset: handled above */
1394 return NULL; /* so if it gets to here, panic! */
1395
1396 rm = -1;
1397 if (i!=-1)
1398 switch (i*256 + b) {
1399 case R_SI*256+R_BX: rm=0; break;
1400 case R_DI*256+R_BX: rm=1; break;
1401 case R_SI*256+R_BP: rm=2; break;
1402 case R_DI*256+R_BP: rm=3; break;
1403 }
1404 else
1405 switch (b) {
1406 case R_SI: rm=4; break;
1407 case R_DI: rm=5; break;
1408 case R_BP: rm=6; break;
1409 case R_BX: rm=7; break;
1410 }
1411 if (rm==-1) /* can't happen, in theory */
1412 return NULL; /* so panic if it does */
1413
H. Peter Anvin76690a12002-04-30 20:52:49 +00001414 if (o==0 && seg==NO_SEG && !forw_ref && rm!=6 &&
1415 !(input->eaflags & (EAF_BYTEOFFS|EAF_WORDOFFS)))
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001416 mod = 0;
H. Peter Anvin76690a12002-04-30 20:52:49 +00001417 else if (input->eaflags & EAF_BYTEOFFS ||
1418 (o>=-128 && o<=127 && seg==NO_SEG && !forw_ref &&
1419 !(input->eaflags & EAF_WORDOFFS)))
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001420 mod = 1;
1421 else
1422 mod = 2;
1423
1424 output->sib_present = FALSE; /* no SIB - it's 16-bit */
1425 output->bytes = mod; /* bytes of offset needed */
1426 output->modrm = (mod<<6) | (rfield<<3) | rm;
1427 }
1428 }
1429 }
1430 output->size = 1 + output->sib_present + output->bytes;
1431 return output;
1432}
1433
H. Peter Anvineba20a72002-04-30 20:53:55 +00001434static int chsize (operand *input, int addrbits)
1435{
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001436 if (!(MEMORY & ~input->type)) {
1437 int i=input->indexreg, b=input->basereg;
1438
1439 if (input->scale==0) i = -1;
1440
1441 if (i == -1 && b == -1) /* pure offset */
1442 return (input->addr_size != 0 && input->addr_size != addrbits);
1443
1444 if (i==R_EAX || i==R_EBX || i==R_ECX || i==R_EDX
1445 || i==R_EBP || i==R_ESP || i==R_ESI || i==R_EDI
1446 || b==R_EAX || b==R_EBX || b==R_ECX || b==R_EDX
1447 || b==R_EBP || b==R_ESP || b==R_ESI || b==R_EDI)
1448 return (addrbits==16);
1449 else
1450 return (addrbits==32);
H. Peter Anvineba20a72002-04-30 20:53:55 +00001451 }
1452 else
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001453 return 0;
1454}