blob: 7a9a1ddbff9a55f36e422e0b326b6ac0623ad3b6 [file] [log] [blame]
Jason Jina63ce952007-07-06 08:34:56 +08001/****************************************************************************
2*
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02003* Realmode X86 Emulator Library
Jason Jina63ce952007-07-06 08:34:56 +08004*
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02005* Copyright (C) 1991-2004 SciTech Software, Inc.
6* Copyright (C) David Mosberger-Tang
7* Copyright (C) 1999 Egbert Eich
Jason Jina63ce952007-07-06 08:34:56 +08008*
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
Wolfgang Denk96bb2e02007-08-06 02:17:36 +020017* without specific, written prior permission. The authors makes no
Jason Jina63ce952007-07-06 08:34:56 +080018* 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*
Wolfgang Denk96bb2e02007-08-06 02:17:36 +020031* Language: ANSI C
32* Environment: Any
33* Developer: Kendall Bennett
Jason Jina63ce952007-07-06 08:34:56 +080034*
Wolfgang Denk96bb2e02007-08-06 02:17:36 +020035* Description: This file includes subroutines which are related to
36* instruction decoding and accessess of immediate data via IP. etc.
Jason Jina63ce952007-07-06 08:34:56 +080037*
38****************************************************************************/
Michal Simekc73a4772007-08-16 10:46:28 +020039#include <common.h>
Jason Jina63ce952007-07-06 08:34:56 +080040
Jason Jin7ed5cd92007-08-08 08:33:11 +080041#if defined(CONFIG_BIOSEMU)
42
Michal Simek952d8612007-08-15 21:15:05 +020043#include "x86emu/x86emui.h"
44
Jason Jina63ce952007-07-06 08:34:56 +080045/*----------------------------- Implementation ----------------------------*/
46
47/****************************************************************************
48REMARKS:
49Handles any pending asychronous interrupts.
50****************************************************************************/
51static void x86emu_intr_handle(void)
52{
Wolfgang Denk96bb2e02007-08-06 02:17:36 +020053 u8 intno;
Jason Jina63ce952007-07-06 08:34:56 +080054
55 if (M.x86.intr & INTR_SYNCH) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +020056 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 }
Jason Jina63ce952007-07-06 08:34:56 +080069 }
70}
71
72/****************************************************************************
73PARAMETERS:
74intrnum - Interrupt number to raise
75
76REMARKS:
77Raise the specified interrupt to be handled before the execution of the
78next instruction.
79****************************************************************************/
80void x86emu_intr_raise(
81 u8 intrnum)
82{
83 M.x86.intno = intrnum;
84 M.x86.intr |= INTR_SYNCH;
85}
86
87/****************************************************************************
88REMARKS:
89Main execution loop for the emulator. We return from here when the system
90halts, which is normally caused by a stack fault when we return from the
91original real mode call.
92****************************************************************************/
93void X86EMU_exec(void)
94{
95 u8 op1;
96
97 M.x86.intr = 0;
98 DB(x86emu_end_instr();)
99
100 for (;;) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200101DB( if (CHECK_IP_FETCH())
102 x86emu_check_ip_access();)
103 /* If debugging, save the IP and CS values. */
104 SAVE_IP_CS(M.x86.R_CS, M.x86.R_IP);
105 INC_DECODED_INST_LEN(1);
106 if (M.x86.intr) {
107 if (M.x86.intr & INTR_HALTED) {
108DB( if (M.x86.R_SP != 0) {
109 printk("halted\n");
110 X86EMU_trace_regs();
111 }
112 else {
113 if (M.x86.debug)
114 printk("Service completed successfully\n");
115 })
116 return;
117 }
118 if (((M.x86.intr & INTR_SYNCH) && (M.x86.intno == 0 || M.x86.intno == 2)) ||
119 !ACCESS_FLAG(F_IF)) {
120 x86emu_intr_handle();
121 }
122 }
123 op1 = (*sys_rdb)(((u32)M.x86.R_CS << 4) + (M.x86.R_IP++));
124 (*x86emu_optab[op1])(op1);
125 if (M.x86.debug & DEBUG_EXIT) {
126 M.x86.debug &= ~DEBUG_EXIT;
127 return;
128 }
Jason Jina63ce952007-07-06 08:34:56 +0800129 }
130}
131
132/****************************************************************************
133REMARKS:
134Halts the system by setting the halted system flag.
135****************************************************************************/
136void X86EMU_halt_sys(void)
137{
138 M.x86.intr |= INTR_HALTED;
139}
140
141/****************************************************************************
142PARAMETERS:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200143mod - Mod value from decoded byte
144regh - Reg h value from decoded byte
145regl - Reg l value from decoded byte
Jason Jina63ce952007-07-06 08:34:56 +0800146
147REMARKS:
148Raise the specified interrupt to be handled before the execution of the
149next instruction.
150
151NOTE: Do not inline this function, as (*sys_rdb) is already inline!
152****************************************************************************/
153void fetch_decode_modrm(
154 int *mod,
155 int *regh,
156 int *regl)
157{
158 int fetched;
159
160DB( if (CHECK_IP_FETCH())
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200161 x86emu_check_ip_access();)
Jason Jina63ce952007-07-06 08:34:56 +0800162 fetched = (*sys_rdb)(((u32)M.x86.R_CS << 4) + (M.x86.R_IP++));
163 INC_DECODED_INST_LEN(1);
164 *mod = (fetched >> 6) & 0x03;
165 *regh = (fetched >> 3) & 0x07;
166 *regl = (fetched >> 0) & 0x07;
167}
168
169/****************************************************************************
170RETURNS:
171Immediate byte value read from instruction queue
172
173REMARKS:
174This function returns the immediate byte from the instruction queue, and
175moves the instruction pointer to the next value.
176
177NOTE: Do not inline this function, as (*sys_rdb) is already inline!
178****************************************************************************/
179u8 fetch_byte_imm(void)
180{
181 u8 fetched;
182
183DB( if (CHECK_IP_FETCH())
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200184 x86emu_check_ip_access();)
Jason Jina63ce952007-07-06 08:34:56 +0800185 fetched = (*sys_rdb)(((u32)M.x86.R_CS << 4) + (M.x86.R_IP++));
186 INC_DECODED_INST_LEN(1);
187 return fetched;
188}
189
190/****************************************************************************
191RETURNS:
192Immediate word value read from instruction queue
193
194REMARKS:
195This function returns the immediate byte from the instruction queue, and
196moves the instruction pointer to the next value.
197
198NOTE: Do not inline this function, as (*sys_rdw) is already inline!
199****************************************************************************/
200u16 fetch_word_imm(void)
201{
202 u16 fetched;
203
204DB( if (CHECK_IP_FETCH())
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200205 x86emu_check_ip_access();)
Jason Jina63ce952007-07-06 08:34:56 +0800206 fetched = (*sys_rdw)(((u32)M.x86.R_CS << 4) + (M.x86.R_IP));
207 M.x86.R_IP += 2;
208 INC_DECODED_INST_LEN(2);
209 return fetched;
210}
211
212/****************************************************************************
213RETURNS:
214Immediate lone value read from instruction queue
215
216REMARKS:
217This function returns the immediate byte from the instruction queue, and
218moves the instruction pointer to the next value.
219
220NOTE: Do not inline this function, as (*sys_rdw) is already inline!
221****************************************************************************/
222u32 fetch_long_imm(void)
223{
224 u32 fetched;
225
226DB( if (CHECK_IP_FETCH())
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200227 x86emu_check_ip_access();)
Jason Jina63ce952007-07-06 08:34:56 +0800228 fetched = (*sys_rdl)(((u32)M.x86.R_CS << 4) + (M.x86.R_IP));
229 M.x86.R_IP += 4;
230 INC_DECODED_INST_LEN(4);
231 return fetched;
232}
233
234/****************************************************************************
235RETURNS:
236Value of the default data segment
237
238REMARKS:
239Inline function that returns the default data segment for the current
240instruction.
241
242On the x86 processor, the default segment is not always DS if there is
243no segment override. Address modes such as -3[BP] or 10[BP+SI] all refer to
244addresses relative to SS (ie: on the stack). So, at the minimum, all
245decodings of addressing modes would have to set/clear a bit describing
246whether the access is relative to DS or SS. That is the function of the
247cpu-state-varible M.x86.mode. There are several potential states:
248
249 repe prefix seen (handled elsewhere)
250 repne prefix seen (ditto)
251
252 cs segment override
253 ds segment override
254 es segment override
255 fs segment override
256 gs segment override
257 ss segment override
258
259 ds/ss select (in absense of override)
260
261Each of the above 7 items are handled with a bit in the mode field.
262****************************************************************************/
263_INLINE u32 get_data_segment(void)
264{
265#define GET_SEGMENT(segment)
266 switch (M.x86.mode & SYSMODE_SEGMASK) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200267 case 0: /* default case: use ds register */
Jason Jina63ce952007-07-06 08:34:56 +0800268 case SYSMODE_SEGOVR_DS:
269 case SYSMODE_SEGOVR_DS | SYSMODE_SEG_DS_SS:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200270 return M.x86.R_DS;
271 case SYSMODE_SEG_DS_SS: /* non-overridden, use ss register */
272 return M.x86.R_SS;
Jason Jina63ce952007-07-06 08:34:56 +0800273 case SYSMODE_SEGOVR_CS:
274 case SYSMODE_SEGOVR_CS | SYSMODE_SEG_DS_SS:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200275 return M.x86.R_CS;
Jason Jina63ce952007-07-06 08:34:56 +0800276 case SYSMODE_SEGOVR_ES:
277 case SYSMODE_SEGOVR_ES | SYSMODE_SEG_DS_SS:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200278 return M.x86.R_ES;
Jason Jina63ce952007-07-06 08:34:56 +0800279 case SYSMODE_SEGOVR_FS:
280 case SYSMODE_SEGOVR_FS | SYSMODE_SEG_DS_SS:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200281 return M.x86.R_FS;
Jason Jina63ce952007-07-06 08:34:56 +0800282 case SYSMODE_SEGOVR_GS:
283 case SYSMODE_SEGOVR_GS | SYSMODE_SEG_DS_SS:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200284 return M.x86.R_GS;
Jason Jina63ce952007-07-06 08:34:56 +0800285 case SYSMODE_SEGOVR_SS:
286 case SYSMODE_SEGOVR_SS | SYSMODE_SEG_DS_SS:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200287 return M.x86.R_SS;
Jason Jina63ce952007-07-06 08:34:56 +0800288 default:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200289#ifdef DEBUG
290 printk("error: should not happen: multiple overrides.\n");
Jason Jina63ce952007-07-06 08:34:56 +0800291#endif
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200292 HALT_SYS();
293 return 0;
Jason Jina63ce952007-07-06 08:34:56 +0800294 }
295}
296
297/****************************************************************************
298PARAMETERS:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200299offset - Offset to load data from
Jason Jina63ce952007-07-06 08:34:56 +0800300
301RETURNS:
302Byte value read from the absolute memory location.
303
304NOTE: Do not inline this function as (*sys_rdX) is already inline!
305****************************************************************************/
306u8 fetch_data_byte(
307 uint offset)
308{
309#ifdef DEBUG
310 if (CHECK_DATA_ACCESS())
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200311 x86emu_check_data_access((u16)get_data_segment(), offset);
Jason Jina63ce952007-07-06 08:34:56 +0800312#endif
313 return (*sys_rdb)((get_data_segment() << 4) + offset);
314}
315
316/****************************************************************************
317PARAMETERS:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200318offset - Offset to load data from
Jason Jina63ce952007-07-06 08:34:56 +0800319
320RETURNS:
321Word value read from the absolute memory location.
322
323NOTE: Do not inline this function as (*sys_rdX) is already inline!
324****************************************************************************/
325u16 fetch_data_word(
326 uint offset)
327{
328#ifdef DEBUG
329 if (CHECK_DATA_ACCESS())
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200330 x86emu_check_data_access((u16)get_data_segment(), offset);
Jason Jina63ce952007-07-06 08:34:56 +0800331#endif
332 return (*sys_rdw)((get_data_segment() << 4) + offset);
333}
334
335/****************************************************************************
336PARAMETERS:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200337offset - Offset to load data from
Jason Jina63ce952007-07-06 08:34:56 +0800338
339RETURNS:
340Long value read from the absolute memory location.
341
342NOTE: Do not inline this function as (*sys_rdX) is already inline!
343****************************************************************************/
344u32 fetch_data_long(
345 uint offset)
346{
347#ifdef DEBUG
348 if (CHECK_DATA_ACCESS())
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200349 x86emu_check_data_access((u16)get_data_segment(), offset);
Jason Jina63ce952007-07-06 08:34:56 +0800350#endif
351 return (*sys_rdl)((get_data_segment() << 4) + offset);
352}
353
354/****************************************************************************
355PARAMETERS:
356segment - Segment to load data from
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200357offset - Offset to load data from
Jason Jina63ce952007-07-06 08:34:56 +0800358
359RETURNS:
360Byte value read from the absolute memory location.
361
362NOTE: Do not inline this function as (*sys_rdX) is already inline!
363****************************************************************************/
364u8 fetch_data_byte_abs(
365 uint segment,
366 uint offset)
367{
368#ifdef DEBUG
369 if (CHECK_DATA_ACCESS())
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200370 x86emu_check_data_access(segment, offset);
Jason Jina63ce952007-07-06 08:34:56 +0800371#endif
372 return (*sys_rdb)(((u32)segment << 4) + offset);
373}
374
375/****************************************************************************
376PARAMETERS:
377segment - Segment to load data from
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200378offset - Offset to load data from
Jason Jina63ce952007-07-06 08:34:56 +0800379
380RETURNS:
381Word value read from the absolute memory location.
382
383NOTE: Do not inline this function as (*sys_rdX) is already inline!
384****************************************************************************/
385u16 fetch_data_word_abs(
386 uint segment,
387 uint offset)
388{
389#ifdef DEBUG
390 if (CHECK_DATA_ACCESS())
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200391 x86emu_check_data_access(segment, offset);
Jason Jina63ce952007-07-06 08:34:56 +0800392#endif
393 return (*sys_rdw)(((u32)segment << 4) + offset);
394}
395
396/****************************************************************************
397PARAMETERS:
398segment - Segment to load data from
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200399offset - Offset to load data from
Jason Jina63ce952007-07-06 08:34:56 +0800400
401RETURNS:
402Long value read from the absolute memory location.
403
404NOTE: Do not inline this function as (*sys_rdX) is already inline!
405****************************************************************************/
406u32 fetch_data_long_abs(
407 uint segment,
408 uint offset)
409{
410#ifdef DEBUG
411 if (CHECK_DATA_ACCESS())
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200412 x86emu_check_data_access(segment, offset);
Jason Jina63ce952007-07-06 08:34:56 +0800413#endif
414 return (*sys_rdl)(((u32)segment << 4) + offset);
415}
416
417/****************************************************************************
418PARAMETERS:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200419offset - Offset to store data at
420val - Value to store
Jason Jina63ce952007-07-06 08:34:56 +0800421
422REMARKS:
423Writes a word value to an segmented memory location. The segment used is
424the current 'default' segment, which may have been overridden.
425
426NOTE: Do not inline this function as (*sys_wrX) is already inline!
427****************************************************************************/
428void store_data_byte(
429 uint offset,
430 u8 val)
431{
432#ifdef DEBUG
433 if (CHECK_DATA_ACCESS())
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200434 x86emu_check_data_access((u16)get_data_segment(), offset);
Jason Jina63ce952007-07-06 08:34:56 +0800435#endif
436 (*sys_wrb)((get_data_segment() << 4) + offset, val);
437}
438
439/****************************************************************************
440PARAMETERS:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200441offset - Offset to store data at
442val - Value to store
Jason Jina63ce952007-07-06 08:34:56 +0800443
444REMARKS:
445Writes a word value to an segmented memory location. The segment used is
446the current 'default' segment, which may have been overridden.
447
448NOTE: Do not inline this function as (*sys_wrX) is already inline!
449****************************************************************************/
450void store_data_word(
451 uint offset,
452 u16 val)
453{
454#ifdef DEBUG
455 if (CHECK_DATA_ACCESS())
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200456 x86emu_check_data_access((u16)get_data_segment(), offset);
Jason Jina63ce952007-07-06 08:34:56 +0800457#endif
458 (*sys_wrw)((get_data_segment() << 4) + offset, val);
459}
460
461/****************************************************************************
462PARAMETERS:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200463offset - Offset to store data at
464val - Value to store
Jason Jina63ce952007-07-06 08:34:56 +0800465
466REMARKS:
467Writes a long value to an segmented memory location. The segment used is
468the current 'default' segment, which may have been overridden.
469
470NOTE: Do not inline this function as (*sys_wrX) is already inline!
471****************************************************************************/
472void store_data_long(
473 uint offset,
474 u32 val)
475{
476#ifdef DEBUG
477 if (CHECK_DATA_ACCESS())
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200478 x86emu_check_data_access((u16)get_data_segment(), offset);
Jason Jina63ce952007-07-06 08:34:56 +0800479#endif
480 (*sys_wrl)((get_data_segment() << 4) + offset, val);
481}
482
483/****************************************************************************
484PARAMETERS:
485segment - Segment to store data at
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200486offset - Offset to store data at
487val - Value to store
Jason Jina63ce952007-07-06 08:34:56 +0800488
489REMARKS:
490Writes a byte value to an absolute memory location.
491
492NOTE: Do not inline this function as (*sys_wrX) is already inline!
493****************************************************************************/
494void store_data_byte_abs(
495 uint segment,
496 uint offset,
497 u8 val)
498{
499#ifdef DEBUG
500 if (CHECK_DATA_ACCESS())
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200501 x86emu_check_data_access(segment, offset);
Jason Jina63ce952007-07-06 08:34:56 +0800502#endif
503 (*sys_wrb)(((u32)segment << 4) + offset, val);
504}
505
506/****************************************************************************
507PARAMETERS:
508segment - Segment to store data at
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200509offset - Offset to store data at
510val - Value to store
Jason Jina63ce952007-07-06 08:34:56 +0800511
512REMARKS:
513Writes a word value to an absolute memory location.
514
515NOTE: Do not inline this function as (*sys_wrX) is already inline!
516****************************************************************************/
517void store_data_word_abs(
518 uint segment,
519 uint offset,
520 u16 val)
521{
522#ifdef DEBUG
523 if (CHECK_DATA_ACCESS())
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200524 x86emu_check_data_access(segment, offset);
Jason Jina63ce952007-07-06 08:34:56 +0800525#endif
526 (*sys_wrw)(((u32)segment << 4) + offset, val);
527}
528
529/****************************************************************************
530PARAMETERS:
531segment - Segment to store data at
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200532offset - Offset to store data at
533val - Value to store
Jason Jina63ce952007-07-06 08:34:56 +0800534
535REMARKS:
536Writes a long value to an absolute memory location.
537
538NOTE: Do not inline this function as (*sys_wrX) is already inline!
539****************************************************************************/
540void store_data_long_abs(
541 uint segment,
542 uint offset,
543 u32 val)
544{
545#ifdef DEBUG
546 if (CHECK_DATA_ACCESS())
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200547 x86emu_check_data_access(segment, offset);
Jason Jina63ce952007-07-06 08:34:56 +0800548#endif
549 (*sys_wrl)(((u32)segment << 4) + offset, val);
550}
551
552/****************************************************************************
553PARAMETERS:
554reg - Register to decode
555
556RETURNS:
557Pointer to the appropriate register
558
559REMARKS:
560Return a pointer to the register given by the R/RM field of the
561modrm byte, for byte operands. Also enables the decoding of instructions.
562****************************************************************************/
563u8* decode_rm_byte_register(
564 int reg)
565{
566 switch (reg) {
567 case 0:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200568 DECODE_PRINTF("AL");
569 return &M.x86.R_AL;
Jason Jina63ce952007-07-06 08:34:56 +0800570 case 1:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200571 DECODE_PRINTF("CL");
572 return &M.x86.R_CL;
Jason Jina63ce952007-07-06 08:34:56 +0800573 case 2:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200574 DECODE_PRINTF("DL");
575 return &M.x86.R_DL;
Jason Jina63ce952007-07-06 08:34:56 +0800576 case 3:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200577 DECODE_PRINTF("BL");
578 return &M.x86.R_BL;
Jason Jina63ce952007-07-06 08:34:56 +0800579 case 4:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200580 DECODE_PRINTF("AH");
581 return &M.x86.R_AH;
Jason Jina63ce952007-07-06 08:34:56 +0800582 case 5:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200583 DECODE_PRINTF("CH");
584 return &M.x86.R_CH;
Jason Jina63ce952007-07-06 08:34:56 +0800585 case 6:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200586 DECODE_PRINTF("DH");
587 return &M.x86.R_DH;
Jason Jina63ce952007-07-06 08:34:56 +0800588 case 7:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200589 DECODE_PRINTF("BH");
590 return &M.x86.R_BH;
Jason Jina63ce952007-07-06 08:34:56 +0800591 }
592 HALT_SYS();
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200593 return NULL; /* NOT REACHED OR REACHED ON ERROR */
Jason Jina63ce952007-07-06 08:34:56 +0800594}
595
596/****************************************************************************
597PARAMETERS:
598reg - Register to decode
599
600RETURNS:
601Pointer to the appropriate register
602
603REMARKS:
604Return a pointer to the register given by the R/RM field of the
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200605modrm byte, for word operands. Also enables the decoding of instructions.
Jason Jina63ce952007-07-06 08:34:56 +0800606****************************************************************************/
607u16* decode_rm_word_register(
608 int reg)
609{
610 switch (reg) {
611 case 0:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200612 DECODE_PRINTF("AX");
613 return &M.x86.R_AX;
Jason Jina63ce952007-07-06 08:34:56 +0800614 case 1:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200615 DECODE_PRINTF("CX");
616 return &M.x86.R_CX;
Jason Jina63ce952007-07-06 08:34:56 +0800617 case 2:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200618 DECODE_PRINTF("DX");
619 return &M.x86.R_DX;
Jason Jina63ce952007-07-06 08:34:56 +0800620 case 3:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200621 DECODE_PRINTF("BX");
622 return &M.x86.R_BX;
Jason Jina63ce952007-07-06 08:34:56 +0800623 case 4:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200624 DECODE_PRINTF("SP");
625 return &M.x86.R_SP;
Jason Jina63ce952007-07-06 08:34:56 +0800626 case 5:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200627 DECODE_PRINTF("BP");
628 return &M.x86.R_BP;
Jason Jina63ce952007-07-06 08:34:56 +0800629 case 6:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200630 DECODE_PRINTF("SI");
631 return &M.x86.R_SI;
Jason Jina63ce952007-07-06 08:34:56 +0800632 case 7:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200633 DECODE_PRINTF("DI");
634 return &M.x86.R_DI;
Jason Jina63ce952007-07-06 08:34:56 +0800635 }
636 HALT_SYS();
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200637 return NULL; /* NOTREACHED OR REACHED ON ERROR */
Jason Jina63ce952007-07-06 08:34:56 +0800638}
639
640/****************************************************************************
641PARAMETERS:
642reg - Register to decode
643
644RETURNS:
645Pointer to the appropriate register
646
647REMARKS:
648Return a pointer to the register given by the R/RM field of the
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200649modrm byte, for dword operands. Also enables the decoding of instructions.
Jason Jina63ce952007-07-06 08:34:56 +0800650****************************************************************************/
651u32* decode_rm_long_register(
652 int reg)
653{
654 switch (reg) {
655 case 0:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200656 DECODE_PRINTF("EAX");
657 return &M.x86.R_EAX;
Jason Jina63ce952007-07-06 08:34:56 +0800658 case 1:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200659 DECODE_PRINTF("ECX");
660 return &M.x86.R_ECX;
Jason Jina63ce952007-07-06 08:34:56 +0800661 case 2:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200662 DECODE_PRINTF("EDX");
663 return &M.x86.R_EDX;
Jason Jina63ce952007-07-06 08:34:56 +0800664 case 3:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200665 DECODE_PRINTF("EBX");
666 return &M.x86.R_EBX;
Jason Jina63ce952007-07-06 08:34:56 +0800667 case 4:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200668 DECODE_PRINTF("ESP");
669 return &M.x86.R_ESP;
Jason Jina63ce952007-07-06 08:34:56 +0800670 case 5:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200671 DECODE_PRINTF("EBP");
672 return &M.x86.R_EBP;
Jason Jina63ce952007-07-06 08:34:56 +0800673 case 6:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200674 DECODE_PRINTF("ESI");
675 return &M.x86.R_ESI;
Jason Jina63ce952007-07-06 08:34:56 +0800676 case 7:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200677 DECODE_PRINTF("EDI");
678 return &M.x86.R_EDI;
Jason Jina63ce952007-07-06 08:34:56 +0800679 }
680 HALT_SYS();
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200681 return NULL; /* NOTREACHED OR REACHED ON ERROR */
Jason Jina63ce952007-07-06 08:34:56 +0800682}
683
684/****************************************************************************
685PARAMETERS:
686reg - Register to decode
687
688RETURNS:
689Pointer to the appropriate register
690
691REMARKS:
692Return a pointer to the register given by the R/RM field of the
693modrm byte, for word operands, modified from above for the weirdo
694special case of segreg operands. Also enables the decoding of instructions.
695****************************************************************************/
696u16* decode_rm_seg_register(
697 int reg)
698{
699 switch (reg) {
700 case 0:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200701 DECODE_PRINTF("ES");
702 return &M.x86.R_ES;
Jason Jina63ce952007-07-06 08:34:56 +0800703 case 1:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200704 DECODE_PRINTF("CS");
705 return &M.x86.R_CS;
Jason Jina63ce952007-07-06 08:34:56 +0800706 case 2:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200707 DECODE_PRINTF("SS");
708 return &M.x86.R_SS;
Jason Jina63ce952007-07-06 08:34:56 +0800709 case 3:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200710 DECODE_PRINTF("DS");
711 return &M.x86.R_DS;
Jason Jina63ce952007-07-06 08:34:56 +0800712 case 4:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200713 DECODE_PRINTF("FS");
714 return &M.x86.R_FS;
Jason Jina63ce952007-07-06 08:34:56 +0800715 case 5:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200716 DECODE_PRINTF("GS");
717 return &M.x86.R_GS;
Jason Jina63ce952007-07-06 08:34:56 +0800718 case 6:
719 case 7:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200720 DECODE_PRINTF("ILLEGAL SEGREG");
721 break;
Jason Jina63ce952007-07-06 08:34:56 +0800722 }
723 HALT_SYS();
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200724 return NULL; /* NOT REACHED OR REACHED ON ERROR */
Jason Jina63ce952007-07-06 08:34:56 +0800725}
726
727/****************************************************************************
728PARAMETERS:
729scale - scale value of SIB byte
730index - index value of SIB byte
731
732RETURNS:
733Value of scale * index
734
735REMARKS:
736Decodes scale/index of SIB byte and returns relevant offset part of
737effective address.
738****************************************************************************/
739unsigned decode_sib_si(
740 int scale,
741 int index)
742{
743 scale = 1 << scale;
744 if (scale > 1) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200745 DECODE_PRINTF2("[%d*", scale);
Jason Jina63ce952007-07-06 08:34:56 +0800746 } else {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200747 DECODE_PRINTF("[");
Jason Jina63ce952007-07-06 08:34:56 +0800748 }
749 switch (index) {
750 case 0:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200751 DECODE_PRINTF("EAX]");
752 return M.x86.R_EAX * index;
Jason Jina63ce952007-07-06 08:34:56 +0800753 case 1:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200754 DECODE_PRINTF("ECX]");
755 return M.x86.R_ECX * index;
Jason Jina63ce952007-07-06 08:34:56 +0800756 case 2:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200757 DECODE_PRINTF("EDX]");
758 return M.x86.R_EDX * index;
Jason Jina63ce952007-07-06 08:34:56 +0800759 case 3:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200760 DECODE_PRINTF("EBX]");
761 return M.x86.R_EBX * index;
Jason Jina63ce952007-07-06 08:34:56 +0800762 case 4:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200763 DECODE_PRINTF("0]");
764 return 0;
Jason Jina63ce952007-07-06 08:34:56 +0800765 case 5:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200766 DECODE_PRINTF("EBP]");
767 return M.x86.R_EBP * index;
Jason Jina63ce952007-07-06 08:34:56 +0800768 case 6:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200769 DECODE_PRINTF("ESI]");
770 return M.x86.R_ESI * index;
Jason Jina63ce952007-07-06 08:34:56 +0800771 case 7:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200772 DECODE_PRINTF("EDI]");
773 return M.x86.R_EDI * index;
Jason Jina63ce952007-07-06 08:34:56 +0800774 }
775 HALT_SYS();
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200776 return 0; /* NOT REACHED OR REACHED ON ERROR */
Jason Jina63ce952007-07-06 08:34:56 +0800777}
778
779/****************************************************************************
780PARAMETERS:
781mod - MOD value of preceding ModR/M byte
782
783RETURNS:
784Offset in memory for the address decoding
785
786REMARKS:
787Decodes SIB addressing byte and returns calculated effective address.
788****************************************************************************/
789unsigned decode_sib_address(
790 int mod)
791{
792 int sib = fetch_byte_imm();
793 int ss = (sib >> 6) & 0x03;
794 int index = (sib >> 3) & 0x07;
795 int base = sib & 0x07;
796 int offset = 0;
797 int displacement;
798
799 switch (base) {
800 case 0:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200801 DECODE_PRINTF("[EAX]");
802 offset = M.x86.R_EAX;
803 break;
Jason Jina63ce952007-07-06 08:34:56 +0800804 case 1:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200805 DECODE_PRINTF("[ECX]");
806 offset = M.x86.R_ECX;
807 break;
Jason Jina63ce952007-07-06 08:34:56 +0800808 case 2:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200809 DECODE_PRINTF("[EDX]");
810 offset = M.x86.R_EDX;
811 break;
Jason Jina63ce952007-07-06 08:34:56 +0800812 case 3:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200813 DECODE_PRINTF("[EBX]");
814 offset = M.x86.R_EBX;
815 break;
Jason Jina63ce952007-07-06 08:34:56 +0800816 case 4:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200817 DECODE_PRINTF("[ESP]");
818 offset = M.x86.R_ESP;
819 break;
Jason Jina63ce952007-07-06 08:34:56 +0800820 case 5:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200821 switch (mod) {
822 case 0:
823 displacement = (s32)fetch_long_imm();
824 DECODE_PRINTF2("[%d]", displacement);
825 offset = displacement;
826 break;
827 case 1:
828 displacement = (s8)fetch_byte_imm();
829 DECODE_PRINTF2("[%d][EBP]", displacement);
830 offset = M.x86.R_EBP + displacement;
831 break;
832 case 2:
833 displacement = (s32)fetch_long_imm();
834 DECODE_PRINTF2("[%d][EBP]", displacement);
835 offset = M.x86.R_EBP + displacement;
836 break;
837 default:
838 HALT_SYS();
839 }
840 DECODE_PRINTF("[EAX]");
841 offset = M.x86.R_EAX;
842 break;
Jason Jina63ce952007-07-06 08:34:56 +0800843 case 6:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200844 DECODE_PRINTF("[ESI]");
845 offset = M.x86.R_ESI;
846 break;
Jason Jina63ce952007-07-06 08:34:56 +0800847 case 7:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200848 DECODE_PRINTF("[EDI]");
849 offset = M.x86.R_EDI;
850 break;
Jason Jina63ce952007-07-06 08:34:56 +0800851 default:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200852 HALT_SYS();
Jason Jina63ce952007-07-06 08:34:56 +0800853 }
854 offset += decode_sib_si(ss, index);
855 return offset;
856
857}
858
859/****************************************************************************
860PARAMETERS:
861rm - RM value to decode
862
863RETURNS:
864Offset in memory for the address decoding
865
866REMARKS:
867Return the offset given by mod=00 addressing. Also enables the
868decoding of instructions.
869
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200870NOTE: The code which specifies the corresponding segment (ds vs ss)
871 below in the case of [BP+..]. The assumption here is that at the
872 point that this subroutine is called, the bit corresponding to
873 SYSMODE_SEG_DS_SS will be zero. After every instruction
874 except the segment override instructions, this bit (as well
875 as any bits indicating segment overrides) will be clear. So
876 if a SS access is needed, set this bit. Otherwise, DS access
877 occurs (unless any of the segment override bits are set).
Jason Jina63ce952007-07-06 08:34:56 +0800878****************************************************************************/
879unsigned decode_rm00_address(
880 int rm)
881{
882 unsigned offset;
883
884 if (M.x86.mode & SYSMODE_PREFIX_ADDR) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200885 /* 32-bit addressing */
886 switch (rm) {
887 case 0:
888 DECODE_PRINTF("[EAX]");
889 return M.x86.R_EAX;
890 case 1:
891 DECODE_PRINTF("[ECX]");
892 return M.x86.R_ECX;
893 case 2:
894 DECODE_PRINTF("[EDX]");
895 return M.x86.R_EDX;
896 case 3:
897 DECODE_PRINTF("[EBX]");
898 return M.x86.R_EBX;
899 case 4:
900 return decode_sib_address(0);
901 case 5:
902 offset = fetch_long_imm();
903 DECODE_PRINTF2("[%08x]", offset);
904 return offset;
905 case 6:
906 DECODE_PRINTF("[ESI]");
907 return M.x86.R_ESI;
908 case 7:
909 DECODE_PRINTF("[EDI]");
910 return M.x86.R_EDI;
911 }
Jason Jina63ce952007-07-06 08:34:56 +0800912 } else {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200913 /* 16-bit addressing */
914 switch (rm) {
915 case 0:
916 DECODE_PRINTF("[BX+SI]");
917 return (M.x86.R_BX + M.x86.R_SI) & 0xffff;
918 case 1:
919 DECODE_PRINTF("[BX+DI]");
920 return (M.x86.R_BX + M.x86.R_DI) & 0xffff;
921 case 2:
922 DECODE_PRINTF("[BP+SI]");
923 M.x86.mode |= SYSMODE_SEG_DS_SS;
924 return (M.x86.R_BP + M.x86.R_SI) & 0xffff;
925 case 3:
926 DECODE_PRINTF("[BP+DI]");
927 M.x86.mode |= SYSMODE_SEG_DS_SS;
928 return (M.x86.R_BP + M.x86.R_DI) & 0xffff;
929 case 4:
930 DECODE_PRINTF("[SI]");
931 return M.x86.R_SI;
932 case 5:
933 DECODE_PRINTF("[DI]");
934 return M.x86.R_DI;
935 case 6:
936 offset = fetch_word_imm();
937 DECODE_PRINTF2("[%04x]", offset);
938 return offset;
939 case 7:
940 DECODE_PRINTF("[BX]");
941 return M.x86.R_BX;
942 }
Jason Jina63ce952007-07-06 08:34:56 +0800943 }
944 HALT_SYS();
945 return 0;
946}
947
948/****************************************************************************
949PARAMETERS:
950rm - RM value to decode
951
952RETURNS:
953Offset in memory for the address decoding
954
955REMARKS:
956Return the offset given by mod=01 addressing. Also enables the
957decoding of instructions.
958****************************************************************************/
959unsigned decode_rm01_address(
960 int rm)
961{
962 int displacement;
963
964 if (M.x86.mode & SYSMODE_PREFIX_ADDR) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200965 /* 32-bit addressing */
966 if (rm != 4)
967 displacement = (s8)fetch_byte_imm();
968 else
969 displacement = 0;
Jason Jina63ce952007-07-06 08:34:56 +0800970
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200971 switch (rm) {
972 case 0:
973 DECODE_PRINTF2("%d[EAX]", displacement);
974 return M.x86.R_EAX + displacement;
975 case 1:
976 DECODE_PRINTF2("%d[ECX]", displacement);
977 return M.x86.R_ECX + displacement;
978 case 2:
979 DECODE_PRINTF2("%d[EDX]", displacement);
980 return M.x86.R_EDX + displacement;
981 case 3:
982 DECODE_PRINTF2("%d[EBX]", displacement);
983 return M.x86.R_EBX + displacement;
984 case 4: {
985 int offset = decode_sib_address(1);
986 displacement = (s8)fetch_byte_imm();
987 DECODE_PRINTF2("[%d]", displacement);
988 return offset + displacement;
989 }
990 case 5:
991 DECODE_PRINTF2("%d[EBP]", displacement);
992 return M.x86.R_EBP + displacement;
993 case 6:
994 DECODE_PRINTF2("%d[ESI]", displacement);
995 return M.x86.R_ESI + displacement;
996 case 7:
997 DECODE_PRINTF2("%d[EDI]", displacement);
998 return M.x86.R_EDI + displacement;
999 }
Jason Jina63ce952007-07-06 08:34:56 +08001000 } else {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001001 /* 16-bit addressing */
1002 displacement = (s8)fetch_byte_imm();
1003 switch (rm) {
1004 case 0:
1005 DECODE_PRINTF2("%d[BX+SI]", displacement);
1006 return (M.x86.R_BX + M.x86.R_SI + displacement) & 0xffff;
1007 case 1:
1008 DECODE_PRINTF2("%d[BX+DI]", displacement);
1009 return (M.x86.R_BX + M.x86.R_DI + displacement) & 0xffff;
1010 case 2:
1011 DECODE_PRINTF2("%d[BP+SI]", displacement);
1012 M.x86.mode |= SYSMODE_SEG_DS_SS;
1013 return (M.x86.R_BP + M.x86.R_SI + displacement) & 0xffff;
1014 case 3:
1015 DECODE_PRINTF2("%d[BP+DI]", displacement);
1016 M.x86.mode |= SYSMODE_SEG_DS_SS;
1017 return (M.x86.R_BP + M.x86.R_DI + displacement) & 0xffff;
1018 case 4:
1019 DECODE_PRINTF2("%d[SI]", displacement);
1020 return (M.x86.R_SI + displacement) & 0xffff;
1021 case 5:
1022 DECODE_PRINTF2("%d[DI]", displacement);
1023 return (M.x86.R_DI + displacement) & 0xffff;
1024 case 6:
1025 DECODE_PRINTF2("%d[BP]", displacement);
1026 M.x86.mode |= SYSMODE_SEG_DS_SS;
1027 return (M.x86.R_BP + displacement) & 0xffff;
1028 case 7:
1029 DECODE_PRINTF2("%d[BX]", displacement);
1030 return (M.x86.R_BX + displacement) & 0xffff;
1031 }
Jason Jina63ce952007-07-06 08:34:56 +08001032 }
1033 HALT_SYS();
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001034 return 0; /* SHOULD NOT HAPPEN */
Jason Jina63ce952007-07-06 08:34:56 +08001035}
1036
1037/****************************************************************************
1038PARAMETERS:
1039rm - RM value to decode
1040
1041RETURNS:
1042Offset in memory for the address decoding
1043
1044REMARKS:
1045Return the offset given by mod=10 addressing. Also enables the
1046decoding of instructions.
1047****************************************************************************/
1048unsigned decode_rm10_address(
1049 int rm)
1050{
1051 if (M.x86.mode & SYSMODE_PREFIX_ADDR) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001052 int displacement;
Jason Jina63ce952007-07-06 08:34:56 +08001053
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001054 /* 32-bit addressing */
1055 if (rm != 4)
1056 displacement = (s32)fetch_long_imm();
1057 else
1058 displacement = 0;
Jason Jina63ce952007-07-06 08:34:56 +08001059
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001060 switch (rm) {
1061 case 0:
1062 DECODE_PRINTF2("%d[EAX]", displacement);
1063 return M.x86.R_EAX + displacement;
1064 case 1:
1065 DECODE_PRINTF2("%d[ECX]", displacement);
1066 return M.x86.R_ECX + displacement;
1067 case 2:
1068 DECODE_PRINTF2("%d[EDX]", displacement);
1069 return M.x86.R_EDX + displacement;
1070 case 3:
1071 DECODE_PRINTF2("%d[EBX]", displacement);
1072 return M.x86.R_EBX + displacement;
1073 case 4: {
1074 int offset = decode_sib_address(2);
1075 displacement = (s32)fetch_long_imm();
1076 DECODE_PRINTF2("[%d]", displacement);
1077 return offset + displacement;
1078 }
1079 case 5:
1080 DECODE_PRINTF2("%d[EBP]", displacement);
1081 return M.x86.R_EBP + displacement;
1082 case 6:
1083 DECODE_PRINTF2("%d[ESI]", displacement);
1084 return M.x86.R_ESI + displacement;
1085 case 7:
1086 DECODE_PRINTF2("%d[EDI]", displacement);
1087 return M.x86.R_EDI + displacement;
1088 }
Jason Jina63ce952007-07-06 08:34:56 +08001089 } else {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001090 int displacement = (s16)fetch_word_imm();
Jason Jina63ce952007-07-06 08:34:56 +08001091
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001092 /* 16-bit addressing */
1093 switch (rm) {
1094 case 0:
1095 DECODE_PRINTF2("%d[BX+SI]", displacement);
1096 return (M.x86.R_BX + M.x86.R_SI + displacement) & 0xffff;
1097 case 1:
1098 DECODE_PRINTF2("%d[BX+DI]", displacement);
1099 return (M.x86.R_BX + M.x86.R_DI + displacement) & 0xffff;
1100 case 2:
1101 DECODE_PRINTF2("%d[BP+SI]", displacement);
1102 M.x86.mode |= SYSMODE_SEG_DS_SS;
1103 return (M.x86.R_BP + M.x86.R_SI + displacement) & 0xffff;
1104 case 3:
1105 DECODE_PRINTF2("%d[BP+DI]", displacement);
1106 M.x86.mode |= SYSMODE_SEG_DS_SS;
1107 return (M.x86.R_BP + M.x86.R_DI + displacement) & 0xffff;
1108 case 4:
1109 DECODE_PRINTF2("%d[SI]", displacement);
1110 return (M.x86.R_SI + displacement) & 0xffff;
1111 case 5:
1112 DECODE_PRINTF2("%d[DI]", displacement);
1113 return (M.x86.R_DI + displacement) & 0xffff;
1114 case 6:
1115 DECODE_PRINTF2("%d[BP]", displacement);
1116 M.x86.mode |= SYSMODE_SEG_DS_SS;
1117 return (M.x86.R_BP + displacement) & 0xffff;
1118 case 7:
1119 DECODE_PRINTF2("%d[BX]", displacement);
1120 return (M.x86.R_BX + displacement) & 0xffff;
1121 }
Jason Jina63ce952007-07-06 08:34:56 +08001122 }
1123 HALT_SYS();
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001124 return 0; /* SHOULD NOT HAPPEN */
Jason Jina63ce952007-07-06 08:34:56 +08001125}
1126
Jason Jina63ce952007-07-06 08:34:56 +08001127/****************************************************************************
1128PARAMETERS:
1129mod - modifier
1130rm - RM value to decode
1131
1132RETURNS:
1133Offset in memory for the address decoding, multiplexing calls to
1134the decode_rmXX_address functions
1135
1136REMARKS:
1137Return the offset given by "mod" addressing.
1138****************************************************************************/
1139
1140unsigned decode_rmXX_address(int mod, int rm)
1141{
1142 if(mod == 0)
1143 return decode_rm00_address(rm);
1144 if(mod == 1)
1145 return decode_rm01_address(rm);
1146 return decode_rm10_address(rm);
1147}
Jason Jin7ed5cd92007-08-08 08:33:11 +08001148
1149#endif