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