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