blob: 9f557595c41ef5f711f740d28cfede784dcee601 [file] [log] [blame]
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001/* assemble.c code generation for the Netwide Assembler
2 *
3 * The Netwide Assembler is copyright (C) 1996 Simon Tatham and
4 * Julian Hall. All rights reserved. The software is
5 * redistributable under the licence given in the file "Licence"
6 * distributed in the NASM archive.
7 *
8 * the actual codes (C syntax, i.e. octal):
9 * \0 - terminates the code. (Unless it's a literal of course.)
10 * \1, \2, \3 - that many literal bytes follow in the code stream
11 * \4, \6 - the POP/PUSH (respectively) codes for CS, DS, ES, SS
12 * (POP is never used for CS) depending on operand 0
13 * \5, \7 - the second byte of POP/PUSH codes for FS, GS, depending
14 * on operand 0
15 * \10, \11, \12 - a literal byte follows in the code stream, to be added
16 * to the register value of operand 0, 1 or 2
17 * \17 - encodes the literal byte 0. (Some compilers don't take
18 * kindly to a zero byte in the _middle_ of a compile time
19 * string constant, so I had to put this hack in.)
20 * \14, \15, \16 - a signed byte immediate operand, from operand 0, 1 or 2
21 * \20, \21, \22 - a byte immediate operand, from operand 0, 1 or 2
22 * \24, \25, \26 - an unsigned byte immediate operand, from operand 0, 1 or 2
23 * \30, \31, \32 - a word immediate operand, from operand 0, 1 or 2
24 * \34, \35, \36 - select between \3[012] and \4[012] depending on 16/32 bit
H. Peter Anvin3ba46772002-05-27 23:19:35 +000025 * assembly mode or the operand-size override on the operand
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000026 * \37 - a word constant, from the _segment_ part of operand 0
27 * \40, \41, \42 - a long immediate operand, from operand 0, 1 or 2
H. Peter Anvin3ba46772002-05-27 23:19:35 +000028 * \44, \45, \46 - select between \3[012] and \4[012] depending on 16/32 bit
29 * assembly mode or the address-size override on the operand
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000030 * \50, \51, \52 - a byte relative operand, from operand 0, 1 or 2
31 * \60, \61, \62 - a word relative operand, from operand 0, 1 or 2
32 * \64, \65, \66 - select between \6[012] and \7[012] depending on 16/32 bit
H. Peter Anvin17799b42002-05-21 03:31:21 +000033 * assembly mode or the operand-size override on the operand
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000034 * \70, \71, \72 - a long relative operand, from operand 0, 1 or 2
35 * \1ab - a ModRM, calculated on EA in operand a, with the spare
36 * field the register value of operand b.
H. Peter Anvinaf535c12002-04-30 20:59:21 +000037 * \130,\131,\132 - an immediate word or signed byte for operand 0, 1, or 2
38 * \133,\134,\135 - or 2 (s-field) into next opcode byte if operand 0, 1, or 2
39 * is a signed byte rather than a word.
40 * \140,\141,\142 - an immediate dword or signed byte for operand 0, 1, or 2
41 * \143,\144,\145 - or 2 (s-field) into next opcode byte if operand 0, 1, or 2
42 * is a signed byte rather than a dword.
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000043 * \2ab - a ModRM, calculated on EA in operand a, with the spare
44 * field equal to digit b.
45 * \30x - might be an 0x67 byte, depending on the address size of
46 * the memory reference in operand x.
47 * \310 - indicates fixed 16-bit address size, i.e. optional 0x67.
48 * \311 - indicates fixed 32-bit address size, i.e. optional 0x67.
H. Peter Anvinaf535c12002-04-30 20:59:21 +000049 * \312 - (disassembler only) marker on LOOP, LOOPxx instructions.
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000050 * \320 - indicates fixed 16-bit operand size, i.e. optional 0x66.
51 * \321 - indicates fixed 32-bit operand size, i.e. optional 0x66.
52 * \322 - indicates that this instruction is only valid when the
53 * operand size is the default (instruction to disassembler,
54 * generates no code in the assembler)
55 * \330 - a literal byte follows in the code stream, to be added
56 * to the condition code value of the instruction.
H. Peter Anvinef7468f2002-04-30 20:57:59 +000057 * \331 - instruction not valid with REP prefix. Hint for
58 * disassembler only; for SSE instructions.
59 * \332 - disassemble a rep (0xF3 byte) prefix as repe not rep.
60 * \333 - REP prefix (0xF3 byte); for SSE instructions. Not encoded
61 * as a literal byte in order to aid the disassembler.
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000062 * \340 - reserve <operand 0> bytes of uninitialised storage.
63 * Operand 0 had better be a segmentless constant.
H. Peter Anvin788e6c12002-04-30 21:02:01 +000064 * \370,\371,\372 - match only if operand 0 meets byte jump criteria.
65 * 370 is used for Jcc, 371 is used for JMP.
H. Peter Anvinaf535c12002-04-30 20:59:21 +000066 * \373 - assemble 0x03 if bits==16, 0x05 if bits==32;
67 * used for conditional jump over longer jump
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000068 */
69
70#include <stdio.h>
71#include <string.h>
72
73#include "nasm.h"
H. Peter Anvin6768eb72002-04-30 20:52:26 +000074#include "nasmlib.h"
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000075#include "assemble.h"
76#include "insns.h"
77
78extern struct itemplate *nasm_instructions[];
79
80typedef struct {
81 int sib_present; /* is a SIB byte necessary? */
82 int bytes; /* # of bytes of offset needed */
83 int size; /* lazy - this is sib+bytes+1 */
84 unsigned char modrm, sib; /* the bytes themselves */
85} ea;
86
H. Peter Anvinaf535c12002-04-30 20:59:21 +000087static unsigned long cpu; /* cpu level received from nasm.c */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000088static efunc errfunc;
89static struct ofmt *outfmt;
H. Peter Anvin6768eb72002-04-30 20:52:26 +000090static ListGen *list;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000091
92static long calcsize (long, long, int, insn *, char *);
93static void gencode (long, long, int, insn *, char *, long);
H. Peter Anvineba20a72002-04-30 20:53:55 +000094static int regval (operand *o);
95static int matches (struct itemplate *, insn *);
96static ea * process_ea (operand *, ea *, int, int, int);
97static int chsize (operand *, int);
H. Peter Anvinea6e34d2002-04-30 20:51:32 +000098
H. Peter Anvin6768eb72002-04-30 20:52:26 +000099/*
100 * This routine wrappers the real output format's output routine,
101 * in order to pass a copy of the data off to the listing file
102 * generator at the same time.
103 */
104static void out (long offset, long segto, void *data, unsigned long type,
H. Peter Anvineba20a72002-04-30 20:53:55 +0000105 long segment, long wrt)
106{
H. Peter Anvin9eb185b2002-04-30 21:02:47 +0000107 long lineno;
108 char *lnfname = NULL;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000109
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000110 if ((type & OUT_TYPMASK) == OUT_ADDRESS) {
111 if (segment != NO_SEG || wrt != NO_SEG) {
112 /*
113 * This address is relocated. We must write it as
114 * OUT_ADDRESS, so there's no work to be done here.
115 */
116 list->output (offset, data, type);
H. Peter Anvineba20a72002-04-30 20:53:55 +0000117 }
118 else {
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000119 unsigned char p[4], *q = p;
120 /*
121 * This is a non-relocated address, and we're going to
122 * convert it into RAWDATA format.
123 */
124 if ((type & OUT_SIZMASK) == 4) {
125 WRITELONG (q, * (long *) data);
126 list->output (offset, p, OUT_RAWDATA+4);
H. Peter Anvineba20a72002-04-30 20:53:55 +0000127 }
128 else {
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000129 WRITESHORT (q, * (long *) data);
130 list->output (offset, p, OUT_RAWDATA+2);
131 }
132 }
H. Peter Anvineba20a72002-04-30 20:53:55 +0000133 }
134 else if ((type & OUT_TYPMASK) == OUT_RAWDATA) {
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000135 list->output (offset, data, type);
H. Peter Anvineba20a72002-04-30 20:53:55 +0000136 }
137 else if ((type & OUT_TYPMASK) == OUT_RESERVE) {
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000138 list->output (offset, NULL, type);
H. Peter Anvineba20a72002-04-30 20:53:55 +0000139 }
140 else if ((type & OUT_TYPMASK) == OUT_REL2ADR ||
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000141 (type & OUT_TYPMASK) == OUT_REL4ADR) {
142 list->output (offset, data, type);
143 }
144
H. Peter Anvineba20a72002-04-30 20:53:55 +0000145 if (src_get(&lineno,&lnfname))
H. Peter Anvince616072002-04-30 21:02:23 +0000146 {
H. Peter Anvineba20a72002-04-30 20:53:55 +0000147 outfmt->current_dfmt->linenum(lnfname,lineno,segto);
H. Peter Anvin9eb185b2002-04-30 21:02:47 +0000148 if (lnfname) nasm_free(lnfname);
H. Peter Anvince616072002-04-30 21:02:23 +0000149 }
H. Peter Anvineba20a72002-04-30 20:53:55 +0000150
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000151 outfmt->output (segto, data, type, segment, wrt);
152}
153
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000154static int jmp_match (long segment, long offset, int bits,
155 insn *ins, char *code)
156{ long isize;
157 unsigned char c = code[0];
158
159
H. Peter Anvin788e6c12002-04-30 21:02:01 +0000160 if (c != 0370 && c != 0371) return 0;
161 if (ins->oprs[0].opflags & OPFLAG_FORWARD) {
H. Peter Anvin01377d82002-05-21 03:16:33 +0000162 if ((optimizing<0 || (ins->oprs[0].type & STRICT))
163 && c==0370) return 1;
H. Peter Anvin788e6c12002-04-30 21:02:01 +0000164 else return (pass0==0); /* match a forward reference */
165 }
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000166 isize = calcsize (segment, offset, bits, ins, code);
167 if (ins->oprs[0].segment != segment) return 0;
168 isize = ins->oprs[0].offset - offset - isize; /* isize is now the delta */
169 if (isize >= -128L && isize <= 127L) return 1; /* it is byte size */
170
171 return 0;
172}
173
174
175long assemble (long segment, long offset, int bits, unsigned long cp,
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000176 insn *instruction, struct ofmt *output, efunc error,
H. Peter Anvineba20a72002-04-30 20:53:55 +0000177 ListGen *listgen)
178{
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000179 struct itemplate *temp;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000180 int j;
181 int size_prob;
182 long insn_end;
183 long itimes;
184 long start = offset;
185 long wsize = 0; /* size for DB etc. */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000186
187 errfunc = error; /* to pass to other functions */
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000188 cpu = cp;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000189 outfmt = output; /* likewise */
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000190 list = listgen; /* and again */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000191
H. Peter Anvineba20a72002-04-30 20:53:55 +0000192 switch (instruction->opcode)
193 {
194 case -1: return 0;
195 case I_DB: wsize = 1; break;
196 case I_DW: wsize = 2; break;
197 case I_DD: wsize = 4; break;
198 case I_DQ: wsize = 8; break;
199 case I_DT: wsize = 10; break;
200 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000201
H. Peter Anvineba20a72002-04-30 20:53:55 +0000202 if (wsize) {
203 extop * e;
204 long t = instruction->times;
205 if (t < 0)
206 errfunc(ERR_PANIC, "instruction->times < 0 (%ld) in assemble()",t);
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000207
H. Peter Anvineba20a72002-04-30 20:53:55 +0000208 while (t--) /* repeat TIMES times */
209 {
210 for (e = instruction->eops; e; e = e->next)
211 {
212 if (e->type == EOT_DB_NUMBER)
213 {
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000214 if (wsize == 1) {
215 if (e->segment != NO_SEG)
216 errfunc (ERR_NONFATAL,
217 "one-byte relocation attempted");
218 else {
H. Peter Anvin41bf8002002-04-30 20:58:18 +0000219 unsigned char out_byte = e->offset;
220 out (offset, segment, &out_byte, OUT_RAWDATA+1,
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000221 NO_SEG, NO_SEG);
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000222 }
H. Peter Anvineba20a72002-04-30 20:53:55 +0000223 }
224 else if (wsize > 5) {
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000225 errfunc (ERR_NONFATAL, "integer supplied to a D%c"
226 " instruction", wsize==8 ? 'Q' : 'T');
H. Peter Anvineba20a72002-04-30 20:53:55 +0000227 }
228 else
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000229 out (offset, segment, &e->offset,
230 OUT_ADDRESS+wsize, e->segment,
231 e->wrt);
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000232 offset += wsize;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000233 }
234 else if (e->type == EOT_DB_STRING)
235 {
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000236 int align;
237
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000238 out (offset, segment, e->stringval,
239 OUT_RAWDATA+e->stringlen, NO_SEG, NO_SEG);
H. Peter Anvineba20a72002-04-30 20:53:55 +0000240 align = e->stringlen % wsize;
241
242 if (align) {
243 align = wsize - align;
244 out (offset, segment, "\0\0\0\0\0\0\0\0",
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000245 OUT_RAWDATA+align, NO_SEG, NO_SEG);
H. Peter Anvineba20a72002-04-30 20:53:55 +0000246 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000247 offset += e->stringlen + align;
248 }
249 }
H. Peter Anvineba20a72002-04-30 20:53:55 +0000250 if (t > 0 && t == instruction->times-1)
251 {
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000252 /*
253 * Dummy call to list->output to give the offset to the
254 * listing module.
255 */
256 list->output (offset, NULL, OUT_RAWDATA);
257 list->uplevel (LIST_TIMES);
258 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000259 }
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000260 if (instruction->times > 1)
261 list->downlevel (LIST_TIMES);
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000262 return offset - start;
263 }
264
H. Peter Anvineba20a72002-04-30 20:53:55 +0000265 if (instruction->opcode == I_INCBIN)
266 {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000267 static char fname[FILENAME_MAX];
H. Peter Anvineba20a72002-04-30 20:53:55 +0000268 FILE * fp;
269 long len;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000270
271 len = FILENAME_MAX-1;
272 if (len > instruction->eops->stringlen)
273 len = instruction->eops->stringlen;
274 strncpy (fname, instruction->eops->stringval, len);
275 fname[len] = '\0';
H. Peter Anvineba20a72002-04-30 20:53:55 +0000276
277 if ( (fp = fopen(fname, "rb")) == NULL)
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000278 error (ERR_NONFATAL, "`incbin': unable to open file `%s'", fname);
279 else if (fseek(fp, 0L, SEEK_END) < 0)
280 error (ERR_NONFATAL, "`incbin': unable to seek on file `%s'",
281 fname);
H. Peter Anvineba20a72002-04-30 20:53:55 +0000282 else
283 {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000284 static char buf[2048];
285 long t = instruction->times;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000286 long base = 0;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000287
288 len = ftell (fp);
289 if (instruction->eops->next) {
H. Peter Anvineba20a72002-04-30 20:53:55 +0000290 base = instruction->eops->next->offset;
291 len -= base;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000292 if (instruction->eops->next->next &&
293 len > instruction->eops->next->next->offset)
294 len = instruction->eops->next->next->offset;
295 }
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000296 /*
297 * Dummy call to list->output to give the offset to the
298 * listing module.
299 */
300 list->output (offset, NULL, OUT_RAWDATA);
301 list->uplevel(LIST_INCBIN);
H. Peter Anvineba20a72002-04-30 20:53:55 +0000302 while (t--)
303 {
304 long l;
305
306 fseek (fp, base, SEEK_SET);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000307 l = len;
308 while (l > 0) {
309 long m = fread (buf, 1, (l>sizeof(buf)?sizeof(buf):l),
310 fp);
311 if (!m) {
312 /*
313 * This shouldn't happen unless the file
314 * actually changes while we are reading
315 * it.
316 */
317 error (ERR_NONFATAL, "`incbin': unexpected EOF while"
318 " reading file `%s'", fname);
H. Peter Anvineba20a72002-04-30 20:53:55 +0000319 t=0; /* Try to exit cleanly */
320 break;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000321 }
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000322 out (offset, segment, buf, OUT_RAWDATA+m,
323 NO_SEG, NO_SEG);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000324 l -= m;
325 }
326 }
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000327 list->downlevel(LIST_INCBIN);
328 if (instruction->times > 1) {
329 /*
330 * Dummy call to list->output to give the offset to the
331 * listing module.
332 */
333 list->output (offset, NULL, OUT_RAWDATA);
334 list->uplevel(LIST_TIMES);
335 list->downlevel(LIST_TIMES);
336 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000337 fclose (fp);
338 return instruction->times * len;
339 }
340 return 0; /* if we're here, there's an error */
341 }
342
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000343 size_prob = FALSE;
344 temp = nasm_instructions[instruction->opcode];
345 while (temp->opcode != -1) {
346 int m = matches (temp, instruction);
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000347 if (m == 99)
348 m += jmp_match(segment, offset, bits, instruction, temp->code);
H. Peter Anvineba20a72002-04-30 20:53:55 +0000349
350 if (m == 100) /* matches! */
351 {
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000352 char *codes = temp->code;
353 long insn_size = calcsize(segment, offset, bits,
354 instruction, codes);
355 itimes = instruction->times;
356 if (insn_size < 0) /* shouldn't be, on pass two */
357 error (ERR_PANIC, "errors made it through from pass one");
358 else while (itimes--) {
359 insn_end = offset + insn_size;
360 for (j=0; j<instruction->nprefix; j++) {
H. Peter Anvineba20a72002-04-30 20:53:55 +0000361 unsigned char c=0;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000362 switch (instruction->prefixes[j]) {
363 case P_LOCK:
364 c = 0xF0; break;
365 case P_REPNE: case P_REPNZ:
366 c = 0xF2; break;
367 case P_REPE: case P_REPZ: case P_REP:
368 c = 0xF3; break;
369 case R_CS: c = 0x2E; break;
370 case R_DS: c = 0x3E; break;
371 case R_ES: c = 0x26; break;
372 case R_FS: c = 0x64; break;
373 case R_GS: c = 0x65; break;
374 case R_SS: c = 0x36; break;
375 case P_A16:
H. Peter Anvineba20a72002-04-30 20:53:55 +0000376 if (bits != 16)
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000377 c = 0x67;
378 break;
379 case P_A32:
H. Peter Anvineba20a72002-04-30 20:53:55 +0000380 if (bits != 32)
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000381 c = 0x67;
382 break;
383 case P_O16:
H. Peter Anvineba20a72002-04-30 20:53:55 +0000384 if (bits != 16)
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000385 c = 0x66;
386 break;
387 case P_O32:
H. Peter Anvineba20a72002-04-30 20:53:55 +0000388 if (bits != 32)
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000389 c = 0x66;
390 break;
391 default:
392 error (ERR_PANIC,
393 "invalid instruction prefix");
394 }
H. Peter Anvineba20a72002-04-30 20:53:55 +0000395 if (c != 0) {
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000396 out (offset, segment, &c, OUT_RAWDATA+1,
397 NO_SEG, NO_SEG);
H. Peter Anvineba20a72002-04-30 20:53:55 +0000398 offset++;
399 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000400 }
401 gencode (segment, offset, bits, instruction, codes, insn_end);
402 offset += insn_size;
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000403 if (itimes > 0 && itimes == instruction->times-1) {
404 /*
405 * Dummy call to list->output to give the offset to the
406 * listing module.
407 */
408 list->output (offset, NULL, OUT_RAWDATA);
409 list->uplevel (LIST_TIMES);
410 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000411 }
H. Peter Anvin6768eb72002-04-30 20:52:26 +0000412 if (instruction->times > 1)
413 list->downlevel (LIST_TIMES);
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000414 return offset - start;
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000415 } else if (m > 0 && m > size_prob) {
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000416 size_prob = m;
417 }
418 temp++;
419 }
H. Peter Anvineba20a72002-04-30 20:53:55 +0000420
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000421 if (temp->opcode == -1) { /* didn't match any instruction */
422 if (size_prob == 1) /* would have matched, but for size */
423 error (ERR_NONFATAL, "operation size not specified");
424 else if (size_prob == 2)
425 error (ERR_NONFATAL, "mismatch in operand sizes");
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000426 else if (size_prob == 3)
427 error (ERR_NONFATAL, "no instruction for this cpu level");
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000428 else
429 error (ERR_NONFATAL,
430 "invalid combination of opcode and operands");
431 }
432 return 0;
433}
434
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000435long insn_size (long segment, long offset, int bits, unsigned long cp,
H. Peter Anvineba20a72002-04-30 20:53:55 +0000436 insn *instruction, efunc error)
437{
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000438 struct itemplate *temp;
439
440 errfunc = error; /* to pass to other functions */
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000441 cpu = cp;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000442
443 if (instruction->opcode == -1)
444 return 0;
445
446 if (instruction->opcode == I_DB ||
447 instruction->opcode == I_DW ||
448 instruction->opcode == I_DD ||
449 instruction->opcode == I_DQ ||
H. Peter Anvineba20a72002-04-30 20:53:55 +0000450 instruction->opcode == I_DT)
451 {
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000452 extop *e;
453 long isize, osize, wsize = 0; /* placate gcc */
454
455 isize = 0;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000456 switch (instruction->opcode)
457 {
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000458 case I_DB: wsize = 1; break;
459 case I_DW: wsize = 2; break;
460 case I_DD: wsize = 4; break;
461 case I_DQ: wsize = 8; break;
462 case I_DT: wsize = 10; break;
463 }
464
H. Peter Anvineba20a72002-04-30 20:53:55 +0000465 for (e = instruction->eops; e; e = e->next)
466 {
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000467 long align;
468
469 osize = 0;
470 if (e->type == EOT_DB_NUMBER)
471 osize = 1;
472 else if (e->type == EOT_DB_STRING)
473 osize = e->stringlen;
474
475 align = (-osize) % wsize;
476 if (align < 0)
477 align += wsize;
478 isize += osize + align;
479 }
480 return isize * instruction->times;
481 }
482
H. Peter Anvineba20a72002-04-30 20:53:55 +0000483 if (instruction->opcode == I_INCBIN)
484 {
485 char fname[FILENAME_MAX];
486 FILE * fp;
487 long len;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000488
489 len = FILENAME_MAX-1;
490 if (len > instruction->eops->stringlen)
491 len = instruction->eops->stringlen;
492 strncpy (fname, instruction->eops->stringval, len);
493 fname[len] = '\0';
H. Peter Anvineba20a72002-04-30 20:53:55 +0000494 if ( (fp = fopen(fname, "rb")) == NULL )
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000495 error (ERR_NONFATAL, "`incbin': unable to open file `%s'", fname);
496 else if (fseek(fp, 0L, SEEK_END) < 0)
497 error (ERR_NONFATAL, "`incbin': unable to seek on file `%s'",
498 fname);
H. Peter Anvineba20a72002-04-30 20:53:55 +0000499 else
500 {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000501 len = ftell (fp);
502 fclose (fp);
H. Peter Anvineba20a72002-04-30 20:53:55 +0000503 if (instruction->eops->next)
504 {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000505 len -= instruction->eops->next->offset;
506 if (instruction->eops->next->next &&
507 len > instruction->eops->next->next->offset)
H. Peter Anvineba20a72002-04-30 20:53:55 +0000508 {
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000509 len = instruction->eops->next->next->offset;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000510 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000511 }
512 return instruction->times * len;
513 }
514 return 0; /* if we're here, there's an error */
515 }
516
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000517 temp = nasm_instructions[instruction->opcode];
518 while (temp->opcode != -1) {
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000519 int m = matches(temp, instruction);
520 if (m == 99)
521 m += jmp_match(segment, offset, bits, instruction, temp->code);
522
523 if (m == 100) {
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000524 /* we've matched an instruction. */
H. Peter Anvineba20a72002-04-30 20:53:55 +0000525 long isize;
526 char * codes = temp->code;
527 int j;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000528
529 isize = calcsize(segment, offset, bits, instruction, codes);
530 if (isize < 0)
531 return -1;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000532 for (j = 0; j < instruction->nprefix; j++)
533 {
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000534 if ((instruction->prefixes[j] != P_A16 &&
535 instruction->prefixes[j] != P_O16 && bits==16) ||
536 (instruction->prefixes[j] != P_A32 &&
537 instruction->prefixes[j] != P_O32 && bits==32))
H. Peter Anvineba20a72002-04-30 20:53:55 +0000538 {
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000539 isize++;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000540 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000541 }
542 return isize * instruction->times;
543 }
544 temp++;
545 }
546 return -1; /* didn't match any instruction */
547}
548
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000549
550/* check that opn[op] is a signed byte of size 16 or 32,
551 and return the signed value*/
552static int is_sbyte (insn *ins, int op, int size)
553{
554 signed long v;
555 int ret;
556
557 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 +0000558 optimizing>=0 &&
559 !(ins->oprs[op].type & STRICT) &&
560 ins->oprs[op].wrt==NO_SEG && ins->oprs[op].segment==NO_SEG;
H. Peter Anvin734b1882002-04-30 21:01:08 +0000561
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000562 v = ins->oprs[op].offset;
563 if (size==16) v = (signed short)v; /* sign extend if 16 bits */
564
565 return ret && v>=-128L && v<=127L;
566}
567
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000568static long calcsize (long segment, long offset, int bits,
H. Peter Anvineba20a72002-04-30 20:53:55 +0000569 insn *ins, char *codes)
570{
571 long length = 0;
572 unsigned char c;
573
574 (void) segment; /* Don't warn that this parameter is unused */
575 (void) offset; /* Don't warn that this parameter is unused */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000576
577 while (*codes) switch (c = *codes++) {
578 case 01: case 02: case 03:
579 codes += c, length += c; break;
580 case 04: case 05: case 06: case 07:
581 length++; break;
582 case 010: case 011: case 012:
583 codes++, length++; break;
584 case 017:
585 length++; break;
586 case 014: case 015: case 016:
587 length++; break;
588 case 020: case 021: case 022:
589 length++; break;
590 case 024: case 025: case 026:
591 length++; break;
592 case 030: case 031: case 032:
593 length += 2; break;
594 case 034: case 035: case 036:
H. Peter Anvin3ba46772002-05-27 23:19:35 +0000595 if ( ins->oprs[c-034].type & (BITS16|BITS32) )
596 length += (ins->oprs[c-034].type & BITS16) ? 2 : 4;
597 else
598 length += (bits == 16) ? 2 : 4;
599 break;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000600 case 037:
601 length += 2; break;
602 case 040: case 041: case 042:
603 length += 4; break;
H. Peter Anvin3ba46772002-05-27 23:19:35 +0000604 case 044: case 045: case 046:
605 length += ((ins->oprs[c-044].addr_size ?
606 ins->oprs[c-044].addr_size : bits) == 16 ? 2 : 4); break;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000607 case 050: case 051: case 052:
608 length++; break;
609 case 060: case 061: case 062:
610 length += 2; break;
611 case 064: case 065: case 066:
H. Peter Anvin17799b42002-05-21 03:31:21 +0000612 if ( ins->oprs[c-064].type & (BITS16|BITS32) )
613 length += (ins->oprs[c-064].type & BITS16) ? 2 : 4;
614 else
615 length += (bits == 16) ? 2 : 4;
616 break;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000617 case 070: case 071: case 072:
618 length += 4; break;
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000619 case 0130: case 0131: case 0132:
620 length += is_sbyte(ins, c-0130, 16) ? 1 : 2; break;
621 case 0133: case 0134: case 0135:
622 codes+=2; length++; break;
623 case 0140: case 0141: case 0142:
624 length += is_sbyte(ins, c-0140, 32) ? 1 : 4; break;
625 case 0143: case 0144: case 0145:
626 codes+=2; length++; break;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000627 case 0300: case 0301: case 0302:
628 length += chsize (&ins->oprs[c-0300], bits);
629 break;
630 case 0310:
631 length += (bits==32);
632 break;
633 case 0311:
634 length += (bits==16);
635 break;
636 case 0312:
637 break;
638 case 0320:
639 length += (bits==32);
640 break;
641 case 0321:
642 length += (bits==16);
643 break;
644 case 0322:
645 break;
646 case 0330:
647 codes++, length++; break;
H. Peter Anvinef7468f2002-04-30 20:57:59 +0000648 case 0331:
649 case 0332:
650 break;
651 case 0333:
652 length++; break;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000653 case 0340: case 0341: case 0342:
654 if (ins->oprs[0].segment != NO_SEG)
655 errfunc (ERR_NONFATAL, "attempt to reserve non-constant"
656 " quantity of BSS space");
657 else
658 length += ins->oprs[0].offset << (c-0340);
659 break;
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000660 case 0370: case 0371: case 0372:
661 break;
662 case 0373:
663 length++; break;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000664 default: /* can't do it by 'case' statements */
665 if (c>=0100 && c<=0277) { /* it's an EA */
666 ea ea_data;
H. Peter Anvinea838272002-04-30 20:51:53 +0000667 if (!process_ea (&ins->oprs[(c>>3)&7], &ea_data, bits, 0,
668 ins->forw_ref)) {
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000669 errfunc (ERR_NONFATAL, "invalid effective address");
670 return -1;
671 } else
672 length += ea_data.size;
673 } else
674 errfunc (ERR_PANIC, "internal instruction table corrupt"
675 ": instruction code 0x%02X given", c);
676 }
677 return length;
678}
679
680static void gencode (long segment, long offset, int bits,
H. Peter Anvineba20a72002-04-30 20:53:55 +0000681 insn *ins, char *codes, long insn_end)
682{
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000683 static char condval[] = { /* conditional opcodes */
684 0x7, 0x3, 0x2, 0x6, 0x2, 0x4, 0xF, 0xD, 0xC, 0xE, 0x6, 0x2,
685 0x3, 0x7, 0x3, 0x5, 0xE, 0xC, 0xD, 0xF, 0x1, 0xB, 0x9, 0x5,
686 0x0, 0xA, 0xA, 0xB, 0x8, 0x4
687 };
H. Peter Anvineba20a72002-04-30 20:53:55 +0000688 unsigned char c;
689 unsigned char bytes[4];
690 long data, size;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000691
H. Peter Anvineba20a72002-04-30 20:53:55 +0000692 while (*codes)
693 switch (c = *codes++)
694 {
695 case 01: case 02: case 03:
696 out (offset, segment, codes, OUT_RAWDATA+c, NO_SEG, NO_SEG);
697 codes += c;
698 offset += c;
699 break;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000700
H. Peter Anvineba20a72002-04-30 20:53:55 +0000701 case 04: case 06:
702 switch (ins->oprs[0].basereg)
703 {
704 case R_CS:
705 bytes[0] = 0x0E + (c == 0x04 ? 1 : 0); break;
706 case R_DS:
707 bytes[0] = 0x1E + (c == 0x04 ? 1 : 0); break;
708 case R_ES:
709 bytes[0] = 0x06 + (c == 0x04 ? 1 : 0); break;
710 case R_SS:
711 bytes[0] = 0x16 + (c == 0x04 ? 1 : 0); break;
712 default:
H. Peter Anvin4836e332002-04-30 20:56:43 +0000713 errfunc (ERR_PANIC, "bizarre 8086 segment register received");
H. Peter Anvinea6e34d2002-04-30 20:51:32 +0000714 }
H. Peter Anvineba20a72002-04-30 20:53:55 +0000715 out (offset, segment, bytes, OUT_RAWDATA+1, NO_SEG, NO_SEG);
716 offset++;
717 break;
718
719 case 05: case 07:
720 switch (ins->oprs[0].basereg) {
721 case R_FS: bytes[0] = 0xA0 + (c == 0x05 ? 1 : 0); break;
722 case R_GS: bytes[0] = 0xA8 + (c == 0x05 ? 1 : 0); break;
723 default:
H. Peter Anvin4836e332002-04-30 20:56:43 +0000724 errfunc (ERR_PANIC, "bizarre 386 segment register received");
H. Peter Anvineba20a72002-04-30 20:53:55 +0000725 }
726 out (offset, segment, bytes, OUT_RAWDATA+1, NO_SEG, NO_SEG);
727 offset++;
728 break;
729
730 case 010: case 011: case 012:
731 bytes[0] = *codes++ + regval(&ins->oprs[c-010]);
732 out (offset, segment, bytes, OUT_RAWDATA+1, NO_SEG, NO_SEG);
733 offset += 1;
734 break;
735
736 case 017:
737 bytes[0] = 0;
738 out (offset, segment, bytes, OUT_RAWDATA+1, NO_SEG, NO_SEG);
739 offset += 1;
740 break;
741
742 case 014: case 015: case 016:
743 if (ins->oprs[c-014].offset < -128
744 || ins->oprs[c-014].offset > 127)
745 {
746 errfunc (ERR_WARNING, "signed byte value exceeds bounds");
747 }
748
749 if (ins->oprs[c-014].segment != NO_SEG)
750 {
751 data = ins->oprs[c-014].offset;
752 out (offset, segment, &data, OUT_ADDRESS+1,
753 ins->oprs[c-014].segment, ins->oprs[c-014].wrt);
754 }
755 else {
756 bytes[0] = ins->oprs[c-014].offset;
757 out (offset, segment, bytes, OUT_RAWDATA+1, NO_SEG, NO_SEG);
758 }
759 offset += 1;
760 break;
761
762 case 020: case 021: case 022:
763 if (ins->oprs[c-020].offset < -256
764 || ins->oprs[c-020].offset > 255)
765 {
766 errfunc (ERR_WARNING, "byte value exceeds bounds");
767 }
768 if (ins->oprs[c-020].segment != NO_SEG) {
769 data = ins->oprs[c-020].offset;
770 out (offset, segment, &data, OUT_ADDRESS+1,
771 ins->oprs[c-020].segment, ins->oprs[c-020].wrt);
772 }
773 else {
774 bytes[0] = ins->oprs[c-020].offset;
775 out (offset, segment, bytes, OUT_RAWDATA+1, NO_SEG, NO_SEG);
776 }
777 offset += 1;
778 break;
779
780 case 024: case 025: case 026:
781 if (ins->oprs[c-024].offset < 0 || ins->oprs[c-024].offset > 255)
782 errfunc (ERR_WARNING, "unsigned byte value exceeds bounds");
783 if (ins->oprs[c-024].segment != NO_SEG) {
784 data = ins->oprs[c-024].offset;
785 out (offset, segment, &data, OUT_ADDRESS+1,
786 ins->oprs[c-024].segment, ins->oprs[c-024].wrt);
787 }
788 else {
789 bytes[0] = ins->oprs[c-024].offset;
790 out (offset, segment, bytes, OUT_RAWDATA+1, NO_SEG, NO_SEG);
791 }
792 offset += 1;
793 break;
794
795 case 030: case 031: case 032:
796 if (ins->oprs[c-030].segment == NO_SEG &&
797 ins->oprs[c-030].wrt == NO_SEG &&
798 (ins->oprs[c-030].offset < -65536L ||
799 ins->oprs[c-030].offset > 65535L))
800 {
801 errfunc (ERR_WARNING, "word value exceeds bounds");
802 }
803 data = ins->oprs[c-030].offset;
804 out (offset, segment, &data, OUT_ADDRESS+2,
805 ins->oprs[c-030].segment, ins->oprs[c-030].wrt);
806 offset += 2;
807 break;
808
809 case 034: case 035: case 036:
H. Peter Anvin3ba46772002-05-27 23:19:35 +0000810 if ( ins->oprs[c-034].type & (BITS16|BITS32) )
811 size = (ins->oprs[c-034].type & BITS16) ? 2 : 4;
812 else
813 size = (bits == 16) ? 2 : 4;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000814 data = ins->oprs[c-034].offset;
H. Peter Anvin4cf17482002-04-30 21:01:38 +0000815 if (size==2 && (data < -65536L || data > 65535L))
H. Peter Anvineba20a72002-04-30 20:53:55 +0000816 errfunc (ERR_WARNING, "word value exceeds bounds");
817 out (offset, segment, &data, OUT_ADDRESS+size,
818 ins->oprs[c-034].segment, ins->oprs[c-034].wrt);
819 offset += size;
820 break;
821
822 case 037:
823 if (ins->oprs[0].segment == NO_SEG)
824 errfunc (ERR_NONFATAL, "value referenced by FAR is not"
825 " relocatable");
826 data = 0L;
827 out (offset, segment, &data, OUT_ADDRESS+2,
828 outfmt->segbase(1+ins->oprs[0].segment),
829 ins->oprs[0].wrt);
830 offset += 2;
831 break;
832
833 case 040: case 041: case 042:
834 data = ins->oprs[c-040].offset;
835 out (offset, segment, &data, OUT_ADDRESS+4,
836 ins->oprs[c-040].segment, ins->oprs[c-040].wrt);
837 offset += 4;
838 break;
839
H. Peter Anvin3ba46772002-05-27 23:19:35 +0000840 case 044: case 045: case 046:
841 data = ins->oprs[c-044].offset;
842 size = ((ins->oprs[c-044].addr_size ?
843 ins->oprs[c-044].addr_size : bits) == 16 ? 2 : 4);
844 if (size==2 && (data < -65536L || data > 65535L))
845 errfunc (ERR_WARNING, "word value exceeds bounds");
846 out (offset, segment, &data, OUT_ADDRESS+size,
847 ins->oprs[c-044].segment, ins->oprs[c-044].wrt);
848 offset += size;
849 break;
850
H. Peter Anvineba20a72002-04-30 20:53:55 +0000851 case 050: case 051: case 052:
852 if (ins->oprs[c-050].segment != segment)
853 errfunc (ERR_NONFATAL, "short relative jump outside segment");
854 data = ins->oprs[c-050].offset - insn_end;
855 if (data > 127 || data < -128)
856 errfunc (ERR_NONFATAL, "short jump is out of range");
857 bytes[0] = data;
858 out (offset, segment, bytes, OUT_RAWDATA+1, NO_SEG, NO_SEG);
859 offset += 1;
860 break;
861
862 case 060: case 061: case 062:
863 if (ins->oprs[c-060].segment != segment) {
864 data = ins->oprs[c-060].offset;
865 out (offset, segment, &data, OUT_REL2ADR+insn_end-offset,
866 ins->oprs[c-060].segment, ins->oprs[c-060].wrt);
867 } else {
868 data = ins->oprs[c-060].offset - insn_end;
869 out (offset, segment, &data,
870 OUT_ADDRESS+2, NO_SEG, NO_SEG);
871 }
872 offset += 2;
873 break;
874
875 case 064: case 065: case 066:
H. Peter Anvin17799b42002-05-21 03:31:21 +0000876 if ( ins->oprs[c-064].type & (BITS16|BITS32) )
877 size = (ins->oprs[c-064].type & BITS16) ? 2 : 4;
878 else
879 size = (bits == 16) ? 2 : 4;
H. Peter Anvineba20a72002-04-30 20:53:55 +0000880 if (ins->oprs[c-064].segment != segment) {
H. Peter Anvin17799b42002-05-21 03:31:21 +0000881 long reltype = (size == 2 ? OUT_REL2ADR : OUT_REL4ADR);
H. Peter Anvineba20a72002-04-30 20:53:55 +0000882 data = ins->oprs[c-064].offset;
H. Peter Anvin17799b42002-05-21 03:31:21 +0000883 out (offset, segment, &data, reltype+insn_end-offset,
H. Peter Anvineba20a72002-04-30 20:53:55 +0000884 ins->oprs[c-064].segment, ins->oprs[c-064].wrt);
H. Peter Anvineba20a72002-04-30 20:53:55 +0000885 } else {
886 data = ins->oprs[c-064].offset - insn_end;
887 out (offset, segment, &data,
888 OUT_ADDRESS+size, NO_SEG, NO_SEG);
889 }
890 offset += size;
891 break;
892
893 case 070: case 071: case 072:
894 if (ins->oprs[c-070].segment != segment) {
895 data = ins->oprs[c-070].offset;
896 out (offset, segment, &data, OUT_REL4ADR+insn_end-offset,
897 ins->oprs[c-070].segment, ins->oprs[c-070].wrt);
898 } else {
899 data = ins->oprs[c-070].offset - insn_end;
900 out (offset, segment, &data,
901 OUT_ADDRESS+4, NO_SEG, NO_SEG);
902 }
903 offset += 4;
904 break;
905
H. Peter Anvinaf535c12002-04-30 20:59:21 +0000906 case 0130: case 0131: case 0132:
907 data = ins->oprs[c-0130].offset;
908 if (is_sbyte(ins, c-0130, 16)) {
909 out (offset, segment, &data, OUT_RAWDATA+1, NO_SEG, NO_SEG);
910 offset++;
911 } else {
912 if (ins->oprs[c-0130].segment == NO_SEG &&
913 ins->oprs[c-0130].wrt == NO_SEG &&
914 (data < -65536L || data > 65535L)) {
915 errfunc (ERR_WARNING, "word value exceeds bounds");
916 }
917 out (offset, segment, &data, OUT_ADDRESS+2,
918 ins->oprs[c-0130].segment, ins->oprs[c-0130].wrt);
919 offset += 2;
920 }
921 break;
922
923 case 0133: case 0134: case 0135:
924 codes++;
925 bytes[0] = *codes++;
926 if (is_sbyte(ins, c-0133, 16)) bytes[0] |= 2; /* s-bit */
927 out (offset, segment, bytes, OUT_RAWDATA+1, NO_SEG, NO_SEG);
928 offset++;
929 break;
930
931 case 0140: case 0141: case 0142:
932 data = ins->oprs[c-0140].offset;
933 if (is_sbyte(ins, c-0140, 32)) {
934 out (offset, segment, &data, OUT_RAWDATA+1, NO_SEG, NO_SEG);
935 offset++;
936 } else {
937 out (offset, segment, &data, OUT_ADDRESS+4,
938 ins->oprs[c-0140].segment, ins->oprs[c-0140].wrt);
939 offset += 4;
940 }
941 break;
942
943 case 0143: case 0144: case 0145:
944 codes++;
945 bytes[0] = *codes++;
946 if (is_sbyte(ins, c-0143, 32)) bytes[0] |= 2; /* s-bit */
947 out (offset, segment, bytes, OUT_RAWDATA+1, NO_SEG, NO_SEG);
948 offset++;
949 break;
950
H. Peter Anvineba20a72002-04-30 20:53:55 +0000951 case 0300: case 0301: case 0302:
952 if (chsize (&ins->oprs[c-0300], bits)) {
953 *bytes = 0x67;
954 out (offset, segment, bytes,
955 OUT_RAWDATA+1, NO_SEG, NO_SEG);
956 offset += 1;
957 } else
958 offset += 0;
959 break;
960
961 case 0310:
962 if (bits==32) {
963 *bytes = 0x67;
964 out (offset, segment, bytes,
965 OUT_RAWDATA+1, NO_SEG, NO_SEG);
966 offset += 1;
967 } else
968 offset += 0;
969 break;
970
971 case 0311:
972 if (bits==16) {
973 *bytes = 0x67;
974 out (offset, segment, bytes,
975 OUT_RAWDATA+1, NO_SEG, NO_SEG);
976 offset += 1;
977 } else
978 offset += 0;
979 break;
980
981 case 0312:
982 break;
983
984 case 0320:
985 if (bits==32) {
986 *bytes = 0x66;
987 out (offset, segment, bytes,
988 OUT_RAWDATA+1, NO_SEG, NO_SEG);
989 offset += 1;
990 } else
991 offset += 0;
992 break;
993
994 case 0321:
995 if (bits==16) {
996 *bytes = 0x66;
997 out (offset, segment, bytes,
998 OUT_RAWDATA+1, NO_SEG, NO_SEG);
999 offset += 1;
1000 } else
1001 offset += 0;
1002 break;
1003
1004 case 0322:
1005 break;
1006
1007 case 0330:
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001008 *bytes = *codes++ ^ condval[ins->condition];
H. Peter Anvineba20a72002-04-30 20:53:55 +00001009 out (offset, segment, bytes,
1010 OUT_RAWDATA+1, NO_SEG, NO_SEG);
1011 offset += 1;
1012 break;
1013
H. Peter Anvinef7468f2002-04-30 20:57:59 +00001014 case 0331:
1015 case 0332:
1016 break;
1017
1018 case 0333:
1019 *bytes = 0xF3;
1020 out (offset, segment, bytes,
1021 OUT_RAWDATA+1, NO_SEG, NO_SEG);
1022 offset += 1;
1023 break;
1024
H. Peter Anvineba20a72002-04-30 20:53:55 +00001025 case 0340: case 0341: case 0342:
1026 if (ins->oprs[0].segment != NO_SEG)
1027 errfunc (ERR_PANIC, "non-constant BSS size in pass two");
1028 else {
1029 long size = ins->oprs[0].offset << (c-0340);
1030 if (size > 0)
1031 out (offset, segment, NULL,
1032 OUT_RESERVE+size, NO_SEG, NO_SEG);
1033 offset += size;
1034 }
1035 break;
1036
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001037 case 0370: case 0371: case 0372:
1038 break;
1039
1040 case 0373:
1041 *bytes = bits==16 ? 3 : 5;
1042 out (offset, segment, bytes,
1043 OUT_RAWDATA+1, NO_SEG, NO_SEG);
1044 offset += 1;
1045 break;
1046
H. Peter Anvineba20a72002-04-30 20:53:55 +00001047 default: /* can't do it by 'case' statements */
1048 if (c>=0100 && c<=0277) { /* it's an EA */
1049 ea ea_data;
1050 int rfield;
1051 unsigned char *p;
1052 long s;
1053
1054 if (c<=0177) /* pick rfield from operand b */
1055 rfield = regval (&ins->oprs[c&7]);
1056 else /* rfield is constant */
1057 rfield = c & 7;
1058
1059 if (!process_ea (&ins->oprs[(c>>3)&7], &ea_data, bits, rfield,
1060 ins->forw_ref))
1061 {
1062 errfunc (ERR_NONFATAL, "invalid effective address");
1063 }
1064
1065 p = bytes;
1066 *p++ = ea_data.modrm;
1067 if (ea_data.sib_present)
1068 *p++ = ea_data.sib;
1069
1070 s = p-bytes;
1071 out (offset, segment, bytes, OUT_RAWDATA + s,
1072 NO_SEG, NO_SEG);
1073
1074 switch (ea_data.bytes) {
1075 case 0:
1076 break;
1077 case 1:
1078 if (ins->oprs[(c>>3)&7].segment != NO_SEG) {
1079 data = ins->oprs[(c>>3)&7].offset;
1080 out (offset, segment, &data, OUT_ADDRESS+1,
1081 ins->oprs[(c>>3)&7].segment,
1082 ins->oprs[(c>>3)&7].wrt);
1083 } else {
1084 *bytes = ins->oprs[(c>>3)&7].offset;
1085 out (offset, segment, bytes, OUT_RAWDATA+1,
1086 NO_SEG, NO_SEG);
1087 }
1088 s++;
1089 break;
1090 case 2:
1091 case 4:
1092 data = ins->oprs[(c>>3)&7].offset;
1093 out (offset, segment, &data,
1094 OUT_ADDRESS+ea_data.bytes,
1095 ins->oprs[(c>>3)&7].segment, ins->oprs[(c>>3)&7].wrt);
1096 s += ea_data.bytes;
1097 break;
1098 }
1099 offset += s;
1100 } else
1101 errfunc (ERR_PANIC, "internal instruction table corrupt"
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001102 ": instruction code 0x%02X given", c);
H. Peter Anvineba20a72002-04-30 20:53:55 +00001103 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001104}
1105
H. Peter Anvineba20a72002-04-30 20:53:55 +00001106static int regval (operand *o)
1107{
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001108 switch (o->basereg) {
1109 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 +00001110 case R_ST0: case R_MM0: case R_XMM0:
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001111 return 0;
1112 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 +00001113 case R_MM1: case R_XMM1:
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001114 return 1;
1115 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 +00001116 case R_ST2: case R_MM2: case R_XMM2:
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001117 return 2;
1118 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 +00001119 case R_TR3: case R_ST3: case R_MM3: case R_XMM3:
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001120 return 3;
1121 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 +00001122 case R_ST4: case R_MM4: case R_XMM4:
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001123 return 4;
1124 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 +00001125 case R_MM5: case R_XMM5:
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001126 return 5;
1127 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 +00001128 case R_MM6: case R_XMM6:
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001129 return 6;
1130 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 +00001131 case R_MM7: case R_XMM7:
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001132 return 7;
1133 default: /* panic */
H. Peter Anvin4836e332002-04-30 20:56:43 +00001134 errfunc (ERR_PANIC, "invalid register operand given to regval()");
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001135 return 0;
1136 }
1137}
1138
H. Peter Anvineba20a72002-04-30 20:53:55 +00001139static int matches (struct itemplate *itemp, insn *instruction)
1140{
H. Peter Anvinef7468f2002-04-30 20:57:59 +00001141 int i, size[3], asize, oprs, ret;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001142
1143 ret = 100;
1144
1145 /*
1146 * Check the opcode
1147 */
1148 if (itemp->opcode != instruction->opcode) return 0;
1149
1150 /*
1151 * Count the operands
1152 */
1153 if (itemp->operands != instruction->operands) return 0;
1154
1155 /*
1156 * Check that no spurious colons or TOs are present
1157 */
1158 for (i=0; i<itemp->operands; i++)
1159 if (instruction->oprs[i].type & ~itemp->opd[i] & (COLON|TO))
1160 return 0;
1161
1162 /*
1163 * Check that the operand flags all match up
1164 */
1165 for (i=0; i<itemp->operands; i++)
1166 if (itemp->opd[i] & ~instruction->oprs[i].type ||
1167 ((itemp->opd[i] & SIZE_MASK) &&
H. Peter Anvineba20a72002-04-30 20:53:55 +00001168 ((itemp->opd[i] ^ instruction->oprs[i].type) & SIZE_MASK)))
1169 {
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001170 if ((itemp->opd[i] & ~instruction->oprs[i].type & NON_SIZE) ||
1171 (instruction->oprs[i].type & SIZE_MASK))
1172 return 0;
1173 else
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001174/* ret = 1; */
1175 return 1;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001176 }
1177
1178 /*
1179 * Check operand sizes
1180 */
H. Peter Anvinef7468f2002-04-30 20:57:59 +00001181 if (itemp->flags & IF_ARMASK) {
1182 size[0] = size[1] = size[2] = 0;
1183
1184 switch (itemp->flags & IF_ARMASK) {
1185 case IF_AR0: i = 0; break;
1186 case IF_AR1: i = 1; break;
1187 case IF_AR2: i = 2; break;
1188 default: break; /* Shouldn't happen */
1189 }
1190 if (itemp->flags & IF_SB) {
1191 size[i] = BITS8;
1192 } else if (itemp->flags & IF_SW) {
1193 size[i] = BITS16;
1194 } else if (itemp->flags & IF_SD) {
1195 size[i] = BITS32;
1196 }
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001197 } else {
H. Peter Anvinef7468f2002-04-30 20:57:59 +00001198 asize = 0;
1199 if (itemp->flags & IF_SB) {
1200 asize = BITS8;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001201 oprs = itemp->operands;
H. Peter Anvinef7468f2002-04-30 20:57:59 +00001202 } else if (itemp->flags & IF_SW) {
1203 asize = BITS16;
1204 oprs = itemp->operands;
1205 } else if (itemp->flags & IF_SD) {
1206 asize = BITS32;
1207 oprs = itemp->operands;
1208 }
1209 size[0] = size[1] = size[2] = asize;
1210 }
1211
1212 if (itemp->flags & (IF_SM | IF_SM2)) {
1213 oprs = (itemp->flags & IF_SM2 ? 2 : itemp->operands);
1214 asize = 0;
1215 for (i=0; i<oprs; i++) {
1216 if ( (asize = itemp->opd[i] & SIZE_MASK) != 0) {
1217 int j;
1218 for (j=0; j<oprs; j++)
1219 size[j] = asize;
1220 break;
1221 }
1222 }
1223 } else {
1224 oprs = itemp->operands;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001225 }
1226
1227 for (i=0; i<itemp->operands; i++)
1228 if (!(itemp->opd[i] & SIZE_MASK) &&
H. Peter Anvinef7468f2002-04-30 20:57:59 +00001229 (instruction->oprs[i].type & SIZE_MASK & ~size[i]))
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001230/* ret = 2; */
1231 return 2;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001232
H. Peter Anvinaf535c12002-04-30 20:59:21 +00001233 /*
1234 * Check template is okay at the set cpu level
1235 */
1236 if ((itemp->flags & IF_PLEVEL) > cpu) return 3;
1237
1238 /*
1239 * Check if special handling needed for Jumps
1240 */
1241 if ((unsigned char)(itemp->code[0]) >= 0370) return 99;
1242
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001243 return ret;
1244}
1245
H. Peter Anvinea838272002-04-30 20:51:53 +00001246static ea *process_ea (operand *input, ea *output, int addrbits, int rfield,
H. Peter Anvineba20a72002-04-30 20:53:55 +00001247 int forw_ref)
1248{
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001249 if (!(REGISTER & ~input->type)) { /* it's a single register */
1250 static int regs[] = {
H. Peter Anvin4836e332002-04-30 20:56:43 +00001251 R_AL, R_CL, R_DL, R_BL, R_AH, R_CH, R_DH, R_BH,
1252 R_AX, R_CX, R_DX, R_BX, R_SP, R_BP, R_SI, R_DI,
1253 R_EAX, R_ECX, R_EDX, R_EBX, R_ESP, R_EBP, R_ESI, R_EDI,
1254 R_MM0, R_MM1, R_MM2, R_MM3, R_MM4, R_MM5, R_MM6, R_MM7,
1255 R_XMM0, R_XMM1, R_XMM2, R_XMM3, R_XMM4, R_XMM5, R_XMM6, R_XMM7
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001256 };
1257 int i;
1258
1259 for (i=0; i<elements(regs); i++)
1260 if (input->basereg == regs[i]) break;
1261 if (i<elements(regs)) {
1262 output->sib_present = FALSE;/* no SIB necessary */
1263 output->bytes = 0; /* no offset necessary either */
H. Peter Anvin4836e332002-04-30 20:56:43 +00001264 output->modrm = 0xC0 | (rfield << 3) | (i & 7);
H. Peter Anvineba20a72002-04-30 20:53:55 +00001265 }
1266 else
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001267 return NULL;
1268 } else { /* it's a memory reference */
1269 if (input->basereg==-1 && (input->indexreg==-1 || input->scale==0)) {
1270 /* it's a pure offset */
1271 if (input->addr_size)
1272 addrbits = input->addr_size;
1273 output->sib_present = FALSE;
1274 output->bytes = (addrbits==32 ? 4 : 2);
1275 output->modrm = (addrbits==32 ? 5 : 6) | (rfield << 3);
H. Peter Anvineba20a72002-04-30 20:53:55 +00001276 }
1277 else { /* it's an indirection */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001278 int i=input->indexreg, b=input->basereg, s=input->scale;
1279 long o=input->offset, seg=input->segment;
H. Peter Anvin76690a12002-04-30 20:52:49 +00001280 int hb=input->hintbase, ht=input->hinttype;
1281 int t;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001282
1283 if (s==0) i = -1; /* make this easy, at least */
1284
1285 if (i==R_EAX || i==R_EBX || i==R_ECX || i==R_EDX
1286 || i==R_EBP || i==R_ESP || i==R_ESI || i==R_EDI
1287 || b==R_EAX || b==R_EBX || b==R_ECX || b==R_EDX
1288 || b==R_EBP || b==R_ESP || b==R_ESI || b==R_EDI) {
1289 /* it must be a 32-bit memory reference. Firstly we have
1290 * to check that all registers involved are type Exx. */
1291 if (i!=-1 && i!=R_EAX && i!=R_EBX && i!=R_ECX && i!=R_EDX
1292 && i!=R_EBP && i!=R_ESP && i!=R_ESI && i!=R_EDI)
1293 return NULL;
1294 if (b!=-1 && b!=R_EAX && b!=R_EBX && b!=R_ECX && b!=R_EDX
1295 && b!=R_EBP && b!=R_ESP && b!=R_ESI && b!=R_EDI)
1296 return NULL;
1297
1298 /* While we're here, ensure the user didn't specify WORD. */
1299 if (input->addr_size == 16)
1300 return NULL;
1301
1302 /* now reorganise base/index */
H. Peter Anvin76690a12002-04-30 20:52:49 +00001303 if (s == 1 && b != i && b != -1 && i != -1 &&
1304 ((hb==b&&ht==EAH_NOTBASE) || (hb==i&&ht==EAH_MAKEBASE)))
1305 t = b, b = i, i = t; /* swap if hints say so */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001306 if (b==i) /* convert EAX+2*EAX to 3*EAX */
1307 b = -1, s++;
H. Peter Anvin76690a12002-04-30 20:52:49 +00001308 if (b==-1 && s==1 && !(hb == i && ht == EAH_NOTBASE))
1309 b = i, i = -1; /* make single reg base, unless hint */
1310 if (((s==2 && i!=R_ESP && !(input->eaflags & EAF_TIMESTWO)) ||
1311 s==3 || s==5 || s==9) && b==-1)
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001312 b = i, s--; /* convert 3*EAX to EAX+2*EAX */
H. Peter Anvinea838272002-04-30 20:51:53 +00001313 if (s==1 && i==R_ESP) /* swap ESP into base if scale is 1 */
1314 i = b, b = R_ESP;
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001315 if (i==R_ESP || (s!=1 && s!=2 && s!=4 && s!=8 && i!=-1))
1316 return NULL; /* wrong, for various reasons */
1317
1318 if (i==-1 && b!=R_ESP) {/* no SIB needed */
1319 int mod, rm;
1320 switch(b) {
1321 case R_EAX: rm = 0; break;
1322 case R_ECX: rm = 1; break;
1323 case R_EDX: rm = 2; break;
1324 case R_EBX: rm = 3; break;
1325 case R_EBP: rm = 5; break;
1326 case R_ESI: rm = 6; break;
1327 case R_EDI: rm = 7; break;
1328 case -1: rm = 5; break;
1329 default: /* should never happen */
1330 return NULL;
1331 }
H. Peter Anvinea838272002-04-30 20:51:53 +00001332 if (b==-1 || (b!=R_EBP && o==0 &&
H. Peter Anvin76690a12002-04-30 20:52:49 +00001333 seg==NO_SEG && !forw_ref &&
1334 !(input->eaflags &
1335 (EAF_BYTEOFFS|EAF_WORDOFFS))))
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001336 mod = 0;
H. Peter Anvin76690a12002-04-30 20:52:49 +00001337 else if (input->eaflags & EAF_BYTEOFFS ||
1338 (o>=-128 && o<=127 && seg==NO_SEG && !forw_ref &&
1339 !(input->eaflags & EAF_WORDOFFS))) {
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001340 mod = 1;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001341 }
1342 else
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001343 mod = 2;
H. Peter Anvinea838272002-04-30 20:51:53 +00001344
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001345 output->sib_present = FALSE;
1346 output->bytes = (b==-1 || mod==2 ? 4 : mod);
1347 output->modrm = (mod<<6) | (rfield<<3) | rm;
H. Peter Anvineba20a72002-04-30 20:53:55 +00001348 }
1349 else { /* we need a SIB */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001350 int mod, scale, index, base;
1351
1352 switch (b) {
1353 case R_EAX: base = 0; break;
1354 case R_ECX: base = 1; break;
1355 case R_EDX: base = 2; break;
1356 case R_EBX: base = 3; break;
1357 case R_ESP: base = 4; break;
1358 case R_EBP: case -1: base = 5; break;
1359 case R_ESI: base = 6; break;
1360 case R_EDI: base = 7; break;
1361 default: /* then what the smeg is it? */
1362 return NULL; /* panic */
1363 }
1364
1365 switch (i) {
1366 case R_EAX: index = 0; break;
1367 case R_ECX: index = 1; break;
1368 case R_EDX: index = 2; break;
1369 case R_EBX: index = 3; break;
1370 case -1: index = 4; break;
1371 case R_EBP: index = 5; break;
1372 case R_ESI: index = 6; break;
1373 case R_EDI: index = 7; break;
1374 default: /* then what the smeg is it? */
1375 return NULL; /* panic */
1376 }
1377
1378 if (i==-1) s = 1;
1379 switch (s) {
1380 case 1: scale = 0; break;
1381 case 2: scale = 1; break;
1382 case 4: scale = 2; break;
1383 case 8: scale = 3; break;
1384 default: /* then what the smeg is it? */
1385 return NULL; /* panic */
1386 }
1387
H. Peter Anvinea838272002-04-30 20:51:53 +00001388 if (b==-1 || (b!=R_EBP && o==0 &&
H. Peter Anvin76690a12002-04-30 20:52:49 +00001389 seg==NO_SEG && !forw_ref &&
1390 !(input->eaflags &
1391 (EAF_BYTEOFFS|EAF_WORDOFFS))))
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001392 mod = 0;
H. Peter Anvin76690a12002-04-30 20:52:49 +00001393 else if (input->eaflags & EAF_BYTEOFFS ||
1394 (o>=-128 && o<=127 && seg==NO_SEG && !forw_ref &&
1395 !(input->eaflags & EAF_WORDOFFS)))
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001396 mod = 1;
1397 else
1398 mod = 2;
1399
1400 output->sib_present = TRUE;
1401 output->bytes = (b==-1 || mod==2 ? 4 : mod);
1402 output->modrm = (mod<<6) | (rfield<<3) | 4;
1403 output->sib = (scale<<6) | (index<<3) | base;
1404 }
H. Peter Anvineba20a72002-04-30 20:53:55 +00001405 }
1406 else { /* it's 16-bit */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001407 int mod, rm;
1408
1409 /* check all registers are BX, BP, SI or DI */
1410 if ((b!=-1 && b!=R_BP && b!=R_BX && b!=R_SI && b!=R_DI) ||
1411 (i!=-1 && i!=R_BP && i!=R_BX && i!=R_SI && i!=R_DI))
1412 return NULL;
1413
1414 /* ensure the user didn't specify DWORD */
1415 if (input->addr_size == 32)
1416 return NULL;
1417
1418 if (s!=1 && i!=-1) return NULL;/* no can do, in 16-bit EA */
H. Peter Anvin87e1fcd2002-05-11 04:01:26 +00001419 if (b==-1 && i!=-1) { int tmp = b; b = i; i = tmp; } /* swap */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001420 if ((b==R_SI || b==R_DI) && i!=-1)
H. Peter Anvin87e1fcd2002-05-11 04:01:26 +00001421 { int tmp = b; b = i; i = tmp; }
1422 /* have BX/BP as base, SI/DI index */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001423 if (b==i) return NULL;/* shouldn't ever happen, in theory */
1424 if (i!=-1 && b!=-1 &&
1425 (i==R_BP || i==R_BX || b==R_SI || b==R_DI))
1426 return NULL; /* invalid combinations */
H. Peter Anvin87e1fcd2002-05-11 04:01:26 +00001427 if (b==-1) /* pure offset: handled above */
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001428 return NULL; /* so if it gets to here, panic! */
1429
1430 rm = -1;
1431 if (i!=-1)
1432 switch (i*256 + b) {
1433 case R_SI*256+R_BX: rm=0; break;
1434 case R_DI*256+R_BX: rm=1; break;
1435 case R_SI*256+R_BP: rm=2; break;
1436 case R_DI*256+R_BP: rm=3; break;
1437 }
1438 else
1439 switch (b) {
1440 case R_SI: rm=4; break;
1441 case R_DI: rm=5; break;
1442 case R_BP: rm=6; break;
1443 case R_BX: rm=7; break;
1444 }
1445 if (rm==-1) /* can't happen, in theory */
1446 return NULL; /* so panic if it does */
1447
H. Peter Anvin76690a12002-04-30 20:52:49 +00001448 if (o==0 && seg==NO_SEG && !forw_ref && rm!=6 &&
1449 !(input->eaflags & (EAF_BYTEOFFS|EAF_WORDOFFS)))
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001450 mod = 0;
H. Peter Anvin76690a12002-04-30 20:52:49 +00001451 else if (input->eaflags & EAF_BYTEOFFS ||
1452 (o>=-128 && o<=127 && seg==NO_SEG && !forw_ref &&
1453 !(input->eaflags & EAF_WORDOFFS)))
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001454 mod = 1;
1455 else
1456 mod = 2;
1457
1458 output->sib_present = FALSE; /* no SIB - it's 16-bit */
1459 output->bytes = mod; /* bytes of offset needed */
1460 output->modrm = (mod<<6) | (rfield<<3) | rm;
1461 }
1462 }
1463 }
1464 output->size = 1 + output->sib_present + output->bytes;
1465 return output;
1466}
1467
H. Peter Anvineba20a72002-04-30 20:53:55 +00001468static int chsize (operand *input, int addrbits)
1469{
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001470 if (!(MEMORY & ~input->type)) {
1471 int i=input->indexreg, b=input->basereg;
1472
1473 if (input->scale==0) i = -1;
1474
1475 if (i == -1 && b == -1) /* pure offset */
1476 return (input->addr_size != 0 && input->addr_size != addrbits);
1477
1478 if (i==R_EAX || i==R_EBX || i==R_ECX || i==R_EDX
1479 || i==R_EBP || i==R_ESP || i==R_ESI || i==R_EDI
1480 || b==R_EAX || b==R_EBX || b==R_ECX || b==R_EDX
1481 || b==R_EBP || b==R_ESP || b==R_ESI || b==R_EDI)
1482 return (addrbits==16);
1483 else
1484 return (addrbits==32);
H. Peter Anvineba20a72002-04-30 20:53:55 +00001485 }
1486 else
H. Peter Anvinea6e34d2002-04-30 20:51:32 +00001487 return 0;
1488}