1 /****************************************************************************
3 * Realmode X86 Emulator Library
5 * Copyright (C) 1991-2004 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 * ========================================================================
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 ****************************************************************************/
41 #if defined(CONFIG_BIOSEMU)
43 #include "x86emu/x86emui.h"
45 /*----------------------------- Implementation ----------------------------*/
47 /****************************************************************************
49 Handles any pending asychronous interrupts.
50 ****************************************************************************/
51 static void x86emu_intr_handle(void)
55 if (M
.x86
.intr
& INTR_SYNCH
) {
57 if (_X86EMU_intrTab
[intno
]) {
58 (*_X86EMU_intrTab
[intno
])(intno
);
60 push_word((u16
)M
.x86
.R_FLG
);
63 push_word(M
.x86
.R_CS
);
64 M
.x86
.R_CS
= mem_access_word(intno
* 4 + 2);
65 push_word(M
.x86
.R_IP
);
66 M
.x86
.R_IP
= mem_access_word(intno
* 4);
72 /****************************************************************************
74 intrnum - Interrupt number to raise
77 Raise the specified interrupt to be handled before the execution of the
79 ****************************************************************************/
80 void x86emu_intr_raise(
83 M
.x86
.intno
= intrnum
;
84 M
.x86
.intr
|= INTR_SYNCH
;
87 /****************************************************************************
89 Main execution loop for the emulator. We return from here when the system
90 halts, which is normally caused by a stack fault when we return from the
91 original real mode call.
92 ****************************************************************************/
93 void X86EMU_exec(void)
98 DB(x86emu_end_instr();)
101 DB( if (CHECK_IP_FETCH())
102 x86emu_check_ip_access();)
103 /* If debugging, save the IP and CS values. */
104 SAVE_IP_CS(M
.x86
.R_CS
, M
.x86
.R_IP
);
105 INC_DECODED_INST_LEN(1);
107 if (M
.x86
.intr
& INTR_HALTED
) {
108 DB( if (M
.x86
.R_SP
!= 0) {
114 printk("Service completed successfully\n");
118 if (((M
.x86
.intr
& INTR_SYNCH
) && (M
.x86
.intno
== 0 || M
.x86
.intno
== 2)) ||
119 !ACCESS_FLAG(F_IF
)) {
120 x86emu_intr_handle();
123 op1
= (*sys_rdb
)(((u32
)M
.x86
.R_CS
<< 4) + (M
.x86
.R_IP
++));
124 (*x86emu_optab
[op1
])(op1
);
125 if (M
.x86
.debug
& DEBUG_EXIT
) {
126 M
.x86
.debug
&= ~DEBUG_EXIT
;
132 /****************************************************************************
134 Halts the system by setting the halted system flag.
135 ****************************************************************************/
136 void X86EMU_halt_sys(void)
138 M
.x86
.intr
|= INTR_HALTED
;
141 /****************************************************************************
143 mod - Mod value from decoded byte
144 regh - Reg h value from decoded byte
145 regl - Reg l value from decoded byte
148 Raise the specified interrupt to be handled before the execution of the
151 NOTE: Do not inline this function, as (*sys_rdb) is already inline!
152 ****************************************************************************/
153 void fetch_decode_modrm(
160 DB( if (CHECK_IP_FETCH())
161 x86emu_check_ip_access();)
162 fetched
= (*sys_rdb
)(((u32
)M
.x86
.R_CS
<< 4) + (M
.x86
.R_IP
++));
163 INC_DECODED_INST_LEN(1);
164 *mod
= (fetched
>> 6) & 0x03;
165 *regh
= (fetched
>> 3) & 0x07;
166 *regl
= (fetched
>> 0) & 0x07;
169 /****************************************************************************
171 Immediate byte value read from instruction queue
174 This function returns the immediate byte from the instruction queue, and
175 moves the instruction pointer to the next value.
177 NOTE: Do not inline this function, as (*sys_rdb) is already inline!
178 ****************************************************************************/
179 u8
fetch_byte_imm(void)
183 DB( if (CHECK_IP_FETCH())
184 x86emu_check_ip_access();)
185 fetched
= (*sys_rdb
)(((u32
)M
.x86
.R_CS
<< 4) + (M
.x86
.R_IP
++));
186 INC_DECODED_INST_LEN(1);
190 /****************************************************************************
192 Immediate word value read from instruction queue
195 This function returns the immediate byte from the instruction queue, and
196 moves the instruction pointer to the next value.
198 NOTE: Do not inline this function, as (*sys_rdw) is already inline!
199 ****************************************************************************/
200 u16
fetch_word_imm(void)
204 DB( if (CHECK_IP_FETCH())
205 x86emu_check_ip_access();)
206 fetched
= (*sys_rdw
)(((u32
)M
.x86
.R_CS
<< 4) + (M
.x86
.R_IP
));
208 INC_DECODED_INST_LEN(2);
212 /****************************************************************************
214 Immediate lone value read from instruction queue
217 This function returns the immediate byte from the instruction queue, and
218 moves the instruction pointer to the next value.
220 NOTE: Do not inline this function, as (*sys_rdw) is already inline!
221 ****************************************************************************/
222 u32
fetch_long_imm(void)
226 DB( if (CHECK_IP_FETCH())
227 x86emu_check_ip_access();)
228 fetched
= (*sys_rdl
)(((u32
)M
.x86
.R_CS
<< 4) + (M
.x86
.R_IP
));
230 INC_DECODED_INST_LEN(4);
234 /****************************************************************************
236 Value of the default data segment
239 Inline function that returns the default data segment for the current
242 On the x86 processor, the default segment is not always DS if there is
243 no segment override. Address modes such as -3[BP] or 10[BP+SI] all refer to
244 addresses relative to SS (ie: on the stack). So, at the minimum, all
245 decodings of addressing modes would have to set/clear a bit describing
246 whether the access is relative to DS or SS. That is the function of the
247 cpu-state-varible M.x86.mode. There are several potential states:
249 repe prefix seen (handled elsewhere)
250 repne prefix seen (ditto)
259 ds/ss select (in absense of override)
261 Each of the above 7 items are handled with a bit in the mode field.
262 ****************************************************************************/
263 _INLINE u32
get_data_segment(void)
265 #define GET_SEGMENT(segment)
266 switch (M
.x86
.mode
& SYSMODE_SEGMASK
) {
267 case 0: /* default case: use ds register */
268 case SYSMODE_SEGOVR_DS
:
269 case SYSMODE_SEGOVR_DS
| SYSMODE_SEG_DS_SS
:
271 case SYSMODE_SEG_DS_SS
: /* non-overridden, use ss register */
273 case SYSMODE_SEGOVR_CS
:
274 case SYSMODE_SEGOVR_CS
| SYSMODE_SEG_DS_SS
:
276 case SYSMODE_SEGOVR_ES
:
277 case SYSMODE_SEGOVR_ES
| SYSMODE_SEG_DS_SS
:
279 case SYSMODE_SEGOVR_FS
:
280 case SYSMODE_SEGOVR_FS
| SYSMODE_SEG_DS_SS
:
282 case SYSMODE_SEGOVR_GS
:
283 case SYSMODE_SEGOVR_GS
| SYSMODE_SEG_DS_SS
:
285 case SYSMODE_SEGOVR_SS
:
286 case SYSMODE_SEGOVR_SS
| SYSMODE_SEG_DS_SS
:
290 printk("error: should not happen: multiple overrides.\n");
297 /****************************************************************************
299 offset - Offset to load data from
302 Byte value read from the absolute memory location.
304 NOTE: Do not inline this function as (*sys_rdX) is already inline!
305 ****************************************************************************/
310 if (CHECK_DATA_ACCESS())
311 x86emu_check_data_access((u16
)get_data_segment(), offset
);
313 return (*sys_rdb
)((get_data_segment() << 4) + offset
);
316 /****************************************************************************
318 offset - Offset to load data from
321 Word value read from the absolute memory location.
323 NOTE: Do not inline this function as (*sys_rdX) is already inline!
324 ****************************************************************************/
329 if (CHECK_DATA_ACCESS())
330 x86emu_check_data_access((u16
)get_data_segment(), offset
);
332 return (*sys_rdw
)((get_data_segment() << 4) + offset
);
335 /****************************************************************************
337 offset - Offset to load data from
340 Long value read from the absolute memory location.
342 NOTE: Do not inline this function as (*sys_rdX) is already inline!
343 ****************************************************************************/
348 if (CHECK_DATA_ACCESS())
349 x86emu_check_data_access((u16
)get_data_segment(), offset
);
351 return (*sys_rdl
)((get_data_segment() << 4) + offset
);
354 /****************************************************************************
356 segment - Segment to load data from
357 offset - Offset to load data from
360 Byte value read from the absolute memory location.
362 NOTE: Do not inline this function as (*sys_rdX) is already inline!
363 ****************************************************************************/
364 u8
fetch_data_byte_abs(
369 if (CHECK_DATA_ACCESS())
370 x86emu_check_data_access(segment
, offset
);
372 return (*sys_rdb
)(((u32
)segment
<< 4) + offset
);
375 /****************************************************************************
377 segment - Segment to load data from
378 offset - Offset to load data from
381 Word value read from the absolute memory location.
383 NOTE: Do not inline this function as (*sys_rdX) is already inline!
384 ****************************************************************************/
385 u16
fetch_data_word_abs(
390 if (CHECK_DATA_ACCESS())
391 x86emu_check_data_access(segment
, offset
);
393 return (*sys_rdw
)(((u32
)segment
<< 4) + offset
);
396 /****************************************************************************
398 segment - Segment to load data from
399 offset - Offset to load data from
402 Long value read from the absolute memory location.
404 NOTE: Do not inline this function as (*sys_rdX) is already inline!
405 ****************************************************************************/
406 u32
fetch_data_long_abs(
411 if (CHECK_DATA_ACCESS())
412 x86emu_check_data_access(segment
, offset
);
414 return (*sys_rdl
)(((u32
)segment
<< 4) + offset
);
417 /****************************************************************************
419 offset - Offset to store data at
423 Writes a word value to an segmented memory location. The segment used is
424 the current 'default' segment, which may have been overridden.
426 NOTE: Do not inline this function as (*sys_wrX) is already inline!
427 ****************************************************************************/
428 void store_data_byte(
433 if (CHECK_DATA_ACCESS())
434 x86emu_check_data_access((u16
)get_data_segment(), offset
);
436 (*sys_wrb
)((get_data_segment() << 4) + offset
, val
);
439 /****************************************************************************
441 offset - Offset to store data at
445 Writes a word value to an segmented memory location. The segment used is
446 the current 'default' segment, which may have been overridden.
448 NOTE: Do not inline this function as (*sys_wrX) is already inline!
449 ****************************************************************************/
450 void store_data_word(
455 if (CHECK_DATA_ACCESS())
456 x86emu_check_data_access((u16
)get_data_segment(), offset
);
458 (*sys_wrw
)((get_data_segment() << 4) + offset
, val
);
461 /****************************************************************************
463 offset - Offset to store data at
467 Writes a long value to an segmented memory location. The segment used is
468 the current 'default' segment, which may have been overridden.
470 NOTE: Do not inline this function as (*sys_wrX) is already inline!
471 ****************************************************************************/
472 void store_data_long(
477 if (CHECK_DATA_ACCESS())
478 x86emu_check_data_access((u16
)get_data_segment(), offset
);
480 (*sys_wrl
)((get_data_segment() << 4) + offset
, val
);
483 /****************************************************************************
485 segment - Segment to store data at
486 offset - Offset to store data at
490 Writes a byte value to an absolute memory location.
492 NOTE: Do not inline this function as (*sys_wrX) is already inline!
493 ****************************************************************************/
494 void store_data_byte_abs(
500 if (CHECK_DATA_ACCESS())
501 x86emu_check_data_access(segment
, offset
);
503 (*sys_wrb
)(((u32
)segment
<< 4) + offset
, val
);
506 /****************************************************************************
508 segment - Segment to store data at
509 offset - Offset to store data at
513 Writes a word value to an absolute memory location.
515 NOTE: Do not inline this function as (*sys_wrX) is already inline!
516 ****************************************************************************/
517 void store_data_word_abs(
523 if (CHECK_DATA_ACCESS())
524 x86emu_check_data_access(segment
, offset
);
526 (*sys_wrw
)(((u32
)segment
<< 4) + offset
, val
);
529 /****************************************************************************
531 segment - Segment to store data at
532 offset - Offset to store data at
536 Writes a long value to an absolute memory location.
538 NOTE: Do not inline this function as (*sys_wrX) is already inline!
539 ****************************************************************************/
540 void store_data_long_abs(
546 if (CHECK_DATA_ACCESS())
547 x86emu_check_data_access(segment
, offset
);
549 (*sys_wrl
)(((u32
)segment
<< 4) + offset
, val
);
552 /****************************************************************************
554 reg - Register to decode
557 Pointer to the appropriate register
560 Return a pointer to the register given by the R/RM field of the
561 modrm byte, for byte operands. Also enables the decoding of instructions.
562 ****************************************************************************/
563 u8
* decode_rm_byte_register(
593 return NULL
; /* NOT REACHED OR REACHED ON ERROR */
596 /****************************************************************************
598 reg - Register to decode
601 Pointer to the appropriate register
604 Return a pointer to the register given by the R/RM field of the
605 modrm byte, for word operands. Also enables the decoding of instructions.
606 ****************************************************************************/
607 u16
* decode_rm_word_register(
637 return NULL
; /* NOTREACHED OR REACHED ON ERROR */
640 /****************************************************************************
642 reg - Register to decode
645 Pointer to the appropriate register
648 Return a pointer to the register given by the R/RM field of the
649 modrm byte, for dword operands. Also enables the decoding of instructions.
650 ****************************************************************************/
651 u32
* decode_rm_long_register(
656 DECODE_PRINTF("EAX");
659 DECODE_PRINTF("ECX");
662 DECODE_PRINTF("EDX");
665 DECODE_PRINTF("EBX");
668 DECODE_PRINTF("ESP");
671 DECODE_PRINTF("EBP");
674 DECODE_PRINTF("ESI");
677 DECODE_PRINTF("EDI");
681 return NULL
; /* NOTREACHED OR REACHED ON ERROR */
684 /****************************************************************************
686 reg - Register to decode
689 Pointer to the appropriate register
692 Return a pointer to the register given by the R/RM field of the
693 modrm byte, for word operands, modified from above for the weirdo
694 special case of segreg operands. Also enables the decoding of instructions.
695 ****************************************************************************/
696 u16
* decode_rm_seg_register(
720 DECODE_PRINTF("ILLEGAL SEGREG");
724 return NULL
; /* NOT REACHED OR REACHED ON ERROR */
727 /****************************************************************************
729 scale - scale value of SIB byte
730 index - index value of SIB byte
733 Value of scale * index
736 Decodes scale/index of SIB byte and returns relevant offset part of
738 ****************************************************************************/
739 unsigned decode_sib_si(
745 DECODE_PRINTF2("[%d*", scale
);
751 DECODE_PRINTF("EAX]");
752 return M
.x86
.R_EAX
* index
;
754 DECODE_PRINTF("ECX]");
755 return M
.x86
.R_ECX
* index
;
757 DECODE_PRINTF("EDX]");
758 return M
.x86
.R_EDX
* index
;
760 DECODE_PRINTF("EBX]");
761 return M
.x86
.R_EBX
* index
;
766 DECODE_PRINTF("EBP]");
767 return M
.x86
.R_EBP
* index
;
769 DECODE_PRINTF("ESI]");
770 return M
.x86
.R_ESI
* index
;
772 DECODE_PRINTF("EDI]");
773 return M
.x86
.R_EDI
* index
;
776 return 0; /* NOT REACHED OR REACHED ON ERROR */
779 /****************************************************************************
781 mod - MOD value of preceding ModR/M byte
784 Offset in memory for the address decoding
787 Decodes SIB addressing byte and returns calculated effective address.
788 ****************************************************************************/
789 unsigned decode_sib_address(
792 int sib
= fetch_byte_imm();
793 int ss
= (sib
>> 6) & 0x03;
794 int index
= (sib
>> 3) & 0x07;
795 int base
= sib
& 0x07;
801 DECODE_PRINTF("[EAX]");
802 offset
= M
.x86
.R_EAX
;
805 DECODE_PRINTF("[ECX]");
806 offset
= M
.x86
.R_ECX
;
809 DECODE_PRINTF("[EDX]");
810 offset
= M
.x86
.R_EDX
;
813 DECODE_PRINTF("[EBX]");
814 offset
= M
.x86
.R_EBX
;
817 DECODE_PRINTF("[ESP]");
818 offset
= M
.x86
.R_ESP
;
823 displacement
= (s32
)fetch_long_imm();
824 DECODE_PRINTF2("[%d]", displacement
);
825 offset
= displacement
;
828 displacement
= (s8
)fetch_byte_imm();
829 DECODE_PRINTF2("[%d][EBP]", displacement
);
830 offset
= M
.x86
.R_EBP
+ displacement
;
833 displacement
= (s32
)fetch_long_imm();
834 DECODE_PRINTF2("[%d][EBP]", displacement
);
835 offset
= M
.x86
.R_EBP
+ displacement
;
840 DECODE_PRINTF("[EAX]");
841 offset
= M
.x86
.R_EAX
;
844 DECODE_PRINTF("[ESI]");
845 offset
= M
.x86
.R_ESI
;
848 DECODE_PRINTF("[EDI]");
849 offset
= M
.x86
.R_EDI
;
854 offset
+= decode_sib_si(ss
, index
);
859 /****************************************************************************
861 rm - RM value to decode
864 Offset in memory for the address decoding
867 Return the offset given by mod=00 addressing. Also enables the
868 decoding of instructions.
870 NOTE: The code which specifies the corresponding segment (ds vs ss)
871 below in the case of [BP+..]. The assumption here is that at the
872 point that this subroutine is called, the bit corresponding to
873 SYSMODE_SEG_DS_SS will be zero. After every instruction
874 except the segment override instructions, this bit (as well
875 as any bits indicating segment overrides) will be clear. So
876 if a SS access is needed, set this bit. Otherwise, DS access
877 occurs (unless any of the segment override bits are set).
878 ****************************************************************************/
879 unsigned decode_rm00_address(
884 if (M
.x86
.mode
& SYSMODE_PREFIX_ADDR
) {
885 /* 32-bit addressing */
888 DECODE_PRINTF("[EAX]");
891 DECODE_PRINTF("[ECX]");
894 DECODE_PRINTF("[EDX]");
897 DECODE_PRINTF("[EBX]");
900 return decode_sib_address(0);
902 offset
= fetch_long_imm();
903 DECODE_PRINTF2("[%08x]", offset
);
906 DECODE_PRINTF("[ESI]");
909 DECODE_PRINTF("[EDI]");
913 /* 16-bit addressing */
916 DECODE_PRINTF("[BX+SI]");
917 return (M
.x86
.R_BX
+ M
.x86
.R_SI
) & 0xffff;
919 DECODE_PRINTF("[BX+DI]");
920 return (M
.x86
.R_BX
+ M
.x86
.R_DI
) & 0xffff;
922 DECODE_PRINTF("[BP+SI]");
923 M
.x86
.mode
|= SYSMODE_SEG_DS_SS
;
924 return (M
.x86
.R_BP
+ M
.x86
.R_SI
) & 0xffff;
926 DECODE_PRINTF("[BP+DI]");
927 M
.x86
.mode
|= SYSMODE_SEG_DS_SS
;
928 return (M
.x86
.R_BP
+ M
.x86
.R_DI
) & 0xffff;
930 DECODE_PRINTF("[SI]");
933 DECODE_PRINTF("[DI]");
936 offset
= fetch_word_imm();
937 DECODE_PRINTF2("[%04x]", offset
);
940 DECODE_PRINTF("[BX]");
948 /****************************************************************************
950 rm - RM value to decode
953 Offset in memory for the address decoding
956 Return the offset given by mod=01 addressing. Also enables the
957 decoding of instructions.
958 ****************************************************************************/
959 unsigned decode_rm01_address(
964 if (M
.x86
.mode
& SYSMODE_PREFIX_ADDR
) {
965 /* 32-bit addressing */
967 displacement
= (s8
)fetch_byte_imm();
973 DECODE_PRINTF2("%d[EAX]", displacement
);
974 return M
.x86
.R_EAX
+ displacement
;
976 DECODE_PRINTF2("%d[ECX]", displacement
);
977 return M
.x86
.R_ECX
+ displacement
;
979 DECODE_PRINTF2("%d[EDX]", displacement
);
980 return M
.x86
.R_EDX
+ displacement
;
982 DECODE_PRINTF2("%d[EBX]", displacement
);
983 return M
.x86
.R_EBX
+ displacement
;
985 int offset
= decode_sib_address(1);
986 displacement
= (s8
)fetch_byte_imm();
987 DECODE_PRINTF2("[%d]", displacement
);
988 return offset
+ displacement
;
991 DECODE_PRINTF2("%d[EBP]", displacement
);
992 return M
.x86
.R_EBP
+ displacement
;
994 DECODE_PRINTF2("%d[ESI]", displacement
);
995 return M
.x86
.R_ESI
+ displacement
;
997 DECODE_PRINTF2("%d[EDI]", displacement
);
998 return M
.x86
.R_EDI
+ displacement
;
1001 /* 16-bit addressing */
1002 displacement
= (s8
)fetch_byte_imm();
1005 DECODE_PRINTF2("%d[BX+SI]", displacement
);
1006 return (M
.x86
.R_BX
+ M
.x86
.R_SI
+ displacement
) & 0xffff;
1008 DECODE_PRINTF2("%d[BX+DI]", displacement
);
1009 return (M
.x86
.R_BX
+ M
.x86
.R_DI
+ displacement
) & 0xffff;
1011 DECODE_PRINTF2("%d[BP+SI]", displacement
);
1012 M
.x86
.mode
|= SYSMODE_SEG_DS_SS
;
1013 return (M
.x86
.R_BP
+ M
.x86
.R_SI
+ displacement
) & 0xffff;
1015 DECODE_PRINTF2("%d[BP+DI]", displacement
);
1016 M
.x86
.mode
|= SYSMODE_SEG_DS_SS
;
1017 return (M
.x86
.R_BP
+ M
.x86
.R_DI
+ displacement
) & 0xffff;
1019 DECODE_PRINTF2("%d[SI]", displacement
);
1020 return (M
.x86
.R_SI
+ displacement
) & 0xffff;
1022 DECODE_PRINTF2("%d[DI]", displacement
);
1023 return (M
.x86
.R_DI
+ displacement
) & 0xffff;
1025 DECODE_PRINTF2("%d[BP]", displacement
);
1026 M
.x86
.mode
|= SYSMODE_SEG_DS_SS
;
1027 return (M
.x86
.R_BP
+ displacement
) & 0xffff;
1029 DECODE_PRINTF2("%d[BX]", displacement
);
1030 return (M
.x86
.R_BX
+ displacement
) & 0xffff;
1034 return 0; /* SHOULD NOT HAPPEN */
1037 /****************************************************************************
1039 rm - RM value to decode
1042 Offset in memory for the address decoding
1045 Return the offset given by mod=10 addressing. Also enables the
1046 decoding of instructions.
1047 ****************************************************************************/
1048 unsigned decode_rm10_address(
1051 if (M
.x86
.mode
& SYSMODE_PREFIX_ADDR
) {
1054 /* 32-bit addressing */
1056 displacement
= (s32
)fetch_long_imm();
1062 DECODE_PRINTF2("%d[EAX]", displacement
);
1063 return M
.x86
.R_EAX
+ displacement
;
1065 DECODE_PRINTF2("%d[ECX]", displacement
);
1066 return M
.x86
.R_ECX
+ displacement
;
1068 DECODE_PRINTF2("%d[EDX]", displacement
);
1069 return M
.x86
.R_EDX
+ displacement
;
1071 DECODE_PRINTF2("%d[EBX]", displacement
);
1072 return M
.x86
.R_EBX
+ displacement
;
1074 int offset
= decode_sib_address(2);
1075 displacement
= (s32
)fetch_long_imm();
1076 DECODE_PRINTF2("[%d]", displacement
);
1077 return offset
+ displacement
;
1080 DECODE_PRINTF2("%d[EBP]", displacement
);
1081 return M
.x86
.R_EBP
+ displacement
;
1083 DECODE_PRINTF2("%d[ESI]", displacement
);
1084 return M
.x86
.R_ESI
+ displacement
;
1086 DECODE_PRINTF2("%d[EDI]", displacement
);
1087 return M
.x86
.R_EDI
+ displacement
;
1090 int displacement
= (s16
)fetch_word_imm();
1092 /* 16-bit addressing */
1095 DECODE_PRINTF2("%d[BX+SI]", displacement
);
1096 return (M
.x86
.R_BX
+ M
.x86
.R_SI
+ displacement
) & 0xffff;
1098 DECODE_PRINTF2("%d[BX+DI]", displacement
);
1099 return (M
.x86
.R_BX
+ M
.x86
.R_DI
+ displacement
) & 0xffff;
1101 DECODE_PRINTF2("%d[BP+SI]", displacement
);
1102 M
.x86
.mode
|= SYSMODE_SEG_DS_SS
;
1103 return (M
.x86
.R_BP
+ M
.x86
.R_SI
+ displacement
) & 0xffff;
1105 DECODE_PRINTF2("%d[BP+DI]", displacement
);
1106 M
.x86
.mode
|= SYSMODE_SEG_DS_SS
;
1107 return (M
.x86
.R_BP
+ M
.x86
.R_DI
+ displacement
) & 0xffff;
1109 DECODE_PRINTF2("%d[SI]", displacement
);
1110 return (M
.x86
.R_SI
+ displacement
) & 0xffff;
1112 DECODE_PRINTF2("%d[DI]", displacement
);
1113 return (M
.x86
.R_DI
+ displacement
) & 0xffff;
1115 DECODE_PRINTF2("%d[BP]", displacement
);
1116 M
.x86
.mode
|= SYSMODE_SEG_DS_SS
;
1117 return (M
.x86
.R_BP
+ displacement
) & 0xffff;
1119 DECODE_PRINTF2("%d[BX]", displacement
);
1120 return (M
.x86
.R_BX
+ displacement
) & 0xffff;
1124 return 0; /* SHOULD NOT HAPPEN */
1127 /****************************************************************************
1130 rm - RM value to decode
1133 Offset in memory for the address decoding, multiplexing calls to
1134 the decode_rmXX_address functions
1137 Return the offset given by "mod" addressing.
1138 ****************************************************************************/
1140 unsigned decode_rmXX_address(int mod
, int rm
)
1143 return decode_rm00_address(rm
);
1145 return decode_rm01_address(rm
);
1146 return decode_rm10_address(rm
);