1 /* assemble.c code generation for the Netwide Assembler
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.
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
15 * \10, \11, \12 - a literal byte follows in the code stream, to be added
16 * to the register value of operand 0, 1 or 2
17 * \17 - encodes the literal byte 0. (Some compilers don't take
18 * kindly to a zero byte in the _middle_ of a compile time
19 * string constant, so I had to put this hack in.)
20 * \14, \15, \16 - a signed byte immediate operand, from operand 0, 1 or 2
21 * \20, \21, \22 - a byte immediate operand, from operand 0, 1 or 2
22 * \24, \25, \26 - an unsigned byte immediate operand, from operand 0, 1 or 2
23 * \30, \31, \32 - a word immediate operand, from operand 0, 1 or 2
24 * \34, \35, \36 - select between \3[012] and \4[012] depending on 16/32 bit
25 * assembly mode or the address-size override on the operand
26 * \37 - a word constant, from the _segment_ part of operand 0
27 * \40, \41, \42 - a long immediate operand, from operand 0, 1 or 2
28 * \50, \51, \52 - a byte relative operand, from operand 0, 1 or 2
29 * \60, \61, \62 - a word relative operand, from operand 0, 1 or 2
30 * \64, \65, \66 - select between \6[012] and \7[012] depending on 16/32 bit
31 * assembly mode or the address-size override on the operand
32 * \70, \71, \72 - a long relative operand, from operand 0, 1 or 2
33 * \1ab - a ModRM, calculated on EA in operand a, with the spare
34 * field the register value of operand b.
35 * \2ab - a ModRM, calculated on EA in operand a, with the spare
36 * field equal to digit b.
37 * \30x - might be an 0x67 byte, depending on the address size of
38 * the memory reference in operand x.
39 * \310 - indicates fixed 16-bit address size, i.e. optional 0x67.
40 * \311 - indicates fixed 32-bit address size, i.e. optional 0x67.
41 * \320 - indicates fixed 16-bit operand size, i.e. optional 0x66.
42 * \321 - indicates fixed 32-bit operand size, i.e. optional 0x66.
43 * \322 - indicates that this instruction is only valid when the
44 * operand size is the default (instruction to disassembler,
45 * generates no code in the assembler)
46 * \330 - a literal byte follows in the code stream, to be added
47 * to the condition code value of the instruction.
48 * \340 - reserve <operand 0> bytes of uninitialised storage.
49 * Operand 0 had better be a segmentless constant.
60 extern struct itemplate
*nasm_instructions
[];
63 int sib_present
; /* is a SIB byte necessary? */
64 int bytes
; /* # of bytes of offset needed */
65 int size
; /* lazy - this is sib+bytes+1 */
66 unsigned char modrm
, sib
; /* the bytes themselves */
70 static struct ofmt
*outfmt
;
73 static long calcsize (long, long, int, insn
*, char *);
74 static void gencode (long, long, int, insn
*, char *, long);
75 static int regval (operand
*o
);
76 static int matches (struct itemplate
*, insn
*);
77 static ea
* process_ea (operand
*, ea
*, int, int, int);
78 static int chsize (operand
*, int);
81 * This routine wrappers the real output format's output routine,
82 * in order to pass a copy of the data off to the listing file
83 * generator at the same time.
85 static void out (long offset
, long segto
, void *data
, unsigned long type
,
86 long segment
, long wrt
)
91 if ((type
& OUT_TYPMASK
) == OUT_ADDRESS
) {
92 if (segment
!= NO_SEG
|| wrt
!= NO_SEG
) {
94 * This address is relocated. We must write it as
95 * OUT_ADDRESS, so there's no work to be done here.
97 list
->output (offset
, data
, type
);
100 unsigned char p
[4], *q
= p
;
102 * This is a non-relocated address, and we're going to
103 * convert it into RAWDATA format.
105 if ((type
& OUT_SIZMASK
) == 4) {
106 WRITELONG (q
, * (long *) data
);
107 list
->output (offset
, p
, OUT_RAWDATA
+4);
110 WRITESHORT (q
, * (long *) data
);
111 list
->output (offset
, p
, OUT_RAWDATA
+2);
115 else if ((type
& OUT_TYPMASK
) == OUT_RAWDATA
) {
116 list
->output (offset
, data
, type
);
118 else if ((type
& OUT_TYPMASK
) == OUT_RESERVE
) {
119 list
->output (offset
, NULL
, type
);
121 else if ((type
& OUT_TYPMASK
) == OUT_REL2ADR
||
122 (type
& OUT_TYPMASK
) == OUT_REL4ADR
) {
123 list
->output (offset
, data
, type
);
126 if (src_get(&lineno
,&lnfname
))
127 outfmt
->current_dfmt
->linenum(lnfname
,lineno
,segto
);
129 outfmt
->output (segto
, data
, type
, segment
, wrt
);
132 long assemble (long segment
, long offset
, int bits
,
133 insn
*instruction
, struct ofmt
*output
, efunc error
,
136 struct itemplate
*temp
;
142 long wsize
= 0; /* size for DB etc. */
144 errfunc
= error
; /* to pass to other functions */
145 outfmt
= output
; /* likewise */
146 list
= listgen
; /* and again */
148 switch (instruction
->opcode
)
151 case I_DB
: wsize
= 1; break;
152 case I_DW
: wsize
= 2; break;
153 case I_DD
: wsize
= 4; break;
154 case I_DQ
: wsize
= 8; break;
155 case I_DT
: wsize
= 10; break;
160 long t
= instruction
->times
;
162 errfunc(ERR_PANIC
, "instruction->times < 0 (%ld) in assemble()",t
);
164 while (t
--) /* repeat TIMES times */
166 for (e
= instruction
->eops
; e
; e
= e
->next
)
168 if (e
->type
== EOT_DB_NUMBER
)
171 if (e
->segment
!= NO_SEG
)
172 errfunc (ERR_NONFATAL
,
173 "one-byte relocation attempted");
175 out (offset
, segment
, &e
->offset
, OUT_RAWDATA
+1,
179 else if (wsize
> 5) {
180 errfunc (ERR_NONFATAL
, "integer supplied to a D%c"
181 " instruction", wsize
==8 ? 'Q' : 'T');
184 out (offset
, segment
, &e
->offset
,
185 OUT_ADDRESS
+wsize
, e
->segment
,
189 else if (e
->type
== EOT_DB_STRING
)
193 out (offset
, segment
, e
->stringval
,
194 OUT_RAWDATA
+e
->stringlen
, NO_SEG
, NO_SEG
);
195 align
= e
->stringlen
% wsize
;
198 align
= wsize
- align
;
199 out (offset
, segment
, "\0\0\0\0\0\0\0\0",
200 OUT_RAWDATA
+align
, NO_SEG
, NO_SEG
);
202 offset
+= e
->stringlen
+ align
;
205 if (t
> 0 && t
== instruction
->times
-1)
208 * Dummy call to list->output to give the offset to the
211 list
->output (offset
, NULL
, OUT_RAWDATA
);
212 list
->uplevel (LIST_TIMES
);
215 if (instruction
->times
> 1)
216 list
->downlevel (LIST_TIMES
);
217 return offset
- start
;
220 if (instruction
->opcode
== I_INCBIN
)
222 static char fname
[FILENAME_MAX
];
226 len
= FILENAME_MAX
-1;
227 if (len
> instruction
->eops
->stringlen
)
228 len
= instruction
->eops
->stringlen
;
229 strncpy (fname
, instruction
->eops
->stringval
, len
);
232 if ( (fp
= fopen(fname
, "rb")) == NULL
)
233 error (ERR_NONFATAL
, "`incbin': unable to open file `%s'", fname
);
234 else if (fseek(fp
, 0L, SEEK_END
) < 0)
235 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 base
= instruction
->eops
->next
->offset
;
247 if (instruction
->eops
->next
->next
&&
248 len
> instruction
->eops
->next
->next
->offset
)
249 len
= instruction
->eops
->next
->next
->offset
;
252 * Dummy call to list->output to give the offset to the
255 list
->output (offset
, NULL
, OUT_RAWDATA
);
256 list
->uplevel(LIST_INCBIN
);
261 fseek (fp
, base
, SEEK_SET
);
264 long m
= fread (buf
, 1, (l
>sizeof(buf
)?sizeof(buf
):l
),
268 * This shouldn't happen unless the file
269 * actually changes while we are reading
272 error (ERR_NONFATAL
, "`incbin': unexpected EOF while"
273 " reading file `%s'", fname
);
274 t
=0; /* Try to exit cleanly */
277 out (offset
, segment
, buf
, OUT_RAWDATA
+m
,
282 list
->downlevel(LIST_INCBIN
);
283 if (instruction
->times
> 1) {
285 * Dummy call to list->output to give the offset to the
288 list
->output (offset
, NULL
, OUT_RAWDATA
);
289 list
->uplevel(LIST_TIMES
);
290 list
->downlevel(LIST_TIMES
);
293 return instruction
->times
* len
;
295 return 0; /* if we're here, there's an error */
299 temp
= nasm_instructions
[instruction
->opcode
];
300 while (temp
->opcode
!= -1) {
301 int m
= matches (temp
, instruction
);
303 if (m
== 100) /* matches! */
305 char *codes
= temp
->code
;
306 long insn_size
= calcsize(segment
, offset
, bits
,
308 itimes
= instruction
->times
;
309 if (insn_size
< 0) /* shouldn't be, on pass two */
310 error (ERR_PANIC
, "errors made it through from pass one");
311 else while (itimes
--) {
312 insn_end
= offset
+ insn_size
;
313 for (j
=0; j
<instruction
->nprefix
; j
++) {
315 switch (instruction
->prefixes
[j
]) {
318 case P_REPNE
: case P_REPNZ
:
320 case P_REPE
: case P_REPZ
: case P_REP
:
322 case R_CS
: c
= 0x2E; break;
323 case R_DS
: c
= 0x3E; break;
324 case R_ES
: c
= 0x26; break;
325 case R_FS
: c
= 0x64; break;
326 case R_GS
: c
= 0x65; break;
327 case R_SS
: c
= 0x36; break;
346 "invalid instruction prefix");
349 out (offset
, segment
, &c
, OUT_RAWDATA
+1,
354 gencode (segment
, offset
, bits
, instruction
, codes
, insn_end
);
356 if (itimes
> 0 && itimes
== instruction
->times
-1) {
358 * Dummy call to list->output to give the offset to the
361 list
->output (offset
, NULL
, OUT_RAWDATA
);
362 list
->uplevel (LIST_TIMES
);
365 if (instruction
->times
> 1)
366 list
->downlevel (LIST_TIMES
);
367 return offset
- start
;
374 if (temp
->opcode
== -1) { /* didn't match any instruction */
375 if (size_prob
== 1) /* would have matched, but for size */
376 error (ERR_NONFATAL
, "operation size not specified");
377 else if (size_prob
== 2)
378 error (ERR_NONFATAL
, "mismatch in operand sizes");
381 "invalid combination of opcode and operands");
386 long insn_size (long segment
, long offset
, int bits
,
387 insn
*instruction
, efunc error
)
389 struct itemplate
*temp
;
391 errfunc
= error
; /* to pass to other functions */
393 if (instruction
->opcode
== -1)
396 if (instruction
->opcode
== I_DB
||
397 instruction
->opcode
== I_DW
||
398 instruction
->opcode
== I_DD
||
399 instruction
->opcode
== I_DQ
||
400 instruction
->opcode
== I_DT
)
403 long isize
, osize
, wsize
= 0; /* placate gcc */
406 switch (instruction
->opcode
)
408 case I_DB
: wsize
= 1; break;
409 case I_DW
: wsize
= 2; break;
410 case I_DD
: wsize
= 4; break;
411 case I_DQ
: wsize
= 8; break;
412 case I_DT
: wsize
= 10; break;
415 for (e
= instruction
->eops
; e
; e
= e
->next
)
420 if (e
->type
== EOT_DB_NUMBER
)
422 else if (e
->type
== EOT_DB_STRING
)
423 osize
= e
->stringlen
;
425 align
= (-osize
) % wsize
;
428 isize
+= osize
+ align
;
430 return isize
* instruction
->times
;
433 if (instruction
->opcode
== I_INCBIN
)
435 char fname
[FILENAME_MAX
];
439 len
= FILENAME_MAX
-1;
440 if (len
> instruction
->eops
->stringlen
)
441 len
= instruction
->eops
->stringlen
;
442 strncpy (fname
, instruction
->eops
->stringval
, len
);
444 if ( (fp
= fopen(fname
, "rb")) == NULL
)
445 error (ERR_NONFATAL
, "`incbin': unable to open file `%s'", fname
);
446 else if (fseek(fp
, 0L, SEEK_END
) < 0)
447 error (ERR_NONFATAL
, "`incbin': unable to seek on file `%s'",
453 if (instruction
->eops
->next
)
455 len
-= instruction
->eops
->next
->offset
;
456 if (instruction
->eops
->next
->next
&&
457 len
> instruction
->eops
->next
->next
->offset
)
459 len
= instruction
->eops
->next
->next
->offset
;
462 return instruction
->times
* len
;
464 return 0; /* if we're here, there's an error */
467 temp
= nasm_instructions
[instruction
->opcode
];
468 while (temp
->opcode
!= -1) {
469 if (matches(temp
, instruction
) == 100) {
470 /* we've matched an instruction. */
472 char * codes
= temp
->code
;
475 isize
= calcsize(segment
, offset
, bits
, instruction
, codes
);
478 for (j
= 0; j
< instruction
->nprefix
; j
++)
480 if ((instruction
->prefixes
[j
] != P_A16
&&
481 instruction
->prefixes
[j
] != P_O16
&& bits
==16) ||
482 (instruction
->prefixes
[j
] != P_A32
&&
483 instruction
->prefixes
[j
] != P_O32
&& bits
==32))
488 return isize
* instruction
->times
;
492 return -1; /* didn't match any instruction */
495 static long calcsize (long segment
, long offset
, int bits
,
496 insn
*ins
, char *codes
)
501 (void) segment
; /* Don't warn that this parameter is unused */
502 (void) offset
; /* Don't warn that this parameter is unused */
504 while (*codes
) switch (c
= *codes
++) {
505 case 01: case 02: case 03:
506 codes
+= c
, length
+= c
; break;
507 case 04: case 05: case 06: case 07:
509 case 010: case 011: case 012:
510 codes
++, length
++; break;
513 case 014: case 015: case 016:
515 case 020: case 021: case 022:
517 case 024: case 025: case 026:
519 case 030: case 031: case 032:
521 case 034: case 035: case 036:
522 length
+= ((ins
->oprs
[c
-034].addr_size
?
523 ins
->oprs
[c
-034].addr_size
: bits
) == 16 ? 2 : 4); break;
526 case 040: case 041: case 042:
528 case 050: case 051: case 052:
530 case 060: case 061: case 062:
532 case 064: case 065: case 066:
533 length
+= ((ins
->oprs
[c
-064].addr_size
?
534 ins
->oprs
[c
-064].addr_size
: bits
) == 16 ? 2 : 4); break;
535 case 070: case 071: case 072:
537 case 0300: case 0301: case 0302:
538 length
+= chsize (&ins
->oprs
[c
-0300], bits
);
541 length
+= (bits
==32);
544 length
+= (bits
==16);
549 length
+= (bits
==32);
552 length
+= (bits
==16);
557 codes
++, length
++; break;
558 case 0340: case 0341: case 0342:
559 if (ins
->oprs
[0].segment
!= NO_SEG
)
560 errfunc (ERR_NONFATAL
, "attempt to reserve non-constant"
561 " quantity of BSS space");
563 length
+= ins
->oprs
[0].offset
<< (c
-0340);
565 default: /* can't do it by 'case' statements */
566 if (c
>=0100 && c
<=0277) { /* it's an EA */
568 if (!process_ea (&ins
->oprs
[(c
>>3)&7], &ea_data
, bits
, 0,
570 errfunc (ERR_NONFATAL
, "invalid effective address");
573 length
+= ea_data
.size
;
575 errfunc (ERR_PANIC
, "internal instruction table corrupt"
576 ": instruction code 0x%02X given", c
);
581 static void gencode (long segment
, long offset
, int bits
,
582 insn
*ins
, char *codes
, long insn_end
)
584 static char condval
[] = { /* conditional opcodes */
585 0x7, 0x3, 0x2, 0x6, 0x2, 0x4, 0xF, 0xD, 0xC, 0xE, 0x6, 0x2,
586 0x3, 0x7, 0x3, 0x5, 0xE, 0xC, 0xD, 0xF, 0x1, 0xB, 0x9, 0x5,
587 0x0, 0xA, 0xA, 0xB, 0x8, 0x4
590 unsigned char bytes
[4];
594 switch (c
= *codes
++)
596 case 01: case 02: case 03:
597 out (offset
, segment
, codes
, OUT_RAWDATA
+c
, NO_SEG
, NO_SEG
);
603 switch (ins
->oprs
[0].basereg
)
606 bytes
[0] = 0x0E + (c
== 0x04 ? 1 : 0); break;
608 bytes
[0] = 0x1E + (c
== 0x04 ? 1 : 0); break;
610 bytes
[0] = 0x06 + (c
== 0x04 ? 1 : 0); break;
612 bytes
[0] = 0x16 + (c
== 0x04 ? 1 : 0); break;
614 errfunc (ERR_PANIC
, "bizarre 8086 segment register received");
616 out (offset
, segment
, bytes
, OUT_RAWDATA
+1, NO_SEG
, NO_SEG
);
621 switch (ins
->oprs
[0].basereg
) {
622 case R_FS
: bytes
[0] = 0xA0 + (c
== 0x05 ? 1 : 0); break;
623 case R_GS
: bytes
[0] = 0xA8 + (c
== 0x05 ? 1 : 0); break;
625 errfunc (ERR_PANIC
, "bizarre 386 segment register received");
627 out (offset
, segment
, bytes
, OUT_RAWDATA
+1, NO_SEG
, NO_SEG
);
631 case 010: case 011: case 012:
632 bytes
[0] = *codes
++ + regval(&ins
->oprs
[c
-010]);
633 out (offset
, segment
, bytes
, OUT_RAWDATA
+1, NO_SEG
, NO_SEG
);
639 out (offset
, segment
, bytes
, OUT_RAWDATA
+1, NO_SEG
, NO_SEG
);
643 case 014: case 015: case 016:
644 if (ins
->oprs
[c
-014].offset
< -128
645 || ins
->oprs
[c
-014].offset
> 127)
647 errfunc (ERR_WARNING
, "signed byte value exceeds bounds");
650 if (ins
->oprs
[c
-014].segment
!= NO_SEG
)
652 data
= ins
->oprs
[c
-014].offset
;
653 out (offset
, segment
, &data
, OUT_ADDRESS
+1,
654 ins
->oprs
[c
-014].segment
, ins
->oprs
[c
-014].wrt
);
657 bytes
[0] = ins
->oprs
[c
-014].offset
;
658 out (offset
, segment
, bytes
, OUT_RAWDATA
+1, NO_SEG
, NO_SEG
);
663 case 020: case 021: case 022:
664 if (ins
->oprs
[c
-020].offset
< -256
665 || ins
->oprs
[c
-020].offset
> 255)
667 errfunc (ERR_WARNING
, "byte value exceeds bounds");
669 if (ins
->oprs
[c
-020].segment
!= NO_SEG
) {
670 data
= ins
->oprs
[c
-020].offset
;
671 out (offset
, segment
, &data
, OUT_ADDRESS
+1,
672 ins
->oprs
[c
-020].segment
, ins
->oprs
[c
-020].wrt
);
675 bytes
[0] = ins
->oprs
[c
-020].offset
;
676 out (offset
, segment
, bytes
, OUT_RAWDATA
+1, NO_SEG
, NO_SEG
);
681 case 024: case 025: case 026:
682 if (ins
->oprs
[c
-024].offset
< 0 || ins
->oprs
[c
-024].offset
> 255)
683 errfunc (ERR_WARNING
, "unsigned byte value exceeds bounds");
684 if (ins
->oprs
[c
-024].segment
!= NO_SEG
) {
685 data
= ins
->oprs
[c
-024].offset
;
686 out (offset
, segment
, &data
, OUT_ADDRESS
+1,
687 ins
->oprs
[c
-024].segment
, ins
->oprs
[c
-024].wrt
);
690 bytes
[0] = ins
->oprs
[c
-024].offset
;
691 out (offset
, segment
, bytes
, OUT_RAWDATA
+1, NO_SEG
, NO_SEG
);
696 case 030: case 031: case 032:
697 if (ins
->oprs
[c
-030].segment
== NO_SEG
&&
698 ins
->oprs
[c
-030].wrt
== NO_SEG
&&
699 (ins
->oprs
[c
-030].offset
< -65536L ||
700 ins
->oprs
[c
-030].offset
> 65535L))
702 errfunc (ERR_WARNING
, "word value exceeds bounds");
704 data
= ins
->oprs
[c
-030].offset
;
705 out (offset
, segment
, &data
, OUT_ADDRESS
+2,
706 ins
->oprs
[c
-030].segment
, ins
->oprs
[c
-030].wrt
);
710 case 034: case 035: case 036:
711 data
= ins
->oprs
[c
-034].offset
;
712 size
= ((ins
->oprs
[c
-034].addr_size
?
713 ins
->oprs
[c
-034].addr_size
: bits
) == 16 ? 2 : 4);
714 if (size
==16 && (data
< -65536L || data
> 65535L))
715 errfunc (ERR_WARNING
, "word value exceeds bounds");
716 out (offset
, segment
, &data
, OUT_ADDRESS
+size
,
717 ins
->oprs
[c
-034].segment
, ins
->oprs
[c
-034].wrt
);
722 if (ins
->oprs
[0].segment
== NO_SEG
)
723 errfunc (ERR_NONFATAL
, "value referenced by FAR is not"
726 out (offset
, segment
, &data
, OUT_ADDRESS
+2,
727 outfmt
->segbase(1+ins
->oprs
[0].segment
),
732 case 040: case 041: case 042:
733 data
= ins
->oprs
[c
-040].offset
;
734 out (offset
, segment
, &data
, OUT_ADDRESS
+4,
735 ins
->oprs
[c
-040].segment
, ins
->oprs
[c
-040].wrt
);
739 case 050: case 051: case 052:
740 if (ins
->oprs
[c
-050].segment
!= segment
)
741 errfunc (ERR_NONFATAL
, "short relative jump outside segment");
742 data
= ins
->oprs
[c
-050].offset
- insn_end
;
743 if (data
> 127 || data
< -128)
744 errfunc (ERR_NONFATAL
, "short jump is out of range");
746 out (offset
, segment
, bytes
, OUT_RAWDATA
+1, NO_SEG
, NO_SEG
);
750 case 060: case 061: case 062:
751 if (ins
->oprs
[c
-060].segment
!= segment
) {
752 data
= ins
->oprs
[c
-060].offset
;
753 out (offset
, segment
, &data
, OUT_REL2ADR
+insn_end
-offset
,
754 ins
->oprs
[c
-060].segment
, ins
->oprs
[c
-060].wrt
);
756 data
= ins
->oprs
[c
-060].offset
- insn_end
;
757 out (offset
, segment
, &data
,
758 OUT_ADDRESS
+2, NO_SEG
, NO_SEG
);
763 case 064: case 065: case 066:
764 size
= ((ins
->oprs
[c
-064].addr_size
?
765 ins
->oprs
[c
-064].addr_size
: bits
) == 16 ? 2 : 4);
766 if (ins
->oprs
[c
-064].segment
!= segment
) {
767 data
= ins
->oprs
[c
-064].offset
;
768 size
= (bits
== 16 ? OUT_REL2ADR
: OUT_REL4ADR
);
769 out (offset
, segment
, &data
, size
+insn_end
-offset
,
770 ins
->oprs
[c
-064].segment
, ins
->oprs
[c
-064].wrt
);
771 size
= (bits
== 16 ? 2 : 4);
773 data
= ins
->oprs
[c
-064].offset
- insn_end
;
774 out (offset
, segment
, &data
,
775 OUT_ADDRESS
+size
, NO_SEG
, NO_SEG
);
780 case 070: case 071: case 072:
781 if (ins
->oprs
[c
-070].segment
!= segment
) {
782 data
= ins
->oprs
[c
-070].offset
;
783 out (offset
, segment
, &data
, OUT_REL4ADR
+insn_end
-offset
,
784 ins
->oprs
[c
-070].segment
, ins
->oprs
[c
-070].wrt
);
786 data
= ins
->oprs
[c
-070].offset
- insn_end
;
787 out (offset
, segment
, &data
,
788 OUT_ADDRESS
+4, NO_SEG
, NO_SEG
);
793 case 0300: case 0301: case 0302:
794 if (chsize (&ins
->oprs
[c
-0300], bits
)) {
796 out (offset
, segment
, bytes
,
797 OUT_RAWDATA
+1, NO_SEG
, NO_SEG
);
806 out (offset
, segment
, bytes
,
807 OUT_RAWDATA
+1, NO_SEG
, NO_SEG
);
816 out (offset
, segment
, bytes
,
817 OUT_RAWDATA
+1, NO_SEG
, NO_SEG
);
829 out (offset
, segment
, bytes
,
830 OUT_RAWDATA
+1, NO_SEG
, NO_SEG
);
839 out (offset
, segment
, bytes
,
840 OUT_RAWDATA
+1, NO_SEG
, NO_SEG
);
850 *bytes
= *codes
++ + condval
[ins
->condition
];
851 out (offset
, segment
, bytes
,
852 OUT_RAWDATA
+1, NO_SEG
, NO_SEG
);
856 case 0340: case 0341: case 0342:
857 if (ins
->oprs
[0].segment
!= NO_SEG
)
858 errfunc (ERR_PANIC
, "non-constant BSS size in pass two");
860 long size
= ins
->oprs
[0].offset
<< (c
-0340);
862 out (offset
, segment
, NULL
,
863 OUT_RESERVE
+size
, NO_SEG
, NO_SEG
);
868 default: /* can't do it by 'case' statements */
869 if (c
>=0100 && c
<=0277) { /* it's an EA */
875 if (c
<=0177) /* pick rfield from operand b */
876 rfield
= regval (&ins
->oprs
[c
&7]);
877 else /* rfield is constant */
880 if (!process_ea (&ins
->oprs
[(c
>>3)&7], &ea_data
, bits
, rfield
,
883 errfunc (ERR_NONFATAL
, "invalid effective address");
887 *p
++ = ea_data
.modrm
;
888 if (ea_data
.sib_present
)
892 out (offset
, segment
, bytes
, OUT_RAWDATA
+ s
,
895 switch (ea_data
.bytes
) {
899 if (ins
->oprs
[(c
>>3)&7].segment
!= NO_SEG
) {
900 data
= ins
->oprs
[(c
>>3)&7].offset
;
901 out (offset
, segment
, &data
, OUT_ADDRESS
+1,
902 ins
->oprs
[(c
>>3)&7].segment
,
903 ins
->oprs
[(c
>>3)&7].wrt
);
905 *bytes
= ins
->oprs
[(c
>>3)&7].offset
;
906 out (offset
, segment
, bytes
, OUT_RAWDATA
+1,
913 data
= ins
->oprs
[(c
>>3)&7].offset
;
914 out (offset
, segment
, &data
,
915 OUT_ADDRESS
+ea_data
.bytes
,
916 ins
->oprs
[(c
>>3)&7].segment
, ins
->oprs
[(c
>>3)&7].wrt
);
922 errfunc (ERR_PANIC
, "internal instruction table corrupt"
923 ": instruction code 0x%02X given", c
);
927 static int regval (operand
*o
)
929 switch (o
->basereg
) {
930 case R_EAX
: case R_AX
: case R_AL
: case R_ES
: case R_CR0
: case R_DR0
:
931 case R_ST0
: case R_MM0
:
933 case R_ECX
: case R_CX
: case R_CL
: case R_CS
: case R_DR1
: case R_ST1
:
936 case R_EDX
: case R_DX
: case R_DL
: case R_SS
: case R_CR2
: case R_DR2
:
937 case R_ST2
: case R_MM2
:
939 case R_EBX
: case R_BX
: case R_BL
: case R_DS
: case R_CR3
: case R_DR3
:
940 case R_TR3
: case R_ST3
: case R_MM3
:
942 case R_ESP
: case R_SP
: case R_AH
: case R_FS
: case R_CR4
: case R_TR4
:
943 case R_ST4
: case R_MM4
:
945 case R_EBP
: case R_BP
: case R_CH
: case R_GS
: case R_TR5
: case R_ST5
:
948 case R_ESI
: case R_SI
: case R_DH
: case R_DR6
: case R_TR6
: case R_ST6
:
951 case R_EDI
: case R_DI
: case R_BH
: case R_DR7
: case R_TR7
: case R_ST7
:
955 errfunc (ERR_PANIC
, "invalid register operand given to regval()");
960 static int matches (struct itemplate
*itemp
, insn
*instruction
)
962 int i
, size
, oprs
, ret
;
969 if (itemp
->opcode
!= instruction
->opcode
) return 0;
974 if (itemp
->operands
!= instruction
->operands
) return 0;
977 * Check that no spurious colons or TOs are present
979 for (i
=0; i
<itemp
->operands
; i
++)
980 if (instruction
->oprs
[i
].type
& ~itemp
->opd
[i
] & (COLON
|TO
))
984 * Check that the operand flags all match up
986 for (i
=0; i
<itemp
->operands
; i
++)
987 if (itemp
->opd
[i
] & ~instruction
->oprs
[i
].type
||
988 ((itemp
->opd
[i
] & SIZE_MASK
) &&
989 ((itemp
->opd
[i
] ^ instruction
->oprs
[i
].type
) & SIZE_MASK
)))
991 if ((itemp
->opd
[i
] & ~instruction
->oprs
[i
].type
& NON_SIZE
) ||
992 (instruction
->oprs
[i
].type
& SIZE_MASK
))
999 * Check operand sizes
1001 if (itemp
->flags
& IF_SB
) {
1003 oprs
= itemp
->operands
;
1004 } else if (itemp
->flags
& IF_SW
) {
1006 oprs
= itemp
->operands
;
1007 } else if (itemp
->flags
& IF_SD
) {
1009 oprs
= itemp
->operands
;
1010 } else if (itemp
->flags
& (IF_SM
| IF_SM2
)) {
1011 oprs
= (itemp
->flags
& IF_SM2
? 2 : itemp
->operands
);
1012 size
= 0; /* placate gcc */
1013 for (i
=0; i
<oprs
; i
++)
1014 if ( (size
= itemp
->opd
[i
] & SIZE_MASK
) != 0)
1018 oprs
= itemp
->operands
;
1021 for (i
=0; i
<itemp
->operands
; i
++)
1022 if (!(itemp
->opd
[i
] & SIZE_MASK
) &&
1023 (instruction
->oprs
[i
].type
& SIZE_MASK
& ~size
))
1029 static ea
*process_ea (operand
*input
, ea
*output
, int addrbits
, int rfield
,
1032 if (!(REGISTER
& ~input
->type
)) { /* it's a single register */
1033 static int regs
[] = {
1034 R_MM0
, R_EAX
, R_AX
, R_AL
, R_MM1
, R_ECX
, R_CX
, R_CL
,
1035 R_MM2
, R_EDX
, R_DX
, R_DL
, R_MM3
, R_EBX
, R_BX
, R_BL
,
1036 R_MM4
, R_ESP
, R_SP
, R_AH
, R_MM5
, R_EBP
, R_BP
, R_CH
,
1037 R_MM6
, R_ESI
, R_SI
, R_DH
, R_MM7
, R_EDI
, R_DI
, R_BH
1041 for (i
=0; i
<elements(regs
); i
++)
1042 if (input
->basereg
== regs
[i
]) break;
1043 if (i
<elements(regs
)) {
1044 output
->sib_present
= FALSE
;/* no SIB necessary */
1045 output
->bytes
= 0; /* no offset necessary either */
1046 output
->modrm
= 0xC0 | (rfield
<< 3) | (i
/4);
1050 } else { /* it's a memory reference */
1051 if (input
->basereg
==-1 && (input
->indexreg
==-1 || input
->scale
==0)) {
1052 /* it's a pure offset */
1053 if (input
->addr_size
)
1054 addrbits
= input
->addr_size
;
1055 output
->sib_present
= FALSE
;
1056 output
->bytes
= (addrbits
==32 ? 4 : 2);
1057 output
->modrm
= (addrbits
==32 ? 5 : 6) | (rfield
<< 3);
1059 else { /* it's an indirection */
1060 int i
=input
->indexreg
, b
=input
->basereg
, s
=input
->scale
;
1061 long o
=input
->offset
, seg
=input
->segment
;
1062 int hb
=input
->hintbase
, ht
=input
->hinttype
;
1065 if (s
==0) i
= -1; /* make this easy, at least */
1067 if (i
==R_EAX
|| i
==R_EBX
|| i
==R_ECX
|| i
==R_EDX
1068 || i
==R_EBP
|| i
==R_ESP
|| i
==R_ESI
|| i
==R_EDI
1069 || b
==R_EAX
|| b
==R_EBX
|| b
==R_ECX
|| b
==R_EDX
1070 || b
==R_EBP
|| b
==R_ESP
|| b
==R_ESI
|| b
==R_EDI
) {
1071 /* it must be a 32-bit memory reference. Firstly we have
1072 * to check that all registers involved are type Exx. */
1073 if (i
!=-1 && i
!=R_EAX
&& i
!=R_EBX
&& i
!=R_ECX
&& i
!=R_EDX
1074 && i
!=R_EBP
&& i
!=R_ESP
&& i
!=R_ESI
&& i
!=R_EDI
)
1076 if (b
!=-1 && b
!=R_EAX
&& b
!=R_EBX
&& b
!=R_ECX
&& b
!=R_EDX
1077 && b
!=R_EBP
&& b
!=R_ESP
&& b
!=R_ESI
&& b
!=R_EDI
)
1080 /* While we're here, ensure the user didn't specify WORD. */
1081 if (input
->addr_size
== 16)
1084 /* now reorganise base/index */
1085 if (s
== 1 && b
!= i
&& b
!= -1 && i
!= -1 &&
1086 ((hb
==b
&&ht
==EAH_NOTBASE
) || (hb
==i
&&ht
==EAH_MAKEBASE
)))
1087 t
= b
, b
= i
, i
= t
; /* swap if hints say so */
1088 if (b
==i
) /* convert EAX+2*EAX to 3*EAX */
1090 if (b
==-1 && s
==1 && !(hb
== i
&& ht
== EAH_NOTBASE
))
1091 b
= i
, i
= -1; /* make single reg base, unless hint */
1092 if (((s
==2 && i
!=R_ESP
&& !(input
->eaflags
& EAF_TIMESTWO
)) ||
1093 s
==3 || s
==5 || s
==9) && b
==-1)
1094 b
= i
, s
--; /* convert 3*EAX to EAX+2*EAX */
1095 if (s
==1 && i
==R_ESP
) /* swap ESP into base if scale is 1 */
1097 if (i
==R_ESP
|| (s
!=1 && s
!=2 && s
!=4 && s
!=8 && i
!=-1))
1098 return NULL
; /* wrong, for various reasons */
1100 if (i
==-1 && b
!=R_ESP
) {/* no SIB needed */
1103 case R_EAX
: rm
= 0; break;
1104 case R_ECX
: rm
= 1; break;
1105 case R_EDX
: rm
= 2; break;
1106 case R_EBX
: rm
= 3; break;
1107 case R_EBP
: rm
= 5; break;
1108 case R_ESI
: rm
= 6; break;
1109 case R_EDI
: rm
= 7; break;
1110 case -1: rm
= 5; break;
1111 default: /* should never happen */
1114 if (b
==-1 || (b
!=R_EBP
&& o
==0 &&
1115 seg
==NO_SEG
&& !forw_ref
&&
1117 (EAF_BYTEOFFS
|EAF_WORDOFFS
))))
1119 else if (input
->eaflags
& EAF_BYTEOFFS
||
1120 (o
>=-128 && o
<=127 && seg
==NO_SEG
&& !forw_ref
&&
1121 !(input
->eaflags
& EAF_WORDOFFS
))) {
1127 output
->sib_present
= FALSE
;
1128 output
->bytes
= (b
==-1 || mod
==2 ? 4 : mod
);
1129 output
->modrm
= (mod
<<6) | (rfield
<<3) | rm
;
1131 else { /* we need a SIB */
1132 int mod
, scale
, index
, base
;
1135 case R_EAX
: base
= 0; break;
1136 case R_ECX
: base
= 1; break;
1137 case R_EDX
: base
= 2; break;
1138 case R_EBX
: base
= 3; break;
1139 case R_ESP
: base
= 4; break;
1140 case R_EBP
: case -1: base
= 5; break;
1141 case R_ESI
: base
= 6; break;
1142 case R_EDI
: base
= 7; break;
1143 default: /* then what the smeg is it? */
1144 return NULL
; /* panic */
1148 case R_EAX
: index
= 0; break;
1149 case R_ECX
: index
= 1; break;
1150 case R_EDX
: index
= 2; break;
1151 case R_EBX
: index
= 3; break;
1152 case -1: index
= 4; break;
1153 case R_EBP
: index
= 5; break;
1154 case R_ESI
: index
= 6; break;
1155 case R_EDI
: index
= 7; break;
1156 default: /* then what the smeg is it? */
1157 return NULL
; /* panic */
1162 case 1: scale
= 0; break;
1163 case 2: scale
= 1; break;
1164 case 4: scale
= 2; break;
1165 case 8: scale
= 3; break;
1166 default: /* then what the smeg is it? */
1167 return NULL
; /* panic */
1170 if (b
==-1 || (b
!=R_EBP
&& o
==0 &&
1171 seg
==NO_SEG
&& !forw_ref
&&
1173 (EAF_BYTEOFFS
|EAF_WORDOFFS
))))
1175 else if (input
->eaflags
& EAF_BYTEOFFS
||
1176 (o
>=-128 && o
<=127 && seg
==NO_SEG
&& !forw_ref
&&
1177 !(input
->eaflags
& EAF_WORDOFFS
)))
1182 output
->sib_present
= TRUE
;
1183 output
->bytes
= (b
==-1 || mod
==2 ? 4 : mod
);
1184 output
->modrm
= (mod
<<6) | (rfield
<<3) | 4;
1185 output
->sib
= (scale
<<6) | (index
<<3) | base
;
1188 else { /* it's 16-bit */
1191 /* check all registers are BX, BP, SI or DI */
1192 if ((b
!=-1 && b
!=R_BP
&& b
!=R_BX
&& b
!=R_SI
&& b
!=R_DI
) ||
1193 (i
!=-1 && i
!=R_BP
&& i
!=R_BX
&& i
!=R_SI
&& i
!=R_DI
))
1196 /* ensure the user didn't specify DWORD */
1197 if (input
->addr_size
== 32)
1200 if (s
!=1 && i
!=-1) return NULL
;/* no can do, in 16-bit EA */
1201 if (b
==-1 && i
!=-1) b
^= i
^= b
^= i
; /* swap them round */
1202 if ((b
==R_SI
|| b
==R_DI
) && i
!=-1)
1203 b
^= i
^= b
^= i
; /* have BX/BP as base, SI/DI index */
1204 if (b
==i
) return NULL
;/* shouldn't ever happen, in theory */
1205 if (i
!=-1 && b
!=-1 &&
1206 (i
==R_BP
|| i
==R_BX
|| b
==R_SI
|| b
==R_DI
))
1207 return NULL
; /* invalid combinations */
1208 if (b
==-1) /* pure offset: handled above */
1209 return NULL
; /* so if it gets to here, panic! */
1213 switch (i
*256 + b
) {
1214 case R_SI
*256+R_BX
: rm
=0; break;
1215 case R_DI
*256+R_BX
: rm
=1; break;
1216 case R_SI
*256+R_BP
: rm
=2; break;
1217 case R_DI
*256+R_BP
: rm
=3; break;
1221 case R_SI
: rm
=4; break;
1222 case R_DI
: rm
=5; break;
1223 case R_BP
: rm
=6; break;
1224 case R_BX
: rm
=7; break;
1226 if (rm
==-1) /* can't happen, in theory */
1227 return NULL
; /* so panic if it does */
1229 if (o
==0 && seg
==NO_SEG
&& !forw_ref
&& rm
!=6 &&
1230 !(input
->eaflags
& (EAF_BYTEOFFS
|EAF_WORDOFFS
)))
1232 else if (input
->eaflags
& EAF_BYTEOFFS
||
1233 (o
>=-128 && o
<=127 && seg
==NO_SEG
&& !forw_ref
&&
1234 !(input
->eaflags
& EAF_WORDOFFS
)))
1239 output
->sib_present
= FALSE
; /* no SIB - it's 16-bit */
1240 output
->bytes
= mod
; /* bytes of offset needed */
1241 output
->modrm
= (mod
<<6) | (rfield
<<3) | rm
;
1245 output
->size
= 1 + output
->sib_present
+ output
->bytes
;
1249 static int chsize (operand
*input
, int addrbits
)
1251 if (!(MEMORY
& ~input
->type
)) {
1252 int i
=input
->indexreg
, b
=input
->basereg
;
1254 if (input
->scale
==0) i
= -1;
1256 if (i
== -1 && b
== -1) /* pure offset */
1257 return (input
->addr_size
!= 0 && input
->addr_size
!= addrbits
);
1259 if (i
==R_EAX
|| i
==R_EBX
|| i
==R_ECX
|| i
==R_EDX
1260 || i
==R_EBP
|| i
==R_ESP
|| i
==R_ESI
|| i
==R_EDI
1261 || b
==R_EAX
|| b
==R_EBX
|| b
==R_ECX
|| b
==R_EDX
1262 || b
==R_EBP
|| b
==R_ESP
|| b
==R_ESI
|| b
==R_EDI
)
1263 return (addrbits
==16);
1265 return (addrbits
==32);