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