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