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 
41 #include "x86emu/x86emui.h"
42 
43 /*----------------------------- Implementation ----------------------------*/
44 
45 /****************************************************************************
46 REMARKS:
47 Handles any pending asychronous interrupts.
48 ****************************************************************************/
x86emu_intr_handle(void)49 static void x86emu_intr_handle(void)
50 {
51         u8      intno;
52 
53         if (M.x86.intr & INTR_SYNCH) {
54                 intno = M.x86.intno;
55                 if (_X86EMU_intrTab[intno]) {
56                         (*_X86EMU_intrTab[intno])(intno);
57                 } else {
58                         push_word((u16)M.x86.R_FLG);
59                         CLEAR_FLAG(F_IF);
60                         CLEAR_FLAG(F_TF);
61                         push_word(M.x86.R_CS);
62                         M.x86.R_CS = mem_access_word(intno * 4 + 2);
63                         push_word(M.x86.R_IP);
64                         M.x86.R_IP = mem_access_word(intno * 4);
65                         M.x86.intr = 0;
66                 }
67         }
68 }
69 
70 /****************************************************************************
71 PARAMETERS:
72 intrnum - Interrupt number to raise
73 
74 REMARKS:
75 Raise the specified interrupt to be handled before the execution of the
76 next instruction.
77 ****************************************************************************/
x86emu_intr_raise(u8 intrnum)78 void x86emu_intr_raise(
79         u8 intrnum)
80 {
81         M.x86.intno = intrnum;
82         M.x86.intr |= INTR_SYNCH;
83 }
84 
85 /****************************************************************************
86 REMARKS:
87 Main execution loop for the emulator. We return from here when the system
88 halts, which is normally caused by a stack fault when we return from the
89 original real mode call.
90 ****************************************************************************/
X86EMU_exec(void)91 void X86EMU_exec(void)
92 {
93         u8 op1;
94 
95         M.x86.intr = 0;
96         DB(x86emu_end_instr();)
97 
98     for (;;) {
99 DB(             if (CHECK_IP_FETCH())
100                   x86emu_check_ip_access();)
101                 /* If debugging, save the IP and CS values. */
102                 SAVE_IP_CS(M.x86.R_CS, M.x86.R_IP);
103                 INC_DECODED_INST_LEN(1);
104                 if (M.x86.intr) {
105                         if (M.x86.intr & INTR_HALTED) {
106 DB(             if (M.x86.R_SP != 0) {
107                     NV_PRINTF(LEVEL_INFO, "halted\n");
108                     X86EMU_trace_regs();
109                     }
110                 else {
111                     if (M.x86.debug)
112                         NV_PRINTF(LEVEL_INFO,
113                                   "Service completed successfully\n");
114                     })
115                                 return;
116             }
117                         if (((M.x86.intr & INTR_SYNCH) && (M.x86.intno == 0 || M.x86.intno == 2)) ||
118                                 !ACCESS_FLAG(F_IF)) {
119                                 x86emu_intr_handle();
120                         }
121                 }
122                 op1 = (*sys_rdb)(((u32)M.x86.R_CS << 4) + (M.x86.R_IP++));
123                 (*x86emu_optab[op1])(op1);
124         if (M.x86.debug & DEBUG_EXIT) {
125             M.x86.debug &= ~DEBUG_EXIT;
126             return;
127         }
128     }
129 }
130 
131 /****************************************************************************
132 REMARKS:
133 Halts the system by setting the halted system flag.
134 ****************************************************************************/
X86EMU_halt_sys(void)135 void X86EMU_halt_sys(void)
136 {
137         M.x86.intr |= INTR_HALTED;
138 }
139 
140 /****************************************************************************
141 PARAMETERS:
142 mod             - Mod value from decoded byte
143 regh    - Reg h value from decoded byte
144 regl    - Reg l value from decoded byte
145 
146 REMARKS:
147 Raise the specified interrupt to be handled before the execution of the
148 next instruction.
149 
150 NOTE: Do not inline this function, as (*sys_rdb) is already inline!
151 ****************************************************************************/
fetch_decode_modrm(int * mod,int * regh,int * regl)152 void fetch_decode_modrm(
153         int *mod,
154         int *regh,
155         int *regl)
156 {
157         int fetched;
158 
159 DB(     if (CHECK_IP_FETCH())
160           x86emu_check_ip_access();)
161         fetched = (*sys_rdb)(((u32)M.x86.R_CS << 4) + (M.x86.R_IP++));
162         INC_DECODED_INST_LEN(1);
163         *mod  = (fetched >> 6) & 0x03;
164         *regh = (fetched >> 3) & 0x07;
165     *regl = (fetched >> 0) & 0x07;
166 }
167 
168 /****************************************************************************
169 RETURNS:
170 Immediate byte value read from instruction queue
171 
172 REMARKS:
173 This function returns the immediate byte from the instruction queue, and
174 moves the instruction pointer to the next value.
175 
176 NOTE: Do not inline this function, as (*sys_rdb) is already inline!
177 ****************************************************************************/
fetch_byte_imm(void)178 u8 fetch_byte_imm(void)
179 {
180         u8 fetched;
181 
182 DB(     if (CHECK_IP_FETCH())
183                 x86emu_check_ip_access();)
184         fetched = (*sys_rdb)(((u32)M.x86.R_CS << 4) + (M.x86.R_IP++));
185         INC_DECODED_INST_LEN(1);
186         return fetched;
187 }
188 
189 /****************************************************************************
190 RETURNS:
191 Immediate word value read from instruction queue
192 
193 REMARKS:
194 This function returns the immediate byte from the instruction queue, and
195 moves the instruction pointer to the next value.
196 
197 NOTE: Do not inline this function, as (*sys_rdw) is already inline!
198 ****************************************************************************/
fetch_word_imm(void)199 u16 fetch_word_imm(void)
200 {
201         u16     fetched;
202 
203 DB(     if (CHECK_IP_FETCH())
204                 x86emu_check_ip_access();)
205         fetched = (*sys_rdw)(((u32)M.x86.R_CS << 4) + (M.x86.R_IP));
206         M.x86.R_IP += 2;
207         INC_DECODED_INST_LEN(2);
208         return fetched;
209 }
210 
211 /****************************************************************************
212 RETURNS:
213 Immediate lone value read from instruction queue
214 
215 REMARKS:
216 This function returns the immediate byte from the instruction queue, and
217 moves the instruction pointer to the next value.
218 
219 NOTE: Do not inline this function, as (*sys_rdw) is already inline!
220 ****************************************************************************/
fetch_long_imm(void)221 u32 fetch_long_imm(void)
222 {
223         u32 fetched;
224 
225 DB(     if (CHECK_IP_FETCH())
226           x86emu_check_ip_access();)
227         fetched = (*sys_rdl)(((u32)M.x86.R_CS << 4) + (M.x86.R_IP));
228         M.x86.R_IP += 4;
229         INC_DECODED_INST_LEN(4);
230         return fetched;
231 }
232 
233 /****************************************************************************
234 RETURNS:
235 Value of the default data segment
236 
237 REMARKS:
238 Inline function that returns the default data segment for the current
239 instruction.
240 
241 On the x86 processor, the default segment is not always DS if there is
242 no segment override. Address modes such as -3[BP] or 10[BP+SI] all refer to
243 addresses relative to SS (ie: on the stack). So, at the minimum, all
244 decodings of addressing modes would have to set/clear a bit describing
245 whether the access is relative to DS or SS.  That is the function of the
246 cpu-state-varible M.x86.mode. There are several potential states:
247 
248         repe prefix seen  (handled elsewhere)
249         repne prefix seen  (ditto)
250 
251         cs segment override
252         ds segment override
253         es segment override
254         fs segment override
255         gs segment override
256         ss segment override
257 
258         ds/ss select (in absense of override)
259 
260 Each of the above 7 items are handled with a bit in the mode field.
261 ****************************************************************************/
get_data_segment(void)262 _INLINE u32 get_data_segment(void)
263 {
264 #define GET_SEGMENT(segment)
265         switch (M.x86.mode & SYSMODE_SEGMASK) {
266           case 0:                                       /* default case: use ds register */
267           case SYSMODE_SEGOVR_DS:
268           case SYSMODE_SEGOVR_DS | SYSMODE_SEG_DS_SS:
269                 return  M.x86.R_DS;
270           case SYSMODE_SEG_DS_SS:       /* non-overridden, use ss register */
271                 return  M.x86.R_SS;
272           case SYSMODE_SEGOVR_CS:
273           case SYSMODE_SEGOVR_CS | SYSMODE_SEG_DS_SS:
274                 return  M.x86.R_CS;
275           case SYSMODE_SEGOVR_ES:
276           case SYSMODE_SEGOVR_ES | SYSMODE_SEG_DS_SS:
277                 return  M.x86.R_ES;
278           case SYSMODE_SEGOVR_FS:
279           case SYSMODE_SEGOVR_FS | SYSMODE_SEG_DS_SS:
280                 return  M.x86.R_FS;
281           case SYSMODE_SEGOVR_GS:
282           case SYSMODE_SEGOVR_GS | SYSMODE_SEG_DS_SS:
283                 return  M.x86.R_GS;
284           case SYSMODE_SEGOVR_SS:
285           case SYSMODE_SEGOVR_SS | SYSMODE_SEG_DS_SS:
286                 return  M.x86.R_SS;
287           default:
288 #ifdef X86EMU_DEBUG
289                 NV_PRINTF(LEVEL_INFO,
290                           "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 ****************************************************************************/
fetch_data_byte(uint offset)306 u8 fetch_data_byte(
307         uint offset)
308 {
309 #ifdef X86EMU_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 ****************************************************************************/
fetch_data_word(uint offset)325 u16 fetch_data_word(
326         uint offset)
327 {
328 #ifdef X86EMU_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 ****************************************************************************/
fetch_data_long(uint offset)344 u32 fetch_data_long(
345         uint offset)
346 {
347 #ifdef X86EMU_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 ****************************************************************************/
fetch_data_byte_abs(uint segment,uint offset)364 u8 fetch_data_byte_abs(
365         uint segment,
366         uint offset)
367 {
368 #ifdef X86EMU_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 ****************************************************************************/
fetch_data_word_abs(uint segment,uint offset)385 u16 fetch_data_word_abs(
386         uint segment,
387         uint offset)
388 {
389 #ifdef X86EMU_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 ****************************************************************************/
fetch_data_long_abs(uint segment,uint offset)406 u32 fetch_data_long_abs(
407         uint segment,
408         uint offset)
409 {
410 #ifdef X86EMU_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 ****************************************************************************/
store_data_byte(uint offset,u8 val)428 void store_data_byte(
429         uint offset,
430         u8 val)
431 {
432 #ifdef X86EMU_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 ****************************************************************************/
store_data_word(uint offset,u16 val)450 void store_data_word(
451         uint offset,
452         u16 val)
453 {
454 #ifdef X86EMU_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 ****************************************************************************/
store_data_long(uint offset,u32 val)472 void store_data_long(
473         uint offset,
474         u32 val)
475 {
476 #ifdef X86EMU_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 ****************************************************************************/
store_data_byte_abs(uint segment,uint offset,u8 val)494 void store_data_byte_abs(
495         uint segment,
496         uint offset,
497         u8 val)
498 {
499 #ifdef X86EMU_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 ****************************************************************************/
store_data_word_abs(uint segment,uint offset,u16 val)517 void store_data_word_abs(
518         uint segment,
519         uint offset,
520         u16 val)
521 {
522 #ifdef X86EMU_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 ****************************************************************************/
store_data_long_abs(uint segment,uint offset,u32 val)540 void store_data_long_abs(
541         uint segment,
542         uint offset,
543         u32 val)
544 {
545 #ifdef X86EMU_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 ****************************************************************************/
decode_rm_byte_register(int reg)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 ****************************************************************************/
decode_rm_word_register(int reg)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 ****************************************************************************/
decode_rm_long_register(int reg)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 ****************************************************************************/
decode_rm_seg_register(int reg)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  *
729  * return offset from the SIB Byte
730  */
decode_sib_address(int sib,int mod)731 u32 decode_sib_address(int sib, int mod)
732 {
733     u32 base = 0, i = 0, scale = 1;
734 
735     switch(sib & 0x07) {
736     case 0:
737         DECODE_PRINTF("[EAX]");
738         base = M.x86.R_EAX;
739         break;
740     case 1:
741         DECODE_PRINTF("[ECX]");
742         base = M.x86.R_ECX;
743         break;
744     case 2:
745         DECODE_PRINTF("[EDX]");
746         base = M.x86.R_EDX;
747         break;
748     case 3:
749         DECODE_PRINTF("[EBX]");
750         base = M.x86.R_EBX;
751         break;
752     case 4:
753         DECODE_PRINTF("[ESP]");
754         base = M.x86.R_ESP;
755         M.x86.mode |= SYSMODE_SEG_DS_SS;
756         break;
757     case 5:
758         if (mod == 0) {
759             base = fetch_long_imm();
760             DECODE_PRINTF2("%08x", base);
761         } else {
762             DECODE_PRINTF("[EBP]");
763             base = M.x86.R_ESP;
764             M.x86.mode |= SYSMODE_SEG_DS_SS;
765         }
766         break;
767     case 6:
768         DECODE_PRINTF("[ESI]");
769         base = M.x86.R_ESI;
770         break;
771     case 7:
772         DECODE_PRINTF("[EDI]");
773         base = M.x86.R_EDI;
774         break;
775     }
776     switch ((sib >> 3) & 0x07) {
777     case 0:
778         DECODE_PRINTF("[EAX");
779         i = M.x86.R_EAX;
780         break;
781     case 1:
782         DECODE_PRINTF("[ECX");
783         i = M.x86.R_ECX;
784         break;
785     case 2:
786         DECODE_PRINTF("[EDX");
787         i = M.x86.R_EDX;
788         break;
789     case 3:
790         DECODE_PRINTF("[EBX");
791         i = M.x86.R_EBX;
792         break;
793     case 4:
794         i = 0;
795         break;
796     case 5:
797         DECODE_PRINTF("[EBP");
798         i = M.x86.R_EBP;
799         break;
800     case 6:
801         DECODE_PRINTF("[ESI");
802         i = M.x86.R_ESI;
803         break;
804     case 7:
805         DECODE_PRINTF("[EDI");
806         i = M.x86.R_EDI;
807         break;
808     }
809     scale = 1 << ((sib >> 6) & 0x03);
810     if (((sib >> 3) & 0x07) != 4) {
811         if (scale == 1) {
812             DECODE_PRINTF("]");
813         } else {
814             DECODE_PRINTF2("*%d]", scale);
815         }
816     }
817     return base + (i * scale);
818 }
819 
820 /****************************************************************************
821 PARAMETERS:
822 rm      - RM value to decode
823 
824 RETURNS:
825 Offset in memory for the address decoding
826 
827 REMARKS:
828 Return the offset given by mod=00 addressing.  Also enables the
829 decoding of instructions.
830 
831 NOTE:   The code which specifies the corresponding segment (ds vs ss)
832                 below in the case of [BP+..].  The assumption here is that at the
833                 point that this subroutine is called, the bit corresponding to
834                 SYSMODE_SEG_DS_SS will be zero.  After every instruction
835                 except the segment override instructions, this bit (as well
836                 as any bits indicating segment overrides) will be clear.  So
837                 if a SS access is needed, set this bit.  Otherwise, DS access
838                 occurs (unless any of the segment override bits are set).
839 ****************************************************************************/
decode_rm00_address(int rm)840 u32 decode_rm00_address(
841         int rm)
842 {
843     u32 offset;
844     int sib;
845 
846     if (M.x86.mode & SYSMODE_PREFIX_ADDR) {
847         /* 32-bit addressing */
848         switch (rm) {
849           case 0:
850                 DECODE_PRINTF("[EAX]");
851                 return M.x86.R_EAX;
852           case 1:
853                 DECODE_PRINTF("[ECX]");
854                 return M.x86.R_ECX;
855           case 2:
856                 DECODE_PRINTF("[EDX]");
857                 return M.x86.R_EDX;
858           case 3:
859                 DECODE_PRINTF("[EBX]");
860                 return M.x86.R_EBX;
861           case 4:
862                 sib = fetch_byte_imm();
863                 return decode_sib_address(sib, 0);
864           case 5:
865                 offset = fetch_long_imm();
866                 DECODE_PRINTF2("[%08x]", offset);
867                 return offset;
868           case 6:
869                 DECODE_PRINTF("[ESI]");
870                 return M.x86.R_ESI;
871           case 7:
872                 DECODE_PRINTF("[EDI]");
873                 return M.x86.R_EDI;
874         }
875         HALT_SYS();
876     } else {
877         /* 16-bit addressing */
878         switch (rm) {
879           case 0:
880                 DECODE_PRINTF("[BX+SI]");
881             return (M.x86.R_BX + M.x86.R_SI) & 0xffff;
882           case 1:
883                 DECODE_PRINTF("[BX+DI]");
884             return (M.x86.R_BX + M.x86.R_DI) & 0xffff;
885           case 2:
886                 DECODE_PRINTF("[BP+SI]");
887                 M.x86.mode |= SYSMODE_SEG_DS_SS;
888             return (M.x86.R_BP + M.x86.R_SI) & 0xffff;
889           case 3:
890                 DECODE_PRINTF("[BP+DI]");
891                 M.x86.mode |= SYSMODE_SEG_DS_SS;
892             return (M.x86.R_BP + M.x86.R_DI) & 0xffff;
893           case 4:
894                 DECODE_PRINTF("[SI]");
895                 return M.x86.R_SI;
896           case 5:
897                 DECODE_PRINTF("[DI]");
898                 return M.x86.R_DI;
899           case 6:
900                 offset = fetch_word_imm();
901                 DECODE_PRINTF2("[%04x]", offset);
902                 return offset;
903           case 7:
904                 DECODE_PRINTF("[BX]");
905                 return M.x86.R_BX;
906         }
907         HALT_SYS();
908     }
909     return 0;
910 }
911 
912 /****************************************************************************
913 PARAMETERS:
914 rm      - RM value to decode
915 
916 RETURNS:
917 Offset in memory for the address decoding
918 
919 REMARKS:
920 Return the offset given by mod=01 addressing.  Also enables the
921 decoding of instructions.
922 ****************************************************************************/
decode_rm01_address(int rm)923 u32 decode_rm01_address(
924         int rm)
925 {
926     int displacement = 0;
927     int sib;
928 
929     /* Fetch disp8 if no SIB byte */
930     if (!((M.x86.mode & SYSMODE_PREFIX_ADDR) && (rm == 4)))
931         displacement = (s8)fetch_byte_imm();
932 
933     if (M.x86.mode & SYSMODE_PREFIX_ADDR) {
934         /* 32-bit addressing */
935         switch (rm) {
936           case 0:
937                 DECODE_PRINTF2("%d[EAX]", displacement);
938                 return M.x86.R_EAX + displacement;
939           case 1:
940                 DECODE_PRINTF2("%d[ECX]", displacement);
941                 return M.x86.R_ECX + displacement;
942           case 2:
943                 DECODE_PRINTF2("%d[EDX]", displacement);
944                 return M.x86.R_EDX + displacement;
945           case 3:
946                 DECODE_PRINTF2("%d[EBX]", displacement);
947                 return M.x86.R_EBX + displacement;
948           case 4:
949                 sib = fetch_byte_imm();
950                 displacement = (s8)fetch_byte_imm();
951                 DECODE_PRINTF2("%d", displacement);
952                 return decode_sib_address(sib, 1) + displacement;
953           case 5:
954                 DECODE_PRINTF2("%d[EBP]", displacement);
955                 return M.x86.R_EBP + displacement;
956           case 6:
957                 DECODE_PRINTF2("%d[ESI]", displacement);
958                 return M.x86.R_ESI + displacement;
959           case 7:
960                 DECODE_PRINTF2("%d[EDI]", displacement);
961                 return M.x86.R_EDI + displacement;
962         }
963         HALT_SYS();
964     } else {
965         /* 16-bit addressing */
966         switch (rm) {
967           case 0:
968                 DECODE_PRINTF2("%d[BX+SI]", displacement);
969             return (M.x86.R_BX + M.x86.R_SI + displacement) & 0xffff;
970           case 1:
971                 DECODE_PRINTF2("%d[BX+DI]", displacement);
972             return (M.x86.R_BX + M.x86.R_DI + displacement) & 0xffff;
973           case 2:
974                 DECODE_PRINTF2("%d[BP+SI]", displacement);
975                 M.x86.mode |= SYSMODE_SEG_DS_SS;
976             return (M.x86.R_BP + M.x86.R_SI + displacement) & 0xffff;
977           case 3:
978                 DECODE_PRINTF2("%d[BP+DI]", displacement);
979                 M.x86.mode |= SYSMODE_SEG_DS_SS;
980             return (M.x86.R_BP + M.x86.R_DI + displacement) & 0xffff;
981           case 4:
982                 DECODE_PRINTF2("%d[SI]", displacement);
983             return (M.x86.R_SI + displacement) & 0xffff;
984           case 5:
985                 DECODE_PRINTF2("%d[DI]", displacement);
986             return (M.x86.R_DI + displacement) & 0xffff;
987           case 6:
988                 DECODE_PRINTF2("%d[BP]", displacement);
989                 M.x86.mode |= SYSMODE_SEG_DS_SS;
990             return (M.x86.R_BP + displacement) & 0xffff;
991           case 7:
992                 DECODE_PRINTF2("%d[BX]", displacement);
993             return (M.x86.R_BX + displacement) & 0xffff;
994         }
995         HALT_SYS();
996     }
997     return 0;                   /* SHOULD NOT HAPPEN */
998 }
999 
1000 /****************************************************************************
1001 PARAMETERS:
1002 rm      - RM value to decode
1003 
1004 RETURNS:
1005 Offset in memory for the address decoding
1006 
1007 REMARKS:
1008 Return the offset given by mod=10 addressing.  Also enables the
1009 decoding of instructions.
1010 ****************************************************************************/
decode_rm10_address(int rm)1011 u32 decode_rm10_address(
1012         int rm)
1013 {
1014     u32 displacement = 0;
1015     int sib;
1016 
1017     /* Fetch disp16 if 16-bit addr mode */
1018     if (!(M.x86.mode & SYSMODE_PREFIX_ADDR))
1019         displacement = (u16)fetch_word_imm();
1020     else {
1021         /* Fetch disp32 if no SIB byte */
1022         if (rm != 4)
1023             displacement = (u32)fetch_long_imm();
1024     }
1025 
1026     if (M.x86.mode & SYSMODE_PREFIX_ADDR) {
1027         /* 32-bit addressing */
1028       switch (rm) {
1029           case 0:
1030                 DECODE_PRINTF2("%08x[EAX]", displacement);
1031                 return M.x86.R_EAX + displacement;
1032           case 1:
1033                 DECODE_PRINTF2("%08x[ECX]", displacement);
1034                 return M.x86.R_ECX + displacement;
1035           case 2:
1036                 DECODE_PRINTF2("%08x[EDX]", displacement);
1037                 M.x86.mode |= SYSMODE_SEG_DS_SS;
1038                 return M.x86.R_EDX + displacement;
1039           case 3:
1040                 DECODE_PRINTF2("%08x[EBX]", displacement);
1041                 return M.x86.R_EBX + displacement;
1042           case 4:
1043                 sib = fetch_byte_imm();
1044                 displacement = (u32)fetch_long_imm();
1045                 DECODE_PRINTF2("%08x", displacement);
1046                 return decode_sib_address(sib, 2) + displacement;
1047                 break;
1048           case 5:
1049                 DECODE_PRINTF2("%08x[EBP]", displacement);
1050                 return M.x86.R_EBP + displacement;
1051           case 6:
1052                 DECODE_PRINTF2("%08x[ESI]", displacement);
1053                 return M.x86.R_ESI + displacement;
1054           case 7:
1055                 DECODE_PRINTF2("%08x[EDI]", displacement);
1056                 return M.x86.R_EDI + displacement;
1057         }
1058         HALT_SYS();
1059     } else {
1060         /* 16-bit addressing */
1061       switch (rm) {
1062           case 0:
1063             DECODE_PRINTF2("%04x[BX+SI]", displacement);
1064             return (M.x86.R_BX + M.x86.R_SI + displacement) & 0xffff;
1065           case 1:
1066             DECODE_PRINTF2("%04x[BX+DI]", displacement);
1067             return (M.x86.R_BX + M.x86.R_DI + displacement) & 0xffff;
1068           case 2:
1069                 DECODE_PRINTF2("%04x[BP+SI]", displacement);
1070                 M.x86.mode |= SYSMODE_SEG_DS_SS;
1071             return (M.x86.R_BP + M.x86.R_SI + displacement) & 0xffff;
1072           case 3:
1073                 DECODE_PRINTF2("%04x[BP+DI]", displacement);
1074                 M.x86.mode |= SYSMODE_SEG_DS_SS;
1075             return (M.x86.R_BP + M.x86.R_DI + displacement) & 0xffff;
1076           case 4:
1077             DECODE_PRINTF2("%04x[SI]", displacement);
1078             return (M.x86.R_SI + displacement) & 0xffff;
1079           case 5:
1080             DECODE_PRINTF2("%04x[DI]", displacement);
1081             return (M.x86.R_DI + displacement) & 0xffff;
1082           case 6:
1083                 DECODE_PRINTF2("%04x[BP]", displacement);
1084                 M.x86.mode |= SYSMODE_SEG_DS_SS;
1085             return (M.x86.R_BP + displacement) & 0xffff;
1086           case 7:
1087             DECODE_PRINTF2("%04x[BX]", displacement);
1088             return (M.x86.R_BX + displacement) & 0xffff;
1089         }
1090         HALT_SYS();
1091     }
1092     return 0;
1093     /*NOTREACHED */
1094 }
1095