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