]>
git.saurik.com Git - apple/boot.git/blob - i386/nasm/assemble.c
2 * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights
7 * Reserved. This file contains Original Code and/or Modifications of
8 * Original Code as defined in and that are subject to the Apple Public
9 * Source License Version 1.1 (the "License"). You may not use this file
10 * except in compliance with the License. Please obtain a copy of the
11 * License at http://www.apple.com/publicsource and read it before using
14 * The Original Code and all software distributed under the License are
15 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE OR NON- INFRINGEMENT. Please see the
19 * License for the specific language governing rights and limitations
22 * @APPLE_LICENSE_HEADER_END@
24 /* assemble.c code generation for the Netwide Assembler
26 * The Netwide Assembler is copyright (C) 1996 Simon Tatham and
27 * Julian Hall. All rights reserved. The software is
28 * redistributable under the licence given in the file "Licence"
29 * distributed in the NASM archive.
31 * the actual codes (C syntax, i.e. octal):
32 * \0 - terminates the code. (Unless it's a literal of course.)
33 * \1, \2, \3 - that many literal bytes follow in the code stream
34 * \4, \6 - the POP/PUSH (respectively) codes for CS, DS, ES, SS
35 * (POP is never used for CS) depending on operand 0
36 * \5, \7 - the second byte of POP/PUSH codes for FS, GS, depending
38 * \10, \11, \12 - a literal byte follows in the code stream, to be added
39 * to the register value of operand 0, 1 or 2
40 * \17 - encodes the literal byte 0. (Some compilers don't take
41 * kindly to a zero byte in the _middle_ of a compile time
42 * string constant, so I had to put this hack in.)
43 * \14, \15, \16 - a signed byte immediate operand, from operand 0, 1 or 2
44 * \20, \21, \22 - a byte immediate operand, from operand 0, 1 or 2
45 * \24, \25, \26 - an unsigned byte immediate operand, from operand 0, 1 or 2
46 * \30, \31, \32 - a word immediate operand, from operand 0, 1 or 2
47 * \34, \35, \36 - select between \3[012] and \4[012] depending on 16/32 bit
48 * assembly mode or the address-size override on the operand
49 * \37 - a word constant, from the _segment_ part of operand 0
50 * \40, \41, \42 - a long immediate operand, from operand 0, 1 or 2
51 * \50, \51, \52 - a byte relative operand, from operand 0, 1 or 2
52 * \60, \61, \62 - a word relative operand, from operand 0, 1 or 2
53 * \64, \65, \66 - select between \6[012] and \7[012] depending on 16/32 bit
54 * assembly mode or the address-size override on the operand
55 * \70, \71, \72 - a long relative operand, from operand 0, 1 or 2
56 * \1ab - a ModRM, calculated on EA in operand a, with the spare
57 * field the register value of operand b.
58 * \2ab - a ModRM, calculated on EA in operand a, with the spare
59 * field equal to digit b.
60 * \30x - might be an 0x67 byte, depending on the address size of
61 * the memory reference in operand x.
62 * \310 - indicates fixed 16-bit address size, i.e. optional 0x67.
63 * \311 - indicates fixed 32-bit address size, i.e. optional 0x67.
64 * \320 - indicates fixed 16-bit operand size, i.e. optional 0x66.
65 * \321 - indicates fixed 32-bit operand size, i.e. optional 0x66.
66 * \322 - indicates that this instruction is only valid when the
67 * operand size is the default (instruction to disassembler,
68 * generates no code in the assembler)
69 * \330 - a literal byte follows in the code stream, to be added
70 * to the condition code value of the instruction.
71 * \340 - reserve <operand 0> bytes of uninitialised storage.
72 * Operand 0 had better be a segmentless constant.
83 extern struct itemplate
*nasm_instructions
[];
86 int sib_present
; /* is a SIB byte necessary? */
87 int bytes
; /* # of bytes of offset needed */
88 int size
; /* lazy - this is sib+bytes+1 */
89 unsigned char modrm
, sib
; /* the bytes themselves */
93 static struct ofmt
*outfmt
;
96 static long calcsize (long, long, int, insn
*, char *);
97 static void gencode (long, long, int, insn
*, char *, long);
98 static int regval (operand
*o
);
99 static int matches (struct itemplate
*, insn
*);
100 static ea
*process_ea (operand
*, ea
*, int, int, int);
101 static int chsize (operand
*, int);
104 * This routine wrappers the real output format's output routine,
105 * in order to pass a copy of the data off to the listing file
106 * generator at the same time.
108 static void out (long offset
, long segto
, void *data
, unsigned long type
,
109 long segment
, long wrt
) {
110 if ((type
& OUT_TYPMASK
) == OUT_ADDRESS
) {
111 if (segment
!= NO_SEG
|| wrt
!= NO_SEG
) {
113 * This address is relocated. We must write it as
114 * OUT_ADDRESS, so there's no work to be done here.
116 list
->output (offset
, data
, type
);
118 unsigned char p
[4], *q
= p
;
120 * This is a non-relocated address, and we're going to
121 * convert it into RAWDATA format.
123 if ((type
& OUT_SIZMASK
) == 4) {
124 WRITELONG (q
, * (long *) data
);
125 list
->output (offset
, p
, OUT_RAWDATA
+4);
127 WRITESHORT (q
, * (long *) data
);
128 list
->output (offset
, p
, OUT_RAWDATA
+2);
131 } else if ((type
& OUT_TYPMASK
) == OUT_RAWDATA
) {
132 list
->output (offset
, data
, type
);
133 } else if ((type
& OUT_TYPMASK
) == OUT_RESERVE
) {
134 list
->output (offset
, NULL
, type
);
135 } else if ((type
& OUT_TYPMASK
) == OUT_REL2ADR
||
136 (type
& OUT_TYPMASK
) == OUT_REL4ADR
) {
137 list
->output (offset
, data
, type
);
140 outfmt
->output (segto
, data
, type
, segment
, wrt
);
143 long assemble (long segment
, long offset
, int bits
,
144 insn
*instruction
, struct ofmt
*output
, efunc error
,
147 long insn_end
, itimes
;
149 struct itemplate
*temp
;
151 errfunc
= error
; /* to pass to other functions */
152 outfmt
= output
; /* likewise */
153 list
= listgen
; /* and again */
155 if (instruction
->opcode
== -1)
158 if (instruction
->opcode
== I_DB
||
159 instruction
->opcode
== I_DW
||
160 instruction
->opcode
== I_DD
||
161 instruction
->opcode
== I_DQ
||
162 instruction
->opcode
== I_DT
) {
164 long wsize
= 0; /* placate gcc */
165 long t
= instruction
->times
;
167 switch (instruction
->opcode
) {
168 case I_DB
: wsize
= 1; break;
169 case I_DW
: wsize
= 2; break;
170 case I_DD
: wsize
= 4; break;
171 case I_DQ
: wsize
= 8; break;
172 case I_DT
: wsize
= 10; break;
176 for (e
= instruction
->eops
; e
; e
= e
->next
) {
177 if (e
->type
== EOT_DB_NUMBER
) {
179 if (e
->segment
!= NO_SEG
)
180 errfunc (ERR_NONFATAL
,
181 "one-byte relocation attempted");
183 unsigned char c
= e
->offset
;
184 out (offset
, segment
, &c
, OUT_RAWDATA
+1,
187 } else if (wsize
> 5) {
188 errfunc (ERR_NONFATAL
, "integer supplied to a D%c"
189 " instruction", wsize
==8 ? 'Q' : 'T');
191 out (offset
, segment
, &e
->offset
,
192 OUT_ADDRESS
+wsize
, e
->segment
,
195 } else if (e
->type
== EOT_DB_STRING
) {
198 align
= (-e
->stringlen
) % wsize
;
201 out (offset
, segment
, e
->stringval
,
202 OUT_RAWDATA
+e
->stringlen
, NO_SEG
, NO_SEG
);
204 out (offset
, segment
, "\0\0\0\0",
205 OUT_RAWDATA
+align
, NO_SEG
, NO_SEG
);
206 offset
+= e
->stringlen
+ align
;
209 if (t
> 0 && t
== instruction
->times
-1) {
211 * Dummy call to list->output to give the offset to the
214 list
->output (offset
, NULL
, OUT_RAWDATA
);
215 list
->uplevel (LIST_TIMES
);
218 if (instruction
->times
> 1)
219 list
->downlevel (LIST_TIMES
);
220 return offset
- start
;
223 if (instruction
->opcode
== I_INCBIN
) {
224 static char fname
[FILENAME_MAX
];
228 len
= FILENAME_MAX
-1;
229 if (len
> instruction
->eops
->stringlen
)
230 len
= instruction
->eops
->stringlen
;
231 strncpy (fname
, instruction
->eops
->stringval
, len
);
233 if (!(fp
= fopen(fname
, "rb")))
234 error (ERR_NONFATAL
, "`incbin': unable to open file `%s'", fname
);
235 else if (fseek(fp
, 0L, SEEK_END
) < 0)
236 error (ERR_NONFATAL
, "`incbin': unable to seek on file `%s'",
239 static char buf
[2048];
240 long t
= instruction
->times
;
244 if (instruction
->eops
->next
) {
245 len
-= instruction
->eops
->next
->offset
;
246 if (instruction
->eops
->next
->next
&&
247 len
> instruction
->eops
->next
->next
->offset
)
248 len
= instruction
->eops
->next
->next
->offset
;
251 * Dummy call to list->output to give the offset to the
254 list
->output (offset
, NULL
, OUT_RAWDATA
);
255 list
->uplevel(LIST_INCBIN
);
258 (instruction
->eops
->next
?
259 instruction
->eops
->next
->offset
: 0),
263 long m
= fread (buf
, 1, (l
>(long)sizeof(buf
)?(long)sizeof(buf
):l
),
267 * This shouldn't happen unless the file
268 * actually changes while we are reading
271 error (ERR_NONFATAL
, "`incbin': unexpected EOF while"
272 " reading file `%s'", fname
);
273 return 0; /* it doesn't much matter... */
275 out (offset
, segment
, buf
, OUT_RAWDATA
+m
,
280 list
->downlevel(LIST_INCBIN
);
281 if (instruction
->times
> 1) {
283 * Dummy call to list->output to give the offset to the
286 list
->output (offset
, NULL
, OUT_RAWDATA
);
287 list
->uplevel(LIST_TIMES
);
288 list
->downlevel(LIST_TIMES
);
291 return instruction
->times
* len
;
293 return 0; /* if we're here, there's an error */
297 temp
= nasm_instructions
[instruction
->opcode
];
298 while (temp
->opcode
!= -1) {
299 int m
= matches (temp
, instruction
);
300 if (m
== 100) { /* matches! */
301 char *codes
= temp
->code
;
302 long insn_size
= calcsize(segment
, offset
, bits
,
304 itimes
= instruction
->times
;
305 if (insn_size
< 0) /* shouldn't be, on pass two */
306 error (ERR_PANIC
, "errors made it through from pass one");
307 else while (itimes
--) {
308 insn_end
= offset
+ insn_size
;
309 for (j
=0; j
<instruction
->nprefix
; j
++) {
311 switch (instruction
->prefixes
[j
]) {
314 case P_REPNE
: case P_REPNZ
:
316 case P_REPE
: case P_REPZ
: case P_REP
:
318 case R_CS
: c
= 0x2E; break;
319 case R_DS
: c
= 0x3E; break;
320 case R_ES
: c
= 0x26; break;
321 case R_FS
: c
= 0x64; break;
322 case R_GS
: c
= 0x65; break;
323 case R_SS
: c
= 0x36; break;
326 c
= 0; /* no prefix */
332 c
= 0; /* no prefix */
338 c
= 0; /* no prefix */
344 c
= 0; /* no prefix */
350 "invalid instruction prefix");
353 out (offset
, segment
, &c
, OUT_RAWDATA
+1,
357 gencode (segment
, offset
, bits
, instruction
, codes
, insn_end
);
359 if (itimes
> 0 && itimes
== instruction
->times
-1) {
361 * Dummy call to list->output to give the offset to the
364 list
->output (offset
, NULL
, OUT_RAWDATA
);
365 list
->uplevel (LIST_TIMES
);
368 if (instruction
->times
> 1)
369 list
->downlevel (LIST_TIMES
);
370 return offset
- start
;
376 if (temp
->opcode
== -1) { /* didn't match any instruction */
377 if (size_prob
== 1) /* would have matched, but for size */
378 error (ERR_NONFATAL
, "operation size not specified");
379 else if (size_prob
== 2)
380 error (ERR_NONFATAL
, "mismatch in operand sizes");
383 "invalid combination of opcode and operands");
388 long insn_size (long segment
, long offset
, int bits
,
389 insn
*instruction
, efunc error
) {
390 struct itemplate
*temp
;
392 errfunc
= error
; /* to pass to other functions */
394 if (instruction
->opcode
== -1)
397 if (instruction
->opcode
== I_DB
||
398 instruction
->opcode
== I_DW
||
399 instruction
->opcode
== I_DD
||
400 instruction
->opcode
== I_DQ
||
401 instruction
->opcode
== I_DT
) {
403 long isize
, osize
, wsize
= 0; /* placate gcc */
406 switch (instruction
->opcode
) {
407 case I_DB
: wsize
= 1; break;
408 case I_DW
: wsize
= 2; break;
409 case I_DD
: wsize
= 4; break;
410 case I_DQ
: wsize
= 8; break;
411 case I_DT
: wsize
= 10; break;
414 for (e
= instruction
->eops
; e
; e
= e
->next
) {
418 if (e
->type
== EOT_DB_NUMBER
)
420 else if (e
->type
== EOT_DB_STRING
)
421 osize
= e
->stringlen
;
423 align
= (-osize
) % wsize
;
426 isize
+= osize
+ align
;
428 return isize
* instruction
->times
;
431 if (instruction
->opcode
== I_INCBIN
) {
432 char fname
[FILENAME_MAX
];
436 len
= FILENAME_MAX
-1;
437 if (len
> instruction
->eops
->stringlen
)
438 len
= instruction
->eops
->stringlen
;
439 strncpy (fname
, instruction
->eops
->stringval
, len
);
441 if (!(fp
= fopen(fname
, "rb")))
442 error (ERR_NONFATAL
, "`incbin': unable to open file `%s'", fname
);
443 else if (fseek(fp
, 0L, SEEK_END
) < 0)
444 error (ERR_NONFATAL
, "`incbin': unable to seek on file `%s'",
449 if (instruction
->eops
->next
) {
450 len
-= instruction
->eops
->next
->offset
;
451 if (instruction
->eops
->next
->next
&&
452 len
> instruction
->eops
->next
->next
->offset
)
453 len
= instruction
->eops
->next
->next
->offset
;
455 return instruction
->times
* len
;
457 return 0; /* if we're here, there's an error */
460 temp
= nasm_instructions
[instruction
->opcode
];
461 while (temp
->opcode
!= -1) {
462 if (matches(temp
, instruction
) == 100) {
463 /* we've matched an instruction. */
465 char *codes
= temp
->code
;
468 isize
= calcsize(segment
, offset
, bits
, instruction
, codes
);
471 for (j
= 0; j
< instruction
->nprefix
; j
++) {
472 if ((instruction
->prefixes
[j
] != P_A16
&&
473 instruction
->prefixes
[j
] != P_O16
&& bits
==16) ||
474 (instruction
->prefixes
[j
] != P_A32
&&
475 instruction
->prefixes
[j
] != P_O32
&& bits
==32))
478 return isize
* instruction
->times
;
482 return -1; /* didn't match any instruction */
485 static long calcsize (long segment
, long offset
, int bits
,
486 insn
*ins
, char *codes
) {
490 while (*codes
) switch (c
= *codes
++) {
491 case 01: case 02: case 03:
492 codes
+= c
, length
+= c
; break;
493 case 04: case 05: case 06: case 07:
495 case 010: case 011: case 012:
496 codes
++, length
++; break;
499 case 014: case 015: case 016:
501 case 020: case 021: case 022:
503 case 024: case 025: case 026:
505 case 030: case 031: case 032:
507 case 034: case 035: case 036:
508 length
+= ((ins
->oprs
[c
-034].addr_size
?
509 ins
->oprs
[c
-034].addr_size
: bits
) == 16 ? 2 : 4); break;
512 case 040: case 041: case 042:
514 case 050: case 051: case 052:
516 case 060: case 061: case 062:
518 case 064: case 065: case 066:
519 length
+= ((ins
->oprs
[c
-064].addr_size
?
520 ins
->oprs
[c
-064].addr_size
: bits
) == 16 ? 2 : 4); break;
521 case 070: case 071: case 072:
523 case 0300: case 0301: case 0302:
524 length
+= chsize (&ins
->oprs
[c
-0300], bits
);
527 length
+= (bits
==32);
530 length
+= (bits
==16);
535 length
+= (bits
==32);
538 length
+= (bits
==16);
543 codes
++, length
++; break;
544 case 0340: case 0341: case 0342:
545 if (ins
->oprs
[0].segment
!= NO_SEG
)
546 errfunc (ERR_NONFATAL
, "attempt to reserve non-constant"
547 " quantity of BSS space");
549 length
+= ins
->oprs
[0].offset
<< (c
-0340);
551 default: /* can't do it by 'case' statements */
552 if (c
>=0100 && c
<=0277) { /* it's an EA */
554 if (!process_ea (&ins
->oprs
[(c
>>3)&7], &ea_data
, bits
, 0,
556 errfunc (ERR_NONFATAL
, "invalid effective address");
559 length
+= ea_data
.size
;
561 errfunc (ERR_PANIC
, "internal instruction table corrupt"
562 ": instruction code 0x%02X given", c
);
567 static void gencode (long segment
, long offset
, int bits
,
568 insn
*ins
, char *codes
, long insn_end
) {
569 static char condval
[] = { /* conditional opcodes */
570 0x7, 0x3, 0x2, 0x6, 0x2, 0x4, 0xF, 0xD, 0xC, 0xE, 0x6, 0x2,
571 0x3, 0x7, 0x3, 0x5, 0xE, 0xC, 0xD, 0xF, 0x1, 0xB, 0x9, 0x5,
572 0x0, 0xA, 0xA, 0xB, 0x8, 0x4
574 unsigned char c
, bytes
[4];
577 while (*codes
) switch (c
= *codes
++) {
578 case 01: case 02: case 03:
579 out (offset
, segment
, codes
, OUT_RAWDATA
+c
, NO_SEG
, NO_SEG
);
584 switch (ins
->oprs
[0].basereg
) {
585 case R_CS
: bytes
[0] = 0x0E + (c
== 0x04 ? 1 : 0); break;
586 case R_DS
: bytes
[0] = 0x1E + (c
== 0x04 ? 1 : 0); break;
587 case R_ES
: bytes
[0] = 0x06 + (c
== 0x04 ? 1 : 0); break;
588 case R_SS
: bytes
[0] = 0x16 + (c
== 0x04 ? 1 : 0); break;
590 errfunc (ERR_PANIC
, "bizarre 8086 segment register received");
592 out (offset
, segment
, bytes
, OUT_RAWDATA
+1, NO_SEG
, NO_SEG
);
596 switch (ins
->oprs
[0].basereg
) {
597 case R_FS
: bytes
[0] = 0xA0 + (c
== 0x05 ? 1 : 0); break;
598 case R_GS
: bytes
[0] = 0xA8 + (c
== 0x05 ? 1 : 0); break;
600 errfunc (ERR_PANIC
, "bizarre 386 segment register received");
602 out (offset
, segment
, bytes
, OUT_RAWDATA
+1, NO_SEG
, NO_SEG
);
605 case 010: case 011: case 012:
606 bytes
[0] = *codes
++ + regval(&ins
->oprs
[c
-010]);
607 out (offset
, segment
, bytes
, OUT_RAWDATA
+1, NO_SEG
, NO_SEG
);
612 out (offset
, segment
, bytes
, OUT_RAWDATA
+1, NO_SEG
, NO_SEG
);
615 case 014: case 015: case 016:
616 if (ins
->oprs
[c
-014].offset
< -128 || ins
->oprs
[c
-014].offset
> 127)
617 errfunc (ERR_WARNING
, "signed byte value exceeds bounds");
618 if (ins
->oprs
[c
-014].segment
!= NO_SEG
) {
619 data
= ins
->oprs
[c
-014].offset
;
620 out (offset
, segment
, &data
, OUT_ADDRESS
+1,
621 ins
->oprs
[c
-014].segment
, ins
->oprs
[c
-014].wrt
);
623 bytes
[0] = ins
->oprs
[c
-014].offset
;
624 out (offset
, segment
, bytes
, OUT_RAWDATA
+1, NO_SEG
, NO_SEG
);
628 case 020: case 021: case 022:
629 if (ins
->oprs
[c
-020].offset
< -256 || ins
->oprs
[c
-020].offset
> 255)
630 errfunc (ERR_WARNING
, "byte value exceeds bounds");
631 if (ins
->oprs
[c
-020].segment
!= NO_SEG
) {
632 data
= ins
->oprs
[c
-020].offset
;
633 out (offset
, segment
, &data
, OUT_ADDRESS
+1,
634 ins
->oprs
[c
-020].segment
, ins
->oprs
[c
-020].wrt
);
636 bytes
[0] = ins
->oprs
[c
-020].offset
;
637 out (offset
, segment
, bytes
, OUT_RAWDATA
+1, NO_SEG
, NO_SEG
);
641 case 024: case 025: case 026:
642 if (ins
->oprs
[c
-024].offset
< 0 || ins
->oprs
[c
-024].offset
> 255)
643 errfunc (ERR_WARNING
, "unsigned byte value exceeds bounds");
644 if (ins
->oprs
[c
-024].segment
!= NO_SEG
) {
645 data
= ins
->oprs
[c
-024].offset
;
646 out (offset
, segment
, &data
, OUT_ADDRESS
+1,
647 ins
->oprs
[c
-024].segment
, ins
->oprs
[c
-024].wrt
);
649 bytes
[0] = ins
->oprs
[c
-024].offset
;
650 out (offset
, segment
, bytes
, OUT_RAWDATA
+1, NO_SEG
, NO_SEG
);
654 case 030: case 031: case 032:
655 if (ins
->oprs
[c
-030].segment
== NO_SEG
&&
656 ins
->oprs
[c
-030].wrt
== NO_SEG
&&
657 (ins
->oprs
[c
-030].offset
< -65536L ||
658 ins
->oprs
[c
-030].offset
> 65535L))
659 errfunc (ERR_WARNING
, "word value exceeds bounds");
660 data
= ins
->oprs
[c
-030].offset
;
661 out (offset
, segment
, &data
, OUT_ADDRESS
+2,
662 ins
->oprs
[c
-030].segment
, ins
->oprs
[c
-030].wrt
);
665 case 034: case 035: case 036:
666 data
= ins
->oprs
[c
-034].offset
;
667 size
= ((ins
->oprs
[c
-034].addr_size
?
668 ins
->oprs
[c
-034].addr_size
: bits
) == 16 ? 2 : 4);
669 if (size
==16 && (data
< -65536L || data
> 65535L))
670 errfunc (ERR_WARNING
, "word value exceeds bounds");
671 out (offset
, segment
, &data
, OUT_ADDRESS
+size
,
672 ins
->oprs
[c
-034].segment
, ins
->oprs
[c
-034].wrt
);
676 if (ins
->oprs
[0].segment
== NO_SEG
)
677 errfunc (ERR_NONFATAL
, "value referenced by FAR is not"
680 out (offset
, segment
, &data
, OUT_ADDRESS
+2,
681 outfmt
->segbase(1+ins
->oprs
[0].segment
),
685 case 040: case 041: case 042:
686 data
= ins
->oprs
[c
-040].offset
;
687 out (offset
, segment
, &data
, OUT_ADDRESS
+4,
688 ins
->oprs
[c
-040].segment
, ins
->oprs
[c
-040].wrt
);
691 case 050: case 051: case 052:
692 if (ins
->oprs
[c
-050].segment
!= segment
)
693 errfunc (ERR_NONFATAL
, "short relative jump outside segment");
694 data
= ins
->oprs
[c
-050].offset
- insn_end
;
695 if (data
> 127 || data
< -128)
696 errfunc (ERR_NONFATAL
, "short jump is out of range");
698 out (offset
, segment
, bytes
, OUT_RAWDATA
+1, NO_SEG
, NO_SEG
);
701 case 060: case 061: case 062:
702 if (ins
->oprs
[c
-060].segment
!= segment
) {
703 data
= ins
->oprs
[c
-060].offset
;
704 out (offset
, segment
, &data
, OUT_REL2ADR
+insn_end
-offset
,
705 ins
->oprs
[c
-060].segment
, ins
->oprs
[c
-060].wrt
);
707 data
= ins
->oprs
[c
-060].offset
- insn_end
;
708 out (offset
, segment
, &data
,
709 OUT_ADDRESS
+2, NO_SEG
, NO_SEG
);
713 case 064: case 065: case 066:
714 size
= ((ins
->oprs
[c
-064].addr_size
?
715 ins
->oprs
[c
-064].addr_size
: bits
) == 16 ? 2 : 4);
716 if (ins
->oprs
[c
-064].segment
!= segment
) {
717 data
= ins
->oprs
[c
-064].offset
;
718 size
= (bits
== 16 ? OUT_REL2ADR
: OUT_REL4ADR
);
719 out (offset
, segment
, &data
, size
+insn_end
-offset
,
720 ins
->oprs
[c
-064].segment
, ins
->oprs
[c
-064].wrt
);
721 size
= (bits
== 16 ? 2 : 4);
723 data
= ins
->oprs
[c
-064].offset
- insn_end
;
724 out (offset
, segment
, &data
,
725 OUT_ADDRESS
+size
, NO_SEG
, NO_SEG
);
729 case 070: case 071: case 072:
730 if (ins
->oprs
[c
-070].segment
!= segment
) {
731 data
= ins
->oprs
[c
-070].offset
;
732 out (offset
, segment
, &data
, OUT_REL4ADR
+insn_end
-offset
,
733 ins
->oprs
[c
-070].segment
, ins
->oprs
[c
-070].wrt
);
735 data
= ins
->oprs
[c
-070].offset
- insn_end
;
736 out (offset
, segment
, &data
,
737 OUT_ADDRESS
+4, NO_SEG
, NO_SEG
);
741 case 0300: case 0301: case 0302:
742 if (chsize (&ins
->oprs
[c
-0300], bits
)) {
744 out (offset
, segment
, bytes
,
745 OUT_RAWDATA
+1, NO_SEG
, NO_SEG
);
753 out (offset
, segment
, bytes
,
754 OUT_RAWDATA
+1, NO_SEG
, NO_SEG
);
762 out (offset
, segment
, bytes
,
763 OUT_RAWDATA
+1, NO_SEG
, NO_SEG
);
773 out (offset
, segment
, bytes
,
774 OUT_RAWDATA
+1, NO_SEG
, NO_SEG
);
782 out (offset
, segment
, bytes
,
783 OUT_RAWDATA
+1, NO_SEG
, NO_SEG
);
791 *bytes
= *codes
++ + condval
[ins
->condition
];
792 out (offset
, segment
, bytes
,
793 OUT_RAWDATA
+1, NO_SEG
, NO_SEG
);
796 case 0340: case 0341: case 0342:
797 if (ins
->oprs
[0].segment
!= NO_SEG
)
798 errfunc (ERR_PANIC
, "non-constant BSS size in pass two");
800 long size
= ins
->oprs
[0].offset
<< (c
-0340);
802 out (offset
, segment
, NULL
,
803 OUT_RESERVE
+size
, NO_SEG
, NO_SEG
);
807 default: /* can't do it by 'case' statements */
808 if (c
>=0100 && c
<=0277) { /* it's an EA */
814 if (c
<=0177) /* pick rfield from operand b */
815 rfield
= regval (&ins
->oprs
[c
&7]);
816 else /* rfield is constant */
818 if (!process_ea (&ins
->oprs
[(c
>>3)&7], &ea_data
, bits
, rfield
,
820 errfunc (ERR_NONFATAL
, "invalid effective address");
823 *p
++ = ea_data
.modrm
;
824 if (ea_data
.sib_present
)
827 * the cast in the next line is to placate MS C...
829 out (offset
, segment
, bytes
, OUT_RAWDATA
+(long)(p
-bytes
),
833 switch (ea_data
.bytes
) {
837 if (ins
->oprs
[(c
>>3)&7].segment
!= NO_SEG
) {
838 data
= ins
->oprs
[(c
>>3)&7].offset
;
839 out (offset
, segment
, &data
, OUT_ADDRESS
+1,
840 ins
->oprs
[(c
>>3)&7].segment
,
841 ins
->oprs
[(c
>>3)&7].wrt
);
843 *bytes
= ins
->oprs
[(c
>>3)&7].offset
;
844 out (offset
, segment
, bytes
, OUT_RAWDATA
+1,
851 data
= ins
->oprs
[(c
>>3)&7].offset
;
852 out (offset
, segment
, &data
,
853 OUT_ADDRESS
+ea_data
.bytes
,
854 ins
->oprs
[(c
>>3)&7].segment
, ins
->oprs
[(c
>>3)&7].wrt
);
860 errfunc (ERR_PANIC
, "internal instruction table corrupt"
861 ": instruction code 0x%02X given", c
);
865 static int regval (operand
*o
) {
866 switch (o
->basereg
) {
867 case R_EAX
: case R_AX
: case R_AL
: case R_ES
: case R_CR0
: case R_DR0
:
868 case R_ST0
: case R_MM0
:
870 case R_ECX
: case R_CX
: case R_CL
: case R_CS
: case R_DR1
: case R_ST1
:
873 case R_EDX
: case R_DX
: case R_DL
: case R_SS
: case R_CR2
: case R_DR2
:
874 case R_ST2
: case R_MM2
:
876 case R_EBX
: case R_BX
: case R_BL
: case R_DS
: case R_CR3
: case R_DR3
:
877 case R_TR3
: case R_ST3
: case R_MM3
:
879 case R_ESP
: case R_SP
: case R_AH
: case R_FS
: case R_CR4
: case R_TR4
:
880 case R_ST4
: case R_MM4
:
882 case R_EBP
: case R_BP
: case R_CH
: case R_GS
: case R_TR5
: case R_ST5
:
885 case R_ESI
: case R_SI
: case R_DH
: case R_DR6
: case R_TR6
: case R_ST6
:
888 case R_EDI
: case R_DI
: case R_BH
: case R_DR7
: case R_TR7
: case R_ST7
:
892 errfunc (ERR_PANIC
, "invalid register operand given to regval()");
897 static int matches (struct itemplate
*itemp
, insn
*instruction
) {
898 int i
, size
, oprs
, ret
;
905 if (itemp
->opcode
!= instruction
->opcode
) return 0;
910 if (itemp
->operands
!= instruction
->operands
) return 0;
913 * Check that no spurious colons or TOs are present
915 for (i
=0; i
<itemp
->operands
; i
++)
916 if (instruction
->oprs
[i
].type
& ~itemp
->opd
[i
] & (COLON
|TO
))
920 * Check that the operand flags all match up
922 for (i
=0; i
<itemp
->operands
; i
++)
923 if (itemp
->opd
[i
] & ~instruction
->oprs
[i
].type
||
924 ((itemp
->opd
[i
] & SIZE_MASK
) &&
925 ((itemp
->opd
[i
] ^ instruction
->oprs
[i
].type
) & SIZE_MASK
))) {
926 if ((itemp
->opd
[i
] & ~instruction
->oprs
[i
].type
& NON_SIZE
) ||
927 (instruction
->oprs
[i
].type
& SIZE_MASK
))
934 * Check operand sizes
936 if (itemp
->flags
& IF_SB
) {
938 oprs
= itemp
->operands
;
939 } else if (itemp
->flags
& IF_SW
) {
941 oprs
= itemp
->operands
;
942 } else if (itemp
->flags
& IF_SD
) {
944 oprs
= itemp
->operands
;
945 } else if (itemp
->flags
& (IF_SM
| IF_SM2
)) {
946 oprs
= (itemp
->flags
& IF_SM2
? 2 : itemp
->operands
);
947 size
= 0; /* placate gcc */
948 for (i
=0; i
<oprs
; i
++)
949 if ( (size
= itemp
->opd
[i
] & SIZE_MASK
) != 0)
953 oprs
= itemp
->operands
;
956 for (i
=0; i
<itemp
->operands
; i
++)
957 if (!(itemp
->opd
[i
] & SIZE_MASK
) &&
958 (instruction
->oprs
[i
].type
& SIZE_MASK
& ~size
))
964 static ea
*process_ea (operand
*input
, ea
*output
, int addrbits
, int rfield
,
966 if (!(REGISTER
& ~input
->type
)) { /* it's a single register */
967 static int regs
[] = {
968 R_MM0
, R_EAX
, R_AX
, R_AL
, R_MM1
, R_ECX
, R_CX
, R_CL
,
969 R_MM2
, R_EDX
, R_DX
, R_DL
, R_MM3
, R_EBX
, R_BX
, R_BL
,
970 R_MM4
, R_ESP
, R_SP
, R_AH
, R_MM5
, R_EBP
, R_BP
, R_CH
,
971 R_MM6
, R_ESI
, R_SI
, R_DH
, R_MM7
, R_EDI
, R_DI
, R_BH
975 for (i
=0; i
<(int)elements(regs
); i
++)
976 if (input
->basereg
== regs
[i
]) break;
977 if (i
<(int)elements(regs
)) {
978 output
->sib_present
= FALSE
;/* no SIB necessary */
979 output
->bytes
= 0; /* no offset necessary either */
980 output
->modrm
= 0xC0 | (rfield
<< 3) | (i
/4);
983 } else { /* it's a memory reference */
984 if (input
->basereg
==-1 && (input
->indexreg
==-1 || input
->scale
==0)) {
985 /* it's a pure offset */
986 if (input
->addr_size
)
987 addrbits
= input
->addr_size
;
988 output
->sib_present
= FALSE
;
989 output
->bytes
= (addrbits
==32 ? 4 : 2);
990 output
->modrm
= (addrbits
==32 ? 5 : 6) | (rfield
<< 3);
991 } else { /* it's an indirection */
992 int i
=input
->indexreg
, b
=input
->basereg
, s
=input
->scale
;
993 long o
=input
->offset
, seg
=input
->segment
;
994 int hb
=input
->hintbase
, ht
=input
->hinttype
;
997 if (s
==0) i
= -1; /* make this easy, at least */
999 if (i
==R_EAX
|| i
==R_EBX
|| i
==R_ECX
|| i
==R_EDX
1000 || i
==R_EBP
|| i
==R_ESP
|| i
==R_ESI
|| i
==R_EDI
1001 || b
==R_EAX
|| b
==R_EBX
|| b
==R_ECX
|| b
==R_EDX
1002 || b
==R_EBP
|| b
==R_ESP
|| b
==R_ESI
|| b
==R_EDI
) {
1003 /* it must be a 32-bit memory reference. Firstly we have
1004 * to check that all registers involved are type Exx. */
1005 if (i
!=-1 && i
!=R_EAX
&& i
!=R_EBX
&& i
!=R_ECX
&& i
!=R_EDX
1006 && i
!=R_EBP
&& i
!=R_ESP
&& i
!=R_ESI
&& i
!=R_EDI
)
1008 if (b
!=-1 && b
!=R_EAX
&& b
!=R_EBX
&& b
!=R_ECX
&& b
!=R_EDX
1009 && b
!=R_EBP
&& b
!=R_ESP
&& b
!=R_ESI
&& b
!=R_EDI
)
1012 /* While we're here, ensure the user didn't specify WORD. */
1013 if (input
->addr_size
== 16)
1016 /* now reorganise base/index */
1017 if (s
== 1 && b
!= i
&& b
!= -1 && i
!= -1 &&
1018 ((hb
==b
&&ht
==EAH_NOTBASE
) || (hb
==i
&&ht
==EAH_MAKEBASE
)))
1019 t
= b
, b
= i
, i
= t
; /* swap if hints say so */
1020 if (b
==i
) /* convert EAX+2*EAX to 3*EAX */
1022 if (b
==-1 && s
==1 && !(hb
== i
&& ht
== EAH_NOTBASE
))
1023 b
= i
, i
= -1; /* make single reg base, unless hint */
1024 if (((s
==2 && i
!=R_ESP
&& !(input
->eaflags
& EAF_TIMESTWO
)) ||
1025 s
==3 || s
==5 || s
==9) && b
==-1)
1026 b
= i
, s
--; /* convert 3*EAX to EAX+2*EAX */
1027 if (s
==1 && i
==R_ESP
) /* swap ESP into base if scale is 1 */
1029 if (i
==R_ESP
|| (s
!=1 && s
!=2 && s
!=4 && s
!=8 && i
!=-1))
1030 return NULL
; /* wrong, for various reasons */
1032 if (i
==-1 && b
!=R_ESP
) {/* no SIB needed */
1035 case R_EAX
: rm
= 0; break;
1036 case R_ECX
: rm
= 1; break;
1037 case R_EDX
: rm
= 2; break;
1038 case R_EBX
: rm
= 3; break;
1039 case R_EBP
: rm
= 5; break;
1040 case R_ESI
: rm
= 6; break;
1041 case R_EDI
: rm
= 7; break;
1042 case -1: rm
= 5; break;
1043 default: /* should never happen */
1046 if (b
==-1 || (b
!=R_EBP
&& o
==0 &&
1047 seg
==NO_SEG
&& !forw_ref
&&
1049 (EAF_BYTEOFFS
|EAF_WORDOFFS
))))
1051 else if (input
->eaflags
& EAF_BYTEOFFS
||
1052 (o
>=-128 && o
<=127 && seg
==NO_SEG
&& !forw_ref
&&
1053 !(input
->eaflags
& EAF_WORDOFFS
))) {
1058 output
->sib_present
= FALSE
;
1059 output
->bytes
= (b
==-1 || mod
==2 ? 4 : mod
);
1060 output
->modrm
= (mod
<<6) | (rfield
<<3) | rm
;
1061 } else { /* we need a SIB */
1062 int mod
, scale
, index
, base
;
1065 case R_EAX
: base
= 0; break;
1066 case R_ECX
: base
= 1; break;
1067 case R_EDX
: base
= 2; break;
1068 case R_EBX
: base
= 3; break;
1069 case R_ESP
: base
= 4; break;
1070 case R_EBP
: case -1: base
= 5; break;
1071 case R_ESI
: base
= 6; break;
1072 case R_EDI
: base
= 7; break;
1073 default: /* then what the smeg is it? */
1074 return NULL
; /* panic */
1078 case R_EAX
: index
= 0; break;
1079 case R_ECX
: index
= 1; break;
1080 case R_EDX
: index
= 2; break;
1081 case R_EBX
: index
= 3; break;
1082 case -1: index
= 4; break;
1083 case R_EBP
: index
= 5; break;
1084 case R_ESI
: index
= 6; break;
1085 case R_EDI
: index
= 7; break;
1086 default: /* then what the smeg is it? */
1087 return NULL
; /* panic */
1092 case 1: scale
= 0; break;
1093 case 2: scale
= 1; break;
1094 case 4: scale
= 2; break;
1095 case 8: scale
= 3; break;
1096 default: /* then what the smeg is it? */
1097 return NULL
; /* panic */
1100 if (b
==-1 || (b
!=R_EBP
&& o
==0 &&
1101 seg
==NO_SEG
&& !forw_ref
&&
1103 (EAF_BYTEOFFS
|EAF_WORDOFFS
))))
1105 else if (input
->eaflags
& EAF_BYTEOFFS
||
1106 (o
>=-128 && o
<=127 && seg
==NO_SEG
&& !forw_ref
&&
1107 !(input
->eaflags
& EAF_WORDOFFS
)))
1112 output
->sib_present
= TRUE
;
1113 output
->bytes
= (b
==-1 || mod
==2 ? 4 : mod
);
1114 output
->modrm
= (mod
<<6) | (rfield
<<3) | 4;
1115 output
->sib
= (scale
<<6) | (index
<<3) | base
;
1117 } else { /* it's 16-bit */
1120 /* check all registers are BX, BP, SI or DI */
1121 if ((b
!=-1 && b
!=R_BP
&& b
!=R_BX
&& b
!=R_SI
&& b
!=R_DI
) ||
1122 (i
!=-1 && i
!=R_BP
&& i
!=R_BX
&& i
!=R_SI
&& i
!=R_DI
))
1125 /* ensure the user didn't specify DWORD */
1126 if (input
->addr_size
== 32)
1129 if (s
!=1 && i
!=-1) return NULL
;/* no can do, in 16-bit EA */
1130 if (b
==-1 && i
!=-1) b
^= i
, i
^= b
, b
^= i
; /* swap them round */
1131 if ((b
==R_SI
|| b
==R_DI
) && i
!=-1)
1132 b
^= i
, i
^= b
, b
^= i
; /* have BX/BP as base, SI/DI index */
1133 if (b
==i
) return NULL
;/* shouldn't ever happen, in theory */
1134 if (i
!=-1 && b
!=-1 &&
1135 (i
==R_BP
|| i
==R_BX
|| b
==R_SI
|| b
==R_DI
))
1136 return NULL
; /* invalid combinations */
1137 if (b
==-1) /* pure offset: handled above */
1138 return NULL
; /* so if it gets to here, panic! */
1142 switch (i
*256 + b
) {
1143 case R_SI
*256+R_BX
: rm
=0; break;
1144 case R_DI
*256+R_BX
: rm
=1; break;
1145 case R_SI
*256+R_BP
: rm
=2; break;
1146 case R_DI
*256+R_BP
: rm
=3; break;
1150 case R_SI
: rm
=4; break;
1151 case R_DI
: rm
=5; break;
1152 case R_BP
: rm
=6; break;
1153 case R_BX
: rm
=7; break;
1155 if (rm
==-1) /* can't happen, in theory */
1156 return NULL
; /* so panic if it does */
1158 if (o
==0 && seg
==NO_SEG
&& !forw_ref
&& rm
!=6 &&
1159 !(input
->eaflags
& (EAF_BYTEOFFS
|EAF_WORDOFFS
)))
1161 else if (input
->eaflags
& EAF_BYTEOFFS
||
1162 (o
>=-128 && o
<=127 && seg
==NO_SEG
&& !forw_ref
&&
1163 !(input
->eaflags
& EAF_WORDOFFS
)))
1168 output
->sib_present
= FALSE
; /* no SIB - it's 16-bit */
1169 output
->bytes
= mod
; /* bytes of offset needed */
1170 output
->modrm
= (mod
<<6) | (rfield
<<3) | rm
;
1174 output
->size
= 1 + output
->sib_present
+ output
->bytes
;
1178 static int chsize (operand
*input
, int addrbits
) {
1179 if (!(MEMORY
& ~input
->type
)) {
1180 int i
=input
->indexreg
, b
=input
->basereg
;
1182 if (input
->scale
==0) i
= -1;
1184 if (i
== -1 && b
== -1) /* pure offset */
1185 return (input
->addr_size
!= 0 && input
->addr_size
!= addrbits
);
1187 if (i
==R_EAX
|| i
==R_EBX
|| i
==R_ECX
|| i
==R_EDX
1188 || i
==R_EBP
|| i
==R_ESP
|| i
==R_ESI
|| i
==R_EDI
1189 || b
==R_EAX
|| b
==R_EBX
|| b
==R_ECX
|| b
==R_EDX
1190 || b
==R_EBP
|| b
==R_ESP
|| b
==R_ESI
|| b
==R_EDI
)
1191 return (addrbits
==16);
1193 return (addrbits
==32);