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