blob: da44c3d8d9f53798d6554e302df4535852e31d97 [file] [log] [blame]
Jason Jinece92f82007-07-06 08:34:56 +08001/****************************************************************************
2*
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02003* Realmode X86 Emulator Library
Jason Jinece92f82007-07-06 08:34:56 +08004*
Wolfgang Denk9c7e4b02007-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 Jinece92f82007-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 Denk9c7e4b02007-08-06 02:17:36 +020017* without specific, written prior permission. The authors makes no
Jason Jinece92f82007-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 Denk9c7e4b02007-08-06 02:17:36 +020031* Language: ANSI C
32* Environment: Any
33* Developer: Kendall Bennett
Jason Jinece92f82007-07-06 08:34:56 +080034*
Wolfgang Denk9c7e4b02007-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 Jinece92f82007-07-06 08:34:56 +080037*
38****************************************************************************/
Michal Simek78cff502007-08-16 10:46:28 +020039#include <common.h>
Michal Simek5b4de932007-08-15 21:15:05 +020040#include "x86emu/x86emui.h"
41
Jason Jinece92f82007-07-06 08:34:56 +080042/*----------------------------- Implementation ----------------------------*/
43
44/****************************************************************************
45REMARKS:
46Handles any pending asychronous interrupts.
47****************************************************************************/
48static void x86emu_intr_handle(void)
49{
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +020050 u8 intno;
Jason Jinece92f82007-07-06 08:34:56 +080051
52 if (M.x86.intr & INTR_SYNCH) {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +020053 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 }
Jason Jinece92f82007-07-06 08:34:56 +080066 }
67}
68
69/****************************************************************************
70PARAMETERS:
71intrnum - Interrupt number to raise
72
73REMARKS:
74Raise the specified interrupt to be handled before the execution of the
75next instruction.
76****************************************************************************/
77void x86emu_intr_raise(
78 u8 intrnum)
79{
80 M.x86.intno = intrnum;
81 M.x86.intr |= INTR_SYNCH;
82}
83
84/****************************************************************************
85REMARKS:
86Main execution loop for the emulator. We return from here when the system
87halts, which is normally caused by a stack fault when we return from the
88original real mode call.
89****************************************************************************/
90void X86EMU_exec(void)
91{
92 u8 op1;
93
94 M.x86.intr = 0;
95 DB(x86emu_end_instr();)
96
97 for (;;) {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +020098DB( if (CHECK_IP_FETCH())
99 x86emu_check_ip_access();)
100 /* If debugging, save the IP and CS values. */
101 SAVE_IP_CS(M.x86.R_CS, M.x86.R_IP);
102 INC_DECODED_INST_LEN(1);
103 if (M.x86.intr) {
104 if (M.x86.intr & INTR_HALTED) {
105DB( if (M.x86.R_SP != 0) {
106 printk("halted\n");
107 X86EMU_trace_regs();
108 }
109 else {
110 if (M.x86.debug)
111 printk("Service completed successfully\n");
112 })
113 return;
114 }
115 if (((M.x86.intr & INTR_SYNCH) && (M.x86.intno == 0 || M.x86.intno == 2)) ||
116 !ACCESS_FLAG(F_IF)) {
117 x86emu_intr_handle();
118 }
119 }
120 op1 = (*sys_rdb)(((u32)M.x86.R_CS << 4) + (M.x86.R_IP++));
121 (*x86emu_optab[op1])(op1);
122 if (M.x86.debug & DEBUG_EXIT) {
123 M.x86.debug &= ~DEBUG_EXIT;
124 return;
125 }
Jason Jinece92f82007-07-06 08:34:56 +0800126 }
127}
128
129/****************************************************************************
130REMARKS:
131Halts the system by setting the halted system flag.
132****************************************************************************/
133void X86EMU_halt_sys(void)
134{
135 M.x86.intr |= INTR_HALTED;
136}
137
138/****************************************************************************
139PARAMETERS:
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200140mod - Mod value from decoded byte
141regh - Reg h value from decoded byte
142regl - Reg l value from decoded byte
Jason Jinece92f82007-07-06 08:34:56 +0800143
144REMARKS:
145Raise the specified interrupt to be handled before the execution of the
146next instruction.
147
148NOTE: Do not inline this function, as (*sys_rdb) is already inline!
149****************************************************************************/
150void fetch_decode_modrm(
151 int *mod,
152 int *regh,
153 int *regl)
154{
155 int fetched;
156
157DB( if (CHECK_IP_FETCH())
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200158 x86emu_check_ip_access();)
Jason Jinece92f82007-07-06 08:34:56 +0800159 fetched = (*sys_rdb)(((u32)M.x86.R_CS << 4) + (M.x86.R_IP++));
160 INC_DECODED_INST_LEN(1);
161 *mod = (fetched >> 6) & 0x03;
162 *regh = (fetched >> 3) & 0x07;
163 *regl = (fetched >> 0) & 0x07;
164}
165
166/****************************************************************************
167RETURNS:
168Immediate byte value read from instruction queue
169
170REMARKS:
171This function returns the immediate byte from the instruction queue, and
172moves the instruction pointer to the next value.
173
174NOTE: Do not inline this function, as (*sys_rdb) is already inline!
175****************************************************************************/
176u8 fetch_byte_imm(void)
177{
178 u8 fetched;
179
180DB( if (CHECK_IP_FETCH())
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200181 x86emu_check_ip_access();)
Jason Jinece92f82007-07-06 08:34:56 +0800182 fetched = (*sys_rdb)(((u32)M.x86.R_CS << 4) + (M.x86.R_IP++));
183 INC_DECODED_INST_LEN(1);
184 return fetched;
185}
186
187/****************************************************************************
188RETURNS:
189Immediate word value read from instruction queue
190
191REMARKS:
192This function returns the immediate byte from the instruction queue, and
193moves the instruction pointer to the next value.
194
195NOTE: Do not inline this function, as (*sys_rdw) is already inline!
196****************************************************************************/
197u16 fetch_word_imm(void)
198{
199 u16 fetched;
200
201DB( if (CHECK_IP_FETCH())
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200202 x86emu_check_ip_access();)
Jason Jinece92f82007-07-06 08:34:56 +0800203 fetched = (*sys_rdw)(((u32)M.x86.R_CS << 4) + (M.x86.R_IP));
204 M.x86.R_IP += 2;
205 INC_DECODED_INST_LEN(2);
206 return fetched;
207}
208
209/****************************************************************************
210RETURNS:
211Immediate lone value read from instruction queue
212
213REMARKS:
214This function returns the immediate byte from the instruction queue, and
215moves the instruction pointer to the next value.
216
217NOTE: Do not inline this function, as (*sys_rdw) is already inline!
218****************************************************************************/
219u32 fetch_long_imm(void)
220{
221 u32 fetched;
222
223DB( if (CHECK_IP_FETCH())
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200224 x86emu_check_ip_access();)
Jason Jinece92f82007-07-06 08:34:56 +0800225 fetched = (*sys_rdl)(((u32)M.x86.R_CS << 4) + (M.x86.R_IP));
226 M.x86.R_IP += 4;
227 INC_DECODED_INST_LEN(4);
228 return fetched;
229}
230
231/****************************************************************************
232RETURNS:
233Value of the default data segment
234
235REMARKS:
236Inline function that returns the default data segment for the current
237instruction.
238
239On the x86 processor, the default segment is not always DS if there is
240no segment override. Address modes such as -3[BP] or 10[BP+SI] all refer to
241addresses relative to SS (ie: on the stack). So, at the minimum, all
242decodings of addressing modes would have to set/clear a bit describing
243whether the access is relative to DS or SS. That is the function of the
244cpu-state-varible M.x86.mode. There are several potential states:
245
246 repe prefix seen (handled elsewhere)
247 repne prefix seen (ditto)
248
249 cs segment override
250 ds segment override
251 es segment override
252 fs segment override
253 gs segment override
254 ss segment override
255
256 ds/ss select (in absense of override)
257
258Each of the above 7 items are handled with a bit in the mode field.
259****************************************************************************/
260_INLINE u32 get_data_segment(void)
261{
262#define GET_SEGMENT(segment)
263 switch (M.x86.mode & SYSMODE_SEGMASK) {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200264 case 0: /* default case: use ds register */
Jason Jinece92f82007-07-06 08:34:56 +0800265 case SYSMODE_SEGOVR_DS:
266 case SYSMODE_SEGOVR_DS | SYSMODE_SEG_DS_SS:
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200267 return M.x86.R_DS;
268 case SYSMODE_SEG_DS_SS: /* non-overridden, use ss register */
269 return M.x86.R_SS;
Jason Jinece92f82007-07-06 08:34:56 +0800270 case SYSMODE_SEGOVR_CS:
271 case SYSMODE_SEGOVR_CS | SYSMODE_SEG_DS_SS:
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200272 return M.x86.R_CS;
Jason Jinece92f82007-07-06 08:34:56 +0800273 case SYSMODE_SEGOVR_ES:
274 case SYSMODE_SEGOVR_ES | SYSMODE_SEG_DS_SS:
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200275 return M.x86.R_ES;
Jason Jinece92f82007-07-06 08:34:56 +0800276 case SYSMODE_SEGOVR_FS:
277 case SYSMODE_SEGOVR_FS | SYSMODE_SEG_DS_SS:
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200278 return M.x86.R_FS;
Jason Jinece92f82007-07-06 08:34:56 +0800279 case SYSMODE_SEGOVR_GS:
280 case SYSMODE_SEGOVR_GS | SYSMODE_SEG_DS_SS:
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200281 return M.x86.R_GS;
Jason Jinece92f82007-07-06 08:34:56 +0800282 case SYSMODE_SEGOVR_SS:
283 case SYSMODE_SEGOVR_SS | SYSMODE_SEG_DS_SS:
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200284 return M.x86.R_SS;
Jason Jinece92f82007-07-06 08:34:56 +0800285 default:
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200286#ifdef DEBUG
287 printk("error: should not happen: multiple overrides.\n");
Jason Jinece92f82007-07-06 08:34:56 +0800288#endif
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200289 HALT_SYS();
290 return 0;
Jason Jinece92f82007-07-06 08:34:56 +0800291 }
292}
293
294/****************************************************************************
295PARAMETERS:
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200296offset - Offset to load data from
Jason Jinece92f82007-07-06 08:34:56 +0800297
298RETURNS:
299Byte value read from the absolute memory location.
300
301NOTE: Do not inline this function as (*sys_rdX) is already inline!
302****************************************************************************/
303u8 fetch_data_byte(
304 uint offset)
305{
Simon Glassb3521f22014-11-14 20:56:42 -0700306#ifdef CONFIG_X86EMU_DEBUG
Jason Jinece92f82007-07-06 08:34:56 +0800307 if (CHECK_DATA_ACCESS())
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200308 x86emu_check_data_access((u16)get_data_segment(), offset);
Jason Jinece92f82007-07-06 08:34:56 +0800309#endif
310 return (*sys_rdb)((get_data_segment() << 4) + offset);
311}
312
313/****************************************************************************
314PARAMETERS:
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200315offset - Offset to load data from
Jason Jinece92f82007-07-06 08:34:56 +0800316
317RETURNS:
318Word value read from the absolute memory location.
319
320NOTE: Do not inline this function as (*sys_rdX) is already inline!
321****************************************************************************/
322u16 fetch_data_word(
323 uint offset)
324{
Simon Glassb3521f22014-11-14 20:56:42 -0700325#ifdef CONFIG_X86EMU_DEBUG
Jason Jinece92f82007-07-06 08:34:56 +0800326 if (CHECK_DATA_ACCESS())
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200327 x86emu_check_data_access((u16)get_data_segment(), offset);
Jason Jinece92f82007-07-06 08:34:56 +0800328#endif
329 return (*sys_rdw)((get_data_segment() << 4) + offset);
330}
331
332/****************************************************************************
333PARAMETERS:
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200334offset - Offset to load data from
Jason Jinece92f82007-07-06 08:34:56 +0800335
336RETURNS:
337Long value read from the absolute memory location.
338
339NOTE: Do not inline this function as (*sys_rdX) is already inline!
340****************************************************************************/
341u32 fetch_data_long(
342 uint offset)
343{
Simon Glassb3521f22014-11-14 20:56:42 -0700344#ifdef CONFIG_X86EMU_DEBUG
Jason Jinece92f82007-07-06 08:34:56 +0800345 if (CHECK_DATA_ACCESS())
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200346 x86emu_check_data_access((u16)get_data_segment(), offset);
Jason Jinece92f82007-07-06 08:34:56 +0800347#endif
348 return (*sys_rdl)((get_data_segment() << 4) + offset);
349}
350
351/****************************************************************************
352PARAMETERS:
353segment - Segment to load data from
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200354offset - Offset to load data from
Jason Jinece92f82007-07-06 08:34:56 +0800355
356RETURNS:
357Byte value read from the absolute memory location.
358
359NOTE: Do not inline this function as (*sys_rdX) is already inline!
360****************************************************************************/
361u8 fetch_data_byte_abs(
362 uint segment,
363 uint offset)
364{
Simon Glassb3521f22014-11-14 20:56:42 -0700365#ifdef CONFIG_X86EMU_DEBUG
Jason Jinece92f82007-07-06 08:34:56 +0800366 if (CHECK_DATA_ACCESS())
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200367 x86emu_check_data_access(segment, offset);
Jason Jinece92f82007-07-06 08:34:56 +0800368#endif
369 return (*sys_rdb)(((u32)segment << 4) + offset);
370}
371
372/****************************************************************************
373PARAMETERS:
374segment - Segment to load data from
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200375offset - Offset to load data from
Jason Jinece92f82007-07-06 08:34:56 +0800376
377RETURNS:
378Word value read from the absolute memory location.
379
380NOTE: Do not inline this function as (*sys_rdX) is already inline!
381****************************************************************************/
382u16 fetch_data_word_abs(
383 uint segment,
384 uint offset)
385{
Simon Glassb3521f22014-11-14 20:56:42 -0700386#ifdef CONFIG_X86EMU_DEBUG
Jason Jinece92f82007-07-06 08:34:56 +0800387 if (CHECK_DATA_ACCESS())
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200388 x86emu_check_data_access(segment, offset);
Jason Jinece92f82007-07-06 08:34:56 +0800389#endif
390 return (*sys_rdw)(((u32)segment << 4) + offset);
391}
392
393/****************************************************************************
394PARAMETERS:
395segment - Segment to load data from
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200396offset - Offset to load data from
Jason Jinece92f82007-07-06 08:34:56 +0800397
398RETURNS:
399Long value read from the absolute memory location.
400
401NOTE: Do not inline this function as (*sys_rdX) is already inline!
402****************************************************************************/
403u32 fetch_data_long_abs(
404 uint segment,
405 uint offset)
406{
Simon Glassb3521f22014-11-14 20:56:42 -0700407#ifdef CONFIG_X86EMU_DEBUG
Jason Jinece92f82007-07-06 08:34:56 +0800408 if (CHECK_DATA_ACCESS())
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200409 x86emu_check_data_access(segment, offset);
Jason Jinece92f82007-07-06 08:34:56 +0800410#endif
411 return (*sys_rdl)(((u32)segment << 4) + offset);
412}
413
414/****************************************************************************
415PARAMETERS:
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200416offset - Offset to store data at
417val - Value to store
Jason Jinece92f82007-07-06 08:34:56 +0800418
419REMARKS:
420Writes a word value to an segmented memory location. The segment used is
421the current 'default' segment, which may have been overridden.
422
423NOTE: Do not inline this function as (*sys_wrX) is already inline!
424****************************************************************************/
425void store_data_byte(
426 uint offset,
427 u8 val)
428{
Simon Glassb3521f22014-11-14 20:56:42 -0700429#ifdef CONFIG_X86EMU_DEBUG
Jason Jinece92f82007-07-06 08:34:56 +0800430 if (CHECK_DATA_ACCESS())
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200431 x86emu_check_data_access((u16)get_data_segment(), offset);
Jason Jinece92f82007-07-06 08:34:56 +0800432#endif
433 (*sys_wrb)((get_data_segment() << 4) + offset, val);
434}
435
436/****************************************************************************
437PARAMETERS:
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200438offset - Offset to store data at
439val - Value to store
Jason Jinece92f82007-07-06 08:34:56 +0800440
441REMARKS:
442Writes a word value to an segmented memory location. The segment used is
443the current 'default' segment, which may have been overridden.
444
445NOTE: Do not inline this function as (*sys_wrX) is already inline!
446****************************************************************************/
447void store_data_word(
448 uint offset,
449 u16 val)
450{
Simon Glassb3521f22014-11-14 20:56:42 -0700451#ifdef CONFIG_X86EMU_DEBUG
Jason Jinece92f82007-07-06 08:34:56 +0800452 if (CHECK_DATA_ACCESS())
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200453 x86emu_check_data_access((u16)get_data_segment(), offset);
Jason Jinece92f82007-07-06 08:34:56 +0800454#endif
455 (*sys_wrw)((get_data_segment() << 4) + offset, val);
456}
457
458/****************************************************************************
459PARAMETERS:
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200460offset - Offset to store data at
461val - Value to store
Jason Jinece92f82007-07-06 08:34:56 +0800462
463REMARKS:
464Writes a long value to an segmented memory location. The segment used is
465the current 'default' segment, which may have been overridden.
466
467NOTE: Do not inline this function as (*sys_wrX) is already inline!
468****************************************************************************/
469void store_data_long(
470 uint offset,
471 u32 val)
472{
Simon Glassb3521f22014-11-14 20:56:42 -0700473#ifdef CONFIG_X86EMU_DEBUG
Jason Jinece92f82007-07-06 08:34:56 +0800474 if (CHECK_DATA_ACCESS())
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200475 x86emu_check_data_access((u16)get_data_segment(), offset);
Jason Jinece92f82007-07-06 08:34:56 +0800476#endif
477 (*sys_wrl)((get_data_segment() << 4) + offset, val);
478}
479
480/****************************************************************************
481PARAMETERS:
482segment - Segment to store data at
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200483offset - Offset to store data at
484val - Value to store
Jason Jinece92f82007-07-06 08:34:56 +0800485
486REMARKS:
487Writes a byte value to an absolute memory location.
488
489NOTE: Do not inline this function as (*sys_wrX) is already inline!
490****************************************************************************/
491void store_data_byte_abs(
492 uint segment,
493 uint offset,
494 u8 val)
495{
Simon Glassb3521f22014-11-14 20:56:42 -0700496#ifdef CONFIG_X86EMU_DEBUG
Jason Jinece92f82007-07-06 08:34:56 +0800497 if (CHECK_DATA_ACCESS())
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200498 x86emu_check_data_access(segment, offset);
Jason Jinece92f82007-07-06 08:34:56 +0800499#endif
500 (*sys_wrb)(((u32)segment << 4) + offset, val);
501}
502
503/****************************************************************************
504PARAMETERS:
505segment - Segment to store data at
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200506offset - Offset to store data at
507val - Value to store
Jason Jinece92f82007-07-06 08:34:56 +0800508
509REMARKS:
510Writes a word value to an absolute memory location.
511
512NOTE: Do not inline this function as (*sys_wrX) is already inline!
513****************************************************************************/
514void store_data_word_abs(
515 uint segment,
516 uint offset,
517 u16 val)
518{
Simon Glassb3521f22014-11-14 20:56:42 -0700519#ifdef CONFIG_X86EMU_DEBUG
Jason Jinece92f82007-07-06 08:34:56 +0800520 if (CHECK_DATA_ACCESS())
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200521 x86emu_check_data_access(segment, offset);
Jason Jinece92f82007-07-06 08:34:56 +0800522#endif
523 (*sys_wrw)(((u32)segment << 4) + offset, val);
524}
525
526/****************************************************************************
527PARAMETERS:
528segment - Segment to store data at
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200529offset - Offset to store data at
530val - Value to store
Jason Jinece92f82007-07-06 08:34:56 +0800531
532REMARKS:
533Writes a long value to an absolute memory location.
534
535NOTE: Do not inline this function as (*sys_wrX) is already inline!
536****************************************************************************/
537void store_data_long_abs(
538 uint segment,
539 uint offset,
540 u32 val)
541{
Simon Glassb3521f22014-11-14 20:56:42 -0700542#ifdef CONFIG_X86EMU_DEBUG
Jason Jinece92f82007-07-06 08:34:56 +0800543 if (CHECK_DATA_ACCESS())
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200544 x86emu_check_data_access(segment, offset);
Jason Jinece92f82007-07-06 08:34:56 +0800545#endif
546 (*sys_wrl)(((u32)segment << 4) + offset, val);
547}
548
549/****************************************************************************
550PARAMETERS:
551reg - Register to decode
552
553RETURNS:
554Pointer to the appropriate register
555
556REMARKS:
557Return a pointer to the register given by the R/RM field of the
558modrm byte, for byte operands. Also enables the decoding of instructions.
559****************************************************************************/
560u8* decode_rm_byte_register(
561 int reg)
562{
563 switch (reg) {
564 case 0:
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200565 DECODE_PRINTF("AL");
566 return &M.x86.R_AL;
Jason Jinece92f82007-07-06 08:34:56 +0800567 case 1:
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200568 DECODE_PRINTF("CL");
569 return &M.x86.R_CL;
Jason Jinece92f82007-07-06 08:34:56 +0800570 case 2:
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200571 DECODE_PRINTF("DL");
572 return &M.x86.R_DL;
Jason Jinece92f82007-07-06 08:34:56 +0800573 case 3:
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200574 DECODE_PRINTF("BL");
575 return &M.x86.R_BL;
Jason Jinece92f82007-07-06 08:34:56 +0800576 case 4:
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200577 DECODE_PRINTF("AH");
578 return &M.x86.R_AH;
Jason Jinece92f82007-07-06 08:34:56 +0800579 case 5:
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200580 DECODE_PRINTF("CH");
581 return &M.x86.R_CH;
Jason Jinece92f82007-07-06 08:34:56 +0800582 case 6:
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200583 DECODE_PRINTF("DH");
584 return &M.x86.R_DH;
Jason Jinece92f82007-07-06 08:34:56 +0800585 case 7:
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200586 DECODE_PRINTF("BH");
587 return &M.x86.R_BH;
Jason Jinece92f82007-07-06 08:34:56 +0800588 }
589 HALT_SYS();
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200590 return NULL; /* NOT REACHED OR REACHED ON ERROR */
Jason Jinece92f82007-07-06 08:34:56 +0800591}
592
593/****************************************************************************
594PARAMETERS:
595reg - Register to decode
596
597RETURNS:
598Pointer to the appropriate register
599
600REMARKS:
601Return a pointer to the register given by the R/RM field of the
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200602modrm byte, for word operands. Also enables the decoding of instructions.
Jason Jinece92f82007-07-06 08:34:56 +0800603****************************************************************************/
604u16* decode_rm_word_register(
605 int reg)
606{
607 switch (reg) {
608 case 0:
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200609 DECODE_PRINTF("AX");
610 return &M.x86.R_AX;
Jason Jinece92f82007-07-06 08:34:56 +0800611 case 1:
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200612 DECODE_PRINTF("CX");
613 return &M.x86.R_CX;
Jason Jinece92f82007-07-06 08:34:56 +0800614 case 2:
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200615 DECODE_PRINTF("DX");
616 return &M.x86.R_DX;
Jason Jinece92f82007-07-06 08:34:56 +0800617 case 3:
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200618 DECODE_PRINTF("BX");
619 return &M.x86.R_BX;
Jason Jinece92f82007-07-06 08:34:56 +0800620 case 4:
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200621 DECODE_PRINTF("SP");
622 return &M.x86.R_SP;
Jason Jinece92f82007-07-06 08:34:56 +0800623 case 5:
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200624 DECODE_PRINTF("BP");
625 return &M.x86.R_BP;
Jason Jinece92f82007-07-06 08:34:56 +0800626 case 6:
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200627 DECODE_PRINTF("SI");
628 return &M.x86.R_SI;
Jason Jinece92f82007-07-06 08:34:56 +0800629 case 7:
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200630 DECODE_PRINTF("DI");
631 return &M.x86.R_DI;
Jason Jinece92f82007-07-06 08:34:56 +0800632 }
633 HALT_SYS();
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200634 return NULL; /* NOTREACHED OR REACHED ON ERROR */
Jason Jinece92f82007-07-06 08:34:56 +0800635}
636
637/****************************************************************************
638PARAMETERS:
639reg - Register to decode
640
641RETURNS:
642Pointer to the appropriate register
643
644REMARKS:
645Return a pointer to the register given by the R/RM field of the
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200646modrm byte, for dword operands. Also enables the decoding of instructions.
Jason Jinece92f82007-07-06 08:34:56 +0800647****************************************************************************/
648u32* decode_rm_long_register(
649 int reg)
650{
651 switch (reg) {
652 case 0:
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200653 DECODE_PRINTF("EAX");
654 return &M.x86.R_EAX;
Jason Jinece92f82007-07-06 08:34:56 +0800655 case 1:
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200656 DECODE_PRINTF("ECX");
657 return &M.x86.R_ECX;
Jason Jinece92f82007-07-06 08:34:56 +0800658 case 2:
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200659 DECODE_PRINTF("EDX");
660 return &M.x86.R_EDX;
Jason Jinece92f82007-07-06 08:34:56 +0800661 case 3:
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200662 DECODE_PRINTF("EBX");
663 return &M.x86.R_EBX;
Jason Jinece92f82007-07-06 08:34:56 +0800664 case 4:
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200665 DECODE_PRINTF("ESP");
666 return &M.x86.R_ESP;
Jason Jinece92f82007-07-06 08:34:56 +0800667 case 5:
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200668 DECODE_PRINTF("EBP");
669 return &M.x86.R_EBP;
Jason Jinece92f82007-07-06 08:34:56 +0800670 case 6:
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200671 DECODE_PRINTF("ESI");
672 return &M.x86.R_ESI;
Jason Jinece92f82007-07-06 08:34:56 +0800673 case 7:
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200674 DECODE_PRINTF("EDI");
675 return &M.x86.R_EDI;
Jason Jinece92f82007-07-06 08:34:56 +0800676 }
677 HALT_SYS();
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200678 return NULL; /* NOTREACHED OR REACHED ON ERROR */
Jason Jinece92f82007-07-06 08:34:56 +0800679}
680
681/****************************************************************************
682PARAMETERS:
683reg - Register to decode
684
685RETURNS:
686Pointer to the appropriate register
687
688REMARKS:
689Return a pointer to the register given by the R/RM field of the
690modrm byte, for word operands, modified from above for the weirdo
691special case of segreg operands. Also enables the decoding of instructions.
692****************************************************************************/
693u16* decode_rm_seg_register(
694 int reg)
695{
696 switch (reg) {
697 case 0:
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200698 DECODE_PRINTF("ES");
699 return &M.x86.R_ES;
Jason Jinece92f82007-07-06 08:34:56 +0800700 case 1:
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200701 DECODE_PRINTF("CS");
702 return &M.x86.R_CS;
Jason Jinece92f82007-07-06 08:34:56 +0800703 case 2:
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200704 DECODE_PRINTF("SS");
705 return &M.x86.R_SS;
Jason Jinece92f82007-07-06 08:34:56 +0800706 case 3:
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200707 DECODE_PRINTF("DS");
708 return &M.x86.R_DS;
Jason Jinece92f82007-07-06 08:34:56 +0800709 case 4:
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200710 DECODE_PRINTF("FS");
711 return &M.x86.R_FS;
Jason Jinece92f82007-07-06 08:34:56 +0800712 case 5:
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200713 DECODE_PRINTF("GS");
714 return &M.x86.R_GS;
Jason Jinece92f82007-07-06 08:34:56 +0800715 case 6:
716 case 7:
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200717 DECODE_PRINTF("ILLEGAL SEGREG");
718 break;
Jason Jinece92f82007-07-06 08:34:56 +0800719 }
720 HALT_SYS();
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200721 return NULL; /* NOT REACHED OR REACHED ON ERROR */
Jason Jinece92f82007-07-06 08:34:56 +0800722}
723
724/****************************************************************************
725PARAMETERS:
726scale - scale value of SIB byte
727index - index value of SIB byte
728
729RETURNS:
730Value of scale * index
731
732REMARKS:
733Decodes scale/index of SIB byte and returns relevant offset part of
734effective address.
735****************************************************************************/
736unsigned decode_sib_si(
737 int scale,
738 int index)
739{
740 scale = 1 << scale;
741 if (scale > 1) {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200742 DECODE_PRINTF2("[%d*", scale);
Jason Jinece92f82007-07-06 08:34:56 +0800743 } else {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200744 DECODE_PRINTF("[");
Jason Jinece92f82007-07-06 08:34:56 +0800745 }
746 switch (index) {
747 case 0:
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200748 DECODE_PRINTF("EAX]");
749 return M.x86.R_EAX * index;
Jason Jinece92f82007-07-06 08:34:56 +0800750 case 1:
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200751 DECODE_PRINTF("ECX]");
752 return M.x86.R_ECX * index;
Jason Jinece92f82007-07-06 08:34:56 +0800753 case 2:
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200754 DECODE_PRINTF("EDX]");
755 return M.x86.R_EDX * index;
Jason Jinece92f82007-07-06 08:34:56 +0800756 case 3:
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200757 DECODE_PRINTF("EBX]");
758 return M.x86.R_EBX * index;
Jason Jinece92f82007-07-06 08:34:56 +0800759 case 4:
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200760 DECODE_PRINTF("0]");
761 return 0;
Jason Jinece92f82007-07-06 08:34:56 +0800762 case 5:
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200763 DECODE_PRINTF("EBP]");
764 return M.x86.R_EBP * index;
Jason Jinece92f82007-07-06 08:34:56 +0800765 case 6:
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200766 DECODE_PRINTF("ESI]");
767 return M.x86.R_ESI * index;
Jason Jinece92f82007-07-06 08:34:56 +0800768 case 7:
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200769 DECODE_PRINTF("EDI]");
770 return M.x86.R_EDI * index;
Jason Jinece92f82007-07-06 08:34:56 +0800771 }
772 HALT_SYS();
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200773 return 0; /* NOT REACHED OR REACHED ON ERROR */
Jason Jinece92f82007-07-06 08:34:56 +0800774}
775
776/****************************************************************************
777PARAMETERS:
778mod - MOD value of preceding ModR/M byte
779
780RETURNS:
781Offset in memory for the address decoding
782
783REMARKS:
784Decodes SIB addressing byte and returns calculated effective address.
785****************************************************************************/
786unsigned decode_sib_address(
787 int mod)
788{
789 int sib = fetch_byte_imm();
790 int ss = (sib >> 6) & 0x03;
791 int index = (sib >> 3) & 0x07;
792 int base = sib & 0x07;
793 int offset = 0;
794 int displacement;
795
796 switch (base) {
797 case 0:
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200798 DECODE_PRINTF("[EAX]");
799 offset = M.x86.R_EAX;
800 break;
Jason Jinece92f82007-07-06 08:34:56 +0800801 case 1:
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200802 DECODE_PRINTF("[ECX]");
803 offset = M.x86.R_ECX;
804 break;
Jason Jinece92f82007-07-06 08:34:56 +0800805 case 2:
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200806 DECODE_PRINTF("[EDX]");
807 offset = M.x86.R_EDX;
808 break;
Jason Jinece92f82007-07-06 08:34:56 +0800809 case 3:
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200810 DECODE_PRINTF("[EBX]");
811 offset = M.x86.R_EBX;
812 break;
Jason Jinece92f82007-07-06 08:34:56 +0800813 case 4:
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200814 DECODE_PRINTF("[ESP]");
815 offset = M.x86.R_ESP;
816 break;
Jason Jinece92f82007-07-06 08:34:56 +0800817 case 5:
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200818 switch (mod) {
819 case 0:
820 displacement = (s32)fetch_long_imm();
821 DECODE_PRINTF2("[%d]", displacement);
822 offset = displacement;
823 break;
824 case 1:
825 displacement = (s8)fetch_byte_imm();
826 DECODE_PRINTF2("[%d][EBP]", displacement);
827 offset = M.x86.R_EBP + displacement;
828 break;
829 case 2:
830 displacement = (s32)fetch_long_imm();
831 DECODE_PRINTF2("[%d][EBP]", displacement);
832 offset = M.x86.R_EBP + displacement;
833 break;
834 default:
835 HALT_SYS();
836 }
837 DECODE_PRINTF("[EAX]");
838 offset = M.x86.R_EAX;
839 break;
Jason Jinece92f82007-07-06 08:34:56 +0800840 case 6:
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200841 DECODE_PRINTF("[ESI]");
842 offset = M.x86.R_ESI;
843 break;
Jason Jinece92f82007-07-06 08:34:56 +0800844 case 7:
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200845 DECODE_PRINTF("[EDI]");
846 offset = M.x86.R_EDI;
847 break;
Jason Jinece92f82007-07-06 08:34:56 +0800848 default:
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200849 HALT_SYS();
Jason Jinece92f82007-07-06 08:34:56 +0800850 }
851 offset += decode_sib_si(ss, index);
852 return offset;
853
854}
855
856/****************************************************************************
857PARAMETERS:
858rm - RM value to decode
859
860RETURNS:
861Offset in memory for the address decoding
862
863REMARKS:
864Return the offset given by mod=00 addressing. Also enables the
865decoding of instructions.
866
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200867NOTE: The code which specifies the corresponding segment (ds vs ss)
868 below in the case of [BP+..]. The assumption here is that at the
869 point that this subroutine is called, the bit corresponding to
870 SYSMODE_SEG_DS_SS will be zero. After every instruction
871 except the segment override instructions, this bit (as well
872 as any bits indicating segment overrides) will be clear. So
873 if a SS access is needed, set this bit. Otherwise, DS access
874 occurs (unless any of the segment override bits are set).
Jason Jinece92f82007-07-06 08:34:56 +0800875****************************************************************************/
876unsigned decode_rm00_address(
877 int rm)
878{
879 unsigned offset;
880
881 if (M.x86.mode & SYSMODE_PREFIX_ADDR) {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200882 /* 32-bit addressing */
883 switch (rm) {
884 case 0:
885 DECODE_PRINTF("[EAX]");
886 return M.x86.R_EAX;
887 case 1:
888 DECODE_PRINTF("[ECX]");
889 return M.x86.R_ECX;
890 case 2:
891 DECODE_PRINTF("[EDX]");
892 return M.x86.R_EDX;
893 case 3:
894 DECODE_PRINTF("[EBX]");
895 return M.x86.R_EBX;
896 case 4:
897 return decode_sib_address(0);
898 case 5:
899 offset = fetch_long_imm();
900 DECODE_PRINTF2("[%08x]", offset);
901 return offset;
902 case 6:
903 DECODE_PRINTF("[ESI]");
904 return M.x86.R_ESI;
905 case 7:
906 DECODE_PRINTF("[EDI]");
907 return M.x86.R_EDI;
908 }
Jason Jinece92f82007-07-06 08:34:56 +0800909 } else {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200910 /* 16-bit addressing */
911 switch (rm) {
912 case 0:
913 DECODE_PRINTF("[BX+SI]");
914 return (M.x86.R_BX + M.x86.R_SI) & 0xffff;
915 case 1:
916 DECODE_PRINTF("[BX+DI]");
917 return (M.x86.R_BX + M.x86.R_DI) & 0xffff;
918 case 2:
919 DECODE_PRINTF("[BP+SI]");
920 M.x86.mode |= SYSMODE_SEG_DS_SS;
921 return (M.x86.R_BP + M.x86.R_SI) & 0xffff;
922 case 3:
923 DECODE_PRINTF("[BP+DI]");
924 M.x86.mode |= SYSMODE_SEG_DS_SS;
925 return (M.x86.R_BP + M.x86.R_DI) & 0xffff;
926 case 4:
927 DECODE_PRINTF("[SI]");
928 return M.x86.R_SI;
929 case 5:
930 DECODE_PRINTF("[DI]");
931 return M.x86.R_DI;
932 case 6:
933 offset = fetch_word_imm();
934 DECODE_PRINTF2("[%04x]", offset);
935 return offset;
936 case 7:
937 DECODE_PRINTF("[BX]");
938 return M.x86.R_BX;
939 }
Jason Jinece92f82007-07-06 08:34:56 +0800940 }
941 HALT_SYS();
942 return 0;
943}
944
945/****************************************************************************
946PARAMETERS:
947rm - RM value to decode
948
949RETURNS:
950Offset in memory for the address decoding
951
952REMARKS:
953Return the offset given by mod=01 addressing. Also enables the
954decoding of instructions.
955****************************************************************************/
956unsigned decode_rm01_address(
957 int rm)
958{
959 int displacement;
960
961 if (M.x86.mode & SYSMODE_PREFIX_ADDR) {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200962 /* 32-bit addressing */
963 if (rm != 4)
964 displacement = (s8)fetch_byte_imm();
965 else
966 displacement = 0;
Jason Jinece92f82007-07-06 08:34:56 +0800967
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200968 switch (rm) {
969 case 0:
970 DECODE_PRINTF2("%d[EAX]", displacement);
971 return M.x86.R_EAX + displacement;
972 case 1:
973 DECODE_PRINTF2("%d[ECX]", displacement);
974 return M.x86.R_ECX + displacement;
975 case 2:
976 DECODE_PRINTF2("%d[EDX]", displacement);
977 return M.x86.R_EDX + displacement;
978 case 3:
979 DECODE_PRINTF2("%d[EBX]", displacement);
980 return M.x86.R_EBX + displacement;
981 case 4: {
982 int offset = decode_sib_address(1);
983 displacement = (s8)fetch_byte_imm();
984 DECODE_PRINTF2("[%d]", displacement);
985 return offset + displacement;
986 }
987 case 5:
988 DECODE_PRINTF2("%d[EBP]", displacement);
989 return M.x86.R_EBP + displacement;
990 case 6:
991 DECODE_PRINTF2("%d[ESI]", displacement);
992 return M.x86.R_ESI + displacement;
993 case 7:
994 DECODE_PRINTF2("%d[EDI]", displacement);
995 return M.x86.R_EDI + displacement;
996 }
Jason Jinece92f82007-07-06 08:34:56 +0800997 } else {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +0200998 /* 16-bit addressing */
999 displacement = (s8)fetch_byte_imm();
1000 switch (rm) {
1001 case 0:
1002 DECODE_PRINTF2("%d[BX+SI]", displacement);
1003 return (M.x86.R_BX + M.x86.R_SI + displacement) & 0xffff;
1004 case 1:
1005 DECODE_PRINTF2("%d[BX+DI]", displacement);
1006 return (M.x86.R_BX + M.x86.R_DI + displacement) & 0xffff;
1007 case 2:
1008 DECODE_PRINTF2("%d[BP+SI]", displacement);
1009 M.x86.mode |= SYSMODE_SEG_DS_SS;
1010 return (M.x86.R_BP + M.x86.R_SI + displacement) & 0xffff;
1011 case 3:
1012 DECODE_PRINTF2("%d[BP+DI]", displacement);
1013 M.x86.mode |= SYSMODE_SEG_DS_SS;
1014 return (M.x86.R_BP + M.x86.R_DI + displacement) & 0xffff;
1015 case 4:
1016 DECODE_PRINTF2("%d[SI]", displacement);
1017 return (M.x86.R_SI + displacement) & 0xffff;
1018 case 5:
1019 DECODE_PRINTF2("%d[DI]", displacement);
1020 return (M.x86.R_DI + displacement) & 0xffff;
1021 case 6:
1022 DECODE_PRINTF2("%d[BP]", displacement);
1023 M.x86.mode |= SYSMODE_SEG_DS_SS;
1024 return (M.x86.R_BP + displacement) & 0xffff;
1025 case 7:
1026 DECODE_PRINTF2("%d[BX]", displacement);
1027 return (M.x86.R_BX + displacement) & 0xffff;
1028 }
Jason Jinece92f82007-07-06 08:34:56 +08001029 }
1030 HALT_SYS();
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02001031 return 0; /* SHOULD NOT HAPPEN */
Jason Jinece92f82007-07-06 08:34:56 +08001032}
1033
1034/****************************************************************************
1035PARAMETERS:
1036rm - RM value to decode
1037
1038RETURNS:
1039Offset in memory for the address decoding
1040
1041REMARKS:
1042Return the offset given by mod=10 addressing. Also enables the
1043decoding of instructions.
1044****************************************************************************/
1045unsigned decode_rm10_address(
1046 int rm)
1047{
1048 if (M.x86.mode & SYSMODE_PREFIX_ADDR) {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02001049 int displacement;
Jason Jinece92f82007-07-06 08:34:56 +08001050
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02001051 /* 32-bit addressing */
1052 if (rm != 4)
1053 displacement = (s32)fetch_long_imm();
1054 else
1055 displacement = 0;
Jason Jinece92f82007-07-06 08:34:56 +08001056
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02001057 switch (rm) {
1058 case 0:
1059 DECODE_PRINTF2("%d[EAX]", displacement);
1060 return M.x86.R_EAX + displacement;
1061 case 1:
1062 DECODE_PRINTF2("%d[ECX]", displacement);
1063 return M.x86.R_ECX + displacement;
1064 case 2:
1065 DECODE_PRINTF2("%d[EDX]", displacement);
1066 return M.x86.R_EDX + displacement;
1067 case 3:
1068 DECODE_PRINTF2("%d[EBX]", displacement);
1069 return M.x86.R_EBX + displacement;
1070 case 4: {
1071 int offset = decode_sib_address(2);
1072 displacement = (s32)fetch_long_imm();
1073 DECODE_PRINTF2("[%d]", displacement);
1074 return offset + displacement;
1075 }
1076 case 5:
1077 DECODE_PRINTF2("%d[EBP]", displacement);
1078 return M.x86.R_EBP + displacement;
1079 case 6:
1080 DECODE_PRINTF2("%d[ESI]", displacement);
1081 return M.x86.R_ESI + displacement;
1082 case 7:
1083 DECODE_PRINTF2("%d[EDI]", displacement);
1084 return M.x86.R_EDI + displacement;
1085 }
Jason Jinece92f82007-07-06 08:34:56 +08001086 } else {
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02001087 int displacement = (s16)fetch_word_imm();
Jason Jinece92f82007-07-06 08:34:56 +08001088
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02001089 /* 16-bit addressing */
1090 switch (rm) {
1091 case 0:
1092 DECODE_PRINTF2("%d[BX+SI]", displacement);
1093 return (M.x86.R_BX + M.x86.R_SI + displacement) & 0xffff;
1094 case 1:
1095 DECODE_PRINTF2("%d[BX+DI]", displacement);
1096 return (M.x86.R_BX + M.x86.R_DI + displacement) & 0xffff;
1097 case 2:
1098 DECODE_PRINTF2("%d[BP+SI]", displacement);
1099 M.x86.mode |= SYSMODE_SEG_DS_SS;
1100 return (M.x86.R_BP + M.x86.R_SI + displacement) & 0xffff;
1101 case 3:
1102 DECODE_PRINTF2("%d[BP+DI]", displacement);
1103 M.x86.mode |= SYSMODE_SEG_DS_SS;
1104 return (M.x86.R_BP + M.x86.R_DI + displacement) & 0xffff;
1105 case 4:
1106 DECODE_PRINTF2("%d[SI]", displacement);
1107 return (M.x86.R_SI + displacement) & 0xffff;
1108 case 5:
1109 DECODE_PRINTF2("%d[DI]", displacement);
1110 return (M.x86.R_DI + displacement) & 0xffff;
1111 case 6:
1112 DECODE_PRINTF2("%d[BP]", displacement);
1113 M.x86.mode |= SYSMODE_SEG_DS_SS;
1114 return (M.x86.R_BP + displacement) & 0xffff;
1115 case 7:
1116 DECODE_PRINTF2("%d[BX]", displacement);
1117 return (M.x86.R_BX + displacement) & 0xffff;
1118 }
Jason Jinece92f82007-07-06 08:34:56 +08001119 }
1120 HALT_SYS();
Wolfgang Denk9c7e4b02007-08-06 02:17:36 +02001121 return 0; /* SHOULD NOT HAPPEN */
Jason Jinece92f82007-07-06 08:34:56 +08001122}
1123
Jason Jinece92f82007-07-06 08:34:56 +08001124/****************************************************************************
1125PARAMETERS:
1126mod - modifier
1127rm - RM value to decode
1128
1129RETURNS:
1130Offset in memory for the address decoding, multiplexing calls to
1131the decode_rmXX_address functions
1132
1133REMARKS:
1134Return the offset given by "mod" addressing.
1135****************************************************************************/
1136
1137unsigned decode_rmXX_address(int mod, int rm)
1138{
1139 if(mod == 0)
1140 return decode_rm00_address(rm);
1141 if(mod == 1)
1142 return decode_rm01_address(rm);
1143 return decode_rm10_address(rm);
1144}