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