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