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