blob: b87b10408ed24309b58b36e82a506a8617eaa70c [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
H. Peter Anvin17799b42002-05-21 03:31:21 +000031 * assembly mode or the operand-size override on the operand
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000032 * \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{
H. Peter Anvin9eb185b2002-04-30 21:02:47 +0000105 long lineno;
106 char *lnfname = NULL;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000107
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))
H. Peter Anvince616072002-04-30 21:02:23 +0000144 {
H. Peter Anvineba20a72002-04-30 20:53:55 +0000145 outfmt->current_dfmt->linenum(lnfname,lineno,segto);
H. Peter Anvin9eb185b2002-04-30 21:02:47 +0000146 if (lnfname) nasm_free(lnfname);
H. Peter Anvince616072002-04-30 21:02:23 +0000147 }
H. Peter Anvineba20a72002-04-30 20:53:55 +0000148
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000149 outfmt->output (segto, data, type, segment, wrt);
150}
151
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000152static int jmp_match (long segment, long offset, int bits,
153 insn *ins, char *code)
154{ long isize;
155 unsigned char c = code[0];
156
157
H. Peter Anvin788e6c12002-04-30 21:02:01 +0000158 if (c != 0370 && c != 0371) return 0;
159 if (ins->oprs[0].opflags & OPFLAG_FORWARD) {
H. Peter Anvin01377d82002-05-21 03:16:33 +0000160 if ((optimizing<0 || (ins->oprs[0].type & STRICT))
161 && c==0370) return 1;
H. Peter Anvin788e6c12002-04-30 21:02:01 +0000162 else return (pass0==0); /* match a forward reference */
163 }
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000164 isize = calcsize (segment, offset, bits, ins, code);
165 if (ins->oprs[0].segment != segment) return 0;
166 isize = ins->oprs[0].offset - offset - isize; /* isize is now the delta */
167 if (isize >= -128L && isize <= 127L) return 1; /* it is byte size */
168
169 return 0;
170}
171
172
173long assemble (long segment, long offset, int bits, unsigned long cp,
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000174 insn *instruction, struct ofmt *output, efunc error,
H. Peter Anvineba20a72002-04-30 20:53:55 +0000175 ListGen *listgen)
176{
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000177 struct itemplate *temp;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000178 int j;
179 int size_prob;
180 long insn_end;
181 long itimes;
182 long start = offset;
183 long wsize = 0; /* size for DB etc. */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000184
185 errfunc = error; /* to pass to other functions */
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000186 cpu = cp;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000187 outfmt = output; /* likewise */
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000188 list = listgen; /* and again */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000189
H. Peter Anvineba20a72002-04-30 20:53:55 +0000190 switch (instruction->opcode)
191 {
192 case -1: return 0;
193 case I_DB: wsize = 1; break;
194 case I_DW: wsize = 2; break;
195 case I_DD: wsize = 4; break;
196 case I_DQ: wsize = 8; break;
197 case I_DT: wsize = 10; break;
198 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000199
H. Peter Anvineba20a72002-04-30 20:53:55 +0000200 if (wsize) {
201 extop * e;
202 long t = instruction->times;
203 if (t < 0)
204 errfunc(ERR_PANIC, "instruction->times < 0 (%ld) in assemble()",t);
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000205
H. Peter Anvineba20a72002-04-30 20:53:55 +0000206 while (t--) /* repeat TIMES times */
207 {
208 for (e = instruction->eops; e; e = e->next)
209 {
210 if (e->type == EOT_DB_NUMBER)
211 {
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000212 if (wsize == 1) {
213 if (e->segment != NO_SEG)
214 errfunc (ERR_NONFATAL,
215 "one-byte relocation attempted");
216 else {
H. Peter Anvin41bf8002002-04-30 20:58:18 +0000217 unsigned char out_byte = e->offset;
218 out (offset, segment, &out_byte, OUT_RAWDATA+1,
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000219 NO_SEG, NO_SEG);
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000220 }
H. Peter Anvineba20a72002-04-30 20:53:55 +0000221 }
222 else if (wsize > 5) {
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000223 errfunc (ERR_NONFATAL, "integer supplied to a D%c"
224 " instruction", wsize==8 ? 'Q' : 'T');
H. Peter Anvineba20a72002-04-30 20:53:55 +0000225 }
226 else
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000227 out (offset, segment, &e->offset,
228 OUT_ADDRESS+wsize, e->segment,
229 e->wrt);
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000230 offset += wsize;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000231 }
232 else if (e->type == EOT_DB_STRING)
233 {
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000234 int align;
235
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000236 out (offset, segment, e->stringval,
237 OUT_RAWDATA+e->stringlen, NO_SEG, NO_SEG);
H. Peter Anvineba20a72002-04-30 20:53:55 +0000238 align = e->stringlen % wsize;
239
240 if (align) {
241 align = wsize - align;
242 out (offset, segment, "\0\0\0\0\0\0\0\0",
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000243 OUT_RAWDATA+align, NO_SEG, NO_SEG);
H. Peter Anvineba20a72002-04-30 20:53:55 +0000244 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000245 offset += e->stringlen + align;
246 }
247 }
H. Peter Anvineba20a72002-04-30 20:53:55 +0000248 if (t > 0 && t == instruction->times-1)
249 {
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000250 /*
251 * Dummy call to list->output to give the offset to the
252 * listing module.
253 */
254 list->output (offset, NULL, OUT_RAWDATA);
255 list->uplevel (LIST_TIMES);
256 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000257 }
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000258 if (instruction->times > 1)
259 list->downlevel (LIST_TIMES);
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000260 return offset - start;
261 }
262
H. Peter Anvineba20a72002-04-30 20:53:55 +0000263 if (instruction->opcode == I_INCBIN)
264 {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000265 static char fname[FILENAME_MAX];
H. Peter Anvineba20a72002-04-30 20:53:55 +0000266 FILE * fp;
267 long len;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000268
269 len = FILENAME_MAX-1;
270 if (len > instruction->eops->stringlen)
271 len = instruction->eops->stringlen;
272 strncpy (fname, instruction->eops->stringval, len);
273 fname[len] = '\0';
H. Peter Anvineba20a72002-04-30 20:53:55 +0000274
275 if ( (fp = fopen(fname, "rb")) == NULL)
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000276 error (ERR_NONFATAL, "`incbin': unable to open file `%s'", fname);
277 else if (fseek(fp, 0L, SEEK_END) < 0)
278 error (ERR_NONFATAL, "`incbin': unable to seek on file `%s'",
279 fname);
H. Peter Anvineba20a72002-04-30 20:53:55 +0000280 else
281 {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000282 static char buf[2048];
283 long t = instruction->times;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000284 long base = 0;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000285
286 len = ftell (fp);
287 if (instruction->eops->next) {
H. Peter Anvineba20a72002-04-30 20:53:55 +0000288 base = instruction->eops->next->offset;
289 len -= base;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000290 if (instruction->eops->next->next &&
291 len > instruction->eops->next->next->offset)
292 len = instruction->eops->next->next->offset;
293 }
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000294 /*
295 * Dummy call to list->output to give the offset to the
296 * listing module.
297 */
298 list->output (offset, NULL, OUT_RAWDATA);
299 list->uplevel(LIST_INCBIN);
H. Peter Anvineba20a72002-04-30 20:53:55 +0000300 while (t--)
301 {
302 long l;
303
304 fseek (fp, base, SEEK_SET);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000305 l = len;
306 while (l > 0) {
307 long m = fread (buf, 1, (l>sizeof(buf)?sizeof(buf):l),
308 fp);
309 if (!m) {
310 /*
311 * This shouldn't happen unless the file
312 * actually changes while we are reading
313 * it.
314 */
315 error (ERR_NONFATAL, "`incbin': unexpected EOF while"
316 " reading file `%s'", fname);
H. Peter Anvineba20a72002-04-30 20:53:55 +0000317 t=0; /* Try to exit cleanly */
318 break;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000319 }
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000320 out (offset, segment, buf, OUT_RAWDATA+m,
321 NO_SEG, NO_SEG);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000322 l -= m;
323 }
324 }
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000325 list->downlevel(LIST_INCBIN);
326 if (instruction->times > 1) {
327 /*
328 * Dummy call to list->output to give the offset to the
329 * listing module.
330 */
331 list->output (offset, NULL, OUT_RAWDATA);
332 list->uplevel(LIST_TIMES);
333 list->downlevel(LIST_TIMES);
334 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000335 fclose (fp);
336 return instruction->times * len;
337 }
338 return 0; /* if we're here, there's an error */
339 }
340
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000341 size_prob = FALSE;
342 temp = nasm_instructions[instruction->opcode];
343 while (temp->opcode != -1) {
344 int m = matches (temp, instruction);
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000345 if (m == 99)
346 m += jmp_match(segment, offset, bits, instruction, temp->code);
H. Peter Anvineba20a72002-04-30 20:53:55 +0000347
348 if (m == 100) /* matches! */
349 {
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000350 char *codes = temp->code;
351 long insn_size = calcsize(segment, offset, bits,
352 instruction, codes);
353 itimes = instruction->times;
354 if (insn_size < 0) /* shouldn't be, on pass two */
355 error (ERR_PANIC, "errors made it through from pass one");
356 else while (itimes--) {
357 insn_end = offset + insn_size;
358 for (j=0; j<instruction->nprefix; j++) {
H. Peter Anvineba20a72002-04-30 20:53:55 +0000359 unsigned char c=0;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000360 switch (instruction->prefixes[j]) {
361 case P_LOCK:
362 c = 0xF0; break;
363 case P_REPNE: case P_REPNZ:
364 c = 0xF2; break;
365 case P_REPE: case P_REPZ: case P_REP:
366 c = 0xF3; break;
367 case R_CS: c = 0x2E; break;
368 case R_DS: c = 0x3E; break;
369 case R_ES: c = 0x26; break;
370 case R_FS: c = 0x64; break;
371 case R_GS: c = 0x65; break;
372 case R_SS: c = 0x36; break;
373 case P_A16:
H. Peter Anvineba20a72002-04-30 20:53:55 +0000374 if (bits != 16)
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000375 c = 0x67;
376 break;
377 case P_A32:
H. Peter Anvineba20a72002-04-30 20:53:55 +0000378 if (bits != 32)
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000379 c = 0x67;
380 break;
381 case P_O16:
H. Peter Anvineba20a72002-04-30 20:53:55 +0000382 if (bits != 16)
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000383 c = 0x66;
384 break;
385 case P_O32:
H. Peter Anvineba20a72002-04-30 20:53:55 +0000386 if (bits != 32)
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000387 c = 0x66;
388 break;
389 default:
390 error (ERR_PANIC,
391 "invalid instruction prefix");
392 }
H. Peter Anvineba20a72002-04-30 20:53:55 +0000393 if (c != 0) {
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000394 out (offset, segment, &c, OUT_RAWDATA+1,
395 NO_SEG, NO_SEG);
H. Peter Anvineba20a72002-04-30 20:53:55 +0000396 offset++;
397 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000398 }
399 gencode (segment, offset, bits, instruction, codes, insn_end);
400 offset += insn_size;
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000401 if (itimes > 0 && itimes == instruction->times-1) {
402 /*
403 * Dummy call to list->output to give the offset to the
404 * listing module.
405 */
406 list->output (offset, NULL, OUT_RAWDATA);
407 list->uplevel (LIST_TIMES);
408 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000409 }
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000410 if (instruction->times > 1)
411 list->downlevel (LIST_TIMES);
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000412 return offset - start;
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000413 } else if (m > 0 && m > size_prob) {
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000414 size_prob = m;
415 }
416 temp++;
417 }
H. Peter Anvineba20a72002-04-30 20:53:55 +0000418
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000419 if (temp->opcode == -1) { /* didn't match any instruction */
420 if (size_prob == 1) /* would have matched, but for size */
421 error (ERR_NONFATAL, "operation size not specified");
422 else if (size_prob == 2)
423 error (ERR_NONFATAL, "mismatch in operand sizes");
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000424 else if (size_prob == 3)
425 error (ERR_NONFATAL, "no instruction for this cpu level");
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000426 else
427 error (ERR_NONFATAL,
428 "invalid combination of opcode and operands");
429 }
430 return 0;
431}
432
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000433long insn_size (long segment, long offset, int bits, unsigned long cp,
H. Peter Anvineba20a72002-04-30 20:53:55 +0000434 insn *instruction, efunc error)
435{
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000436 struct itemplate *temp;
437
438 errfunc = error; /* to pass to other functions */
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000439 cpu = cp;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000440
441 if (instruction->opcode == -1)
442 return 0;
443
444 if (instruction->opcode == I_DB ||
445 instruction->opcode == I_DW ||
446 instruction->opcode == I_DD ||
447 instruction->opcode == I_DQ ||
H. Peter Anvineba20a72002-04-30 20:53:55 +0000448 instruction->opcode == I_DT)
449 {
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000450 extop *e;
451 long isize, osize, wsize = 0; /* placate gcc */
452
453 isize = 0;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000454 switch (instruction->opcode)
455 {
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000456 case I_DB: wsize = 1; break;
457 case I_DW: wsize = 2; break;
458 case I_DD: wsize = 4; break;
459 case I_DQ: wsize = 8; break;
460 case I_DT: wsize = 10; break;
461 }
462
H. Peter Anvineba20a72002-04-30 20:53:55 +0000463 for (e = instruction->eops; e; e = e->next)
464 {
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000465 long align;
466
467 osize = 0;
468 if (e->type == EOT_DB_NUMBER)
469 osize = 1;
470 else if (e->type == EOT_DB_STRING)
471 osize = e->stringlen;
472
473 align = (-osize) % wsize;
474 if (align < 0)
475 align += wsize;
476 isize += osize + align;
477 }
478 return isize * instruction->times;
479 }
480
H. Peter Anvineba20a72002-04-30 20:53:55 +0000481 if (instruction->opcode == I_INCBIN)
482 {
483 char fname[FILENAME_MAX];
484 FILE * fp;
485 long len;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000486
487 len = FILENAME_MAX-1;
488 if (len > instruction->eops->stringlen)
489 len = instruction->eops->stringlen;
490 strncpy (fname, instruction->eops->stringval, len);
491 fname[len] = '\0';
H. Peter Anvineba20a72002-04-30 20:53:55 +0000492 if ( (fp = fopen(fname, "rb")) == NULL )
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000493 error (ERR_NONFATAL, "`incbin': unable to open file `%s'", fname);
494 else if (fseek(fp, 0L, SEEK_END) < 0)
495 error (ERR_NONFATAL, "`incbin': unable to seek on file `%s'",
496 fname);
H. Peter Anvineba20a72002-04-30 20:53:55 +0000497 else
498 {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000499 len = ftell (fp);
500 fclose (fp);
H. Peter Anvineba20a72002-04-30 20:53:55 +0000501 if (instruction->eops->next)
502 {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000503 len -= instruction->eops->next->offset;
504 if (instruction->eops->next->next &&
505 len > instruction->eops->next->next->offset)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000506 {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000507 len = instruction->eops->next->next->offset;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000508 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000509 }
510 return instruction->times * len;
511 }
512 return 0; /* if we're here, there's an error */
513 }
514
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000515 temp = nasm_instructions[instruction->opcode];
516 while (temp->opcode != -1) {
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000517 int m = matches(temp, instruction);
518 if (m == 99)
519 m += jmp_match(segment, offset, bits, instruction, temp->code);
520
521 if (m == 100) {
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000522 /* we've matched an instruction. */
H. Peter Anvineba20a72002-04-30 20:53:55 +0000523 long isize;
524 char * codes = temp->code;
525 int j;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000526
527 isize = calcsize(segment, offset, bits, instruction, codes);
528 if (isize < 0)
529 return -1;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000530 for (j = 0; j < instruction->nprefix; j++)
531 {
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000532 if ((instruction->prefixes[j] != P_A16 &&
533 instruction->prefixes[j] != P_O16 && bits==16) ||
534 (instruction->prefixes[j] != P_A32 &&
535 instruction->prefixes[j] != P_O32 && bits==32))
H. Peter Anvineba20a72002-04-30 20:53:55 +0000536 {
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000537 isize++;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000538 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000539 }
540 return isize * instruction->times;
541 }
542 temp++;
543 }
544 return -1; /* didn't match any instruction */
545}
546
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000547
548/* check that opn[op] is a signed byte of size 16 or 32,
549 and return the signed value*/
550static int is_sbyte (insn *ins, int op, int size)
551{
552 signed long v;
553 int ret;
554
555 ret = !(ins->forw_ref && ins->oprs[op].opflags ) && /* dead in the water on forward reference or External */
H. Peter Anvin01377d82002-05-21 03:16:33 +0000556 optimizing>=0 &&
557 !(ins->oprs[op].type & STRICT) &&
558 ins->oprs[op].wrt==NO_SEG && ins->oprs[op].segment==NO_SEG;
H. Peter Anvin734b1882002-04-30 21:01:08 +0000559
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000560 v = ins->oprs[op].offset;
561 if (size==16) v = (signed short)v; /* sign extend if 16 bits */
562
563 return ret && v>=-128L && v<=127L;
564}
565
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000566static long calcsize (long segment, long offset, int bits,
H. Peter Anvineba20a72002-04-30 20:53:55 +0000567 insn *ins, char *codes)
568{
569 long length = 0;
570 unsigned char c;
571
572 (void) segment; /* Don't warn that this parameter is unused */
573 (void) offset; /* Don't warn that this parameter is unused */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000574
575 while (*codes) switch (c = *codes++) {
576 case 01: case 02: case 03:
577 codes += c, length += c; break;
578 case 04: case 05: case 06: case 07:
579 length++; break;
580 case 010: case 011: case 012:
581 codes++, length++; break;
582 case 017:
583 length++; break;
584 case 014: case 015: case 016:
585 length++; break;
586 case 020: case 021: case 022:
587 length++; break;
588 case 024: case 025: case 026:
589 length++; break;
590 case 030: case 031: case 032:
591 length += 2; break;
592 case 034: case 035: case 036:
593 length += ((ins->oprs[c-034].addr_size ?
594 ins->oprs[c-034].addr_size : bits) == 16 ? 2 : 4); break;
595 case 037:
596 length += 2; break;
597 case 040: case 041: case 042:
598 length += 4; break;
599 case 050: case 051: case 052:
600 length++; break;
601 case 060: case 061: case 062:
602 length += 2; break;
603 case 064: case 065: case 066:
H. Peter Anvin17799b42002-05-21 03:31:21 +0000604 if ( ins->oprs[c-064].type & (BITS16|BITS32) )
605 length += (ins->oprs[c-064].type & BITS16) ? 2 : 4;
606 else
607 length += (bits == 16) ? 2 : 4;
608 break;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000609 case 070: case 071: case 072:
610 length += 4; break;
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000611 case 0130: case 0131: case 0132:
612 length += is_sbyte(ins, c-0130, 16) ? 1 : 2; break;
613 case 0133: case 0134: case 0135:
614 codes+=2; length++; break;
615 case 0140: case 0141: case 0142:
616 length += is_sbyte(ins, c-0140, 32) ? 1 : 4; break;
617 case 0143: case 0144: case 0145:
618 codes+=2; length++; break;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000619 case 0300: case 0301: case 0302:
620 length += chsize (&ins->oprs[c-0300], bits);
621 break;
622 case 0310:
623 length += (bits==32);
624 break;
625 case 0311:
626 length += (bits==16);
627 break;
628 case 0312:
629 break;
630 case 0320:
631 length += (bits==32);
632 break;
633 case 0321:
634 length += (bits==16);
635 break;
636 case 0322:
637 break;
638 case 0330:
639 codes++, length++; break;
H. Peter Anvinef7468f2002-04-30 20:57:59 +0000640 case 0331:
641 case 0332:
642 break;
643 case 0333:
644 length++; break;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000645 case 0340: case 0341: case 0342:
646 if (ins->oprs[0].segment != NO_SEG)
647 errfunc (ERR_NONFATAL, "attempt to reserve non-constant"
648 " quantity of BSS space");
649 else
650 length += ins->oprs[0].offset << (c-0340);
651 break;
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000652 case 0370: case 0371: case 0372:
653 break;
654 case 0373:
655 length++; break;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000656 default: /* can't do it by 'case' statements */
657 if (c>=0100 && c<=0277) { /* it's an EA */
658 ea ea_data;
H. Peter Anvinea838272002-04-30 20:51:53 +0000659 if (!process_ea (&ins->oprs[(c>>3)&7], &ea_data, bits, 0,
660 ins->forw_ref)) {
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000661 errfunc (ERR_NONFATAL, "invalid effective address");
662 return -1;
663 } else
664 length += ea_data.size;
665 } else
666 errfunc (ERR_PANIC, "internal instruction table corrupt"
667 ": instruction code 0x%02X given", c);
668 }
669 return length;
670}
671
672static void gencode (long segment, long offset, int bits,
H. Peter Anvineba20a72002-04-30 20:53:55 +0000673 insn *ins, char *codes, long insn_end)
674{
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000675 static char condval[] = { /* conditional opcodes */
676 0x7, 0x3, 0x2, 0x6, 0x2, 0x4, 0xF, 0xD, 0xC, 0xE, 0x6, 0x2,
677 0x3, 0x7, 0x3, 0x5, 0xE, 0xC, 0xD, 0xF, 0x1, 0xB, 0x9, 0x5,
678 0x0, 0xA, 0xA, 0xB, 0x8, 0x4
679 };
H. Peter Anvineba20a72002-04-30 20:53:55 +0000680 unsigned char c;
681 unsigned char bytes[4];
682 long data, size;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000683
H. Peter Anvineba20a72002-04-30 20:53:55 +0000684 while (*codes)
685 switch (c = *codes++)
686 {
687 case 01: case 02: case 03:
688 out (offset, segment, codes, OUT_RAWDATA+c, NO_SEG, NO_SEG);
689 codes += c;
690 offset += c;
691 break;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000692
H. Peter Anvineba20a72002-04-30 20:53:55 +0000693 case 04: case 06:
694 switch (ins->oprs[0].basereg)
695 {
696 case R_CS:
697 bytes[0] = 0x0E + (c == 0x04 ? 1 : 0); break;
698 case R_DS:
699 bytes[0] = 0x1E + (c == 0x04 ? 1 : 0); break;
700 case R_ES:
701 bytes[0] = 0x06 + (c == 0x04 ? 1 : 0); break;
702 case R_SS:
703 bytes[0] = 0x16 + (c == 0x04 ? 1 : 0); break;
704 default:
H. Peter Anvin4836e332002-04-30 20:56:43 +0000705 errfunc (ERR_PANIC, "bizarre 8086 segment register received");
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000706 }
H. Peter Anvineba20a72002-04-30 20:53:55 +0000707 out (offset, segment, bytes, OUT_RAWDATA+1, NO_SEG, NO_SEG);
708 offset++;
709 break;
710
711 case 05: case 07:
712 switch (ins->oprs[0].basereg) {
713 case R_FS: bytes[0] = 0xA0 + (c == 0x05 ? 1 : 0); break;
714 case R_GS: bytes[0] = 0xA8 + (c == 0x05 ? 1 : 0); break;
715 default:
H. Peter Anvin4836e332002-04-30 20:56:43 +0000716 errfunc (ERR_PANIC, "bizarre 386 segment register received");
H. Peter Anvineba20a72002-04-30 20:53:55 +0000717 }
718 out (offset, segment, bytes, OUT_RAWDATA+1, NO_SEG, NO_SEG);
719 offset++;
720 break;
721
722 case 010: case 011: case 012:
723 bytes[0] = *codes++ + regval(&ins->oprs[c-010]);
724 out (offset, segment, bytes, OUT_RAWDATA+1, NO_SEG, NO_SEG);
725 offset += 1;
726 break;
727
728 case 017:
729 bytes[0] = 0;
730 out (offset, segment, bytes, OUT_RAWDATA+1, NO_SEG, NO_SEG);
731 offset += 1;
732 break;
733
734 case 014: case 015: case 016:
735 if (ins->oprs[c-014].offset < -128
736 || ins->oprs[c-014].offset > 127)
737 {
738 errfunc (ERR_WARNING, "signed byte value exceeds bounds");
739 }
740
741 if (ins->oprs[c-014].segment != NO_SEG)
742 {
743 data = ins->oprs[c-014].offset;
744 out (offset, segment, &data, OUT_ADDRESS+1,
745 ins->oprs[c-014].segment, ins->oprs[c-014].wrt);
746 }
747 else {
748 bytes[0] = ins->oprs[c-014].offset;
749 out (offset, segment, bytes, OUT_RAWDATA+1, NO_SEG, NO_SEG);
750 }
751 offset += 1;
752 break;
753
754 case 020: case 021: case 022:
755 if (ins->oprs[c-020].offset < -256
756 || ins->oprs[c-020].offset > 255)
757 {
758 errfunc (ERR_WARNING, "byte value exceeds bounds");
759 }
760 if (ins->oprs[c-020].segment != NO_SEG) {
761 data = ins->oprs[c-020].offset;
762 out (offset, segment, &data, OUT_ADDRESS+1,
763 ins->oprs[c-020].segment, ins->oprs[c-020].wrt);
764 }
765 else {
766 bytes[0] = ins->oprs[c-020].offset;
767 out (offset, segment, bytes, OUT_RAWDATA+1, NO_SEG, NO_SEG);
768 }
769 offset += 1;
770 break;
771
772 case 024: case 025: case 026:
773 if (ins->oprs[c-024].offset < 0 || ins->oprs[c-024].offset > 255)
774 errfunc (ERR_WARNING, "unsigned byte value exceeds bounds");
775 if (ins->oprs[c-024].segment != NO_SEG) {
776 data = ins->oprs[c-024].offset;
777 out (offset, segment, &data, OUT_ADDRESS+1,
778 ins->oprs[c-024].segment, ins->oprs[c-024].wrt);
779 }
780 else {
781 bytes[0] = ins->oprs[c-024].offset;
782 out (offset, segment, bytes, OUT_RAWDATA+1, NO_SEG, NO_SEG);
783 }
784 offset += 1;
785 break;
786
787 case 030: case 031: case 032:
788 if (ins->oprs[c-030].segment == NO_SEG &&
789 ins->oprs[c-030].wrt == NO_SEG &&
790 (ins->oprs[c-030].offset < -65536L ||
791 ins->oprs[c-030].offset > 65535L))
792 {
793 errfunc (ERR_WARNING, "word value exceeds bounds");
794 }
795 data = ins->oprs[c-030].offset;
796 out (offset, segment, &data, OUT_ADDRESS+2,
797 ins->oprs[c-030].segment, ins->oprs[c-030].wrt);
798 offset += 2;
799 break;
800
801 case 034: case 035: case 036:
802 data = ins->oprs[c-034].offset;
803 size = ((ins->oprs[c-034].addr_size ?
804 ins->oprs[c-034].addr_size : bits) == 16 ? 2 : 4);
H. Peter Anvin4cf17482002-04-30 21:01:38 +0000805 if (size==2 && (data < -65536L || data > 65535L))
H. Peter Anvineba20a72002-04-30 20:53:55 +0000806 errfunc (ERR_WARNING, "word value exceeds bounds");
807 out (offset, segment, &data, OUT_ADDRESS+size,
808 ins->oprs[c-034].segment, ins->oprs[c-034].wrt);
809 offset += size;
810 break;
811
812 case 037:
813 if (ins->oprs[0].segment == NO_SEG)
814 errfunc (ERR_NONFATAL, "value referenced by FAR is not"
815 " relocatable");
816 data = 0L;
817 out (offset, segment, &data, OUT_ADDRESS+2,
818 outfmt->segbase(1+ins->oprs[0].segment),
819 ins->oprs[0].wrt);
820 offset += 2;
821 break;
822
823 case 040: case 041: case 042:
824 data = ins->oprs[c-040].offset;
825 out (offset, segment, &data, OUT_ADDRESS+4,
826 ins->oprs[c-040].segment, ins->oprs[c-040].wrt);
827 offset += 4;
828 break;
829
830 case 050: case 051: case 052:
831 if (ins->oprs[c-050].segment != segment)
832 errfunc (ERR_NONFATAL, "short relative jump outside segment");
833 data = ins->oprs[c-050].offset - insn_end;
834 if (data > 127 || data < -128)
835 errfunc (ERR_NONFATAL, "short jump is out of range");
836 bytes[0] = data;
837 out (offset, segment, bytes, OUT_RAWDATA+1, NO_SEG, NO_SEG);
838 offset += 1;
839 break;
840
841 case 060: case 061: case 062:
842 if (ins->oprs[c-060].segment != segment) {
843 data = ins->oprs[c-060].offset;
844 out (offset, segment, &data, OUT_REL2ADR+insn_end-offset,
845 ins->oprs[c-060].segment, ins->oprs[c-060].wrt);
846 } else {
847 data = ins->oprs[c-060].offset - insn_end;
848 out (offset, segment, &data,
849 OUT_ADDRESS+2, NO_SEG, NO_SEG);
850 }
851 offset += 2;
852 break;
853
854 case 064: case 065: case 066:
H. Peter Anvin17799b42002-05-21 03:31:21 +0000855 if ( ins->oprs[c-064].type & (BITS16|BITS32) )
856 size = (ins->oprs[c-064].type & BITS16) ? 2 : 4;
857 else
858 size = (bits == 16) ? 2 : 4;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000859 if (ins->oprs[c-064].segment != segment) {
H. Peter Anvin17799b42002-05-21 03:31:21 +0000860 long reltype = (size == 2 ? OUT_REL2ADR : OUT_REL4ADR);
H. Peter Anvineba20a72002-04-30 20:53:55 +0000861 data = ins->oprs[c-064].offset;
H. Peter Anvin17799b42002-05-21 03:31:21 +0000862 out (offset, segment, &data, reltype+insn_end-offset,
H. Peter Anvineba20a72002-04-30 20:53:55 +0000863 ins->oprs[c-064].segment, ins->oprs[c-064].wrt);
H. Peter Anvineba20a72002-04-30 20:53:55 +0000864 } else {
865 data = ins->oprs[c-064].offset - insn_end;
866 out (offset, segment, &data,
867 OUT_ADDRESS+size, NO_SEG, NO_SEG);
868 }
869 offset += size;
870 break;
871
872 case 070: case 071: case 072:
873 if (ins->oprs[c-070].segment != segment) {
874 data = ins->oprs[c-070].offset;
875 out (offset, segment, &data, OUT_REL4ADR+insn_end-offset,
876 ins->oprs[c-070].segment, ins->oprs[c-070].wrt);
877 } else {
878 data = ins->oprs[c-070].offset - insn_end;
879 out (offset, segment, &data,
880 OUT_ADDRESS+4, NO_SEG, NO_SEG);
881 }
882 offset += 4;
883 break;
884
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000885 case 0130: case 0131: case 0132:
886 data = ins->oprs[c-0130].offset;
887 if (is_sbyte(ins, c-0130, 16)) {
888 out (offset, segment, &data, OUT_RAWDATA+1, NO_SEG, NO_SEG);
889 offset++;
890 } else {
891 if (ins->oprs[c-0130].segment == NO_SEG &&
892 ins->oprs[c-0130].wrt == NO_SEG &&
893 (data < -65536L || data > 65535L)) {
894 errfunc (ERR_WARNING, "word value exceeds bounds");
895 }
896 out (offset, segment, &data, OUT_ADDRESS+2,
897 ins->oprs[c-0130].segment, ins->oprs[c-0130].wrt);
898 offset += 2;
899 }
900 break;
901
902 case 0133: case 0134: case 0135:
903 codes++;
904 bytes[0] = *codes++;
905 if (is_sbyte(ins, c-0133, 16)) bytes[0] |= 2; /* s-bit */
906 out (offset, segment, bytes, OUT_RAWDATA+1, NO_SEG, NO_SEG);
907 offset++;
908 break;
909
910 case 0140: case 0141: case 0142:
911 data = ins->oprs[c-0140].offset;
912 if (is_sbyte(ins, c-0140, 32)) {
913 out (offset, segment, &data, OUT_RAWDATA+1, NO_SEG, NO_SEG);
914 offset++;
915 } else {
916 out (offset, segment, &data, OUT_ADDRESS+4,
917 ins->oprs[c-0140].segment, ins->oprs[c-0140].wrt);
918 offset += 4;
919 }
920 break;
921
922 case 0143: case 0144: case 0145:
923 codes++;
924 bytes[0] = *codes++;
925 if (is_sbyte(ins, c-0143, 32)) bytes[0] |= 2; /* s-bit */
926 out (offset, segment, bytes, OUT_RAWDATA+1, NO_SEG, NO_SEG);
927 offset++;
928 break;
929
H. Peter Anvineba20a72002-04-30 20:53:55 +0000930 case 0300: case 0301: case 0302:
931 if (chsize (&ins->oprs[c-0300], bits)) {
932 *bytes = 0x67;
933 out (offset, segment, bytes,
934 OUT_RAWDATA+1, NO_SEG, NO_SEG);
935 offset += 1;
936 } else
937 offset += 0;
938 break;
939
940 case 0310:
941 if (bits==32) {
942 *bytes = 0x67;
943 out (offset, segment, bytes,
944 OUT_RAWDATA+1, NO_SEG, NO_SEG);
945 offset += 1;
946 } else
947 offset += 0;
948 break;
949
950 case 0311:
951 if (bits==16) {
952 *bytes = 0x67;
953 out (offset, segment, bytes,
954 OUT_RAWDATA+1, NO_SEG, NO_SEG);
955 offset += 1;
956 } else
957 offset += 0;
958 break;
959
960 case 0312:
961 break;
962
963 case 0320:
964 if (bits==32) {
965 *bytes = 0x66;
966 out (offset, segment, bytes,
967 OUT_RAWDATA+1, NO_SEG, NO_SEG);
968 offset += 1;
969 } else
970 offset += 0;
971 break;
972
973 case 0321:
974 if (bits==16) {
975 *bytes = 0x66;
976 out (offset, segment, bytes,
977 OUT_RAWDATA+1, NO_SEG, NO_SEG);
978 offset += 1;
979 } else
980 offset += 0;
981 break;
982
983 case 0322:
984 break;
985
986 case 0330:
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000987 *bytes = *codes++ ^ condval[ins->condition];
H. Peter Anvineba20a72002-04-30 20:53:55 +0000988 out (offset, segment, bytes,
989 OUT_RAWDATA+1, NO_SEG, NO_SEG);
990 offset += 1;
991 break;
992
H. Peter Anvinef7468f2002-04-30 20:57:59 +0000993 case 0331:
994 case 0332:
995 break;
996
997 case 0333:
998 *bytes = 0xF3;
999 out (offset, segment, bytes,
1000 OUT_RAWDATA+1, NO_SEG, NO_SEG);
1001 offset += 1;
1002 break;
1003
H. Peter Anvineba20a72002-04-30 20:53:55 +00001004 case 0340: case 0341: case 0342:
1005 if (ins->oprs[0].segment != NO_SEG)
1006 errfunc (ERR_PANIC, "non-constant BSS size in pass two");
1007 else {
1008 long size = ins->oprs[0].offset << (c-0340);
1009 if (size > 0)
1010 out (offset, segment, NULL,
1011 OUT_RESERVE+size, NO_SEG, NO_SEG);
1012 offset += size;
1013 }
1014 break;
1015
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001016 case 0370: case 0371: case 0372:
1017 break;
1018
1019 case 0373:
1020 *bytes = bits==16 ? 3 : 5;
1021 out (offset, segment, bytes,
1022 OUT_RAWDATA+1, NO_SEG, NO_SEG);
1023 offset += 1;
1024 break;
1025
H. Peter Anvineba20a72002-04-30 20:53:55 +00001026 default: /* can't do it by 'case' statements */
1027 if (c>=0100 && c<=0277) { /* it's an EA */
1028 ea ea_data;
1029 int rfield;
1030 unsigned char *p;
1031 long s;
1032
1033 if (c<=0177) /* pick rfield from operand b */
1034 rfield = regval (&ins->oprs[c&7]);
1035 else /* rfield is constant */
1036 rfield = c & 7;
1037
1038 if (!process_ea (&ins->oprs[(c>>3)&7], &ea_data, bits, rfield,
1039 ins->forw_ref))
1040 {
1041 errfunc (ERR_NONFATAL, "invalid effective address");
1042 }
1043
1044 p = bytes;
1045 *p++ = ea_data.modrm;
1046 if (ea_data.sib_present)
1047 *p++ = ea_data.sib;
1048
1049 s = p-bytes;
1050 out (offset, segment, bytes, OUT_RAWDATA + s,
1051 NO_SEG, NO_SEG);
1052
1053 switch (ea_data.bytes) {
1054 case 0:
1055 break;
1056 case 1:
1057 if (ins->oprs[(c>>3)&7].segment != NO_SEG) {
1058 data = ins->oprs[(c>>3)&7].offset;
1059 out (offset, segment, &data, OUT_ADDRESS+1,
1060 ins->oprs[(c>>3)&7].segment,
1061 ins->oprs[(c>>3)&7].wrt);
1062 } else {
1063 *bytes = ins->oprs[(c>>3)&7].offset;
1064 out (offset, segment, bytes, OUT_RAWDATA+1,
1065 NO_SEG, NO_SEG);
1066 }
1067 s++;
1068 break;
1069 case 2:
1070 case 4:
1071 data = ins->oprs[(c>>3)&7].offset;
1072 out (offset, segment, &data,
1073 OUT_ADDRESS+ea_data.bytes,
1074 ins->oprs[(c>>3)&7].segment, ins->oprs[(c>>3)&7].wrt);
1075 s += ea_data.bytes;
1076 break;
1077 }
1078 offset += s;
1079 } else
1080 errfunc (ERR_PANIC, "internal instruction table corrupt"
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001081 ": instruction code 0x%02X given", c);
H. Peter Anvineba20a72002-04-30 20:53:55 +00001082 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001083}
1084
H. Peter Anvineba20a72002-04-30 20:53:55 +00001085static int regval (operand *o)
1086{
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001087 switch (o->basereg) {
1088 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 +00001089 case R_ST0: case R_MM0: case R_XMM0:
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001090 return 0;
1091 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 +00001092 case R_MM1: case R_XMM1:
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001093 return 1;
1094 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 +00001095 case R_ST2: case R_MM2: case R_XMM2:
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001096 return 2;
1097 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 +00001098 case R_TR3: case R_ST3: case R_MM3: case R_XMM3:
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001099 return 3;
1100 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 +00001101 case R_ST4: case R_MM4: case R_XMM4:
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001102 return 4;
1103 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 +00001104 case R_MM5: case R_XMM5:
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001105 return 5;
1106 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 +00001107 case R_MM6: case R_XMM6:
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001108 return 6;
1109 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 +00001110 case R_MM7: case R_XMM7:
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001111 return 7;
1112 default: /* panic */
H. Peter Anvin4836e332002-04-30 20:56:43 +00001113 errfunc (ERR_PANIC, "invalid register operand given to regval()");
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001114 return 0;
1115 }
1116}
1117
H. Peter Anvineba20a72002-04-30 20:53:55 +00001118static int matches (struct itemplate *itemp, insn *instruction)
1119{
H. Peter Anvinef7468f2002-04-30 20:57:59 +00001120 int i, size[3], asize, oprs, ret;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001121
1122 ret = 100;
1123
1124 /*
1125 * Check the opcode
1126 */
1127 if (itemp->opcode != instruction->opcode) return 0;
1128
1129 /*
1130 * Count the operands
1131 */
1132 if (itemp->operands != instruction->operands) return 0;
1133
1134 /*
1135 * Check that no spurious colons or TOs are present
1136 */
1137 for (i=0; i<itemp->operands; i++)
1138 if (instruction->oprs[i].type & ~itemp->opd[i] & (COLON|TO))
1139 return 0;
1140
1141 /*
1142 * Check that the operand flags all match up
1143 */
1144 for (i=0; i<itemp->operands; i++)
1145 if (itemp->opd[i] & ~instruction->oprs[i].type ||
1146 ((itemp->opd[i] & SIZE_MASK) &&
H. Peter Anvineba20a72002-04-30 20:53:55 +00001147 ((itemp->opd[i] ^ instruction->oprs[i].type) & SIZE_MASK)))
1148 {
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001149 if ((itemp->opd[i] & ~instruction->oprs[i].type & NON_SIZE) ||
1150 (instruction->oprs[i].type & SIZE_MASK))
1151 return 0;
1152 else
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001153/* ret = 1; */
1154 return 1;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001155 }
1156
1157 /*
1158 * Check operand sizes
1159 */
H. Peter Anvinef7468f2002-04-30 20:57:59 +00001160 if (itemp->flags & IF_ARMASK) {
1161 size[0] = size[1] = size[2] = 0;
1162
1163 switch (itemp->flags & IF_ARMASK) {
1164 case IF_AR0: i = 0; break;
1165 case IF_AR1: i = 1; break;
1166 case IF_AR2: i = 2; break;
1167 default: break; /* Shouldn't happen */
1168 }
1169 if (itemp->flags & IF_SB) {
1170 size[i] = BITS8;
1171 } else if (itemp->flags & IF_SW) {
1172 size[i] = BITS16;
1173 } else if (itemp->flags & IF_SD) {
1174 size[i] = BITS32;
1175 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001176 } else {
H. Peter Anvinef7468f2002-04-30 20:57:59 +00001177 asize = 0;
1178 if (itemp->flags & IF_SB) {
1179 asize = BITS8;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001180 oprs = itemp->operands;
H. Peter Anvinef7468f2002-04-30 20:57:59 +00001181 } else if (itemp->flags & IF_SW) {
1182 asize = BITS16;
1183 oprs = itemp->operands;
1184 } else if (itemp->flags & IF_SD) {
1185 asize = BITS32;
1186 oprs = itemp->operands;
1187 }
1188 size[0] = size[1] = size[2] = asize;
1189 }
1190
1191 if (itemp->flags & (IF_SM | IF_SM2)) {
1192 oprs = (itemp->flags & IF_SM2 ? 2 : itemp->operands);
1193 asize = 0;
1194 for (i=0; i<oprs; i++) {
1195 if ( (asize = itemp->opd[i] & SIZE_MASK) != 0) {
1196 int j;
1197 for (j=0; j<oprs; j++)
1198 size[j] = asize;
1199 break;
1200 }
1201 }
1202 } else {
1203 oprs = itemp->operands;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001204 }
1205
1206 for (i=0; i<itemp->operands; i++)
1207 if (!(itemp->opd[i] & SIZE_MASK) &&
H. Peter Anvinef7468f2002-04-30 20:57:59 +00001208 (instruction->oprs[i].type & SIZE_MASK & ~size[i]))
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001209/* ret = 2; */
1210 return 2;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001211
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001212 /*
1213 * Check template is okay at the set cpu level
1214 */
1215 if ((itemp->flags & IF_PLEVEL) > cpu) return 3;
1216
1217 /*
1218 * Check if special handling needed for Jumps
1219 */
1220 if ((unsigned char)(itemp->code[0]) >= 0370) return 99;
1221
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001222 return ret;
1223}
1224
H. Peter Anvinea838272002-04-30 20:51:53 +00001225static ea *process_ea (operand *input, ea *output, int addrbits, int rfield,
H. Peter Anvineba20a72002-04-30 20:53:55 +00001226 int forw_ref)
1227{
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001228 if (!(REGISTER & ~input->type)) { /* it's a single register */
1229 static int regs[] = {
H. Peter Anvin4836e332002-04-30 20:56:43 +00001230 R_AL, R_CL, R_DL, R_BL, R_AH, R_CH, R_DH, R_BH,
1231 R_AX, R_CX, R_DX, R_BX, R_SP, R_BP, R_SI, R_DI,
1232 R_EAX, R_ECX, R_EDX, R_EBX, R_ESP, R_EBP, R_ESI, R_EDI,
1233 R_MM0, R_MM1, R_MM2, R_MM3, R_MM4, R_MM5, R_MM6, R_MM7,
1234 R_XMM0, R_XMM1, R_XMM2, R_XMM3, R_XMM4, R_XMM5, R_XMM6, R_XMM7
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001235 };
1236 int i;
1237
1238 for (i=0; i<elements(regs); i++)
1239 if (input->basereg == regs[i]) break;
1240 if (i<elements(regs)) {
1241 output->sib_present = FALSE;/* no SIB necessary */
1242 output->bytes = 0; /* no offset necessary either */
H. Peter Anvin4836e332002-04-30 20:56:43 +00001243 output->modrm = 0xC0 | (rfield << 3) | (i & 7);
H. Peter Anvineba20a72002-04-30 20:53:55 +00001244 }
1245 else
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001246 return NULL;
1247 } else { /* it's a memory reference */
1248 if (input->basereg==-1 && (input->indexreg==-1 || input->scale==0)) {
1249 /* it's a pure offset */
1250 if (input->addr_size)
1251 addrbits = input->addr_size;
1252 output->sib_present = FALSE;
1253 output->bytes = (addrbits==32 ? 4 : 2);
1254 output->modrm = (addrbits==32 ? 5 : 6) | (rfield << 3);
H. Peter Anvineba20a72002-04-30 20:53:55 +00001255 }
1256 else { /* it's an indirection */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001257 int i=input->indexreg, b=input->basereg, s=input->scale;
1258 long o=input->offset, seg=input->segment;
H. Peter Anvin76690a12002-04-30 20:52:49 +00001259 int hb=input->hintbase, ht=input->hinttype;
1260 int t;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001261
1262 if (s==0) i = -1; /* make this easy, at least */
1263
1264 if (i==R_EAX || i==R_EBX || i==R_ECX || i==R_EDX
1265 || i==R_EBP || i==R_ESP || i==R_ESI || i==R_EDI
1266 || b==R_EAX || b==R_EBX || b==R_ECX || b==R_EDX
1267 || b==R_EBP || b==R_ESP || b==R_ESI || b==R_EDI) {
1268 /* it must be a 32-bit memory reference. Firstly we have
1269 * to check that all registers involved are type Exx. */
1270 if (i!=-1 && i!=R_EAX && i!=R_EBX && i!=R_ECX && i!=R_EDX
1271 && i!=R_EBP && i!=R_ESP && i!=R_ESI && i!=R_EDI)
1272 return NULL;
1273 if (b!=-1 && b!=R_EAX && b!=R_EBX && b!=R_ECX && b!=R_EDX
1274 && b!=R_EBP && b!=R_ESP && b!=R_ESI && b!=R_EDI)
1275 return NULL;
1276
1277 /* While we're here, ensure the user didn't specify WORD. */
1278 if (input->addr_size == 16)
1279 return NULL;
1280
1281 /* now reorganise base/index */
H. Peter Anvin76690a12002-04-30 20:52:49 +00001282 if (s == 1 && b != i && b != -1 && i != -1 &&
1283 ((hb==b&&ht==EAH_NOTBASE) || (hb==i&&ht==EAH_MAKEBASE)))
1284 t = b, b = i, i = t; /* swap if hints say so */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001285 if (b==i) /* convert EAX+2*EAX to 3*EAX */
1286 b = -1, s++;
H. Peter Anvin76690a12002-04-30 20:52:49 +00001287 if (b==-1 && s==1 && !(hb == i && ht == EAH_NOTBASE))
1288 b = i, i = -1; /* make single reg base, unless hint */
1289 if (((s==2 && i!=R_ESP && !(input->eaflags & EAF_TIMESTWO)) ||
1290 s==3 || s==5 || s==9) && b==-1)
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001291 b = i, s--; /* convert 3*EAX to EAX+2*EAX */
H. Peter Anvinea838272002-04-30 20:51:53 +00001292 if (s==1 && i==R_ESP) /* swap ESP into base if scale is 1 */
1293 i = b, b = R_ESP;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001294 if (i==R_ESP || (s!=1 && s!=2 && s!=4 && s!=8 && i!=-1))
1295 return NULL; /* wrong, for various reasons */
1296
1297 if (i==-1 && b!=R_ESP) {/* no SIB needed */
1298 int mod, rm;
1299 switch(b) {
1300 case R_EAX: rm = 0; break;
1301 case R_ECX: rm = 1; break;
1302 case R_EDX: rm = 2; break;
1303 case R_EBX: rm = 3; break;
1304 case R_EBP: rm = 5; break;
1305 case R_ESI: rm = 6; break;
1306 case R_EDI: rm = 7; break;
1307 case -1: rm = 5; break;
1308 default: /* should never happen */
1309 return NULL;
1310 }
H. Peter Anvinea838272002-04-30 20:51:53 +00001311 if (b==-1 || (b!=R_EBP && o==0 &&
H. Peter Anvin76690a12002-04-30 20:52:49 +00001312 seg==NO_SEG && !forw_ref &&
1313 !(input->eaflags &
1314 (EAF_BYTEOFFS|EAF_WORDOFFS))))
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001315 mod = 0;
H. Peter Anvin76690a12002-04-30 20:52:49 +00001316 else if (input->eaflags & EAF_BYTEOFFS ||
1317 (o>=-128 && o<=127 && seg==NO_SEG && !forw_ref &&
1318 !(input->eaflags & EAF_WORDOFFS))) {
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001319 mod = 1;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001320 }
1321 else
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001322 mod = 2;
H. Peter Anvinea838272002-04-30 20:51:53 +00001323
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001324 output->sib_present = FALSE;
1325 output->bytes = (b==-1 || mod==2 ? 4 : mod);
1326 output->modrm = (mod<<6) | (rfield<<3) | rm;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001327 }
1328 else { /* we need a SIB */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001329 int mod, scale, index, base;
1330
1331 switch (b) {
1332 case R_EAX: base = 0; break;
1333 case R_ECX: base = 1; break;
1334 case R_EDX: base = 2; break;
1335 case R_EBX: base = 3; break;
1336 case R_ESP: base = 4; break;
1337 case R_EBP: case -1: base = 5; break;
1338 case R_ESI: base = 6; break;
1339 case R_EDI: base = 7; break;
1340 default: /* then what the smeg is it? */
1341 return NULL; /* panic */
1342 }
1343
1344 switch (i) {
1345 case R_EAX: index = 0; break;
1346 case R_ECX: index = 1; break;
1347 case R_EDX: index = 2; break;
1348 case R_EBX: index = 3; break;
1349 case -1: index = 4; break;
1350 case R_EBP: index = 5; break;
1351 case R_ESI: index = 6; break;
1352 case R_EDI: index = 7; break;
1353 default: /* then what the smeg is it? */
1354 return NULL; /* panic */
1355 }
1356
1357 if (i==-1) s = 1;
1358 switch (s) {
1359 case 1: scale = 0; break;
1360 case 2: scale = 1; break;
1361 case 4: scale = 2; break;
1362 case 8: scale = 3; break;
1363 default: /* then what the smeg is it? */
1364 return NULL; /* panic */
1365 }
1366
H. Peter Anvinea838272002-04-30 20:51:53 +00001367 if (b==-1 || (b!=R_EBP && o==0 &&
H. Peter Anvin76690a12002-04-30 20:52:49 +00001368 seg==NO_SEG && !forw_ref &&
1369 !(input->eaflags &
1370 (EAF_BYTEOFFS|EAF_WORDOFFS))))
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001371 mod = 0;
H. Peter Anvin76690a12002-04-30 20:52:49 +00001372 else if (input->eaflags & EAF_BYTEOFFS ||
1373 (o>=-128 && o<=127 && seg==NO_SEG && !forw_ref &&
1374 !(input->eaflags & EAF_WORDOFFS)))
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001375 mod = 1;
1376 else
1377 mod = 2;
1378
1379 output->sib_present = TRUE;
1380 output->bytes = (b==-1 || mod==2 ? 4 : mod);
1381 output->modrm = (mod<<6) | (rfield<<3) | 4;
1382 output->sib = (scale<<6) | (index<<3) | base;
1383 }
H. Peter Anvineba20a72002-04-30 20:53:55 +00001384 }
1385 else { /* it's 16-bit */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001386 int mod, rm;
1387
1388 /* check all registers are BX, BP, SI or DI */
1389 if ((b!=-1 && b!=R_BP && b!=R_BX && b!=R_SI && b!=R_DI) ||
1390 (i!=-1 && i!=R_BP && i!=R_BX && i!=R_SI && i!=R_DI))
1391 return NULL;
1392
1393 /* ensure the user didn't specify DWORD */
1394 if (input->addr_size == 32)
1395 return NULL;
1396
1397 if (s!=1 && i!=-1) return NULL;/* no can do, in 16-bit EA */
H. Peter Anvin87e1fcd2002-05-11 04:01:26 +00001398 if (b==-1 && i!=-1) { int tmp = b; b = i; i = tmp; } /* swap */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001399 if ((b==R_SI || b==R_DI) && i!=-1)
H. Peter Anvin87e1fcd2002-05-11 04:01:26 +00001400 { int tmp = b; b = i; i = tmp; }
1401 /* have BX/BP as base, SI/DI index */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001402 if (b==i) return NULL;/* shouldn't ever happen, in theory */
1403 if (i!=-1 && b!=-1 &&
1404 (i==R_BP || i==R_BX || b==R_SI || b==R_DI))
1405 return NULL; /* invalid combinations */
H. Peter Anvin87e1fcd2002-05-11 04:01:26 +00001406 if (b==-1) /* pure offset: handled above */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001407 return NULL; /* so if it gets to here, panic! */
1408
1409 rm = -1;
1410 if (i!=-1)
1411 switch (i*256 + b) {
1412 case R_SI*256+R_BX: rm=0; break;
1413 case R_DI*256+R_BX: rm=1; break;
1414 case R_SI*256+R_BP: rm=2; break;
1415 case R_DI*256+R_BP: rm=3; break;
1416 }
1417 else
1418 switch (b) {
1419 case R_SI: rm=4; break;
1420 case R_DI: rm=5; break;
1421 case R_BP: rm=6; break;
1422 case R_BX: rm=7; break;
1423 }
1424 if (rm==-1) /* can't happen, in theory */
1425 return NULL; /* so panic if it does */
1426
H. Peter Anvin76690a12002-04-30 20:52:49 +00001427 if (o==0 && seg==NO_SEG && !forw_ref && rm!=6 &&
1428 !(input->eaflags & (EAF_BYTEOFFS|EAF_WORDOFFS)))
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001429 mod = 0;
H. Peter Anvin76690a12002-04-30 20:52:49 +00001430 else if (input->eaflags & EAF_BYTEOFFS ||
1431 (o>=-128 && o<=127 && seg==NO_SEG && !forw_ref &&
1432 !(input->eaflags & EAF_WORDOFFS)))
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001433 mod = 1;
1434 else
1435 mod = 2;
1436
1437 output->sib_present = FALSE; /* no SIB - it's 16-bit */
1438 output->bytes = mod; /* bytes of offset needed */
1439 output->modrm = (mod<<6) | (rfield<<3) | rm;
1440 }
1441 }
1442 }
1443 output->size = 1 + output->sib_present + output->bytes;
1444 return output;
1445}
1446
H. Peter Anvineba20a72002-04-30 20:53:55 +00001447static int chsize (operand *input, int addrbits)
1448{
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001449 if (!(MEMORY & ~input->type)) {
1450 int i=input->indexreg, b=input->basereg;
1451
1452 if (input->scale==0) i = -1;
1453
1454 if (i == -1 && b == -1) /* pure offset */
1455 return (input->addr_size != 0 && input->addr_size != addrbits);
1456
1457 if (i==R_EAX || i==R_EBX || i==R_ECX || i==R_EDX
1458 || i==R_EBP || i==R_ESP || i==R_ESI || i==R_EDI
1459 || b==R_EAX || b==R_EBX || b==R_ECX || b==R_EDX
1460 || b==R_EBP || b==R_ESP || b==R_ESI || b==R_EDI)
1461 return (addrbits==16);
1462 else
1463 return (addrbits==32);
H. Peter Anvineba20a72002-04-30 20:53:55 +00001464 }
1465 else
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001466 return 0;
1467}