blob: f93457d9ea12e0baee6efe5325d6d022919727df [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 Anvin788e6c12002-04-30 21:02:01 +000062 * \370,\371,\372 - match only if operand 0 meets byte jump criteria.
63 * 370 is used for Jcc, 371 is used for JMP.
H. Peter Anvinaf535c12002-04-30 20:59:21 +000064 * \373 - assemble 0x03 if bits==16, 0x05 if bits==32;
65 * used for conditional jump over longer jump
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000066 */
67
68#include <stdio.h>
69#include <string.h>
70
71#include "nasm.h"
H. Peter Anvin6768eb72002-04-30 20:52:26 +000072#include "nasmlib.h"
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000073#include "assemble.h"
74#include "insns.h"
75
76extern struct itemplate *nasm_instructions[];
77
78typedef struct {
79 int sib_present; /* is a SIB byte necessary? */
80 int bytes; /* # of bytes of offset needed */
81 int size; /* lazy - this is sib+bytes+1 */
82 unsigned char modrm, sib; /* the bytes themselves */
83} ea;
84
H. Peter Anvinaf535c12002-04-30 20:59:21 +000085static unsigned long cpu; /* cpu level received from nasm.c */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000086static efunc errfunc;
87static struct ofmt *outfmt;
H. Peter Anvin6768eb72002-04-30 20:52:26 +000088static ListGen *list;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000089
90static long calcsize (long, long, int, insn *, char *);
91static void gencode (long, long, int, insn *, char *, long);
H. Peter Anvineba20a72002-04-30 20:53:55 +000092static int regval (operand *o);
93static int matches (struct itemplate *, insn *);
94static ea * process_ea (operand *, ea *, int, int, int);
95static int chsize (operand *, int);
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000096
H. Peter Anvin6768eb72002-04-30 20:52:26 +000097/*
98 * This routine wrappers the real output format's output routine,
99 * in order to pass a copy of the data off to the listing file
100 * generator at the same time.
101 */
102static void out (long offset, long segto, void *data, unsigned long type,
H. Peter Anvineba20a72002-04-30 20:53:55 +0000103 long segment, long wrt)
104{
105 static long lineno;
106 static char *lnfname;
107
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000108 if ((type & OUT_TYPMASK) == OUT_ADDRESS) {
109 if (segment != NO_SEG || wrt != NO_SEG) {
110 /*
111 * This address is relocated. We must write it as
112 * OUT_ADDRESS, so there's no work to be done here.
113 */
114 list->output (offset, data, type);
H. Peter Anvineba20a72002-04-30 20:53:55 +0000115 }
116 else {
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000117 unsigned char p[4], *q = p;
118 /*
119 * This is a non-relocated address, and we're going to
120 * convert it into RAWDATA format.
121 */
122 if ((type & OUT_SIZMASK) == 4) {
123 WRITELONG (q, * (long *) data);
124 list->output (offset, p, OUT_RAWDATA+4);
H. Peter Anvineba20a72002-04-30 20:53:55 +0000125 }
126 else {
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000127 WRITESHORT (q, * (long *) data);
128 list->output (offset, p, OUT_RAWDATA+2);
129 }
130 }
H. Peter Anvineba20a72002-04-30 20:53:55 +0000131 }
132 else if ((type & OUT_TYPMASK) == OUT_RAWDATA) {
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000133 list->output (offset, data, type);
H. Peter Anvineba20a72002-04-30 20:53:55 +0000134 }
135 else if ((type & OUT_TYPMASK) == OUT_RESERVE) {
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000136 list->output (offset, NULL, type);
H. Peter Anvineba20a72002-04-30 20:53:55 +0000137 }
138 else if ((type & OUT_TYPMASK) == OUT_REL2ADR ||
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000139 (type & OUT_TYPMASK) == OUT_REL4ADR) {
140 list->output (offset, data, type);
141 }
142
H. Peter Anvineba20a72002-04-30 20:53:55 +0000143 if (src_get(&lineno,&lnfname))
144 outfmt->current_dfmt->linenum(lnfname,lineno,segto);
145
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000146 outfmt->output (segto, data, type, segment, wrt);
147}
148
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000149static int jmp_match (long segment, long offset, int bits,
150 insn *ins, char *code)
151{ long isize;
152 unsigned char c = code[0];
153
154
H. Peter Anvin788e6c12002-04-30 21:02:01 +0000155 if (c != 0370 && c != 0371) return 0;
156 if (ins->oprs[0].opflags & OPFLAG_FORWARD) {
157 if (optimizing<0 && c==0370) return 1;
158 else return (pass0==0); /* match a forward reference */
159 }
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000160 isize = calcsize (segment, offset, bits, ins, code);
161 if (ins->oprs[0].segment != segment) return 0;
162 isize = ins->oprs[0].offset - offset - isize; /* isize is now the delta */
163 if (isize >= -128L && isize <= 127L) return 1; /* it is byte size */
164
165 return 0;
166}
167
168
169long assemble (long segment, long offset, int bits, unsigned long cp,
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000170 insn *instruction, struct ofmt *output, efunc error,
H. Peter Anvineba20a72002-04-30 20:53:55 +0000171 ListGen *listgen)
172{
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000173 struct itemplate *temp;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000174 int j;
175 int size_prob;
176 long insn_end;
177 long itimes;
178 long start = offset;
179 long wsize = 0; /* size for DB etc. */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000180
181 errfunc = error; /* to pass to other functions */
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000182 cpu = cp;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000183 outfmt = output; /* likewise */
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000184 list = listgen; /* and again */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000185
H. Peter Anvineba20a72002-04-30 20:53:55 +0000186 switch (instruction->opcode)
187 {
188 case -1: return 0;
189 case I_DB: wsize = 1; break;
190 case I_DW: wsize = 2; break;
191 case I_DD: wsize = 4; break;
192 case I_DQ: wsize = 8; break;
193 case I_DT: wsize = 10; break;
194 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000195
H. Peter Anvineba20a72002-04-30 20:53:55 +0000196 if (wsize) {
197 extop * e;
198 long t = instruction->times;
199 if (t < 0)
200 errfunc(ERR_PANIC, "instruction->times < 0 (%ld) in assemble()",t);
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000201
H. Peter Anvineba20a72002-04-30 20:53:55 +0000202 while (t--) /* repeat TIMES times */
203 {
204 for (e = instruction->eops; e; e = e->next)
205 {
206 if (e->type == EOT_DB_NUMBER)
207 {
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000208 if (wsize == 1) {
209 if (e->segment != NO_SEG)
210 errfunc (ERR_NONFATAL,
211 "one-byte relocation attempted");
212 else {
H. Peter Anvin41bf8002002-04-30 20:58:18 +0000213 unsigned char out_byte = e->offset;
214 out (offset, segment, &out_byte, OUT_RAWDATA+1,
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000215 NO_SEG, NO_SEG);
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000216 }
H. Peter Anvineba20a72002-04-30 20:53:55 +0000217 }
218 else if (wsize > 5) {
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000219 errfunc (ERR_NONFATAL, "integer supplied to a D%c"
220 " instruction", wsize==8 ? 'Q' : 'T');
H. Peter Anvineba20a72002-04-30 20:53:55 +0000221 }
222 else
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000223 out (offset, segment, &e->offset,
224 OUT_ADDRESS+wsize, e->segment,
225 e->wrt);
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000226 offset += wsize;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000227 }
228 else if (e->type == EOT_DB_STRING)
229 {
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000230 int align;
231
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000232 out (offset, segment, e->stringval,
233 OUT_RAWDATA+e->stringlen, NO_SEG, NO_SEG);
H. Peter Anvineba20a72002-04-30 20:53:55 +0000234 align = e->stringlen % wsize;
235
236 if (align) {
237 align = wsize - align;
238 out (offset, segment, "\0\0\0\0\0\0\0\0",
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000239 OUT_RAWDATA+align, NO_SEG, NO_SEG);
H. Peter Anvineba20a72002-04-30 20:53:55 +0000240 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000241 offset += e->stringlen + align;
242 }
243 }
H. Peter Anvineba20a72002-04-30 20:53:55 +0000244 if (t > 0 && t == instruction->times-1)
245 {
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000246 /*
247 * Dummy call to list->output to give the offset to the
248 * listing module.
249 */
250 list->output (offset, NULL, OUT_RAWDATA);
251 list->uplevel (LIST_TIMES);
252 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000253 }
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000254 if (instruction->times > 1)
255 list->downlevel (LIST_TIMES);
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000256 return offset - start;
257 }
258
H. Peter Anvineba20a72002-04-30 20:53:55 +0000259 if (instruction->opcode == I_INCBIN)
260 {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000261 static char fname[FILENAME_MAX];
H. Peter Anvineba20a72002-04-30 20:53:55 +0000262 FILE * fp;
263 long len;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000264
265 len = FILENAME_MAX-1;
266 if (len > instruction->eops->stringlen)
267 len = instruction->eops->stringlen;
268 strncpy (fname, instruction->eops->stringval, len);
269 fname[len] = '\0';
H. Peter Anvineba20a72002-04-30 20:53:55 +0000270
271 if ( (fp = fopen(fname, "rb")) == NULL)
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000272 error (ERR_NONFATAL, "`incbin': unable to open file `%s'", fname);
273 else if (fseek(fp, 0L, SEEK_END) < 0)
274 error (ERR_NONFATAL, "`incbin': unable to seek on file `%s'",
275 fname);
H. Peter Anvineba20a72002-04-30 20:53:55 +0000276 else
277 {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000278 static char buf[2048];
279 long t = instruction->times;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000280 long base = 0;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000281
282 len = ftell (fp);
283 if (instruction->eops->next) {
H. Peter Anvineba20a72002-04-30 20:53:55 +0000284 base = instruction->eops->next->offset;
285 len -= base;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000286 if (instruction->eops->next->next &&
287 len > instruction->eops->next->next->offset)
288 len = instruction->eops->next->next->offset;
289 }
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000290 /*
291 * Dummy call to list->output to give the offset to the
292 * listing module.
293 */
294 list->output (offset, NULL, OUT_RAWDATA);
295 list->uplevel(LIST_INCBIN);
H. Peter Anvineba20a72002-04-30 20:53:55 +0000296 while (t--)
297 {
298 long l;
299
300 fseek (fp, base, SEEK_SET);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000301 l = len;
302 while (l > 0) {
303 long m = fread (buf, 1, (l>sizeof(buf)?sizeof(buf):l),
304 fp);
305 if (!m) {
306 /*
307 * This shouldn't happen unless the file
308 * actually changes while we are reading
309 * it.
310 */
311 error (ERR_NONFATAL, "`incbin': unexpected EOF while"
312 " reading file `%s'", fname);
H. Peter Anvineba20a72002-04-30 20:53:55 +0000313 t=0; /* Try to exit cleanly */
314 break;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000315 }
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000316 out (offset, segment, buf, OUT_RAWDATA+m,
317 NO_SEG, NO_SEG);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000318 l -= m;
319 }
320 }
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000321 list->downlevel(LIST_INCBIN);
322 if (instruction->times > 1) {
323 /*
324 * Dummy call to list->output to give the offset to the
325 * listing module.
326 */
327 list->output (offset, NULL, OUT_RAWDATA);
328 list->uplevel(LIST_TIMES);
329 list->downlevel(LIST_TIMES);
330 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000331 fclose (fp);
332 return instruction->times * len;
333 }
334 return 0; /* if we're here, there's an error */
335 }
336
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000337 size_prob = FALSE;
338 temp = nasm_instructions[instruction->opcode];
339 while (temp->opcode != -1) {
340 int m = matches (temp, instruction);
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000341 if (m == 99)
342 m += jmp_match(segment, offset, bits, instruction, temp->code);
H. Peter Anvineba20a72002-04-30 20:53:55 +0000343
344 if (m == 100) /* matches! */
345 {
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000346 char *codes = temp->code;
347 long insn_size = calcsize(segment, offset, bits,
348 instruction, codes);
349 itimes = instruction->times;
350 if (insn_size < 0) /* shouldn't be, on pass two */
351 error (ERR_PANIC, "errors made it through from pass one");
352 else while (itimes--) {
353 insn_end = offset + insn_size;
354 for (j=0; j<instruction->nprefix; j++) {
H. Peter Anvineba20a72002-04-30 20:53:55 +0000355 unsigned char c=0;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000356 switch (instruction->prefixes[j]) {
357 case P_LOCK:
358 c = 0xF0; break;
359 case P_REPNE: case P_REPNZ:
360 c = 0xF2; break;
361 case P_REPE: case P_REPZ: case P_REP:
362 c = 0xF3; break;
363 case R_CS: c = 0x2E; break;
364 case R_DS: c = 0x3E; break;
365 case R_ES: c = 0x26; break;
366 case R_FS: c = 0x64; break;
367 case R_GS: c = 0x65; break;
368 case R_SS: c = 0x36; break;
369 case P_A16:
H. Peter Anvineba20a72002-04-30 20:53:55 +0000370 if (bits != 16)
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000371 c = 0x67;
372 break;
373 case P_A32:
H. Peter Anvineba20a72002-04-30 20:53:55 +0000374 if (bits != 32)
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000375 c = 0x67;
376 break;
377 case P_O16:
H. Peter Anvineba20a72002-04-30 20:53:55 +0000378 if (bits != 16)
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000379 c = 0x66;
380 break;
381 case P_O32:
H. Peter Anvineba20a72002-04-30 20:53:55 +0000382 if (bits != 32)
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000383 c = 0x66;
384 break;
385 default:
386 error (ERR_PANIC,
387 "invalid instruction prefix");
388 }
H. Peter Anvineba20a72002-04-30 20:53:55 +0000389 if (c != 0) {
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000390 out (offset, segment, &c, OUT_RAWDATA+1,
391 NO_SEG, NO_SEG);
H. Peter Anvineba20a72002-04-30 20:53:55 +0000392 offset++;
393 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000394 }
395 gencode (segment, offset, bits, instruction, codes, insn_end);
396 offset += insn_size;
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000397 if (itimes > 0 && itimes == instruction->times-1) {
398 /*
399 * Dummy call to list->output to give the offset to the
400 * listing module.
401 */
402 list->output (offset, NULL, OUT_RAWDATA);
403 list->uplevel (LIST_TIMES);
404 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000405 }
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000406 if (instruction->times > 1)
407 list->downlevel (LIST_TIMES);
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000408 return offset - start;
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000409 } else if (m > 0 && m > size_prob) {
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000410 size_prob = m;
411 }
412 temp++;
413 }
H. Peter Anvineba20a72002-04-30 20:53:55 +0000414
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000415 if (temp->opcode == -1) { /* didn't match any instruction */
416 if (size_prob == 1) /* would have matched, but for size */
417 error (ERR_NONFATAL, "operation size not specified");
418 else if (size_prob == 2)
419 error (ERR_NONFATAL, "mismatch in operand sizes");
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000420 else if (size_prob == 3)
421 error (ERR_NONFATAL, "no instruction for this cpu level");
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000422 else
423 error (ERR_NONFATAL,
424 "invalid combination of opcode and operands");
425 }
426 return 0;
427}
428
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000429long insn_size (long segment, long offset, int bits, unsigned long cp,
H. Peter Anvineba20a72002-04-30 20:53:55 +0000430 insn *instruction, efunc error)
431{
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000432 struct itemplate *temp;
433
434 errfunc = error; /* to pass to other functions */
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000435 cpu = cp;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000436
437 if (instruction->opcode == -1)
438 return 0;
439
440 if (instruction->opcode == I_DB ||
441 instruction->opcode == I_DW ||
442 instruction->opcode == I_DD ||
443 instruction->opcode == I_DQ ||
H. Peter Anvineba20a72002-04-30 20:53:55 +0000444 instruction->opcode == I_DT)
445 {
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000446 extop *e;
447 long isize, osize, wsize = 0; /* placate gcc */
448
449 isize = 0;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000450 switch (instruction->opcode)
451 {
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000452 case I_DB: wsize = 1; break;
453 case I_DW: wsize = 2; break;
454 case I_DD: wsize = 4; break;
455 case I_DQ: wsize = 8; break;
456 case I_DT: wsize = 10; break;
457 }
458
H. Peter Anvineba20a72002-04-30 20:53:55 +0000459 for (e = instruction->eops; e; e = e->next)
460 {
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000461 long align;
462
463 osize = 0;
464 if (e->type == EOT_DB_NUMBER)
465 osize = 1;
466 else if (e->type == EOT_DB_STRING)
467 osize = e->stringlen;
468
469 align = (-osize) % wsize;
470 if (align < 0)
471 align += wsize;
472 isize += osize + align;
473 }
474 return isize * instruction->times;
475 }
476
H. Peter Anvineba20a72002-04-30 20:53:55 +0000477 if (instruction->opcode == I_INCBIN)
478 {
479 char fname[FILENAME_MAX];
480 FILE * fp;
481 long len;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000482
483 len = FILENAME_MAX-1;
484 if (len > instruction->eops->stringlen)
485 len = instruction->eops->stringlen;
486 strncpy (fname, instruction->eops->stringval, len);
487 fname[len] = '\0';
H. Peter Anvineba20a72002-04-30 20:53:55 +0000488 if ( (fp = fopen(fname, "rb")) == NULL )
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000489 error (ERR_NONFATAL, "`incbin': unable to open file `%s'", fname);
490 else if (fseek(fp, 0L, SEEK_END) < 0)
491 error (ERR_NONFATAL, "`incbin': unable to seek on file `%s'",
492 fname);
H. Peter Anvineba20a72002-04-30 20:53:55 +0000493 else
494 {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000495 len = ftell (fp);
496 fclose (fp);
H. Peter Anvineba20a72002-04-30 20:53:55 +0000497 if (instruction->eops->next)
498 {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000499 len -= instruction->eops->next->offset;
500 if (instruction->eops->next->next &&
501 len > instruction->eops->next->next->offset)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000502 {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000503 len = instruction->eops->next->next->offset;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000504 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000505 }
506 return instruction->times * len;
507 }
508 return 0; /* if we're here, there's an error */
509 }
510
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000511 temp = nasm_instructions[instruction->opcode];
512 while (temp->opcode != -1) {
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000513 int m = matches(temp, instruction);
514 if (m == 99)
515 m += jmp_match(segment, offset, bits, instruction, temp->code);
516
517 if (m == 100) {
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000518 /* we've matched an instruction. */
H. Peter Anvineba20a72002-04-30 20:53:55 +0000519 long isize;
520 char * codes = temp->code;
521 int j;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000522
523 isize = calcsize(segment, offset, bits, instruction, codes);
524 if (isize < 0)
525 return -1;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000526 for (j = 0; j < instruction->nprefix; j++)
527 {
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000528 if ((instruction->prefixes[j] != P_A16 &&
529 instruction->prefixes[j] != P_O16 && bits==16) ||
530 (instruction->prefixes[j] != P_A32 &&
531 instruction->prefixes[j] != P_O32 && bits==32))
H. Peter Anvineba20a72002-04-30 20:53:55 +0000532 {
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000533 isize++;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000534 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000535 }
536 return isize * instruction->times;
537 }
538 temp++;
539 }
540 return -1; /* didn't match any instruction */
541}
542
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000543
544/* check that opn[op] is a signed byte of size 16 or 32,
545 and return the signed value*/
546static int is_sbyte (insn *ins, int op, int size)
547{
548 signed long v;
549 int ret;
550
551 ret = !(ins->forw_ref && ins->oprs[op].opflags ) && /* dead in the water on forward reference or External */
H. Peter Anvin788e6c12002-04-30 21:02:01 +0000552 (optimizing>0 || !(ins->oprs[op].type & (BITS16|BITS32))) &&
H. Peter Anvin734b1882002-04-30 21:01:08 +0000553 ins->oprs[op].wrt==NO_SEG && ins->oprs[op].segment==NO_SEG;
554
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000555 v = ins->oprs[op].offset;
556 if (size==16) v = (signed short)v; /* sign extend if 16 bits */
557
558 return ret && v>=-128L && v<=127L;
559}
560
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000561static long calcsize (long segment, long offset, int bits,
H. Peter Anvineba20a72002-04-30 20:53:55 +0000562 insn *ins, char *codes)
563{
564 long length = 0;
565 unsigned char c;
566
567 (void) segment; /* Don't warn that this parameter is unused */
568 (void) offset; /* Don't warn that this parameter is unused */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000569
570 while (*codes) switch (c = *codes++) {
571 case 01: case 02: case 03:
572 codes += c, length += c; break;
573 case 04: case 05: case 06: case 07:
574 length++; break;
575 case 010: case 011: case 012:
576 codes++, length++; break;
577 case 017:
578 length++; break;
579 case 014: case 015: case 016:
580 length++; break;
581 case 020: case 021: case 022:
582 length++; break;
583 case 024: case 025: case 026:
584 length++; break;
585 case 030: case 031: case 032:
586 length += 2; break;
587 case 034: case 035: case 036:
588 length += ((ins->oprs[c-034].addr_size ?
589 ins->oprs[c-034].addr_size : bits) == 16 ? 2 : 4); break;
590 case 037:
591 length += 2; break;
592 case 040: case 041: case 042:
593 length += 4; break;
594 case 050: case 051: case 052:
595 length++; break;
596 case 060: case 061: case 062:
597 length += 2; break;
598 case 064: case 065: case 066:
599 length += ((ins->oprs[c-064].addr_size ?
600 ins->oprs[c-064].addr_size : bits) == 16 ? 2 : 4); break;
601 case 070: case 071: case 072:
602 length += 4; break;
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000603 case 0130: case 0131: case 0132:
604 length += is_sbyte(ins, c-0130, 16) ? 1 : 2; break;
605 case 0133: case 0134: case 0135:
606 codes+=2; length++; break;
607 case 0140: case 0141: case 0142:
608 length += is_sbyte(ins, c-0140, 32) ? 1 : 4; break;
609 case 0143: case 0144: case 0145:
610 codes+=2; length++; break;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000611 case 0300: case 0301: case 0302:
612 length += chsize (&ins->oprs[c-0300], bits);
613 break;
614 case 0310:
615 length += (bits==32);
616 break;
617 case 0311:
618 length += (bits==16);
619 break;
620 case 0312:
621 break;
622 case 0320:
623 length += (bits==32);
624 break;
625 case 0321:
626 length += (bits==16);
627 break;
628 case 0322:
629 break;
630 case 0330:
631 codes++, length++; break;
H. Peter Anvinef7468f2002-04-30 20:57:59 +0000632 case 0331:
633 case 0332:
634 break;
635 case 0333:
636 length++; break;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000637 case 0340: case 0341: case 0342:
638 if (ins->oprs[0].segment != NO_SEG)
639 errfunc (ERR_NONFATAL, "attempt to reserve non-constant"
640 " quantity of BSS space");
641 else
642 length += ins->oprs[0].offset << (c-0340);
643 break;
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000644 case 0370: case 0371: case 0372:
645 break;
646 case 0373:
647 length++; break;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000648 default: /* can't do it by 'case' statements */
649 if (c>=0100 && c<=0277) { /* it's an EA */
650 ea ea_data;
H. Peter Anvinea838272002-04-30 20:51:53 +0000651 if (!process_ea (&ins->oprs[(c>>3)&7], &ea_data, bits, 0,
652 ins->forw_ref)) {
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000653 errfunc (ERR_NONFATAL, "invalid effective address");
654 return -1;
655 } else
656 length += ea_data.size;
657 } else
658 errfunc (ERR_PANIC, "internal instruction table corrupt"
659 ": instruction code 0x%02X given", c);
660 }
661 return length;
662}
663
664static void gencode (long segment, long offset, int bits,
H. Peter Anvineba20a72002-04-30 20:53:55 +0000665 insn *ins, char *codes, long insn_end)
666{
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000667 static char condval[] = { /* conditional opcodes */
668 0x7, 0x3, 0x2, 0x6, 0x2, 0x4, 0xF, 0xD, 0xC, 0xE, 0x6, 0x2,
669 0x3, 0x7, 0x3, 0x5, 0xE, 0xC, 0xD, 0xF, 0x1, 0xB, 0x9, 0x5,
670 0x0, 0xA, 0xA, 0xB, 0x8, 0x4
671 };
H. Peter Anvineba20a72002-04-30 20:53:55 +0000672 unsigned char c;
673 unsigned char bytes[4];
674 long data, size;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000675
H. Peter Anvineba20a72002-04-30 20:53:55 +0000676 while (*codes)
677 switch (c = *codes++)
678 {
679 case 01: case 02: case 03:
680 out (offset, segment, codes, OUT_RAWDATA+c, NO_SEG, NO_SEG);
681 codes += c;
682 offset += c;
683 break;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000684
H. Peter Anvineba20a72002-04-30 20:53:55 +0000685 case 04: case 06:
686 switch (ins->oprs[0].basereg)
687 {
688 case R_CS:
689 bytes[0] = 0x0E + (c == 0x04 ? 1 : 0); break;
690 case R_DS:
691 bytes[0] = 0x1E + (c == 0x04 ? 1 : 0); break;
692 case R_ES:
693 bytes[0] = 0x06 + (c == 0x04 ? 1 : 0); break;
694 case R_SS:
695 bytes[0] = 0x16 + (c == 0x04 ? 1 : 0); break;
696 default:
H. Peter Anvin4836e332002-04-30 20:56:43 +0000697 errfunc (ERR_PANIC, "bizarre 8086 segment register received");
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000698 }
H. Peter Anvineba20a72002-04-30 20:53:55 +0000699 out (offset, segment, bytes, OUT_RAWDATA+1, NO_SEG, NO_SEG);
700 offset++;
701 break;
702
703 case 05: case 07:
704 switch (ins->oprs[0].basereg) {
705 case R_FS: bytes[0] = 0xA0 + (c == 0x05 ? 1 : 0); break;
706 case R_GS: bytes[0] = 0xA8 + (c == 0x05 ? 1 : 0); break;
707 default:
H. Peter Anvin4836e332002-04-30 20:56:43 +0000708 errfunc (ERR_PANIC, "bizarre 386 segment register received");
H. Peter Anvineba20a72002-04-30 20:53:55 +0000709 }
710 out (offset, segment, bytes, OUT_RAWDATA+1, NO_SEG, NO_SEG);
711 offset++;
712 break;
713
714 case 010: case 011: case 012:
715 bytes[0] = *codes++ + regval(&ins->oprs[c-010]);
716 out (offset, segment, bytes, OUT_RAWDATA+1, NO_SEG, NO_SEG);
717 offset += 1;
718 break;
719
720 case 017:
721 bytes[0] = 0;
722 out (offset, segment, bytes, OUT_RAWDATA+1, NO_SEG, NO_SEG);
723 offset += 1;
724 break;
725
726 case 014: case 015: case 016:
727 if (ins->oprs[c-014].offset < -128
728 || ins->oprs[c-014].offset > 127)
729 {
730 errfunc (ERR_WARNING, "signed byte value exceeds bounds");
731 }
732
733 if (ins->oprs[c-014].segment != NO_SEG)
734 {
735 data = ins->oprs[c-014].offset;
736 out (offset, segment, &data, OUT_ADDRESS+1,
737 ins->oprs[c-014].segment, ins->oprs[c-014].wrt);
738 }
739 else {
740 bytes[0] = ins->oprs[c-014].offset;
741 out (offset, segment, bytes, OUT_RAWDATA+1, NO_SEG, NO_SEG);
742 }
743 offset += 1;
744 break;
745
746 case 020: case 021: case 022:
747 if (ins->oprs[c-020].offset < -256
748 || ins->oprs[c-020].offset > 255)
749 {
750 errfunc (ERR_WARNING, "byte value exceeds bounds");
751 }
752 if (ins->oprs[c-020].segment != NO_SEG) {
753 data = ins->oprs[c-020].offset;
754 out (offset, segment, &data, OUT_ADDRESS+1,
755 ins->oprs[c-020].segment, ins->oprs[c-020].wrt);
756 }
757 else {
758 bytes[0] = ins->oprs[c-020].offset;
759 out (offset, segment, bytes, OUT_RAWDATA+1, NO_SEG, NO_SEG);
760 }
761 offset += 1;
762 break;
763
764 case 024: case 025: case 026:
765 if (ins->oprs[c-024].offset < 0 || ins->oprs[c-024].offset > 255)
766 errfunc (ERR_WARNING, "unsigned byte value exceeds bounds");
767 if (ins->oprs[c-024].segment != NO_SEG) {
768 data = ins->oprs[c-024].offset;
769 out (offset, segment, &data, OUT_ADDRESS+1,
770 ins->oprs[c-024].segment, ins->oprs[c-024].wrt);
771 }
772 else {
773 bytes[0] = ins->oprs[c-024].offset;
774 out (offset, segment, bytes, OUT_RAWDATA+1, NO_SEG, NO_SEG);
775 }
776 offset += 1;
777 break;
778
779 case 030: case 031: case 032:
780 if (ins->oprs[c-030].segment == NO_SEG &&
781 ins->oprs[c-030].wrt == NO_SEG &&
782 (ins->oprs[c-030].offset < -65536L ||
783 ins->oprs[c-030].offset > 65535L))
784 {
785 errfunc (ERR_WARNING, "word value exceeds bounds");
786 }
787 data = ins->oprs[c-030].offset;
788 out (offset, segment, &data, OUT_ADDRESS+2,
789 ins->oprs[c-030].segment, ins->oprs[c-030].wrt);
790 offset += 2;
791 break;
792
793 case 034: case 035: case 036:
794 data = ins->oprs[c-034].offset;
795 size = ((ins->oprs[c-034].addr_size ?
796 ins->oprs[c-034].addr_size : bits) == 16 ? 2 : 4);
H. Peter Anvin4cf17482002-04-30 21:01:38 +0000797 if (size==2 && (data < -65536L || data > 65535L))
H. Peter Anvineba20a72002-04-30 20:53:55 +0000798 errfunc (ERR_WARNING, "word value exceeds bounds");
799 out (offset, segment, &data, OUT_ADDRESS+size,
800 ins->oprs[c-034].segment, ins->oprs[c-034].wrt);
801 offset += size;
802 break;
803
804 case 037:
805 if (ins->oprs[0].segment == NO_SEG)
806 errfunc (ERR_NONFATAL, "value referenced by FAR is not"
807 " relocatable");
808 data = 0L;
809 out (offset, segment, &data, OUT_ADDRESS+2,
810 outfmt->segbase(1+ins->oprs[0].segment),
811 ins->oprs[0].wrt);
812 offset += 2;
813 break;
814
815 case 040: case 041: case 042:
816 data = ins->oprs[c-040].offset;
817 out (offset, segment, &data, OUT_ADDRESS+4,
818 ins->oprs[c-040].segment, ins->oprs[c-040].wrt);
819 offset += 4;
820 break;
821
822 case 050: case 051: case 052:
823 if (ins->oprs[c-050].segment != segment)
824 errfunc (ERR_NONFATAL, "short relative jump outside segment");
825 data = ins->oprs[c-050].offset - insn_end;
826 if (data > 127 || data < -128)
827 errfunc (ERR_NONFATAL, "short jump is out of range");
828 bytes[0] = data;
829 out (offset, segment, bytes, OUT_RAWDATA+1, NO_SEG, NO_SEG);
830 offset += 1;
831 break;
832
833 case 060: case 061: case 062:
834 if (ins->oprs[c-060].segment != segment) {
835 data = ins->oprs[c-060].offset;
836 out (offset, segment, &data, OUT_REL2ADR+insn_end-offset,
837 ins->oprs[c-060].segment, ins->oprs[c-060].wrt);
838 } else {
839 data = ins->oprs[c-060].offset - insn_end;
840 out (offset, segment, &data,
841 OUT_ADDRESS+2, NO_SEG, NO_SEG);
842 }
843 offset += 2;
844 break;
845
846 case 064: case 065: case 066:
847 size = ((ins->oprs[c-064].addr_size ?
848 ins->oprs[c-064].addr_size : bits) == 16 ? 2 : 4);
849 if (ins->oprs[c-064].segment != segment) {
850 data = ins->oprs[c-064].offset;
851 size = (bits == 16 ? OUT_REL2ADR : OUT_REL4ADR);
852 out (offset, segment, &data, size+insn_end-offset,
853 ins->oprs[c-064].segment, ins->oprs[c-064].wrt);
854 size = (bits == 16 ? 2 : 4);
855 } else {
856 data = ins->oprs[c-064].offset - insn_end;
857 out (offset, segment, &data,
858 OUT_ADDRESS+size, NO_SEG, NO_SEG);
859 }
860 offset += size;
861 break;
862
863 case 070: case 071: case 072:
864 if (ins->oprs[c-070].segment != segment) {
865 data = ins->oprs[c-070].offset;
866 out (offset, segment, &data, OUT_REL4ADR+insn_end-offset,
867 ins->oprs[c-070].segment, ins->oprs[c-070].wrt);
868 } else {
869 data = ins->oprs[c-070].offset - insn_end;
870 out (offset, segment, &data,
871 OUT_ADDRESS+4, NO_SEG, NO_SEG);
872 }
873 offset += 4;
874 break;
875
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000876 case 0130: case 0131: case 0132:
877 data = ins->oprs[c-0130].offset;
878 if (is_sbyte(ins, c-0130, 16)) {
879 out (offset, segment, &data, OUT_RAWDATA+1, NO_SEG, NO_SEG);
880 offset++;
881 } else {
882 if (ins->oprs[c-0130].segment == NO_SEG &&
883 ins->oprs[c-0130].wrt == NO_SEG &&
884 (data < -65536L || data > 65535L)) {
885 errfunc (ERR_WARNING, "word value exceeds bounds");
886 }
887 out (offset, segment, &data, OUT_ADDRESS+2,
888 ins->oprs[c-0130].segment, ins->oprs[c-0130].wrt);
889 offset += 2;
890 }
891 break;
892
893 case 0133: case 0134: case 0135:
894 codes++;
895 bytes[0] = *codes++;
896 if (is_sbyte(ins, c-0133, 16)) bytes[0] |= 2; /* s-bit */
897 out (offset, segment, bytes, OUT_RAWDATA+1, NO_SEG, NO_SEG);
898 offset++;
899 break;
900
901 case 0140: case 0141: case 0142:
902 data = ins->oprs[c-0140].offset;
903 if (is_sbyte(ins, c-0140, 32)) {
904 out (offset, segment, &data, OUT_RAWDATA+1, NO_SEG, NO_SEG);
905 offset++;
906 } else {
907 out (offset, segment, &data, OUT_ADDRESS+4,
908 ins->oprs[c-0140].segment, ins->oprs[c-0140].wrt);
909 offset += 4;
910 }
911 break;
912
913 case 0143: case 0144: case 0145:
914 codes++;
915 bytes[0] = *codes++;
916 if (is_sbyte(ins, c-0143, 32)) bytes[0] |= 2; /* s-bit */
917 out (offset, segment, bytes, OUT_RAWDATA+1, NO_SEG, NO_SEG);
918 offset++;
919 break;
920
H. Peter Anvineba20a72002-04-30 20:53:55 +0000921 case 0300: case 0301: case 0302:
922 if (chsize (&ins->oprs[c-0300], bits)) {
923 *bytes = 0x67;
924 out (offset, segment, bytes,
925 OUT_RAWDATA+1, NO_SEG, NO_SEG);
926 offset += 1;
927 } else
928 offset += 0;
929 break;
930
931 case 0310:
932 if (bits==32) {
933 *bytes = 0x67;
934 out (offset, segment, bytes,
935 OUT_RAWDATA+1, NO_SEG, NO_SEG);
936 offset += 1;
937 } else
938 offset += 0;
939 break;
940
941 case 0311:
942 if (bits==16) {
943 *bytes = 0x67;
944 out (offset, segment, bytes,
945 OUT_RAWDATA+1, NO_SEG, NO_SEG);
946 offset += 1;
947 } else
948 offset += 0;
949 break;
950
951 case 0312:
952 break;
953
954 case 0320:
955 if (bits==32) {
956 *bytes = 0x66;
957 out (offset, segment, bytes,
958 OUT_RAWDATA+1, NO_SEG, NO_SEG);
959 offset += 1;
960 } else
961 offset += 0;
962 break;
963
964 case 0321:
965 if (bits==16) {
966 *bytes = 0x66;
967 out (offset, segment, bytes,
968 OUT_RAWDATA+1, NO_SEG, NO_SEG);
969 offset += 1;
970 } else
971 offset += 0;
972 break;
973
974 case 0322:
975 break;
976
977 case 0330:
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000978 *bytes = *codes++ ^ condval[ins->condition];
H. Peter Anvineba20a72002-04-30 20:53:55 +0000979 out (offset, segment, bytes,
980 OUT_RAWDATA+1, NO_SEG, NO_SEG);
981 offset += 1;
982 break;
983
H. Peter Anvinef7468f2002-04-30 20:57:59 +0000984 case 0331:
985 case 0332:
986 break;
987
988 case 0333:
989 *bytes = 0xF3;
990 out (offset, segment, bytes,
991 OUT_RAWDATA+1, NO_SEG, NO_SEG);
992 offset += 1;
993 break;
994
H. Peter Anvineba20a72002-04-30 20:53:55 +0000995 case 0340: case 0341: case 0342:
996 if (ins->oprs[0].segment != NO_SEG)
997 errfunc (ERR_PANIC, "non-constant BSS size in pass two");
998 else {
999 long size = ins->oprs[0].offset << (c-0340);
1000 if (size > 0)
1001 out (offset, segment, NULL,
1002 OUT_RESERVE+size, NO_SEG, NO_SEG);
1003 offset += size;
1004 }
1005 break;
1006
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001007 case 0370: case 0371: case 0372:
1008 break;
1009
1010 case 0373:
1011 *bytes = bits==16 ? 3 : 5;
1012 out (offset, segment, bytes,
1013 OUT_RAWDATA+1, NO_SEG, NO_SEG);
1014 offset += 1;
1015 break;
1016
H. Peter Anvineba20a72002-04-30 20:53:55 +00001017 default: /* can't do it by 'case' statements */
1018 if (c>=0100 && c<=0277) { /* it's an EA */
1019 ea ea_data;
1020 int rfield;
1021 unsigned char *p;
1022 long s;
1023
1024 if (c<=0177) /* pick rfield from operand b */
1025 rfield = regval (&ins->oprs[c&7]);
1026 else /* rfield is constant */
1027 rfield = c & 7;
1028
1029 if (!process_ea (&ins->oprs[(c>>3)&7], &ea_data, bits, rfield,
1030 ins->forw_ref))
1031 {
1032 errfunc (ERR_NONFATAL, "invalid effective address");
1033 }
1034
1035 p = bytes;
1036 *p++ = ea_data.modrm;
1037 if (ea_data.sib_present)
1038 *p++ = ea_data.sib;
1039
1040 s = p-bytes;
1041 out (offset, segment, bytes, OUT_RAWDATA + s,
1042 NO_SEG, NO_SEG);
1043
1044 switch (ea_data.bytes) {
1045 case 0:
1046 break;
1047 case 1:
1048 if (ins->oprs[(c>>3)&7].segment != NO_SEG) {
1049 data = ins->oprs[(c>>3)&7].offset;
1050 out (offset, segment, &data, OUT_ADDRESS+1,
1051 ins->oprs[(c>>3)&7].segment,
1052 ins->oprs[(c>>3)&7].wrt);
1053 } else {
1054 *bytes = ins->oprs[(c>>3)&7].offset;
1055 out (offset, segment, bytes, OUT_RAWDATA+1,
1056 NO_SEG, NO_SEG);
1057 }
1058 s++;
1059 break;
1060 case 2:
1061 case 4:
1062 data = ins->oprs[(c>>3)&7].offset;
1063 out (offset, segment, &data,
1064 OUT_ADDRESS+ea_data.bytes,
1065 ins->oprs[(c>>3)&7].segment, ins->oprs[(c>>3)&7].wrt);
1066 s += ea_data.bytes;
1067 break;
1068 }
1069 offset += s;
1070 } else
1071 errfunc (ERR_PANIC, "internal instruction table corrupt"
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001072 ": instruction code 0x%02X given", c);
H. Peter Anvineba20a72002-04-30 20:53:55 +00001073 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001074}
1075
H. Peter Anvineba20a72002-04-30 20:53:55 +00001076static int regval (operand *o)
1077{
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001078 switch (o->basereg) {
1079 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 +00001080 case R_ST0: case R_MM0: case R_XMM0:
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001081 return 0;
1082 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 +00001083 case R_MM1: case R_XMM1:
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001084 return 1;
1085 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 +00001086 case R_ST2: case R_MM2: case R_XMM2:
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001087 return 2;
1088 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 +00001089 case R_TR3: case R_ST3: case R_MM3: case R_XMM3:
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001090 return 3;
1091 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 +00001092 case R_ST4: case R_MM4: case R_XMM4:
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001093 return 4;
1094 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 +00001095 case R_MM5: case R_XMM5:
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001096 return 5;
1097 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 +00001098 case R_MM6: case R_XMM6:
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001099 return 6;
1100 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 +00001101 case R_MM7: case R_XMM7:
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001102 return 7;
1103 default: /* panic */
H. Peter Anvin4836e332002-04-30 20:56:43 +00001104 errfunc (ERR_PANIC, "invalid register operand given to regval()");
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001105 return 0;
1106 }
1107}
1108
H. Peter Anvineba20a72002-04-30 20:53:55 +00001109static int matches (struct itemplate *itemp, insn *instruction)
1110{
H. Peter Anvinef7468f2002-04-30 20:57:59 +00001111 int i, size[3], asize, oprs, ret;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001112
1113 ret = 100;
1114
1115 /*
1116 * Check the opcode
1117 */
1118 if (itemp->opcode != instruction->opcode) return 0;
1119
1120 /*
1121 * Count the operands
1122 */
1123 if (itemp->operands != instruction->operands) return 0;
1124
1125 /*
1126 * Check that no spurious colons or TOs are present
1127 */
1128 for (i=0; i<itemp->operands; i++)
1129 if (instruction->oprs[i].type & ~itemp->opd[i] & (COLON|TO))
1130 return 0;
1131
1132 /*
1133 * Check that the operand flags all match up
1134 */
1135 for (i=0; i<itemp->operands; i++)
1136 if (itemp->opd[i] & ~instruction->oprs[i].type ||
1137 ((itemp->opd[i] & SIZE_MASK) &&
H. Peter Anvineba20a72002-04-30 20:53:55 +00001138 ((itemp->opd[i] ^ instruction->oprs[i].type) & SIZE_MASK)))
1139 {
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001140 if ((itemp->opd[i] & ~instruction->oprs[i].type & NON_SIZE) ||
1141 (instruction->oprs[i].type & SIZE_MASK))
1142 return 0;
1143 else
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001144/* ret = 1; */
1145 return 1;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001146 }
1147
1148 /*
1149 * Check operand sizes
1150 */
H. Peter Anvinef7468f2002-04-30 20:57:59 +00001151 if (itemp->flags & IF_ARMASK) {
1152 size[0] = size[1] = size[2] = 0;
1153
1154 switch (itemp->flags & IF_ARMASK) {
1155 case IF_AR0: i = 0; break;
1156 case IF_AR1: i = 1; break;
1157 case IF_AR2: i = 2; break;
1158 default: break; /* Shouldn't happen */
1159 }
1160 if (itemp->flags & IF_SB) {
1161 size[i] = BITS8;
1162 } else if (itemp->flags & IF_SW) {
1163 size[i] = BITS16;
1164 } else if (itemp->flags & IF_SD) {
1165 size[i] = BITS32;
1166 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001167 } else {
H. Peter Anvinef7468f2002-04-30 20:57:59 +00001168 asize = 0;
1169 if (itemp->flags & IF_SB) {
1170 asize = BITS8;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001171 oprs = itemp->operands;
H. Peter Anvinef7468f2002-04-30 20:57:59 +00001172 } else if (itemp->flags & IF_SW) {
1173 asize = BITS16;
1174 oprs = itemp->operands;
1175 } else if (itemp->flags & IF_SD) {
1176 asize = BITS32;
1177 oprs = itemp->operands;
1178 }
1179 size[0] = size[1] = size[2] = asize;
1180 }
1181
1182 if (itemp->flags & (IF_SM | IF_SM2)) {
1183 oprs = (itemp->flags & IF_SM2 ? 2 : itemp->operands);
1184 asize = 0;
1185 for (i=0; i<oprs; i++) {
1186 if ( (asize = itemp->opd[i] & SIZE_MASK) != 0) {
1187 int j;
1188 for (j=0; j<oprs; j++)
1189 size[j] = asize;
1190 break;
1191 }
1192 }
1193 } else {
1194 oprs = itemp->operands;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001195 }
1196
1197 for (i=0; i<itemp->operands; i++)
1198 if (!(itemp->opd[i] & SIZE_MASK) &&
H. Peter Anvinef7468f2002-04-30 20:57:59 +00001199 (instruction->oprs[i].type & SIZE_MASK & ~size[i]))
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001200/* ret = 2; */
1201 return 2;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001202
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001203 /*
1204 * Check template is okay at the set cpu level
1205 */
1206 if ((itemp->flags & IF_PLEVEL) > cpu) return 3;
1207
1208 /*
1209 * Check if special handling needed for Jumps
1210 */
1211 if ((unsigned char)(itemp->code[0]) >= 0370) return 99;
1212
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001213 return ret;
1214}
1215
H. Peter Anvinea838272002-04-30 20:51:53 +00001216static ea *process_ea (operand *input, ea *output, int addrbits, int rfield,
H. Peter Anvineba20a72002-04-30 20:53:55 +00001217 int forw_ref)
1218{
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001219 if (!(REGISTER & ~input->type)) { /* it's a single register */
1220 static int regs[] = {
H. Peter Anvin4836e332002-04-30 20:56:43 +00001221 R_AL, R_CL, R_DL, R_BL, R_AH, R_CH, R_DH, R_BH,
1222 R_AX, R_CX, R_DX, R_BX, R_SP, R_BP, R_SI, R_DI,
1223 R_EAX, R_ECX, R_EDX, R_EBX, R_ESP, R_EBP, R_ESI, R_EDI,
1224 R_MM0, R_MM1, R_MM2, R_MM3, R_MM4, R_MM5, R_MM6, R_MM7,
1225 R_XMM0, R_XMM1, R_XMM2, R_XMM3, R_XMM4, R_XMM5, R_XMM6, R_XMM7
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001226 };
1227 int i;
1228
1229 for (i=0; i<elements(regs); i++)
1230 if (input->basereg == regs[i]) break;
1231 if (i<elements(regs)) {
1232 output->sib_present = FALSE;/* no SIB necessary */
1233 output->bytes = 0; /* no offset necessary either */
H. Peter Anvin4836e332002-04-30 20:56:43 +00001234 output->modrm = 0xC0 | (rfield << 3) | (i & 7);
H. Peter Anvineba20a72002-04-30 20:53:55 +00001235 }
1236 else
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001237 return NULL;
1238 } else { /* it's a memory reference */
1239 if (input->basereg==-1 && (input->indexreg==-1 || input->scale==0)) {
1240 /* it's a pure offset */
1241 if (input->addr_size)
1242 addrbits = input->addr_size;
1243 output->sib_present = FALSE;
1244 output->bytes = (addrbits==32 ? 4 : 2);
1245 output->modrm = (addrbits==32 ? 5 : 6) | (rfield << 3);
H. Peter Anvineba20a72002-04-30 20:53:55 +00001246 }
1247 else { /* it's an indirection */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001248 int i=input->indexreg, b=input->basereg, s=input->scale;
1249 long o=input->offset, seg=input->segment;
H. Peter Anvin76690a12002-04-30 20:52:49 +00001250 int hb=input->hintbase, ht=input->hinttype;
1251 int t;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001252
1253 if (s==0) i = -1; /* make this easy, at least */
1254
1255 if (i==R_EAX || i==R_EBX || i==R_ECX || i==R_EDX
1256 || i==R_EBP || i==R_ESP || i==R_ESI || i==R_EDI
1257 || b==R_EAX || b==R_EBX || b==R_ECX || b==R_EDX
1258 || b==R_EBP || b==R_ESP || b==R_ESI || b==R_EDI) {
1259 /* it must be a 32-bit memory reference. Firstly we have
1260 * to check that all registers involved are type Exx. */
1261 if (i!=-1 && i!=R_EAX && i!=R_EBX && i!=R_ECX && i!=R_EDX
1262 && i!=R_EBP && i!=R_ESP && i!=R_ESI && i!=R_EDI)
1263 return NULL;
1264 if (b!=-1 && b!=R_EAX && b!=R_EBX && b!=R_ECX && b!=R_EDX
1265 && b!=R_EBP && b!=R_ESP && b!=R_ESI && b!=R_EDI)
1266 return NULL;
1267
1268 /* While we're here, ensure the user didn't specify WORD. */
1269 if (input->addr_size == 16)
1270 return NULL;
1271
1272 /* now reorganise base/index */
H. Peter Anvin76690a12002-04-30 20:52:49 +00001273 if (s == 1 && b != i && b != -1 && i != -1 &&
1274 ((hb==b&&ht==EAH_NOTBASE) || (hb==i&&ht==EAH_MAKEBASE)))
1275 t = b, b = i, i = t; /* swap if hints say so */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001276 if (b==i) /* convert EAX+2*EAX to 3*EAX */
1277 b = -1, s++;
H. Peter Anvin76690a12002-04-30 20:52:49 +00001278 if (b==-1 && s==1 && !(hb == i && ht == EAH_NOTBASE))
1279 b = i, i = -1; /* make single reg base, unless hint */
1280 if (((s==2 && i!=R_ESP && !(input->eaflags & EAF_TIMESTWO)) ||
1281 s==3 || s==5 || s==9) && b==-1)
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001282 b = i, s--; /* convert 3*EAX to EAX+2*EAX */
H. Peter Anvinea838272002-04-30 20:51:53 +00001283 if (s==1 && i==R_ESP) /* swap ESP into base if scale is 1 */
1284 i = b, b = R_ESP;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001285 if (i==R_ESP || (s!=1 && s!=2 && s!=4 && s!=8 && i!=-1))
1286 return NULL; /* wrong, for various reasons */
1287
1288 if (i==-1 && b!=R_ESP) {/* no SIB needed */
1289 int mod, rm;
1290 switch(b) {
1291 case R_EAX: rm = 0; break;
1292 case R_ECX: rm = 1; break;
1293 case R_EDX: rm = 2; break;
1294 case R_EBX: rm = 3; break;
1295 case R_EBP: rm = 5; break;
1296 case R_ESI: rm = 6; break;
1297 case R_EDI: rm = 7; break;
1298 case -1: rm = 5; break;
1299 default: /* should never happen */
1300 return NULL;
1301 }
H. Peter Anvinea838272002-04-30 20:51:53 +00001302 if (b==-1 || (b!=R_EBP && o==0 &&
H. Peter Anvin76690a12002-04-30 20:52:49 +00001303 seg==NO_SEG && !forw_ref &&
1304 !(input->eaflags &
1305 (EAF_BYTEOFFS|EAF_WORDOFFS))))
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001306 mod = 0;
H. Peter Anvin76690a12002-04-30 20:52:49 +00001307 else if (input->eaflags & EAF_BYTEOFFS ||
1308 (o>=-128 && o<=127 && seg==NO_SEG && !forw_ref &&
1309 !(input->eaflags & EAF_WORDOFFS))) {
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001310 mod = 1;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001311 }
1312 else
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001313 mod = 2;
H. Peter Anvinea838272002-04-30 20:51:53 +00001314
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001315 output->sib_present = FALSE;
1316 output->bytes = (b==-1 || mod==2 ? 4 : mod);
1317 output->modrm = (mod<<6) | (rfield<<3) | rm;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001318 }
1319 else { /* we need a SIB */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001320 int mod, scale, index, base;
1321
1322 switch (b) {
1323 case R_EAX: base = 0; break;
1324 case R_ECX: base = 1; break;
1325 case R_EDX: base = 2; break;
1326 case R_EBX: base = 3; break;
1327 case R_ESP: base = 4; break;
1328 case R_EBP: case -1: base = 5; break;
1329 case R_ESI: base = 6; break;
1330 case R_EDI: base = 7; break;
1331 default: /* then what the smeg is it? */
1332 return NULL; /* panic */
1333 }
1334
1335 switch (i) {
1336 case R_EAX: index = 0; break;
1337 case R_ECX: index = 1; break;
1338 case R_EDX: index = 2; break;
1339 case R_EBX: index = 3; break;
1340 case -1: index = 4; break;
1341 case R_EBP: index = 5; break;
1342 case R_ESI: index = 6; break;
1343 case R_EDI: index = 7; break;
1344 default: /* then what the smeg is it? */
1345 return NULL; /* panic */
1346 }
1347
1348 if (i==-1) s = 1;
1349 switch (s) {
1350 case 1: scale = 0; break;
1351 case 2: scale = 1; break;
1352 case 4: scale = 2; break;
1353 case 8: scale = 3; break;
1354 default: /* then what the smeg is it? */
1355 return NULL; /* panic */
1356 }
1357
H. Peter Anvinea838272002-04-30 20:51:53 +00001358 if (b==-1 || (b!=R_EBP && o==0 &&
H. Peter Anvin76690a12002-04-30 20:52:49 +00001359 seg==NO_SEG && !forw_ref &&
1360 !(input->eaflags &
1361 (EAF_BYTEOFFS|EAF_WORDOFFS))))
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001362 mod = 0;
H. Peter Anvin76690a12002-04-30 20:52:49 +00001363 else if (input->eaflags & EAF_BYTEOFFS ||
1364 (o>=-128 && o<=127 && seg==NO_SEG && !forw_ref &&
1365 !(input->eaflags & EAF_WORDOFFS)))
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001366 mod = 1;
1367 else
1368 mod = 2;
1369
1370 output->sib_present = TRUE;
1371 output->bytes = (b==-1 || mod==2 ? 4 : mod);
1372 output->modrm = (mod<<6) | (rfield<<3) | 4;
1373 output->sib = (scale<<6) | (index<<3) | base;
1374 }
H. Peter Anvineba20a72002-04-30 20:53:55 +00001375 }
1376 else { /* it's 16-bit */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001377 int mod, rm;
1378
1379 /* check all registers are BX, BP, SI or DI */
1380 if ((b!=-1 && b!=R_BP && b!=R_BX && b!=R_SI && b!=R_DI) ||
1381 (i!=-1 && i!=R_BP && i!=R_BX && i!=R_SI && i!=R_DI))
1382 return NULL;
1383
1384 /* ensure the user didn't specify DWORD */
1385 if (input->addr_size == 32)
1386 return NULL;
1387
1388 if (s!=1 && i!=-1) return NULL;/* no can do, in 16-bit EA */
1389 if (b==-1 && i!=-1) b ^= i ^= b ^= i; /* swap them round */
1390 if ((b==R_SI || b==R_DI) && i!=-1)
1391 b ^= i ^= b ^= i; /* have BX/BP as base, SI/DI index */
1392 if (b==i) return NULL;/* shouldn't ever happen, in theory */
1393 if (i!=-1 && b!=-1 &&
1394 (i==R_BP || i==R_BX || b==R_SI || b==R_DI))
1395 return NULL; /* invalid combinations */
1396 if (b==-1) /* pure offset: handled above */
1397 return NULL; /* so if it gets to here, panic! */
1398
1399 rm = -1;
1400 if (i!=-1)
1401 switch (i*256 + b) {
1402 case R_SI*256+R_BX: rm=0; break;
1403 case R_DI*256+R_BX: rm=1; break;
1404 case R_SI*256+R_BP: rm=2; break;
1405 case R_DI*256+R_BP: rm=3; break;
1406 }
1407 else
1408 switch (b) {
1409 case R_SI: rm=4; break;
1410 case R_DI: rm=5; break;
1411 case R_BP: rm=6; break;
1412 case R_BX: rm=7; break;
1413 }
1414 if (rm==-1) /* can't happen, in theory */
1415 return NULL; /* so panic if it does */
1416
H. Peter Anvin76690a12002-04-30 20:52:49 +00001417 if (o==0 && seg==NO_SEG && !forw_ref && rm!=6 &&
1418 !(input->eaflags & (EAF_BYTEOFFS|EAF_WORDOFFS)))
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001419 mod = 0;
H. Peter Anvin76690a12002-04-30 20:52:49 +00001420 else if (input->eaflags & EAF_BYTEOFFS ||
1421 (o>=-128 && o<=127 && seg==NO_SEG && !forw_ref &&
1422 !(input->eaflags & EAF_WORDOFFS)))
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001423 mod = 1;
1424 else
1425 mod = 2;
1426
1427 output->sib_present = FALSE; /* no SIB - it's 16-bit */
1428 output->bytes = mod; /* bytes of offset needed */
1429 output->modrm = (mod<<6) | (rfield<<3) | rm;
1430 }
1431 }
1432 }
1433 output->size = 1 + output->sib_present + output->bytes;
1434 return output;
1435}
1436
H. Peter Anvineba20a72002-04-30 20:53:55 +00001437static int chsize (operand *input, int addrbits)
1438{
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001439 if (!(MEMORY & ~input->type)) {
1440 int i=input->indexreg, b=input->basereg;
1441
1442 if (input->scale==0) i = -1;
1443
1444 if (i == -1 && b == -1) /* pure offset */
1445 return (input->addr_size != 0 && input->addr_size != addrbits);
1446
1447 if (i==R_EAX || i==R_EBX || i==R_ECX || i==R_EDX
1448 || i==R_EBP || i==R_ESP || i==R_ESI || i==R_EDI
1449 || b==R_EAX || b==R_EBX || b==R_ECX || b==R_EDX
1450 || b==R_EBP || b==R_ESP || b==R_ESI || b==R_EDI)
1451 return (addrbits==16);
1452 else
1453 return (addrbits==32);
H. Peter Anvineba20a72002-04-30 20:53:55 +00001454 }
1455 else
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001456 return 0;
1457}