Add preliminary support for the x86emu backend.
[v86d.git] / libs / x86emu / decode.c
blob7d9a34a0348826e303698dd4d85dd5493e4ea077
1 /****************************************************************************
3 * Realmode X86 Emulator Library
5 * Copyright (C) 1996-1999 SciTech Software, Inc.
6 * Copyright (C) David Mosberger-Tang
7 * Copyright (C) 1999 Egbert Eich
9 * ========================================================================
11 * Permission to use, copy, modify, distribute, and sell this software and
12 * its documentation for any purpose is hereby granted without fee,
13 * provided that the above copyright notice appear in all copies and that
14 * both that copyright notice and this permission notice appear in
15 * supporting documentation, and that the name of the authors not be used
16 * in advertising or publicity pertaining to distribution of the software
17 * without specific, written prior permission. The authors makes no
18 * representations about the suitability of this software for any purpose.
19 * It is provided "as is" without express or implied warranty.
21 * THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
22 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
23 * EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
24 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
25 * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
26 * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
27 * PERFORMANCE OF THIS SOFTWARE.
29 * ========================================================================
31 * Language: ANSI C
32 * Environment: Any
33 * Developer: Kendall Bennett
35 * Description: This file includes subroutines which are related to
36 * instruction decoding and accessess of immediate data via IP. etc.
38 ****************************************************************************/
40 #include <stdlib.h>
41 #include "x86emu/x86emui.h"
43 /*----------------------------- Implementation ----------------------------*/
45 /****************************************************************************
46 REMARKS:
47 Handles any pending asychronous interrupts.
48 ****************************************************************************/
49 static void x86emu_intr_handle(void)
51 u8 intno;
53 if (M.x86.intr & INTR_SYNCH) {
54 intno = M.x86.intno;
55 if (_X86EMU_intrTab[intno]) {
56 (*_X86EMU_intrTab[intno])(intno);
57 } else {
58 push_word((u16)M.x86.R_FLG);
59 CLEAR_FLAG(F_IF);
60 CLEAR_FLAG(F_TF);
61 push_word(M.x86.R_CS);
62 M.x86.R_CS = mem_access_word(intno * 4 + 2);
63 push_word(M.x86.R_IP);
64 M.x86.R_IP = mem_access_word(intno * 4);
65 M.x86.intr = 0;
70 /****************************************************************************
71 PARAMETERS:
72 intrnum - Interrupt number to raise
74 REMARKS:
75 Raise the specified interrupt to be handled before the execution of the
76 next instruction.
77 ****************************************************************************/
78 void x86emu_intr_raise(
79 u8 intrnum)
81 M.x86.intno = intrnum;
82 M.x86.intr |= INTR_SYNCH;
85 /****************************************************************************
86 REMARKS:
87 Main execution loop for the emulator. We return from here when the system
88 halts, which is normally caused by a stack fault when we return from the
89 original real mode call.
90 ****************************************************************************/
91 void X86EMU_exec(void)
93 u8 op1;
95 M.x86.intr = 0;
96 DB(x86emu_end_instr();)
98 for (;;) {
99 DB( if (CHECK_IP_FETCH())
100 x86emu_check_ip_access();)
101 /* If debugging, save the IP and CS values. */
102 SAVE_IP_CS(M.x86.R_CS, M.x86.R_IP);
103 INC_DECODED_INST_LEN(1);
104 if (M.x86.intr) {
105 if (M.x86.intr & INTR_HALTED) {
106 DB( if (M.x86.R_SP != 0) {
107 printk("halted\n");
108 X86EMU_trace_regs();
110 else {
111 if (M.x86.debug)
112 printk("Service completed successfully\n");
114 return;
116 if (((M.x86.intr & INTR_SYNCH) && (M.x86.intno == 0 || M.x86.intno == 2)) ||
117 !ACCESS_FLAG(F_IF)) {
118 x86emu_intr_handle();
122 op1 = (*sys_rdb)(((u32)M.x86.R_CS << 4) + (M.x86.R_IP++));
123 (*x86emu_optab[op1])(op1);
124 if (M.x86.debug & DEBUG_EXIT) {
125 M.x86.debug &= ~DEBUG_EXIT;
126 return;
131 /****************************************************************************
132 REMARKS:
133 Halts the system by setting the halted system flag.
134 ****************************************************************************/
135 void X86EMU_halt_sys(void)
137 M.x86.intr |= INTR_HALTED;
140 /****************************************************************************
141 PARAMETERS:
142 mod - Mod value from decoded byte
143 regh - Reg h value from decoded byte
144 regl - Reg l value from decoded byte
146 REMARKS:
147 Raise the specified interrupt to be handled before the execution of the
148 next instruction.
150 NOTE: Do not inline this function, as (*sys_rdb) is already inline!
151 ****************************************************************************/
152 void fetch_decode_modrm(
153 int *mod,
154 int *regh,
155 int *regl)
157 int fetched;
159 DB( if (CHECK_IP_FETCH())
160 x86emu_check_ip_access();)
161 fetched = (*sys_rdb)(((u32)M.x86.R_CS << 4) + (M.x86.R_IP++));
162 INC_DECODED_INST_LEN(1);
163 *mod = (fetched >> 6) & 0x03;
164 *regh = (fetched >> 3) & 0x07;
165 *regl = (fetched >> 0) & 0x07;
168 /****************************************************************************
169 RETURNS:
170 Immediate byte value read from instruction queue
172 REMARKS:
173 This function returns the immediate byte from the instruction queue, and
174 moves the instruction pointer to the next value.
176 NOTE: Do not inline this function, as (*sys_rdb) is already inline!
177 ****************************************************************************/
178 u8 fetch_byte_imm(void)
180 u8 fetched;
182 DB( if (CHECK_IP_FETCH())
183 x86emu_check_ip_access();)
184 fetched = (*sys_rdb)(((u32)M.x86.R_CS << 4) + (M.x86.R_IP++));
185 INC_DECODED_INST_LEN(1);
186 return fetched;
189 /****************************************************************************
190 RETURNS:
191 Immediate word value read from instruction queue
193 REMARKS:
194 This function returns the immediate byte from the instruction queue, and
195 moves the instruction pointer to the next value.
197 NOTE: Do not inline this function, as (*sys_rdw) is already inline!
198 ****************************************************************************/
199 u16 fetch_word_imm(void)
201 u16 fetched;
203 DB( if (CHECK_IP_FETCH())
204 x86emu_check_ip_access();)
205 fetched = (*sys_rdw)(((u32)M.x86.R_CS << 4) + (M.x86.R_IP));
206 M.x86.R_IP += 2;
207 INC_DECODED_INST_LEN(2);
208 return fetched;
211 /****************************************************************************
212 RETURNS:
213 Immediate lone value read from instruction queue
215 REMARKS:
216 This function returns the immediate byte from the instruction queue, and
217 moves the instruction pointer to the next value.
219 NOTE: Do not inline this function, as (*sys_rdw) is already inline!
220 ****************************************************************************/
221 u32 fetch_long_imm(void)
223 u32 fetched;
225 DB( if (CHECK_IP_FETCH())
226 x86emu_check_ip_access();)
227 fetched = (*sys_rdl)(((u32)M.x86.R_CS << 4) + (M.x86.R_IP));
228 M.x86.R_IP += 4;
229 INC_DECODED_INST_LEN(4);
230 return fetched;
233 /****************************************************************************
234 RETURNS:
235 Value of the default data segment
237 REMARKS:
238 Inline function that returns the default data segment for the current
239 instruction.
241 On the x86 processor, the default segment is not always DS if there is
242 no segment override. Address modes such as -3[BP] or 10[BP+SI] all refer to
243 addresses relative to SS (ie: on the stack). So, at the minimum, all
244 decodings of addressing modes would have to set/clear a bit describing
245 whether the access is relative to DS or SS. That is the function of the
246 cpu-state-varible M.x86.mode. There are several potential states:
248 repe prefix seen (handled elsewhere)
249 repne prefix seen (ditto)
251 cs segment override
252 ds segment override
253 es segment override
254 fs segment override
255 gs segment override
256 ss segment override
258 ds/ss select (in absense of override)
260 Each of the above 7 items are handled with a bit in the mode field.
261 ****************************************************************************/
262 _INLINE u32 get_data_segment(void)
264 #define GET_SEGMENT(segment)
265 switch (M.x86.mode & SYSMODE_SEGMASK) {
266 case 0: /* default case: use ds register */
267 case SYSMODE_SEGOVR_DS:
268 case SYSMODE_SEGOVR_DS | SYSMODE_SEG_DS_SS:
269 return M.x86.R_DS;
270 case SYSMODE_SEG_DS_SS: /* non-overridden, use ss register */
271 return M.x86.R_SS;
272 case SYSMODE_SEGOVR_CS:
273 case SYSMODE_SEGOVR_CS | SYSMODE_SEG_DS_SS:
274 return M.x86.R_CS;
275 case SYSMODE_SEGOVR_ES:
276 case SYSMODE_SEGOVR_ES | SYSMODE_SEG_DS_SS:
277 return M.x86.R_ES;
278 case SYSMODE_SEGOVR_FS:
279 case SYSMODE_SEGOVR_FS | SYSMODE_SEG_DS_SS:
280 return M.x86.R_FS;
281 case SYSMODE_SEGOVR_GS:
282 case SYSMODE_SEGOVR_GS | SYSMODE_SEG_DS_SS:
283 return M.x86.R_GS;
284 case SYSMODE_SEGOVR_SS:
285 case SYSMODE_SEGOVR_SS | SYSMODE_SEG_DS_SS:
286 return M.x86.R_SS;
287 default:
288 #ifdef DEBUG
289 printk("error: should not happen: multiple overrides.\n");
290 #endif
291 HALT_SYS();
292 return 0;
296 /****************************************************************************
297 PARAMETERS:
298 offset - Offset to load data from
300 RETURNS:
301 Byte value read from the absolute memory location.
303 NOTE: Do not inline this function as (*sys_rdX) is already inline!
304 ****************************************************************************/
305 u8 fetch_data_byte(
306 uint offset)
308 #ifdef DEBUG
309 if (CHECK_DATA_ACCESS())
310 x86emu_check_data_access((u16)get_data_segment(), offset);
311 #endif
312 return (*sys_rdb)((get_data_segment() << 4) + offset);
315 /****************************************************************************
316 PARAMETERS:
317 offset - Offset to load data from
319 RETURNS:
320 Word value read from the absolute memory location.
322 NOTE: Do not inline this function as (*sys_rdX) is already inline!
323 ****************************************************************************/
324 u16 fetch_data_word(
325 uint offset)
327 #ifdef DEBUG
328 if (CHECK_DATA_ACCESS())
329 x86emu_check_data_access((u16)get_data_segment(), offset);
330 #endif
331 return (*sys_rdw)((get_data_segment() << 4) + offset);
334 /****************************************************************************
335 PARAMETERS:
336 offset - Offset to load data from
338 RETURNS:
339 Long value read from the absolute memory location.
341 NOTE: Do not inline this function as (*sys_rdX) is already inline!
342 ****************************************************************************/
343 u32 fetch_data_long(
344 uint offset)
346 #ifdef DEBUG
347 if (CHECK_DATA_ACCESS())
348 x86emu_check_data_access((u16)get_data_segment(), offset);
349 #endif
350 return (*sys_rdl)((get_data_segment() << 4) + offset);
353 /****************************************************************************
354 PARAMETERS:
355 segment - Segment to load data from
356 offset - Offset to load data from
358 RETURNS:
359 Byte value read from the absolute memory location.
361 NOTE: Do not inline this function as (*sys_rdX) is already inline!
362 ****************************************************************************/
363 u8 fetch_data_byte_abs(
364 uint segment,
365 uint offset)
367 #ifdef DEBUG
368 if (CHECK_DATA_ACCESS())
369 x86emu_check_data_access(segment, offset);
370 #endif
371 return (*sys_rdb)(((u32)segment << 4) + offset);
374 /****************************************************************************
375 PARAMETERS:
376 segment - Segment to load data from
377 offset - Offset to load data from
379 RETURNS:
380 Word value read from the absolute memory location.
382 NOTE: Do not inline this function as (*sys_rdX) is already inline!
383 ****************************************************************************/
384 u16 fetch_data_word_abs(
385 uint segment,
386 uint offset)
388 #ifdef DEBUG
389 if (CHECK_DATA_ACCESS())
390 x86emu_check_data_access(segment, offset);
391 #endif
392 return (*sys_rdw)(((u32)segment << 4) + offset);
395 /****************************************************************************
396 PARAMETERS:
397 segment - Segment to load data from
398 offset - Offset to load data from
400 RETURNS:
401 Long value read from the absolute memory location.
403 NOTE: Do not inline this function as (*sys_rdX) is already inline!
404 ****************************************************************************/
405 u32 fetch_data_long_abs(
406 uint segment,
407 uint offset)
409 #ifdef DEBUG
410 if (CHECK_DATA_ACCESS())
411 x86emu_check_data_access(segment, offset);
412 #endif
413 return (*sys_rdl)(((u32)segment << 4) + offset);
416 /****************************************************************************
417 PARAMETERS:
418 offset - Offset to store data at
419 val - Value to store
421 REMARKS:
422 Writes a word value to an segmented memory location. The segment used is
423 the current 'default' segment, which may have been overridden.
425 NOTE: Do not inline this function as (*sys_wrX) is already inline!
426 ****************************************************************************/
427 void store_data_byte(
428 uint offset,
429 u8 val)
431 #ifdef DEBUG
432 if (CHECK_DATA_ACCESS())
433 x86emu_check_data_access((u16)get_data_segment(), offset);
434 #endif
435 (*sys_wrb)((get_data_segment() << 4) + offset, val);
438 /****************************************************************************
439 PARAMETERS:
440 offset - Offset to store data at
441 val - Value to store
443 REMARKS:
444 Writes a word value to an segmented memory location. The segment used is
445 the current 'default' segment, which may have been overridden.
447 NOTE: Do not inline this function as (*sys_wrX) is already inline!
448 ****************************************************************************/
449 void store_data_word(
450 uint offset,
451 u16 val)
453 #ifdef DEBUG
454 if (CHECK_DATA_ACCESS())
455 x86emu_check_data_access((u16)get_data_segment(), offset);
456 #endif
457 (*sys_wrw)((get_data_segment() << 4) + offset, val);
460 /****************************************************************************
461 PARAMETERS:
462 offset - Offset to store data at
463 val - Value to store
465 REMARKS:
466 Writes a long value to an segmented memory location. The segment used is
467 the current 'default' segment, which may have been overridden.
469 NOTE: Do not inline this function as (*sys_wrX) is already inline!
470 ****************************************************************************/
471 void store_data_long(
472 uint offset,
473 u32 val)
475 #ifdef DEBUG
476 if (CHECK_DATA_ACCESS())
477 x86emu_check_data_access((u16)get_data_segment(), offset);
478 #endif
479 (*sys_wrl)((get_data_segment() << 4) + offset, val);
482 /****************************************************************************
483 PARAMETERS:
484 segment - Segment to store data at
485 offset - Offset to store data at
486 val - Value to store
488 REMARKS:
489 Writes a byte value to an absolute memory location.
491 NOTE: Do not inline this function as (*sys_wrX) is already inline!
492 ****************************************************************************/
493 void store_data_byte_abs(
494 uint segment,
495 uint offset,
496 u8 val)
498 #ifdef DEBUG
499 if (CHECK_DATA_ACCESS())
500 x86emu_check_data_access(segment, offset);
501 #endif
502 (*sys_wrb)(((u32)segment << 4) + offset, val);
505 /****************************************************************************
506 PARAMETERS:
507 segment - Segment to store data at
508 offset - Offset to store data at
509 val - Value to store
511 REMARKS:
512 Writes a word value to an absolute memory location.
514 NOTE: Do not inline this function as (*sys_wrX) is already inline!
515 ****************************************************************************/
516 void store_data_word_abs(
517 uint segment,
518 uint offset,
519 u16 val)
521 #ifdef DEBUG
522 if (CHECK_DATA_ACCESS())
523 x86emu_check_data_access(segment, offset);
524 #endif
525 (*sys_wrw)(((u32)segment << 4) + offset, val);
528 /****************************************************************************
529 PARAMETERS:
530 segment - Segment to store data at
531 offset - Offset to store data at
532 val - Value to store
534 REMARKS:
535 Writes a long value to an absolute memory location.
537 NOTE: Do not inline this function as (*sys_wrX) is already inline!
538 ****************************************************************************/
539 void store_data_long_abs(
540 uint segment,
541 uint offset,
542 u32 val)
544 #ifdef DEBUG
545 if (CHECK_DATA_ACCESS())
546 x86emu_check_data_access(segment, offset);
547 #endif
548 (*sys_wrl)(((u32)segment << 4) + offset, val);
551 /****************************************************************************
552 PARAMETERS:
553 reg - Register to decode
555 RETURNS:
556 Pointer to the appropriate register
558 REMARKS:
559 Return a pointer to the register given by the R/RM field of the
560 modrm byte, for byte operands. Also enables the decoding of instructions.
561 ****************************************************************************/
562 u8* decode_rm_byte_register(
563 int reg)
565 switch (reg) {
566 case 0:
567 DECODE_PRINTF("AL");
568 return &M.x86.R_AL;
569 case 1:
570 DECODE_PRINTF("CL");
571 return &M.x86.R_CL;
572 case 2:
573 DECODE_PRINTF("DL");
574 return &M.x86.R_DL;
575 case 3:
576 DECODE_PRINTF("BL");
577 return &M.x86.R_BL;
578 case 4:
579 DECODE_PRINTF("AH");
580 return &M.x86.R_AH;
581 case 5:
582 DECODE_PRINTF("CH");
583 return &M.x86.R_CH;
584 case 6:
585 DECODE_PRINTF("DH");
586 return &M.x86.R_DH;
587 case 7:
588 DECODE_PRINTF("BH");
589 return &M.x86.R_BH;
591 HALT_SYS();
592 return NULL; /* NOT REACHED OR REACHED ON ERROR */
595 /****************************************************************************
596 PARAMETERS:
597 reg - Register to decode
599 RETURNS:
600 Pointer to the appropriate register
602 REMARKS:
603 Return a pointer to the register given by the R/RM field of the
604 modrm byte, for word operands. Also enables the decoding of instructions.
605 ****************************************************************************/
606 u16* decode_rm_word_register(
607 int reg)
609 switch (reg) {
610 case 0:
611 DECODE_PRINTF("AX");
612 return &M.x86.R_AX;
613 case 1:
614 DECODE_PRINTF("CX");
615 return &M.x86.R_CX;
616 case 2:
617 DECODE_PRINTF("DX");
618 return &M.x86.R_DX;
619 case 3:
620 DECODE_PRINTF("BX");
621 return &M.x86.R_BX;
622 case 4:
623 DECODE_PRINTF("SP");
624 return &M.x86.R_SP;
625 case 5:
626 DECODE_PRINTF("BP");
627 return &M.x86.R_BP;
628 case 6:
629 DECODE_PRINTF("SI");
630 return &M.x86.R_SI;
631 case 7:
632 DECODE_PRINTF("DI");
633 return &M.x86.R_DI;
635 HALT_SYS();
636 return NULL; /* NOTREACHED OR REACHED ON ERROR */
639 /****************************************************************************
640 PARAMETERS:
641 reg - Register to decode
643 RETURNS:
644 Pointer to the appropriate register
646 REMARKS:
647 Return a pointer to the register given by the R/RM field of the
648 modrm byte, for dword operands. Also enables the decoding of instructions.
649 ****************************************************************************/
650 u32* decode_rm_long_register(
651 int reg)
653 switch (reg) {
654 case 0:
655 DECODE_PRINTF("EAX");
656 return &M.x86.R_EAX;
657 case 1:
658 DECODE_PRINTF("ECX");
659 return &M.x86.R_ECX;
660 case 2:
661 DECODE_PRINTF("EDX");
662 return &M.x86.R_EDX;
663 case 3:
664 DECODE_PRINTF("EBX");
665 return &M.x86.R_EBX;
666 case 4:
667 DECODE_PRINTF("ESP");
668 return &M.x86.R_ESP;
669 case 5:
670 DECODE_PRINTF("EBP");
671 return &M.x86.R_EBP;
672 case 6:
673 DECODE_PRINTF("ESI");
674 return &M.x86.R_ESI;
675 case 7:
676 DECODE_PRINTF("EDI");
677 return &M.x86.R_EDI;
679 HALT_SYS();
680 return NULL; /* NOTREACHED OR REACHED ON ERROR */
683 /****************************************************************************
684 PARAMETERS:
685 reg - Register to decode
687 RETURNS:
688 Pointer to the appropriate register
690 REMARKS:
691 Return a pointer to the register given by the R/RM field of the
692 modrm byte, for word operands, modified from above for the weirdo
693 special case of segreg operands. Also enables the decoding of instructions.
694 ****************************************************************************/
695 u16* decode_rm_seg_register(
696 int reg)
698 switch (reg) {
699 case 0:
700 DECODE_PRINTF("ES");
701 return &M.x86.R_ES;
702 case 1:
703 DECODE_PRINTF("CS");
704 return &M.x86.R_CS;
705 case 2:
706 DECODE_PRINTF("SS");
707 return &M.x86.R_SS;
708 case 3:
709 DECODE_PRINTF("DS");
710 return &M.x86.R_DS;
711 case 4:
712 DECODE_PRINTF("FS");
713 return &M.x86.R_FS;
714 case 5:
715 DECODE_PRINTF("GS");
716 return &M.x86.R_GS;
717 case 6:
718 case 7:
719 DECODE_PRINTF("ILLEGAL SEGREG");
720 break;
722 HALT_SYS();
723 return NULL; /* NOT REACHED OR REACHED ON ERROR */
728 * return offset from the SIB Byte
730 u32 decode_sib_address(int sib, int mod)
732 u32 base = 0, i = 0, scale = 1;
734 switch(sib & 0x07) {
735 case 0:
736 DECODE_PRINTF("[EAX]");
737 base = M.x86.R_EAX;
738 break;
739 case 1:
740 DECODE_PRINTF("[ECX]");
741 base = M.x86.R_ECX;
742 break;
743 case 2:
744 DECODE_PRINTF("[EDX]");
745 base = M.x86.R_EDX;
746 break;
747 case 3:
748 DECODE_PRINTF("[EBX]");
749 base = M.x86.R_EBX;
750 break;
751 case 4:
752 DECODE_PRINTF("[ESP]");
753 base = M.x86.R_ESP;
754 M.x86.mode |= SYSMODE_SEG_DS_SS;
755 break;
756 case 5:
757 if (mod == 0) {
758 base = fetch_long_imm();
759 DECODE_PRINTF2("%08x", base);
760 } else {
761 DECODE_PRINTF("[EBP]");
762 base = M.x86.R_ESP;
763 M.x86.mode |= SYSMODE_SEG_DS_SS;
765 break;
766 case 6:
767 DECODE_PRINTF("[ESI]");
768 base = M.x86.R_ESI;
769 break;
770 case 7:
771 DECODE_PRINTF("[EDI]");
772 base = M.x86.R_EDI;
773 break;
775 switch ((sib >> 3) & 0x07) {
776 case 0:
777 DECODE_PRINTF("[EAX");
778 i = M.x86.R_EAX;
779 break;
780 case 1:
781 DECODE_PRINTF("[ECX");
782 i = M.x86.R_ECX;
783 break;
784 case 2:
785 DECODE_PRINTF("[EDX");
786 i = M.x86.R_EDX;
787 break;
788 case 3:
789 DECODE_PRINTF("[EBX");
790 i = M.x86.R_EBX;
791 break;
792 case 4:
793 i = 0;
794 break;
795 case 5:
796 DECODE_PRINTF("[EBP");
797 i = M.x86.R_EBP;
798 break;
799 case 6:
800 DECODE_PRINTF("[ESI");
801 i = M.x86.R_ESI;
802 break;
803 case 7:
804 DECODE_PRINTF("[EDI");
805 i = M.x86.R_EDI;
806 break;
808 scale = 1 << ((sib >> 6) & 0x03);
809 if (((sib >> 3) & 0x07) != 4) {
810 if (scale == 1) {
811 DECODE_PRINTF("]");
812 } else {
813 DECODE_PRINTF2("*%d]", scale);
816 return base + (i * scale);
819 /****************************************************************************
820 PARAMETERS:
821 rm - RM value to decode
823 RETURNS:
824 Offset in memory for the address decoding
826 REMARKS:
827 Return the offset given by mod=00 addressing. Also enables the
828 decoding of instructions.
830 NOTE: The code which specifies the corresponding segment (ds vs ss)
831 below in the case of [BP+..]. The assumption here is that at the
832 point that this subroutine is called, the bit corresponding to
833 SYSMODE_SEG_DS_SS will be zero. After every instruction
834 except the segment override instructions, this bit (as well
835 as any bits indicating segment overrides) will be clear. So
836 if a SS access is needed, set this bit. Otherwise, DS access
837 occurs (unless any of the segment override bits are set).
838 ****************************************************************************/
839 u32 decode_rm00_address(
840 int rm)
842 u32 offset;
843 int sib;
845 if (M.x86.mode & SYSMODE_PREFIX_ADDR) {
846 /* 32-bit addressing */
847 switch (rm) {
848 case 0:
849 DECODE_PRINTF("[EAX]");
850 return M.x86.R_EAX;
851 case 1:
852 DECODE_PRINTF("[ECX]");
853 return M.x86.R_ECX;
854 case 2:
855 DECODE_PRINTF("[EDX]");
856 return M.x86.R_EDX;
857 case 3:
858 DECODE_PRINTF("[EBX]");
859 return M.x86.R_EBX;
860 case 4:
861 sib = fetch_byte_imm();
862 return decode_sib_address(sib, 0);
863 case 5:
864 offset = fetch_long_imm();
865 DECODE_PRINTF2("[%08x]", offset);
866 return offset;
867 case 6:
868 DECODE_PRINTF("[ESI]");
869 return M.x86.R_ESI;
870 case 7:
871 DECODE_PRINTF("[EDI]");
872 return M.x86.R_EDI;
874 HALT_SYS();
875 } else {
876 /* 16-bit addressing */
877 switch (rm) {
878 case 0:
879 DECODE_PRINTF("[BX+SI]");
880 return (M.x86.R_BX + M.x86.R_SI) & 0xffff;
881 case 1:
882 DECODE_PRINTF("[BX+DI]");
883 return (M.x86.R_BX + M.x86.R_DI) & 0xffff;
884 case 2:
885 DECODE_PRINTF("[BP+SI]");
886 M.x86.mode |= SYSMODE_SEG_DS_SS;
887 return (M.x86.R_BP + M.x86.R_SI) & 0xffff;
888 case 3:
889 DECODE_PRINTF("[BP+DI]");
890 M.x86.mode |= SYSMODE_SEG_DS_SS;
891 return (M.x86.R_BP + M.x86.R_DI) & 0xffff;
892 case 4:
893 DECODE_PRINTF("[SI]");
894 return M.x86.R_SI;
895 case 5:
896 DECODE_PRINTF("[DI]");
897 return M.x86.R_DI;
898 case 6:
899 offset = fetch_word_imm();
900 DECODE_PRINTF2("[%04x]", offset);
901 return offset;
902 case 7:
903 DECODE_PRINTF("[BX]");
904 return M.x86.R_BX;
906 HALT_SYS();
908 return 0;
911 /****************************************************************************
912 PARAMETERS:
913 rm - RM value to decode
915 RETURNS:
916 Offset in memory for the address decoding
918 REMARKS:
919 Return the offset given by mod=01 addressing. Also enables the
920 decoding of instructions.
921 ****************************************************************************/
922 u32 decode_rm01_address(
923 int rm)
925 int displacement = 0;
926 int sib;
928 /* Fetch disp8 if no SIB byte */
929 if (!((M.x86.mode & SYSMODE_PREFIX_ADDR) && (rm == 4)))
930 displacement = (s8)fetch_byte_imm();
932 if (M.x86.mode & SYSMODE_PREFIX_ADDR) {
933 /* 32-bit addressing */
934 switch (rm) {
935 case 0:
936 DECODE_PRINTF2("%d[EAX]", displacement);
937 return M.x86.R_EAX + displacement;
938 case 1:
939 DECODE_PRINTF2("%d[ECX]", displacement);
940 return M.x86.R_ECX + displacement;
941 case 2:
942 DECODE_PRINTF2("%d[EDX]", displacement);
943 return M.x86.R_EDX + displacement;
944 case 3:
945 DECODE_PRINTF2("%d[EBX]", displacement);
946 return M.x86.R_EBX + displacement;
947 case 4:
948 sib = fetch_byte_imm();
949 displacement = (s8)fetch_byte_imm();
950 DECODE_PRINTF2("%d", displacement);
951 return decode_sib_address(sib, 1) + displacement;
952 case 5:
953 DECODE_PRINTF2("%d[EBP]", displacement);
954 return M.x86.R_EBP + displacement;
955 case 6:
956 DECODE_PRINTF2("%d[ESI]", displacement);
957 return M.x86.R_ESI + displacement;
958 case 7:
959 DECODE_PRINTF2("%d[EDI]", displacement);
960 return M.x86.R_EDI + displacement;
962 HALT_SYS();
963 } else {
964 /* 16-bit addressing */
965 switch (rm) {
966 case 0:
967 DECODE_PRINTF2("%d[BX+SI]", displacement);
968 return (M.x86.R_BX + M.x86.R_SI + displacement) & 0xffff;
969 case 1:
970 DECODE_PRINTF2("%d[BX+DI]", displacement);
971 return (M.x86.R_BX + M.x86.R_DI + displacement) & 0xffff;
972 case 2:
973 DECODE_PRINTF2("%d[BP+SI]", displacement);
974 M.x86.mode |= SYSMODE_SEG_DS_SS;
975 return (M.x86.R_BP + M.x86.R_SI + displacement) & 0xffff;
976 case 3:
977 DECODE_PRINTF2("%d[BP+DI]", displacement);
978 M.x86.mode |= SYSMODE_SEG_DS_SS;
979 return (M.x86.R_BP + M.x86.R_DI + displacement) & 0xffff;
980 case 4:
981 DECODE_PRINTF2("%d[SI]", displacement);
982 return (M.x86.R_SI + displacement) & 0xffff;
983 case 5:
984 DECODE_PRINTF2("%d[DI]", displacement);
985 return (M.x86.R_DI + displacement) & 0xffff;
986 case 6:
987 DECODE_PRINTF2("%d[BP]", displacement);
988 M.x86.mode |= SYSMODE_SEG_DS_SS;
989 return (M.x86.R_BP + displacement) & 0xffff;
990 case 7:
991 DECODE_PRINTF2("%d[BX]", displacement);
992 return (M.x86.R_BX + displacement) & 0xffff;
994 HALT_SYS();
996 return 0; /* SHOULD NOT HAPPEN */
999 /****************************************************************************
1000 PARAMETERS:
1001 rm - RM value to decode
1003 RETURNS:
1004 Offset in memory for the address decoding
1006 REMARKS:
1007 Return the offset given by mod=10 addressing. Also enables the
1008 decoding of instructions.
1009 ****************************************************************************/
1010 u32 decode_rm10_address(
1011 int rm)
1013 u32 displacement = 0;
1014 int sib;
1016 /* Fetch disp16 if 16-bit addr mode */
1017 if (!(M.x86.mode & SYSMODE_PREFIX_ADDR))
1018 displacement = (u16)fetch_word_imm();
1019 else {
1020 /* Fetch disp32 if no SIB byte */
1021 if (rm != 4)
1022 displacement = (u32)fetch_long_imm();
1025 if (M.x86.mode & SYSMODE_PREFIX_ADDR) {
1026 /* 32-bit addressing */
1027 switch (rm) {
1028 case 0:
1029 DECODE_PRINTF2("%08x[EAX]", displacement);
1030 return M.x86.R_EAX + displacement;
1031 case 1:
1032 DECODE_PRINTF2("%08x[ECX]", displacement);
1033 return M.x86.R_ECX + displacement;
1034 case 2:
1035 DECODE_PRINTF2("%08x[EDX]", displacement);
1036 M.x86.mode |= SYSMODE_SEG_DS_SS;
1037 return M.x86.R_EDX + displacement;
1038 case 3:
1039 DECODE_PRINTF2("%08x[EBX]", displacement);
1040 return M.x86.R_EBX + displacement;
1041 case 4:
1042 sib = fetch_byte_imm();
1043 displacement = (u32)fetch_long_imm();
1044 DECODE_PRINTF2("%08x", displacement);
1045 return decode_sib_address(sib, 2) + displacement;
1046 break;
1047 case 5:
1048 DECODE_PRINTF2("%08x[EBP]", displacement);
1049 return M.x86.R_EBP + displacement;
1050 case 6:
1051 DECODE_PRINTF2("%08x[ESI]", displacement);
1052 return M.x86.R_ESI + displacement;
1053 case 7:
1054 DECODE_PRINTF2("%08x[EDI]", displacement);
1055 return M.x86.R_EDI + displacement;
1057 HALT_SYS();
1058 } else {
1059 /* 16-bit addressing */
1060 switch (rm) {
1061 case 0:
1062 DECODE_PRINTF2("%04x[BX+SI]", displacement);
1063 return (M.x86.R_BX + M.x86.R_SI + displacement) & 0xffff;
1064 case 1:
1065 DECODE_PRINTF2("%04x[BX+DI]", displacement);
1066 return (M.x86.R_BX + M.x86.R_DI + displacement) & 0xffff;
1067 case 2:
1068 DECODE_PRINTF2("%04x[BP+SI]", displacement);
1069 M.x86.mode |= SYSMODE_SEG_DS_SS;
1070 return (M.x86.R_BP + M.x86.R_SI + displacement) & 0xffff;
1071 case 3:
1072 DECODE_PRINTF2("%04x[BP+DI]", displacement);
1073 M.x86.mode |= SYSMODE_SEG_DS_SS;
1074 return (M.x86.R_BP + M.x86.R_DI + displacement) & 0xffff;
1075 case 4:
1076 DECODE_PRINTF2("%04x[SI]", displacement);
1077 return (M.x86.R_SI + displacement) & 0xffff;
1078 case 5:
1079 DECODE_PRINTF2("%04x[DI]", displacement);
1080 return (M.x86.R_DI + displacement) & 0xffff;
1081 case 6:
1082 DECODE_PRINTF2("%04x[BP]", displacement);
1083 M.x86.mode |= SYSMODE_SEG_DS_SS;
1084 return (M.x86.R_BP + displacement) & 0xffff;
1085 case 7:
1086 DECODE_PRINTF2("%04x[BX]", displacement);
1087 return (M.x86.R_BX + displacement) & 0xffff;
1089 HALT_SYS();
1091 return 0;
1092 /*NOTREACHED */