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