blob: 21c5729a85020bf9ce2808f360bdb2538c680b5a [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;
155 if (ins->oprs[0].opflags & OPFLAG_FORWARD) return 1; /* match a forward reference */
156
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 */
549 ins->oprs[op].wrt==NO_SEG && ins->oprs[op].segment==NO_SEG;
550 v = ins->oprs[op].offset;
551 if (size==16) v = (signed short)v; /* sign extend if 16 bits */
552
553 return ret && v>=-128L && v<=127L;
554}
555
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000556static long calcsize (long segment, long offset, int bits,
H. Peter Anvineba20a72002-04-30 20:53:55 +0000557 insn *ins, char *codes)
558{
559 long length = 0;
560 unsigned char c;
561
562 (void) segment; /* Don't warn that this parameter is unused */
563 (void) offset; /* Don't warn that this parameter is unused */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000564
565 while (*codes) switch (c = *codes++) {
566 case 01: case 02: case 03:
567 codes += c, length += c; break;
568 case 04: case 05: case 06: case 07:
569 length++; break;
570 case 010: case 011: case 012:
571 codes++, length++; break;
572 case 017:
573 length++; break;
574 case 014: case 015: case 016:
575 length++; break;
576 case 020: case 021: case 022:
577 length++; break;
578 case 024: case 025: case 026:
579 length++; break;
580 case 030: case 031: case 032:
581 length += 2; break;
582 case 034: case 035: case 036:
583 length += ((ins->oprs[c-034].addr_size ?
584 ins->oprs[c-034].addr_size : bits) == 16 ? 2 : 4); break;
585 case 037:
586 length += 2; break;
587 case 040: case 041: case 042:
588 length += 4; break;
589 case 050: case 051: case 052:
590 length++; break;
591 case 060: case 061: case 062:
592 length += 2; break;
593 case 064: case 065: case 066:
594 length += ((ins->oprs[c-064].addr_size ?
595 ins->oprs[c-064].addr_size : bits) == 16 ? 2 : 4); break;
596 case 070: case 071: case 072:
597 length += 4; break;
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000598 case 0130: case 0131: case 0132:
599 length += is_sbyte(ins, c-0130, 16) ? 1 : 2; break;
600 case 0133: case 0134: case 0135:
601 codes+=2; length++; break;
602 case 0140: case 0141: case 0142:
603 length += is_sbyte(ins, c-0140, 32) ? 1 : 4; break;
604 case 0143: case 0144: case 0145:
605 codes+=2; length++; break;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000606 case 0300: case 0301: case 0302:
607 length += chsize (&ins->oprs[c-0300], bits);
608 break;
609 case 0310:
610 length += (bits==32);
611 break;
612 case 0311:
613 length += (bits==16);
614 break;
615 case 0312:
616 break;
617 case 0320:
618 length += (bits==32);
619 break;
620 case 0321:
621 length += (bits==16);
622 break;
623 case 0322:
624 break;
625 case 0330:
626 codes++, length++; break;
H. Peter Anvinef7468f2002-04-30 20:57:59 +0000627 case 0331:
628 case 0332:
629 break;
630 case 0333:
631 length++; break;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000632 case 0340: case 0341: case 0342:
633 if (ins->oprs[0].segment != NO_SEG)
634 errfunc (ERR_NONFATAL, "attempt to reserve non-constant"
635 " quantity of BSS space");
636 else
637 length += ins->oprs[0].offset << (c-0340);
638 break;
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000639 case 0370: case 0371: case 0372:
640 break;
641 case 0373:
642 length++; break;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000643 default: /* can't do it by 'case' statements */
644 if (c>=0100 && c<=0277) { /* it's an EA */
645 ea ea_data;
H. Peter Anvinea838272002-04-30 20:51:53 +0000646 if (!process_ea (&ins->oprs[(c>>3)&7], &ea_data, bits, 0,
647 ins->forw_ref)) {
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000648 errfunc (ERR_NONFATAL, "invalid effective address");
649 return -1;
650 } else
651 length += ea_data.size;
652 } else
653 errfunc (ERR_PANIC, "internal instruction table corrupt"
654 ": instruction code 0x%02X given", c);
655 }
656 return length;
657}
658
659static void gencode (long segment, long offset, int bits,
H. Peter Anvineba20a72002-04-30 20:53:55 +0000660 insn *ins, char *codes, long insn_end)
661{
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000662 static char condval[] = { /* conditional opcodes */
663 0x7, 0x3, 0x2, 0x6, 0x2, 0x4, 0xF, 0xD, 0xC, 0xE, 0x6, 0x2,
664 0x3, 0x7, 0x3, 0x5, 0xE, 0xC, 0xD, 0xF, 0x1, 0xB, 0x9, 0x5,
665 0x0, 0xA, 0xA, 0xB, 0x8, 0x4
666 };
H. Peter Anvineba20a72002-04-30 20:53:55 +0000667 unsigned char c;
668 unsigned char bytes[4];
669 long data, size;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000670
H. Peter Anvineba20a72002-04-30 20:53:55 +0000671 while (*codes)
672 switch (c = *codes++)
673 {
674 case 01: case 02: case 03:
675 out (offset, segment, codes, OUT_RAWDATA+c, NO_SEG, NO_SEG);
676 codes += c;
677 offset += c;
678 break;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000679
H. Peter Anvineba20a72002-04-30 20:53:55 +0000680 case 04: case 06:
681 switch (ins->oprs[0].basereg)
682 {
683 case R_CS:
684 bytes[0] = 0x0E + (c == 0x04 ? 1 : 0); break;
685 case R_DS:
686 bytes[0] = 0x1E + (c == 0x04 ? 1 : 0); break;
687 case R_ES:
688 bytes[0] = 0x06 + (c == 0x04 ? 1 : 0); break;
689 case R_SS:
690 bytes[0] = 0x16 + (c == 0x04 ? 1 : 0); break;
691 default:
H. Peter Anvin4836e332002-04-30 20:56:43 +0000692 errfunc (ERR_PANIC, "bizarre 8086 segment register received");
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000693 }
H. Peter Anvineba20a72002-04-30 20:53:55 +0000694 out (offset, segment, bytes, OUT_RAWDATA+1, NO_SEG, NO_SEG);
695 offset++;
696 break;
697
698 case 05: case 07:
699 switch (ins->oprs[0].basereg) {
700 case R_FS: bytes[0] = 0xA0 + (c == 0x05 ? 1 : 0); break;
701 case R_GS: bytes[0] = 0xA8 + (c == 0x05 ? 1 : 0); break;
702 default:
H. Peter Anvin4836e332002-04-30 20:56:43 +0000703 errfunc (ERR_PANIC, "bizarre 386 segment register received");
H. Peter Anvineba20a72002-04-30 20:53:55 +0000704 }
705 out (offset, segment, bytes, OUT_RAWDATA+1, NO_SEG, NO_SEG);
706 offset++;
707 break;
708
709 case 010: case 011: case 012:
710 bytes[0] = *codes++ + regval(&ins->oprs[c-010]);
711 out (offset, segment, bytes, OUT_RAWDATA+1, NO_SEG, NO_SEG);
712 offset += 1;
713 break;
714
715 case 017:
716 bytes[0] = 0;
717 out (offset, segment, bytes, OUT_RAWDATA+1, NO_SEG, NO_SEG);
718 offset += 1;
719 break;
720
721 case 014: case 015: case 016:
722 if (ins->oprs[c-014].offset < -128
723 || ins->oprs[c-014].offset > 127)
724 {
725 errfunc (ERR_WARNING, "signed byte value exceeds bounds");
726 }
727
728 if (ins->oprs[c-014].segment != NO_SEG)
729 {
730 data = ins->oprs[c-014].offset;
731 out (offset, segment, &data, OUT_ADDRESS+1,
732 ins->oprs[c-014].segment, ins->oprs[c-014].wrt);
733 }
734 else {
735 bytes[0] = ins->oprs[c-014].offset;
736 out (offset, segment, bytes, OUT_RAWDATA+1, NO_SEG, NO_SEG);
737 }
738 offset += 1;
739 break;
740
741 case 020: case 021: case 022:
742 if (ins->oprs[c-020].offset < -256
743 || ins->oprs[c-020].offset > 255)
744 {
745 errfunc (ERR_WARNING, "byte value exceeds bounds");
746 }
747 if (ins->oprs[c-020].segment != NO_SEG) {
748 data = ins->oprs[c-020].offset;
749 out (offset, segment, &data, OUT_ADDRESS+1,
750 ins->oprs[c-020].segment, ins->oprs[c-020].wrt);
751 }
752 else {
753 bytes[0] = ins->oprs[c-020].offset;
754 out (offset, segment, bytes, OUT_RAWDATA+1, NO_SEG, NO_SEG);
755 }
756 offset += 1;
757 break;
758
759 case 024: case 025: case 026:
760 if (ins->oprs[c-024].offset < 0 || ins->oprs[c-024].offset > 255)
761 errfunc (ERR_WARNING, "unsigned byte value exceeds bounds");
762 if (ins->oprs[c-024].segment != NO_SEG) {
763 data = ins->oprs[c-024].offset;
764 out (offset, segment, &data, OUT_ADDRESS+1,
765 ins->oprs[c-024].segment, ins->oprs[c-024].wrt);
766 }
767 else {
768 bytes[0] = ins->oprs[c-024].offset;
769 out (offset, segment, bytes, OUT_RAWDATA+1, NO_SEG, NO_SEG);
770 }
771 offset += 1;
772 break;
773
774 case 030: case 031: case 032:
775 if (ins->oprs[c-030].segment == NO_SEG &&
776 ins->oprs[c-030].wrt == NO_SEG &&
777 (ins->oprs[c-030].offset < -65536L ||
778 ins->oprs[c-030].offset > 65535L))
779 {
780 errfunc (ERR_WARNING, "word value exceeds bounds");
781 }
782 data = ins->oprs[c-030].offset;
783 out (offset, segment, &data, OUT_ADDRESS+2,
784 ins->oprs[c-030].segment, ins->oprs[c-030].wrt);
785 offset += 2;
786 break;
787
788 case 034: case 035: case 036:
789 data = ins->oprs[c-034].offset;
790 size = ((ins->oprs[c-034].addr_size ?
791 ins->oprs[c-034].addr_size : bits) == 16 ? 2 : 4);
792 if (size==16 && (data < -65536L || data > 65535L))
793 errfunc (ERR_WARNING, "word value exceeds bounds");
794 out (offset, segment, &data, OUT_ADDRESS+size,
795 ins->oprs[c-034].segment, ins->oprs[c-034].wrt);
796 offset += size;
797 break;
798
799 case 037:
800 if (ins->oprs[0].segment == NO_SEG)
801 errfunc (ERR_NONFATAL, "value referenced by FAR is not"
802 " relocatable");
803 data = 0L;
804 out (offset, segment, &data, OUT_ADDRESS+2,
805 outfmt->segbase(1+ins->oprs[0].segment),
806 ins->oprs[0].wrt);
807 offset += 2;
808 break;
809
810 case 040: case 041: case 042:
811 data = ins->oprs[c-040].offset;
812 out (offset, segment, &data, OUT_ADDRESS+4,
813 ins->oprs[c-040].segment, ins->oprs[c-040].wrt);
814 offset += 4;
815 break;
816
817 case 050: case 051: case 052:
818 if (ins->oprs[c-050].segment != segment)
819 errfunc (ERR_NONFATAL, "short relative jump outside segment");
820 data = ins->oprs[c-050].offset - insn_end;
821 if (data > 127 || data < -128)
822 errfunc (ERR_NONFATAL, "short jump is out of range");
823 bytes[0] = data;
824 out (offset, segment, bytes, OUT_RAWDATA+1, NO_SEG, NO_SEG);
825 offset += 1;
826 break;
827
828 case 060: case 061: case 062:
829 if (ins->oprs[c-060].segment != segment) {
830 data = ins->oprs[c-060].offset;
831 out (offset, segment, &data, OUT_REL2ADR+insn_end-offset,
832 ins->oprs[c-060].segment, ins->oprs[c-060].wrt);
833 } else {
834 data = ins->oprs[c-060].offset - insn_end;
835 out (offset, segment, &data,
836 OUT_ADDRESS+2, NO_SEG, NO_SEG);
837 }
838 offset += 2;
839 break;
840
841 case 064: case 065: case 066:
842 size = ((ins->oprs[c-064].addr_size ?
843 ins->oprs[c-064].addr_size : bits) == 16 ? 2 : 4);
844 if (ins->oprs[c-064].segment != segment) {
845 data = ins->oprs[c-064].offset;
846 size = (bits == 16 ? OUT_REL2ADR : OUT_REL4ADR);
847 out (offset, segment, &data, size+insn_end-offset,
848 ins->oprs[c-064].segment, ins->oprs[c-064].wrt);
849 size = (bits == 16 ? 2 : 4);
850 } else {
851 data = ins->oprs[c-064].offset - insn_end;
852 out (offset, segment, &data,
853 OUT_ADDRESS+size, NO_SEG, NO_SEG);
854 }
855 offset += size;
856 break;
857
858 case 070: case 071: case 072:
859 if (ins->oprs[c-070].segment != segment) {
860 data = ins->oprs[c-070].offset;
861 out (offset, segment, &data, OUT_REL4ADR+insn_end-offset,
862 ins->oprs[c-070].segment, ins->oprs[c-070].wrt);
863 } else {
864 data = ins->oprs[c-070].offset - insn_end;
865 out (offset, segment, &data,
866 OUT_ADDRESS+4, NO_SEG, NO_SEG);
867 }
868 offset += 4;
869 break;
870
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000871 case 0130: case 0131: case 0132:
872 data = ins->oprs[c-0130].offset;
873 if (is_sbyte(ins, c-0130, 16)) {
874 out (offset, segment, &data, OUT_RAWDATA+1, NO_SEG, NO_SEG);
875 offset++;
876 } else {
877 if (ins->oprs[c-0130].segment == NO_SEG &&
878 ins->oprs[c-0130].wrt == NO_SEG &&
879 (data < -65536L || data > 65535L)) {
880 errfunc (ERR_WARNING, "word value exceeds bounds");
881 }
882 out (offset, segment, &data, OUT_ADDRESS+2,
883 ins->oprs[c-0130].segment, ins->oprs[c-0130].wrt);
884 offset += 2;
885 }
886 break;
887
888 case 0133: case 0134: case 0135:
889 codes++;
890 bytes[0] = *codes++;
891 if (is_sbyte(ins, c-0133, 16)) bytes[0] |= 2; /* s-bit */
892 out (offset, segment, bytes, OUT_RAWDATA+1, NO_SEG, NO_SEG);
893 offset++;
894 break;
895
896 case 0140: case 0141: case 0142:
897 data = ins->oprs[c-0140].offset;
898 if (is_sbyte(ins, c-0140, 32)) {
899 out (offset, segment, &data, OUT_RAWDATA+1, NO_SEG, NO_SEG);
900 offset++;
901 } else {
902 out (offset, segment, &data, OUT_ADDRESS+4,
903 ins->oprs[c-0140].segment, ins->oprs[c-0140].wrt);
904 offset += 4;
905 }
906 break;
907
908 case 0143: case 0144: case 0145:
909 codes++;
910 bytes[0] = *codes++;
911 if (is_sbyte(ins, c-0143, 32)) bytes[0] |= 2; /* s-bit */
912 out (offset, segment, bytes, OUT_RAWDATA+1, NO_SEG, NO_SEG);
913 offset++;
914 break;
915
H. Peter Anvineba20a72002-04-30 20:53:55 +0000916 case 0300: case 0301: case 0302:
917 if (chsize (&ins->oprs[c-0300], bits)) {
918 *bytes = 0x67;
919 out (offset, segment, bytes,
920 OUT_RAWDATA+1, NO_SEG, NO_SEG);
921 offset += 1;
922 } else
923 offset += 0;
924 break;
925
926 case 0310:
927 if (bits==32) {
928 *bytes = 0x67;
929 out (offset, segment, bytes,
930 OUT_RAWDATA+1, NO_SEG, NO_SEG);
931 offset += 1;
932 } else
933 offset += 0;
934 break;
935
936 case 0311:
937 if (bits==16) {
938 *bytes = 0x67;
939 out (offset, segment, bytes,
940 OUT_RAWDATA+1, NO_SEG, NO_SEG);
941 offset += 1;
942 } else
943 offset += 0;
944 break;
945
946 case 0312:
947 break;
948
949 case 0320:
950 if (bits==32) {
951 *bytes = 0x66;
952 out (offset, segment, bytes,
953 OUT_RAWDATA+1, NO_SEG, NO_SEG);
954 offset += 1;
955 } else
956 offset += 0;
957 break;
958
959 case 0321:
960 if (bits==16) {
961 *bytes = 0x66;
962 out (offset, segment, bytes,
963 OUT_RAWDATA+1, NO_SEG, NO_SEG);
964 offset += 1;
965 } else
966 offset += 0;
967 break;
968
969 case 0322:
970 break;
971
972 case 0330:
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000973 *bytes = *codes++ ^ condval[ins->condition];
H. Peter Anvineba20a72002-04-30 20:53:55 +0000974 out (offset, segment, bytes,
975 OUT_RAWDATA+1, NO_SEG, NO_SEG);
976 offset += 1;
977 break;
978
H. Peter Anvinef7468f2002-04-30 20:57:59 +0000979 case 0331:
980 case 0332:
981 break;
982
983 case 0333:
984 *bytes = 0xF3;
985 out (offset, segment, bytes,
986 OUT_RAWDATA+1, NO_SEG, NO_SEG);
987 offset += 1;
988 break;
989
H. Peter Anvineba20a72002-04-30 20:53:55 +0000990 case 0340: case 0341: case 0342:
991 if (ins->oprs[0].segment != NO_SEG)
992 errfunc (ERR_PANIC, "non-constant BSS size in pass two");
993 else {
994 long size = ins->oprs[0].offset << (c-0340);
995 if (size > 0)
996 out (offset, segment, NULL,
997 OUT_RESERVE+size, NO_SEG, NO_SEG);
998 offset += size;
999 }
1000 break;
1001
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001002 case 0370: case 0371: case 0372:
1003 break;
1004
1005 case 0373:
1006 *bytes = bits==16 ? 3 : 5;
1007 out (offset, segment, bytes,
1008 OUT_RAWDATA+1, NO_SEG, NO_SEG);
1009 offset += 1;
1010 break;
1011
H. Peter Anvineba20a72002-04-30 20:53:55 +00001012 default: /* can't do it by 'case' statements */
1013 if (c>=0100 && c<=0277) { /* it's an EA */
1014 ea ea_data;
1015 int rfield;
1016 unsigned char *p;
1017 long s;
1018
1019 if (c<=0177) /* pick rfield from operand b */
1020 rfield = regval (&ins->oprs[c&7]);
1021 else /* rfield is constant */
1022 rfield = c & 7;
1023
1024 if (!process_ea (&ins->oprs[(c>>3)&7], &ea_data, bits, rfield,
1025 ins->forw_ref))
1026 {
1027 errfunc (ERR_NONFATAL, "invalid effective address");
1028 }
1029
1030 p = bytes;
1031 *p++ = ea_data.modrm;
1032 if (ea_data.sib_present)
1033 *p++ = ea_data.sib;
1034
1035 s = p-bytes;
1036 out (offset, segment, bytes, OUT_RAWDATA + s,
1037 NO_SEG, NO_SEG);
1038
1039 switch (ea_data.bytes) {
1040 case 0:
1041 break;
1042 case 1:
1043 if (ins->oprs[(c>>3)&7].segment != NO_SEG) {
1044 data = ins->oprs[(c>>3)&7].offset;
1045 out (offset, segment, &data, OUT_ADDRESS+1,
1046 ins->oprs[(c>>3)&7].segment,
1047 ins->oprs[(c>>3)&7].wrt);
1048 } else {
1049 *bytes = ins->oprs[(c>>3)&7].offset;
1050 out (offset, segment, bytes, OUT_RAWDATA+1,
1051 NO_SEG, NO_SEG);
1052 }
1053 s++;
1054 break;
1055 case 2:
1056 case 4:
1057 data = ins->oprs[(c>>3)&7].offset;
1058 out (offset, segment, &data,
1059 OUT_ADDRESS+ea_data.bytes,
1060 ins->oprs[(c>>3)&7].segment, ins->oprs[(c>>3)&7].wrt);
1061 s += ea_data.bytes;
1062 break;
1063 }
1064 offset += s;
1065 } else
1066 errfunc (ERR_PANIC, "internal instruction table corrupt"
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001067 ": instruction code 0x%02X given", c);
H. Peter Anvineba20a72002-04-30 20:53:55 +00001068 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001069}
1070
H. Peter Anvineba20a72002-04-30 20:53:55 +00001071static int regval (operand *o)
1072{
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001073 switch (o->basereg) {
1074 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 +00001075 case R_ST0: case R_MM0: case R_XMM0:
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001076 return 0;
1077 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 +00001078 case R_MM1: case R_XMM1:
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001079 return 1;
1080 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 +00001081 case R_ST2: case R_MM2: case R_XMM2:
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001082 return 2;
1083 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 +00001084 case R_TR3: case R_ST3: case R_MM3: case R_XMM3:
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001085 return 3;
1086 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 +00001087 case R_ST4: case R_MM4: case R_XMM4:
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001088 return 4;
1089 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 +00001090 case R_MM5: case R_XMM5:
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001091 return 5;
1092 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 +00001093 case R_MM6: case R_XMM6:
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001094 return 6;
1095 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 +00001096 case R_MM7: case R_XMM7:
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001097 return 7;
1098 default: /* panic */
H. Peter Anvin4836e332002-04-30 20:56:43 +00001099 errfunc (ERR_PANIC, "invalid register operand given to regval()");
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001100 return 0;
1101 }
1102}
1103
H. Peter Anvineba20a72002-04-30 20:53:55 +00001104static int matches (struct itemplate *itemp, insn *instruction)
1105{
H. Peter Anvinef7468f2002-04-30 20:57:59 +00001106 int i, size[3], asize, oprs, ret;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001107
1108 ret = 100;
1109
1110 /*
1111 * Check the opcode
1112 */
1113 if (itemp->opcode != instruction->opcode) return 0;
1114
1115 /*
1116 * Count the operands
1117 */
1118 if (itemp->operands != instruction->operands) return 0;
1119
1120 /*
1121 * Check that no spurious colons or TOs are present
1122 */
1123 for (i=0; i<itemp->operands; i++)
1124 if (instruction->oprs[i].type & ~itemp->opd[i] & (COLON|TO))
1125 return 0;
1126
1127 /*
1128 * Check that the operand flags all match up
1129 */
1130 for (i=0; i<itemp->operands; i++)
1131 if (itemp->opd[i] & ~instruction->oprs[i].type ||
1132 ((itemp->opd[i] & SIZE_MASK) &&
H. Peter Anvineba20a72002-04-30 20:53:55 +00001133 ((itemp->opd[i] ^ instruction->oprs[i].type) & SIZE_MASK)))
1134 {
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001135 if ((itemp->opd[i] & ~instruction->oprs[i].type & NON_SIZE) ||
1136 (instruction->oprs[i].type & SIZE_MASK))
1137 return 0;
1138 else
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001139/* ret = 1; */
1140 return 1;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001141 }
1142
1143 /*
1144 * Check operand sizes
1145 */
H. Peter Anvinef7468f2002-04-30 20:57:59 +00001146 if (itemp->flags & IF_ARMASK) {
1147 size[0] = size[1] = size[2] = 0;
1148
1149 switch (itemp->flags & IF_ARMASK) {
1150 case IF_AR0: i = 0; break;
1151 case IF_AR1: i = 1; break;
1152 case IF_AR2: i = 2; break;
1153 default: break; /* Shouldn't happen */
1154 }
1155 if (itemp->flags & IF_SB) {
1156 size[i] = BITS8;
1157 } else if (itemp->flags & IF_SW) {
1158 size[i] = BITS16;
1159 } else if (itemp->flags & IF_SD) {
1160 size[i] = BITS32;
1161 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001162 } else {
H. Peter Anvinef7468f2002-04-30 20:57:59 +00001163 asize = 0;
1164 if (itemp->flags & IF_SB) {
1165 asize = BITS8;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001166 oprs = itemp->operands;
H. Peter Anvinef7468f2002-04-30 20:57:59 +00001167 } else if (itemp->flags & IF_SW) {
1168 asize = BITS16;
1169 oprs = itemp->operands;
1170 } else if (itemp->flags & IF_SD) {
1171 asize = BITS32;
1172 oprs = itemp->operands;
1173 }
1174 size[0] = size[1] = size[2] = asize;
1175 }
1176
1177 if (itemp->flags & (IF_SM | IF_SM2)) {
1178 oprs = (itemp->flags & IF_SM2 ? 2 : itemp->operands);
1179 asize = 0;
1180 for (i=0; i<oprs; i++) {
1181 if ( (asize = itemp->opd[i] & SIZE_MASK) != 0) {
1182 int j;
1183 for (j=0; j<oprs; j++)
1184 size[j] = asize;
1185 break;
1186 }
1187 }
1188 } else {
1189 oprs = itemp->operands;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001190 }
1191
1192 for (i=0; i<itemp->operands; i++)
1193 if (!(itemp->opd[i] & SIZE_MASK) &&
H. Peter Anvinef7468f2002-04-30 20:57:59 +00001194 (instruction->oprs[i].type & SIZE_MASK & ~size[i]))
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001195/* ret = 2; */
1196 return 2;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001197
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001198 /*
1199 * Check template is okay at the set cpu level
1200 */
1201 if ((itemp->flags & IF_PLEVEL) > cpu) return 3;
1202
1203 /*
1204 * Check if special handling needed for Jumps
1205 */
1206 if ((unsigned char)(itemp->code[0]) >= 0370) return 99;
1207
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001208 return ret;
1209}
1210
H. Peter Anvinea838272002-04-30 20:51:53 +00001211static ea *process_ea (operand *input, ea *output, int addrbits, int rfield,
H. Peter Anvineba20a72002-04-30 20:53:55 +00001212 int forw_ref)
1213{
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001214 if (!(REGISTER & ~input->type)) { /* it's a single register */
1215 static int regs[] = {
H. Peter Anvin4836e332002-04-30 20:56:43 +00001216 R_AL, R_CL, R_DL, R_BL, R_AH, R_CH, R_DH, R_BH,
1217 R_AX, R_CX, R_DX, R_BX, R_SP, R_BP, R_SI, R_DI,
1218 R_EAX, R_ECX, R_EDX, R_EBX, R_ESP, R_EBP, R_ESI, R_EDI,
1219 R_MM0, R_MM1, R_MM2, R_MM3, R_MM4, R_MM5, R_MM6, R_MM7,
1220 R_XMM0, R_XMM1, R_XMM2, R_XMM3, R_XMM4, R_XMM5, R_XMM6, R_XMM7
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001221 };
1222 int i;
1223
1224 for (i=0; i<elements(regs); i++)
1225 if (input->basereg == regs[i]) break;
1226 if (i<elements(regs)) {
1227 output->sib_present = FALSE;/* no SIB necessary */
1228 output->bytes = 0; /* no offset necessary either */
H. Peter Anvin4836e332002-04-30 20:56:43 +00001229 output->modrm = 0xC0 | (rfield << 3) | (i & 7);
H. Peter Anvineba20a72002-04-30 20:53:55 +00001230 }
1231 else
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001232 return NULL;
1233 } else { /* it's a memory reference */
1234 if (input->basereg==-1 && (input->indexreg==-1 || input->scale==0)) {
1235 /* it's a pure offset */
1236 if (input->addr_size)
1237 addrbits = input->addr_size;
1238 output->sib_present = FALSE;
1239 output->bytes = (addrbits==32 ? 4 : 2);
1240 output->modrm = (addrbits==32 ? 5 : 6) | (rfield << 3);
H. Peter Anvineba20a72002-04-30 20:53:55 +00001241 }
1242 else { /* it's an indirection */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001243 int i=input->indexreg, b=input->basereg, s=input->scale;
1244 long o=input->offset, seg=input->segment;
H. Peter Anvin76690a12002-04-30 20:52:49 +00001245 int hb=input->hintbase, ht=input->hinttype;
1246 int t;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001247
1248 if (s==0) i = -1; /* make this easy, at least */
1249
1250 if (i==R_EAX || i==R_EBX || i==R_ECX || i==R_EDX
1251 || i==R_EBP || i==R_ESP || i==R_ESI || i==R_EDI
1252 || b==R_EAX || b==R_EBX || b==R_ECX || b==R_EDX
1253 || b==R_EBP || b==R_ESP || b==R_ESI || b==R_EDI) {
1254 /* it must be a 32-bit memory reference. Firstly we have
1255 * to check that all registers involved are type Exx. */
1256 if (i!=-1 && i!=R_EAX && i!=R_EBX && i!=R_ECX && i!=R_EDX
1257 && i!=R_EBP && i!=R_ESP && i!=R_ESI && i!=R_EDI)
1258 return NULL;
1259 if (b!=-1 && b!=R_EAX && b!=R_EBX && b!=R_ECX && b!=R_EDX
1260 && b!=R_EBP && b!=R_ESP && b!=R_ESI && b!=R_EDI)
1261 return NULL;
1262
1263 /* While we're here, ensure the user didn't specify WORD. */
1264 if (input->addr_size == 16)
1265 return NULL;
1266
1267 /* now reorganise base/index */
H. Peter Anvin76690a12002-04-30 20:52:49 +00001268 if (s == 1 && b != i && b != -1 && i != -1 &&
1269 ((hb==b&&ht==EAH_NOTBASE) || (hb==i&&ht==EAH_MAKEBASE)))
1270 t = b, b = i, i = t; /* swap if hints say so */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001271 if (b==i) /* convert EAX+2*EAX to 3*EAX */
1272 b = -1, s++;
H. Peter Anvin76690a12002-04-30 20:52:49 +00001273 if (b==-1 && s==1 && !(hb == i && ht == EAH_NOTBASE))
1274 b = i, i = -1; /* make single reg base, unless hint */
1275 if (((s==2 && i!=R_ESP && !(input->eaflags & EAF_TIMESTWO)) ||
1276 s==3 || s==5 || s==9) && b==-1)
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001277 b = i, s--; /* convert 3*EAX to EAX+2*EAX */
H. Peter Anvinea838272002-04-30 20:51:53 +00001278 if (s==1 && i==R_ESP) /* swap ESP into base if scale is 1 */
1279 i = b, b = R_ESP;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001280 if (i==R_ESP || (s!=1 && s!=2 && s!=4 && s!=8 && i!=-1))
1281 return NULL; /* wrong, for various reasons */
1282
1283 if (i==-1 && b!=R_ESP) {/* no SIB needed */
1284 int mod, rm;
1285 switch(b) {
1286 case R_EAX: rm = 0; break;
1287 case R_ECX: rm = 1; break;
1288 case R_EDX: rm = 2; break;
1289 case R_EBX: rm = 3; break;
1290 case R_EBP: rm = 5; break;
1291 case R_ESI: rm = 6; break;
1292 case R_EDI: rm = 7; break;
1293 case -1: rm = 5; break;
1294 default: /* should never happen */
1295 return NULL;
1296 }
H. Peter Anvinea838272002-04-30 20:51:53 +00001297 if (b==-1 || (b!=R_EBP && o==0 &&
H. Peter Anvin76690a12002-04-30 20:52:49 +00001298 seg==NO_SEG && !forw_ref &&
1299 !(input->eaflags &
1300 (EAF_BYTEOFFS|EAF_WORDOFFS))))
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001301 mod = 0;
H. Peter Anvin76690a12002-04-30 20:52:49 +00001302 else if (input->eaflags & EAF_BYTEOFFS ||
1303 (o>=-128 && o<=127 && seg==NO_SEG && !forw_ref &&
1304 !(input->eaflags & EAF_WORDOFFS))) {
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001305 mod = 1;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001306 }
1307 else
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001308 mod = 2;
H. Peter Anvinea838272002-04-30 20:51:53 +00001309
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001310 output->sib_present = FALSE;
1311 output->bytes = (b==-1 || mod==2 ? 4 : mod);
1312 output->modrm = (mod<<6) | (rfield<<3) | rm;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001313 }
1314 else { /* we need a SIB */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001315 int mod, scale, index, base;
1316
1317 switch (b) {
1318 case R_EAX: base = 0; break;
1319 case R_ECX: base = 1; break;
1320 case R_EDX: base = 2; break;
1321 case R_EBX: base = 3; break;
1322 case R_ESP: base = 4; break;
1323 case R_EBP: case -1: base = 5; break;
1324 case R_ESI: base = 6; break;
1325 case R_EDI: base = 7; break;
1326 default: /* then what the smeg is it? */
1327 return NULL; /* panic */
1328 }
1329
1330 switch (i) {
1331 case R_EAX: index = 0; break;
1332 case R_ECX: index = 1; break;
1333 case R_EDX: index = 2; break;
1334 case R_EBX: index = 3; break;
1335 case -1: index = 4; break;
1336 case R_EBP: index = 5; break;
1337 case R_ESI: index = 6; break;
1338 case R_EDI: index = 7; break;
1339 default: /* then what the smeg is it? */
1340 return NULL; /* panic */
1341 }
1342
1343 if (i==-1) s = 1;
1344 switch (s) {
1345 case 1: scale = 0; break;
1346 case 2: scale = 1; break;
1347 case 4: scale = 2; break;
1348 case 8: scale = 3; break;
1349 default: /* then what the smeg is it? */
1350 return NULL; /* panic */
1351 }
1352
H. Peter Anvinea838272002-04-30 20:51:53 +00001353 if (b==-1 || (b!=R_EBP && o==0 &&
H. Peter Anvin76690a12002-04-30 20:52:49 +00001354 seg==NO_SEG && !forw_ref &&
1355 !(input->eaflags &
1356 (EAF_BYTEOFFS|EAF_WORDOFFS))))
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001357 mod = 0;
H. Peter Anvin76690a12002-04-30 20:52:49 +00001358 else if (input->eaflags & EAF_BYTEOFFS ||
1359 (o>=-128 && o<=127 && seg==NO_SEG && !forw_ref &&
1360 !(input->eaflags & EAF_WORDOFFS)))
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001361 mod = 1;
1362 else
1363 mod = 2;
1364
1365 output->sib_present = TRUE;
1366 output->bytes = (b==-1 || mod==2 ? 4 : mod);
1367 output->modrm = (mod<<6) | (rfield<<3) | 4;
1368 output->sib = (scale<<6) | (index<<3) | base;
1369 }
H. Peter Anvineba20a72002-04-30 20:53:55 +00001370 }
1371 else { /* it's 16-bit */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001372 int mod, rm;
1373
1374 /* check all registers are BX, BP, SI or DI */
1375 if ((b!=-1 && b!=R_BP && b!=R_BX && b!=R_SI && b!=R_DI) ||
1376 (i!=-1 && i!=R_BP && i!=R_BX && i!=R_SI && i!=R_DI))
1377 return NULL;
1378
1379 /* ensure the user didn't specify DWORD */
1380 if (input->addr_size == 32)
1381 return NULL;
1382
1383 if (s!=1 && i!=-1) return NULL;/* no can do, in 16-bit EA */
1384 if (b==-1 && i!=-1) b ^= i ^= b ^= i; /* swap them round */
1385 if ((b==R_SI || b==R_DI) && i!=-1)
1386 b ^= i ^= b ^= i; /* have BX/BP as base, SI/DI index */
1387 if (b==i) return NULL;/* shouldn't ever happen, in theory */
1388 if (i!=-1 && b!=-1 &&
1389 (i==R_BP || i==R_BX || b==R_SI || b==R_DI))
1390 return NULL; /* invalid combinations */
1391 if (b==-1) /* pure offset: handled above */
1392 return NULL; /* so if it gets to here, panic! */
1393
1394 rm = -1;
1395 if (i!=-1)
1396 switch (i*256 + b) {
1397 case R_SI*256+R_BX: rm=0; break;
1398 case R_DI*256+R_BX: rm=1; break;
1399 case R_SI*256+R_BP: rm=2; break;
1400 case R_DI*256+R_BP: rm=3; break;
1401 }
1402 else
1403 switch (b) {
1404 case R_SI: rm=4; break;
1405 case R_DI: rm=5; break;
1406 case R_BP: rm=6; break;
1407 case R_BX: rm=7; break;
1408 }
1409 if (rm==-1) /* can't happen, in theory */
1410 return NULL; /* so panic if it does */
1411
H. Peter Anvin76690a12002-04-30 20:52:49 +00001412 if (o==0 && seg==NO_SEG && !forw_ref && rm!=6 &&
1413 !(input->eaflags & (EAF_BYTEOFFS|EAF_WORDOFFS)))
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001414 mod = 0;
H. Peter Anvin76690a12002-04-30 20:52:49 +00001415 else if (input->eaflags & EAF_BYTEOFFS ||
1416 (o>=-128 && o<=127 && seg==NO_SEG && !forw_ref &&
1417 !(input->eaflags & EAF_WORDOFFS)))
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001418 mod = 1;
1419 else
1420 mod = 2;
1421
1422 output->sib_present = FALSE; /* no SIB - it's 16-bit */
1423 output->bytes = mod; /* bytes of offset needed */
1424 output->modrm = (mod<<6) | (rfield<<3) | rm;
1425 }
1426 }
1427 }
1428 output->size = 1 + output->sib_present + output->bytes;
1429 return output;
1430}
1431
H. Peter Anvineba20a72002-04-30 20:53:55 +00001432static int chsize (operand *input, int addrbits)
1433{
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001434 if (!(MEMORY & ~input->type)) {
1435 int i=input->indexreg, b=input->basereg;
1436
1437 if (input->scale==0) i = -1;
1438
1439 if (i == -1 && b == -1) /* pure offset */
1440 return (input->addr_size != 0 && input->addr_size != addrbits);
1441
1442 if (i==R_EAX || i==R_EBX || i==R_ECX || i==R_EDX
1443 || i==R_EBP || i==R_ESP || i==R_ESI || i==R_EDI
1444 || b==R_EAX || b==R_EBX || b==R_ECX || b==R_EDX
1445 || b==R_EBP || b==R_ESP || b==R_ESI || b==R_EDI)
1446 return (addrbits==16);
1447 else
1448 return (addrbits==32);
H. Peter Anvineba20a72002-04-30 20:53:55 +00001449 }
1450 else
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001451 return 0;
1452}