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