blob: e2028eaf08339c712940dfad8cc36de6cad1e069 [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>
Simon Glassbdd5f812023-09-14 18:21:46 -060040#include <linux/printk.h>
Michal Simek952d8612007-08-15 21:15:05 +020041#include "x86emu/x86emui.h"
42
Jason Jina63ce952007-07-06 08:34:56 +080043/*----------------------------- Implementation ----------------------------*/
44
45/****************************************************************************
46REMARKS:
47Handles any pending asychronous interrupts.
48****************************************************************************/
49static void x86emu_intr_handle(void)
50{
Wolfgang Denk96bb2e02007-08-06 02:17:36 +020051 u8 intno;
Jason Jina63ce952007-07-06 08:34:56 +080052
53 if (M.x86.intr & INTR_SYNCH) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +020054 intno = M.x86.intno;
55 if (_X86EMU_intrTab[intno]) {
56 (*_X86EMU_intrTab[intno])(intno);
57 } else {
58 push_word((u16)M.x86.R_FLG);
59 CLEAR_FLAG(F_IF);
60 CLEAR_FLAG(F_TF);
61 push_word(M.x86.R_CS);
62 M.x86.R_CS = mem_access_word(intno * 4 + 2);
63 push_word(M.x86.R_IP);
64 M.x86.R_IP = mem_access_word(intno * 4);
65 M.x86.intr = 0;
66 }
Jason Jina63ce952007-07-06 08:34:56 +080067 }
68}
69
70/****************************************************************************
71PARAMETERS:
72intrnum - Interrupt number to raise
73
74REMARKS:
75Raise the specified interrupt to be handled before the execution of the
76next instruction.
77****************************************************************************/
78void x86emu_intr_raise(
79 u8 intrnum)
80{
81 M.x86.intno = intrnum;
82 M.x86.intr |= INTR_SYNCH;
83}
84
85/****************************************************************************
86REMARKS:
87Main execution loop for the emulator. We return from here when the system
88halts, which is normally caused by a stack fault when we return from the
89original real mode call.
90****************************************************************************/
91void X86EMU_exec(void)
92{
93 u8 op1;
94
95 M.x86.intr = 0;
96 DB(x86emu_end_instr();)
97
98 for (;;) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +020099DB( if (CHECK_IP_FETCH())
100 x86emu_check_ip_access();)
101 /* If debugging, save the IP and CS values. */
102 SAVE_IP_CS(M.x86.R_CS, M.x86.R_IP);
103 INC_DECODED_INST_LEN(1);
104 if (M.x86.intr) {
105 if (M.x86.intr & INTR_HALTED) {
106DB( if (M.x86.R_SP != 0) {
107 printk("halted\n");
108 X86EMU_trace_regs();
109 }
110 else {
111 if (M.x86.debug)
112 printk("Service completed successfully\n");
113 })
114 return;
115 }
116 if (((M.x86.intr & INTR_SYNCH) && (M.x86.intno == 0 || M.x86.intno == 2)) ||
117 !ACCESS_FLAG(F_IF)) {
118 x86emu_intr_handle();
119 }
120 }
121 op1 = (*sys_rdb)(((u32)M.x86.R_CS << 4) + (M.x86.R_IP++));
122 (*x86emu_optab[op1])(op1);
123 if (M.x86.debug & DEBUG_EXIT) {
124 M.x86.debug &= ~DEBUG_EXIT;
125 return;
126 }
Jason Jina63ce952007-07-06 08:34:56 +0800127 }
128}
129
130/****************************************************************************
131REMARKS:
132Halts the system by setting the halted system flag.
133****************************************************************************/
134void X86EMU_halt_sys(void)
135{
136 M.x86.intr |= INTR_HALTED;
137}
138
139/****************************************************************************
140PARAMETERS:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200141mod - Mod value from decoded byte
142regh - Reg h value from decoded byte
143regl - Reg l value from decoded byte
Jason Jina63ce952007-07-06 08:34:56 +0800144
145REMARKS:
146Raise the specified interrupt to be handled before the execution of the
147next instruction.
148
149NOTE: Do not inline this function, as (*sys_rdb) is already inline!
150****************************************************************************/
151void fetch_decode_modrm(
152 int *mod,
153 int *regh,
154 int *regl)
155{
156 int fetched;
157
158DB( if (CHECK_IP_FETCH())
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200159 x86emu_check_ip_access();)
Jason Jina63ce952007-07-06 08:34:56 +0800160 fetched = (*sys_rdb)(((u32)M.x86.R_CS << 4) + (M.x86.R_IP++));
161 INC_DECODED_INST_LEN(1);
162 *mod = (fetched >> 6) & 0x03;
163 *regh = (fetched >> 3) & 0x07;
164 *regl = (fetched >> 0) & 0x07;
165}
166
167/****************************************************************************
168RETURNS:
169Immediate byte value read from instruction queue
170
171REMARKS:
172This function returns the immediate byte from the instruction queue, and
173moves the instruction pointer to the next value.
174
175NOTE: Do not inline this function, as (*sys_rdb) is already inline!
176****************************************************************************/
177u8 fetch_byte_imm(void)
178{
179 u8 fetched;
180
181DB( if (CHECK_IP_FETCH())
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200182 x86emu_check_ip_access();)
Jason Jina63ce952007-07-06 08:34:56 +0800183 fetched = (*sys_rdb)(((u32)M.x86.R_CS << 4) + (M.x86.R_IP++));
184 INC_DECODED_INST_LEN(1);
185 return fetched;
186}
187
188/****************************************************************************
189RETURNS:
190Immediate word value read from instruction queue
191
192REMARKS:
193This function returns the immediate byte from the instruction queue, and
194moves the instruction pointer to the next value.
195
196NOTE: Do not inline this function, as (*sys_rdw) is already inline!
197****************************************************************************/
198u16 fetch_word_imm(void)
199{
200 u16 fetched;
201
202DB( if (CHECK_IP_FETCH())
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200203 x86emu_check_ip_access();)
Jason Jina63ce952007-07-06 08:34:56 +0800204 fetched = (*sys_rdw)(((u32)M.x86.R_CS << 4) + (M.x86.R_IP));
205 M.x86.R_IP += 2;
206 INC_DECODED_INST_LEN(2);
207 return fetched;
208}
209
210/****************************************************************************
211RETURNS:
212Immediate lone value read from instruction queue
213
214REMARKS:
215This function returns the immediate byte from the instruction queue, and
216moves the instruction pointer to the next value.
217
218NOTE: Do not inline this function, as (*sys_rdw) is already inline!
219****************************************************************************/
220u32 fetch_long_imm(void)
221{
222 u32 fetched;
223
224DB( if (CHECK_IP_FETCH())
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200225 x86emu_check_ip_access();)
Jason Jina63ce952007-07-06 08:34:56 +0800226 fetched = (*sys_rdl)(((u32)M.x86.R_CS << 4) + (M.x86.R_IP));
227 M.x86.R_IP += 4;
228 INC_DECODED_INST_LEN(4);
229 return fetched;
230}
231
232/****************************************************************************
233RETURNS:
234Value of the default data segment
235
236REMARKS:
237Inline function that returns the default data segment for the current
238instruction.
239
240On the x86 processor, the default segment is not always DS if there is
241no segment override. Address modes such as -3[BP] or 10[BP+SI] all refer to
242addresses relative to SS (ie: on the stack). So, at the minimum, all
243decodings of addressing modes would have to set/clear a bit describing
244whether the access is relative to DS or SS. That is the function of the
Robert P. J. Day8c60f922016-05-04 04:47:31 -0400245cpu-state-variable M.x86.mode. There are several potential states:
Jason Jina63ce952007-07-06 08:34:56 +0800246
247 repe prefix seen (handled elsewhere)
248 repne prefix seen (ditto)
249
250 cs segment override
251 ds segment override
252 es segment override
253 fs segment override
254 gs segment override
255 ss segment override
256
257 ds/ss select (in absense of override)
258
259Each of the above 7 items are handled with a bit in the mode field.
260****************************************************************************/
261_INLINE u32 get_data_segment(void)
262{
263#define GET_SEGMENT(segment)
264 switch (M.x86.mode & SYSMODE_SEGMASK) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200265 case 0: /* default case: use ds register */
Jason Jina63ce952007-07-06 08:34:56 +0800266 case SYSMODE_SEGOVR_DS:
267 case SYSMODE_SEGOVR_DS | SYSMODE_SEG_DS_SS:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200268 return M.x86.R_DS;
269 case SYSMODE_SEG_DS_SS: /* non-overridden, use ss register */
270 return M.x86.R_SS;
Jason Jina63ce952007-07-06 08:34:56 +0800271 case SYSMODE_SEGOVR_CS:
272 case SYSMODE_SEGOVR_CS | SYSMODE_SEG_DS_SS:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200273 return M.x86.R_CS;
Jason Jina63ce952007-07-06 08:34:56 +0800274 case SYSMODE_SEGOVR_ES:
275 case SYSMODE_SEGOVR_ES | SYSMODE_SEG_DS_SS:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200276 return M.x86.R_ES;
Jason Jina63ce952007-07-06 08:34:56 +0800277 case SYSMODE_SEGOVR_FS:
278 case SYSMODE_SEGOVR_FS | SYSMODE_SEG_DS_SS:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200279 return M.x86.R_FS;
Jason Jina63ce952007-07-06 08:34:56 +0800280 case SYSMODE_SEGOVR_GS:
281 case SYSMODE_SEGOVR_GS | SYSMODE_SEG_DS_SS:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200282 return M.x86.R_GS;
Jason Jina63ce952007-07-06 08:34:56 +0800283 case SYSMODE_SEGOVR_SS:
284 case SYSMODE_SEGOVR_SS | SYSMODE_SEG_DS_SS:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200285 return M.x86.R_SS;
Jason Jina63ce952007-07-06 08:34:56 +0800286 default:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200287#ifdef DEBUG
288 printk("error: should not happen: multiple overrides.\n");
Jason Jina63ce952007-07-06 08:34:56 +0800289#endif
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200290 HALT_SYS();
291 return 0;
Jason Jina63ce952007-07-06 08:34:56 +0800292 }
293}
294
295/****************************************************************************
296PARAMETERS:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200297offset - Offset to load data from
Jason Jina63ce952007-07-06 08:34:56 +0800298
299RETURNS:
300Byte value read from the absolute memory location.
301
302NOTE: Do not inline this function as (*sys_rdX) is already inline!
303****************************************************************************/
304u8 fetch_data_byte(
305 uint offset)
306{
Simon Glassd8414fc2014-11-14 20:56:42 -0700307#ifdef CONFIG_X86EMU_DEBUG
Jason Jina63ce952007-07-06 08:34:56 +0800308 if (CHECK_DATA_ACCESS())
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200309 x86emu_check_data_access((u16)get_data_segment(), offset);
Jason Jina63ce952007-07-06 08:34:56 +0800310#endif
311 return (*sys_rdb)((get_data_segment() << 4) + offset);
312}
313
314/****************************************************************************
315PARAMETERS:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200316offset - Offset to load data from
Jason Jina63ce952007-07-06 08:34:56 +0800317
318RETURNS:
319Word value read from the absolute memory location.
320
321NOTE: Do not inline this function as (*sys_rdX) is already inline!
322****************************************************************************/
323u16 fetch_data_word(
324 uint offset)
325{
Simon Glassd8414fc2014-11-14 20:56:42 -0700326#ifdef CONFIG_X86EMU_DEBUG
Jason Jina63ce952007-07-06 08:34:56 +0800327 if (CHECK_DATA_ACCESS())
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200328 x86emu_check_data_access((u16)get_data_segment(), offset);
Jason Jina63ce952007-07-06 08:34:56 +0800329#endif
330 return (*sys_rdw)((get_data_segment() << 4) + offset);
331}
332
333/****************************************************************************
334PARAMETERS:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200335offset - Offset to load data from
Jason Jina63ce952007-07-06 08:34:56 +0800336
337RETURNS:
338Long value read from the absolute memory location.
339
340NOTE: Do not inline this function as (*sys_rdX) is already inline!
341****************************************************************************/
342u32 fetch_data_long(
343 uint offset)
344{
Simon Glassd8414fc2014-11-14 20:56:42 -0700345#ifdef CONFIG_X86EMU_DEBUG
Jason Jina63ce952007-07-06 08:34:56 +0800346 if (CHECK_DATA_ACCESS())
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200347 x86emu_check_data_access((u16)get_data_segment(), offset);
Jason Jina63ce952007-07-06 08:34:56 +0800348#endif
349 return (*sys_rdl)((get_data_segment() << 4) + offset);
350}
351
352/****************************************************************************
353PARAMETERS:
354segment - Segment to load data from
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200355offset - Offset to load data from
Jason Jina63ce952007-07-06 08:34:56 +0800356
357RETURNS:
358Byte value read from the absolute memory location.
359
360NOTE: Do not inline this function as (*sys_rdX) is already inline!
361****************************************************************************/
362u8 fetch_data_byte_abs(
363 uint segment,
364 uint offset)
365{
Simon Glassd8414fc2014-11-14 20:56:42 -0700366#ifdef CONFIG_X86EMU_DEBUG
Jason Jina63ce952007-07-06 08:34:56 +0800367 if (CHECK_DATA_ACCESS())
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200368 x86emu_check_data_access(segment, offset);
Jason Jina63ce952007-07-06 08:34:56 +0800369#endif
370 return (*sys_rdb)(((u32)segment << 4) + offset);
371}
372
373/****************************************************************************
374PARAMETERS:
375segment - Segment to load data from
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200376offset - Offset to load data from
Jason Jina63ce952007-07-06 08:34:56 +0800377
378RETURNS:
379Word value read from the absolute memory location.
380
381NOTE: Do not inline this function as (*sys_rdX) is already inline!
382****************************************************************************/
383u16 fetch_data_word_abs(
384 uint segment,
385 uint offset)
386{
Simon Glassd8414fc2014-11-14 20:56:42 -0700387#ifdef CONFIG_X86EMU_DEBUG
Jason Jina63ce952007-07-06 08:34:56 +0800388 if (CHECK_DATA_ACCESS())
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200389 x86emu_check_data_access(segment, offset);
Jason Jina63ce952007-07-06 08:34:56 +0800390#endif
391 return (*sys_rdw)(((u32)segment << 4) + offset);
392}
393
394/****************************************************************************
395PARAMETERS:
396segment - Segment to load data from
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200397offset - Offset to load data from
Jason Jina63ce952007-07-06 08:34:56 +0800398
399RETURNS:
400Long value read from the absolute memory location.
401
402NOTE: Do not inline this function as (*sys_rdX) is already inline!
403****************************************************************************/
404u32 fetch_data_long_abs(
405 uint segment,
406 uint offset)
407{
Simon Glassd8414fc2014-11-14 20:56:42 -0700408#ifdef CONFIG_X86EMU_DEBUG
Jason Jina63ce952007-07-06 08:34:56 +0800409 if (CHECK_DATA_ACCESS())
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200410 x86emu_check_data_access(segment, offset);
Jason Jina63ce952007-07-06 08:34:56 +0800411#endif
412 return (*sys_rdl)(((u32)segment << 4) + offset);
413}
414
415/****************************************************************************
416PARAMETERS:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200417offset - Offset to store data at
418val - Value to store
Jason Jina63ce952007-07-06 08:34:56 +0800419
420REMARKS:
421Writes a word value to an segmented memory location. The segment used is
422the current 'default' segment, which may have been overridden.
423
424NOTE: Do not inline this function as (*sys_wrX) is already inline!
425****************************************************************************/
426void store_data_byte(
427 uint offset,
428 u8 val)
429{
Simon Glassd8414fc2014-11-14 20:56:42 -0700430#ifdef CONFIG_X86EMU_DEBUG
Jason Jina63ce952007-07-06 08:34:56 +0800431 if (CHECK_DATA_ACCESS())
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200432 x86emu_check_data_access((u16)get_data_segment(), offset);
Jason Jina63ce952007-07-06 08:34:56 +0800433#endif
434 (*sys_wrb)((get_data_segment() << 4) + offset, val);
435}
436
437/****************************************************************************
438PARAMETERS:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200439offset - Offset to store data at
440val - Value to store
Jason Jina63ce952007-07-06 08:34:56 +0800441
442REMARKS:
443Writes a word value to an segmented memory location. The segment used is
444the current 'default' segment, which may have been overridden.
445
446NOTE: Do not inline this function as (*sys_wrX) is already inline!
447****************************************************************************/
448void store_data_word(
449 uint offset,
450 u16 val)
451{
Simon Glassd8414fc2014-11-14 20:56:42 -0700452#ifdef CONFIG_X86EMU_DEBUG
Jason Jina63ce952007-07-06 08:34:56 +0800453 if (CHECK_DATA_ACCESS())
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200454 x86emu_check_data_access((u16)get_data_segment(), offset);
Jason Jina63ce952007-07-06 08:34:56 +0800455#endif
456 (*sys_wrw)((get_data_segment() << 4) + offset, val);
457}
458
459/****************************************************************************
460PARAMETERS:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200461offset - Offset to store data at
462val - Value to store
Jason Jina63ce952007-07-06 08:34:56 +0800463
464REMARKS:
465Writes a long value to an segmented memory location. The segment used is
466the current 'default' segment, which may have been overridden.
467
468NOTE: Do not inline this function as (*sys_wrX) is already inline!
469****************************************************************************/
470void store_data_long(
471 uint offset,
472 u32 val)
473{
Simon Glassd8414fc2014-11-14 20:56:42 -0700474#ifdef CONFIG_X86EMU_DEBUG
Jason Jina63ce952007-07-06 08:34:56 +0800475 if (CHECK_DATA_ACCESS())
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200476 x86emu_check_data_access((u16)get_data_segment(), offset);
Jason Jina63ce952007-07-06 08:34:56 +0800477#endif
478 (*sys_wrl)((get_data_segment() << 4) + offset, val);
479}
480
481/****************************************************************************
482PARAMETERS:
483segment - Segment to store data at
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200484offset - Offset to store data at
485val - Value to store
Jason Jina63ce952007-07-06 08:34:56 +0800486
487REMARKS:
488Writes a byte value to an absolute memory location.
489
490NOTE: Do not inline this function as (*sys_wrX) is already inline!
491****************************************************************************/
492void store_data_byte_abs(
493 uint segment,
494 uint offset,
495 u8 val)
496{
Simon Glassd8414fc2014-11-14 20:56:42 -0700497#ifdef CONFIG_X86EMU_DEBUG
Jason Jina63ce952007-07-06 08:34:56 +0800498 if (CHECK_DATA_ACCESS())
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200499 x86emu_check_data_access(segment, offset);
Jason Jina63ce952007-07-06 08:34:56 +0800500#endif
501 (*sys_wrb)(((u32)segment << 4) + offset, val);
502}
503
504/****************************************************************************
505PARAMETERS:
506segment - Segment to store data at
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200507offset - Offset to store data at
508val - Value to store
Jason Jina63ce952007-07-06 08:34:56 +0800509
510REMARKS:
511Writes a word value to an absolute memory location.
512
513NOTE: Do not inline this function as (*sys_wrX) is already inline!
514****************************************************************************/
515void store_data_word_abs(
516 uint segment,
517 uint offset,
518 u16 val)
519{
Simon Glassd8414fc2014-11-14 20:56:42 -0700520#ifdef CONFIG_X86EMU_DEBUG
Jason Jina63ce952007-07-06 08:34:56 +0800521 if (CHECK_DATA_ACCESS())
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200522 x86emu_check_data_access(segment, offset);
Jason Jina63ce952007-07-06 08:34:56 +0800523#endif
524 (*sys_wrw)(((u32)segment << 4) + offset, val);
525}
526
527/****************************************************************************
528PARAMETERS:
529segment - Segment to store data at
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200530offset - Offset to store data at
531val - Value to store
Jason Jina63ce952007-07-06 08:34:56 +0800532
533REMARKS:
534Writes a long value to an absolute memory location.
535
536NOTE: Do not inline this function as (*sys_wrX) is already inline!
537****************************************************************************/
538void store_data_long_abs(
539 uint segment,
540 uint offset,
541 u32 val)
542{
Simon Glassd8414fc2014-11-14 20:56:42 -0700543#ifdef CONFIG_X86EMU_DEBUG
Jason Jina63ce952007-07-06 08:34:56 +0800544 if (CHECK_DATA_ACCESS())
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200545 x86emu_check_data_access(segment, offset);
Jason Jina63ce952007-07-06 08:34:56 +0800546#endif
547 (*sys_wrl)(((u32)segment << 4) + offset, val);
548}
549
550/****************************************************************************
551PARAMETERS:
552reg - Register to decode
553
554RETURNS:
555Pointer to the appropriate register
556
557REMARKS:
558Return a pointer to the register given by the R/RM field of the
559modrm byte, for byte operands. Also enables the decoding of instructions.
560****************************************************************************/
561u8* decode_rm_byte_register(
562 int reg)
563{
564 switch (reg) {
565 case 0:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200566 DECODE_PRINTF("AL");
567 return &M.x86.R_AL;
Jason Jina63ce952007-07-06 08:34:56 +0800568 case 1:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200569 DECODE_PRINTF("CL");
570 return &M.x86.R_CL;
Jason Jina63ce952007-07-06 08:34:56 +0800571 case 2:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200572 DECODE_PRINTF("DL");
573 return &M.x86.R_DL;
Jason Jina63ce952007-07-06 08:34:56 +0800574 case 3:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200575 DECODE_PRINTF("BL");
576 return &M.x86.R_BL;
Jason Jina63ce952007-07-06 08:34:56 +0800577 case 4:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200578 DECODE_PRINTF("AH");
579 return &M.x86.R_AH;
Jason Jina63ce952007-07-06 08:34:56 +0800580 case 5:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200581 DECODE_PRINTF("CH");
582 return &M.x86.R_CH;
Jason Jina63ce952007-07-06 08:34:56 +0800583 case 6:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200584 DECODE_PRINTF("DH");
585 return &M.x86.R_DH;
Jason Jina63ce952007-07-06 08:34:56 +0800586 case 7:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200587 DECODE_PRINTF("BH");
588 return &M.x86.R_BH;
Jason Jina63ce952007-07-06 08:34:56 +0800589 }
590 HALT_SYS();
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200591 return NULL; /* NOT REACHED OR REACHED ON ERROR */
Jason Jina63ce952007-07-06 08:34:56 +0800592}
593
594/****************************************************************************
595PARAMETERS:
596reg - Register to decode
597
598RETURNS:
599Pointer to the appropriate register
600
601REMARKS:
602Return a pointer to the register given by the R/RM field of the
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200603modrm byte, for word operands. Also enables the decoding of instructions.
Jason Jina63ce952007-07-06 08:34:56 +0800604****************************************************************************/
605u16* decode_rm_word_register(
606 int reg)
607{
608 switch (reg) {
609 case 0:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200610 DECODE_PRINTF("AX");
611 return &M.x86.R_AX;
Jason Jina63ce952007-07-06 08:34:56 +0800612 case 1:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200613 DECODE_PRINTF("CX");
614 return &M.x86.R_CX;
Jason Jina63ce952007-07-06 08:34:56 +0800615 case 2:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200616 DECODE_PRINTF("DX");
617 return &M.x86.R_DX;
Jason Jina63ce952007-07-06 08:34:56 +0800618 case 3:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200619 DECODE_PRINTF("BX");
620 return &M.x86.R_BX;
Jason Jina63ce952007-07-06 08:34:56 +0800621 case 4:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200622 DECODE_PRINTF("SP");
623 return &M.x86.R_SP;
Jason Jina63ce952007-07-06 08:34:56 +0800624 case 5:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200625 DECODE_PRINTF("BP");
626 return &M.x86.R_BP;
Jason Jina63ce952007-07-06 08:34:56 +0800627 case 6:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200628 DECODE_PRINTF("SI");
629 return &M.x86.R_SI;
Jason Jina63ce952007-07-06 08:34:56 +0800630 case 7:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200631 DECODE_PRINTF("DI");
632 return &M.x86.R_DI;
Jason Jina63ce952007-07-06 08:34:56 +0800633 }
634 HALT_SYS();
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200635 return NULL; /* NOTREACHED OR REACHED ON ERROR */
Jason Jina63ce952007-07-06 08:34:56 +0800636}
637
638/****************************************************************************
639PARAMETERS:
640reg - Register to decode
641
642RETURNS:
643Pointer to the appropriate register
644
645REMARKS:
646Return a pointer to the register given by the R/RM field of the
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200647modrm byte, for dword operands. Also enables the decoding of instructions.
Jason Jina63ce952007-07-06 08:34:56 +0800648****************************************************************************/
649u32* decode_rm_long_register(
650 int reg)
651{
652 switch (reg) {
653 case 0:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200654 DECODE_PRINTF("EAX");
655 return &M.x86.R_EAX;
Jason Jina63ce952007-07-06 08:34:56 +0800656 case 1:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200657 DECODE_PRINTF("ECX");
658 return &M.x86.R_ECX;
Jason Jina63ce952007-07-06 08:34:56 +0800659 case 2:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200660 DECODE_PRINTF("EDX");
661 return &M.x86.R_EDX;
Jason Jina63ce952007-07-06 08:34:56 +0800662 case 3:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200663 DECODE_PRINTF("EBX");
664 return &M.x86.R_EBX;
Jason Jina63ce952007-07-06 08:34:56 +0800665 case 4:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200666 DECODE_PRINTF("ESP");
667 return &M.x86.R_ESP;
Jason Jina63ce952007-07-06 08:34:56 +0800668 case 5:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200669 DECODE_PRINTF("EBP");
670 return &M.x86.R_EBP;
Jason Jina63ce952007-07-06 08:34:56 +0800671 case 6:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200672 DECODE_PRINTF("ESI");
673 return &M.x86.R_ESI;
Jason Jina63ce952007-07-06 08:34:56 +0800674 case 7:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200675 DECODE_PRINTF("EDI");
676 return &M.x86.R_EDI;
Jason Jina63ce952007-07-06 08:34:56 +0800677 }
678 HALT_SYS();
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200679 return NULL; /* NOTREACHED OR REACHED ON ERROR */
Jason Jina63ce952007-07-06 08:34:56 +0800680}
681
682/****************************************************************************
683PARAMETERS:
684reg - Register to decode
685
686RETURNS:
687Pointer to the appropriate register
688
689REMARKS:
690Return a pointer to the register given by the R/RM field of the
691modrm byte, for word operands, modified from above for the weirdo
692special case of segreg operands. Also enables the decoding of instructions.
693****************************************************************************/
694u16* decode_rm_seg_register(
695 int reg)
696{
697 switch (reg) {
698 case 0:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200699 DECODE_PRINTF("ES");
700 return &M.x86.R_ES;
Jason Jina63ce952007-07-06 08:34:56 +0800701 case 1:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200702 DECODE_PRINTF("CS");
703 return &M.x86.R_CS;
Jason Jina63ce952007-07-06 08:34:56 +0800704 case 2:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200705 DECODE_PRINTF("SS");
706 return &M.x86.R_SS;
Jason Jina63ce952007-07-06 08:34:56 +0800707 case 3:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200708 DECODE_PRINTF("DS");
709 return &M.x86.R_DS;
Jason Jina63ce952007-07-06 08:34:56 +0800710 case 4:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200711 DECODE_PRINTF("FS");
712 return &M.x86.R_FS;
Jason Jina63ce952007-07-06 08:34:56 +0800713 case 5:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200714 DECODE_PRINTF("GS");
715 return &M.x86.R_GS;
Jason Jina63ce952007-07-06 08:34:56 +0800716 case 6:
717 case 7:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200718 DECODE_PRINTF("ILLEGAL SEGREG");
719 break;
Jason Jina63ce952007-07-06 08:34:56 +0800720 }
721 HALT_SYS();
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200722 return NULL; /* NOT REACHED OR REACHED ON ERROR */
Jason Jina63ce952007-07-06 08:34:56 +0800723}
724
725/****************************************************************************
726PARAMETERS:
727scale - scale value of SIB byte
728index - index value of SIB byte
729
730RETURNS:
731Value of scale * index
732
733REMARKS:
734Decodes scale/index of SIB byte and returns relevant offset part of
735effective address.
736****************************************************************************/
737unsigned decode_sib_si(
738 int scale,
739 int index)
740{
741 scale = 1 << scale;
742 if (scale > 1) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200743 DECODE_PRINTF2("[%d*", scale);
Jason Jina63ce952007-07-06 08:34:56 +0800744 } else {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200745 DECODE_PRINTF("[");
Jason Jina63ce952007-07-06 08:34:56 +0800746 }
747 switch (index) {
748 case 0:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200749 DECODE_PRINTF("EAX]");
750 return M.x86.R_EAX * index;
Jason Jina63ce952007-07-06 08:34:56 +0800751 case 1:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200752 DECODE_PRINTF("ECX]");
753 return M.x86.R_ECX * index;
Jason Jina63ce952007-07-06 08:34:56 +0800754 case 2:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200755 DECODE_PRINTF("EDX]");
756 return M.x86.R_EDX * index;
Jason Jina63ce952007-07-06 08:34:56 +0800757 case 3:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200758 DECODE_PRINTF("EBX]");
759 return M.x86.R_EBX * index;
Jason Jina63ce952007-07-06 08:34:56 +0800760 case 4:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200761 DECODE_PRINTF("0]");
762 return 0;
Jason Jina63ce952007-07-06 08:34:56 +0800763 case 5:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200764 DECODE_PRINTF("EBP]");
765 return M.x86.R_EBP * index;
Jason Jina63ce952007-07-06 08:34:56 +0800766 case 6:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200767 DECODE_PRINTF("ESI]");
768 return M.x86.R_ESI * index;
Jason Jina63ce952007-07-06 08:34:56 +0800769 case 7:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200770 DECODE_PRINTF("EDI]");
771 return M.x86.R_EDI * index;
Jason Jina63ce952007-07-06 08:34:56 +0800772 }
773 HALT_SYS();
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200774 return 0; /* NOT REACHED OR REACHED ON ERROR */
Jason Jina63ce952007-07-06 08:34:56 +0800775}
776
777/****************************************************************************
778PARAMETERS:
779mod - MOD value of preceding ModR/M byte
780
781RETURNS:
782Offset in memory for the address decoding
783
784REMARKS:
785Decodes SIB addressing byte and returns calculated effective address.
786****************************************************************************/
787unsigned decode_sib_address(
788 int mod)
789{
790 int sib = fetch_byte_imm();
791 int ss = (sib >> 6) & 0x03;
792 int index = (sib >> 3) & 0x07;
793 int base = sib & 0x07;
794 int offset = 0;
795 int displacement;
796
797 switch (base) {
798 case 0:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200799 DECODE_PRINTF("[EAX]");
800 offset = M.x86.R_EAX;
801 break;
Jason Jina63ce952007-07-06 08:34:56 +0800802 case 1:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200803 DECODE_PRINTF("[ECX]");
804 offset = M.x86.R_ECX;
805 break;
Jason Jina63ce952007-07-06 08:34:56 +0800806 case 2:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200807 DECODE_PRINTF("[EDX]");
808 offset = M.x86.R_EDX;
809 break;
Jason Jina63ce952007-07-06 08:34:56 +0800810 case 3:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200811 DECODE_PRINTF("[EBX]");
812 offset = M.x86.R_EBX;
813 break;
Jason Jina63ce952007-07-06 08:34:56 +0800814 case 4:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200815 DECODE_PRINTF("[ESP]");
816 offset = M.x86.R_ESP;
817 break;
Jason Jina63ce952007-07-06 08:34:56 +0800818 case 5:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200819 switch (mod) {
820 case 0:
821 displacement = (s32)fetch_long_imm();
822 DECODE_PRINTF2("[%d]", displacement);
823 offset = displacement;
824 break;
825 case 1:
826 displacement = (s8)fetch_byte_imm();
827 DECODE_PRINTF2("[%d][EBP]", displacement);
828 offset = M.x86.R_EBP + displacement;
829 break;
830 case 2:
831 displacement = (s32)fetch_long_imm();
832 DECODE_PRINTF2("[%d][EBP]", displacement);
833 offset = M.x86.R_EBP + displacement;
834 break;
835 default:
836 HALT_SYS();
837 }
838 DECODE_PRINTF("[EAX]");
839 offset = M.x86.R_EAX;
840 break;
Jason Jina63ce952007-07-06 08:34:56 +0800841 case 6:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200842 DECODE_PRINTF("[ESI]");
843 offset = M.x86.R_ESI;
844 break;
Jason Jina63ce952007-07-06 08:34:56 +0800845 case 7:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200846 DECODE_PRINTF("[EDI]");
847 offset = M.x86.R_EDI;
848 break;
Jason Jina63ce952007-07-06 08:34:56 +0800849 default:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200850 HALT_SYS();
Jason Jina63ce952007-07-06 08:34:56 +0800851 }
852 offset += decode_sib_si(ss, index);
853 return offset;
854
855}
856
857/****************************************************************************
858PARAMETERS:
859rm - RM value to decode
860
861RETURNS:
862Offset in memory for the address decoding
863
864REMARKS:
865Return the offset given by mod=00 addressing. Also enables the
866decoding of instructions.
867
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200868NOTE: The code which specifies the corresponding segment (ds vs ss)
869 below in the case of [BP+..]. The assumption here is that at the
870 point that this subroutine is called, the bit corresponding to
871 SYSMODE_SEG_DS_SS will be zero. After every instruction
872 except the segment override instructions, this bit (as well
873 as any bits indicating segment overrides) will be clear. So
874 if a SS access is needed, set this bit. Otherwise, DS access
875 occurs (unless any of the segment override bits are set).
Jason Jina63ce952007-07-06 08:34:56 +0800876****************************************************************************/
877unsigned decode_rm00_address(
878 int rm)
879{
880 unsigned offset;
881
882 if (M.x86.mode & SYSMODE_PREFIX_ADDR) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200883 /* 32-bit addressing */
884 switch (rm) {
885 case 0:
886 DECODE_PRINTF("[EAX]");
887 return M.x86.R_EAX;
888 case 1:
889 DECODE_PRINTF("[ECX]");
890 return M.x86.R_ECX;
891 case 2:
892 DECODE_PRINTF("[EDX]");
893 return M.x86.R_EDX;
894 case 3:
895 DECODE_PRINTF("[EBX]");
896 return M.x86.R_EBX;
897 case 4:
898 return decode_sib_address(0);
899 case 5:
900 offset = fetch_long_imm();
901 DECODE_PRINTF2("[%08x]", offset);
902 return offset;
903 case 6:
904 DECODE_PRINTF("[ESI]");
905 return M.x86.R_ESI;
906 case 7:
907 DECODE_PRINTF("[EDI]");
908 return M.x86.R_EDI;
909 }
Jason Jina63ce952007-07-06 08:34:56 +0800910 } else {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200911 /* 16-bit addressing */
912 switch (rm) {
913 case 0:
914 DECODE_PRINTF("[BX+SI]");
915 return (M.x86.R_BX + M.x86.R_SI) & 0xffff;
916 case 1:
917 DECODE_PRINTF("[BX+DI]");
918 return (M.x86.R_BX + M.x86.R_DI) & 0xffff;
919 case 2:
920 DECODE_PRINTF("[BP+SI]");
921 M.x86.mode |= SYSMODE_SEG_DS_SS;
922 return (M.x86.R_BP + M.x86.R_SI) & 0xffff;
923 case 3:
924 DECODE_PRINTF("[BP+DI]");
925 M.x86.mode |= SYSMODE_SEG_DS_SS;
926 return (M.x86.R_BP + M.x86.R_DI) & 0xffff;
927 case 4:
928 DECODE_PRINTF("[SI]");
929 return M.x86.R_SI;
930 case 5:
931 DECODE_PRINTF("[DI]");
932 return M.x86.R_DI;
933 case 6:
934 offset = fetch_word_imm();
935 DECODE_PRINTF2("[%04x]", offset);
936 return offset;
937 case 7:
938 DECODE_PRINTF("[BX]");
939 return M.x86.R_BX;
940 }
Jason Jina63ce952007-07-06 08:34:56 +0800941 }
942 HALT_SYS();
943 return 0;
944}
945
946/****************************************************************************
947PARAMETERS:
948rm - RM value to decode
949
950RETURNS:
951Offset in memory for the address decoding
952
953REMARKS:
954Return the offset given by mod=01 addressing. Also enables the
955decoding of instructions.
956****************************************************************************/
957unsigned decode_rm01_address(
958 int rm)
959{
960 int displacement;
961
962 if (M.x86.mode & SYSMODE_PREFIX_ADDR) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200963 /* 32-bit addressing */
964 if (rm != 4)
965 displacement = (s8)fetch_byte_imm();
966 else
967 displacement = 0;
Jason Jina63ce952007-07-06 08:34:56 +0800968
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200969 switch (rm) {
970 case 0:
971 DECODE_PRINTF2("%d[EAX]", displacement);
972 return M.x86.R_EAX + displacement;
973 case 1:
974 DECODE_PRINTF2("%d[ECX]", displacement);
975 return M.x86.R_ECX + displacement;
976 case 2:
977 DECODE_PRINTF2("%d[EDX]", displacement);
978 return M.x86.R_EDX + displacement;
979 case 3:
980 DECODE_PRINTF2("%d[EBX]", displacement);
981 return M.x86.R_EBX + displacement;
982 case 4: {
983 int offset = decode_sib_address(1);
984 displacement = (s8)fetch_byte_imm();
985 DECODE_PRINTF2("[%d]", displacement);
986 return offset + displacement;
987 }
988 case 5:
989 DECODE_PRINTF2("%d[EBP]", displacement);
990 return M.x86.R_EBP + displacement;
991 case 6:
992 DECODE_PRINTF2("%d[ESI]", displacement);
993 return M.x86.R_ESI + displacement;
994 case 7:
995 DECODE_PRINTF2("%d[EDI]", displacement);
996 return M.x86.R_EDI + displacement;
997 }
Jason Jina63ce952007-07-06 08:34:56 +0800998 } else {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200999 /* 16-bit addressing */
1000 displacement = (s8)fetch_byte_imm();
1001 switch (rm) {
1002 case 0:
1003 DECODE_PRINTF2("%d[BX+SI]", displacement);
1004 return (M.x86.R_BX + M.x86.R_SI + displacement) & 0xffff;
1005 case 1:
1006 DECODE_PRINTF2("%d[BX+DI]", displacement);
1007 return (M.x86.R_BX + M.x86.R_DI + displacement) & 0xffff;
1008 case 2:
1009 DECODE_PRINTF2("%d[BP+SI]", displacement);
1010 M.x86.mode |= SYSMODE_SEG_DS_SS;
1011 return (M.x86.R_BP + M.x86.R_SI + displacement) & 0xffff;
1012 case 3:
1013 DECODE_PRINTF2("%d[BP+DI]", displacement);
1014 M.x86.mode |= SYSMODE_SEG_DS_SS;
1015 return (M.x86.R_BP + M.x86.R_DI + displacement) & 0xffff;
1016 case 4:
1017 DECODE_PRINTF2("%d[SI]", displacement);
1018 return (M.x86.R_SI + displacement) & 0xffff;
1019 case 5:
1020 DECODE_PRINTF2("%d[DI]", displacement);
1021 return (M.x86.R_DI + displacement) & 0xffff;
1022 case 6:
1023 DECODE_PRINTF2("%d[BP]", displacement);
1024 M.x86.mode |= SYSMODE_SEG_DS_SS;
1025 return (M.x86.R_BP + displacement) & 0xffff;
1026 case 7:
1027 DECODE_PRINTF2("%d[BX]", displacement);
1028 return (M.x86.R_BX + displacement) & 0xffff;
1029 }
Jason Jina63ce952007-07-06 08:34:56 +08001030 }
1031 HALT_SYS();
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001032 return 0; /* SHOULD NOT HAPPEN */
Jason Jina63ce952007-07-06 08:34:56 +08001033}
1034
1035/****************************************************************************
1036PARAMETERS:
1037rm - RM value to decode
1038
1039RETURNS:
1040Offset in memory for the address decoding
1041
1042REMARKS:
1043Return the offset given by mod=10 addressing. Also enables the
1044decoding of instructions.
1045****************************************************************************/
1046unsigned decode_rm10_address(
1047 int rm)
1048{
1049 if (M.x86.mode & SYSMODE_PREFIX_ADDR) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001050 int displacement;
Jason Jina63ce952007-07-06 08:34:56 +08001051
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001052 /* 32-bit addressing */
1053 if (rm != 4)
1054 displacement = (s32)fetch_long_imm();
1055 else
1056 displacement = 0;
Jason Jina63ce952007-07-06 08:34:56 +08001057
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001058 switch (rm) {
1059 case 0:
1060 DECODE_PRINTF2("%d[EAX]", displacement);
1061 return M.x86.R_EAX + displacement;
1062 case 1:
1063 DECODE_PRINTF2("%d[ECX]", displacement);
1064 return M.x86.R_ECX + displacement;
1065 case 2:
1066 DECODE_PRINTF2("%d[EDX]", displacement);
1067 return M.x86.R_EDX + displacement;
1068 case 3:
1069 DECODE_PRINTF2("%d[EBX]", displacement);
1070 return M.x86.R_EBX + displacement;
1071 case 4: {
1072 int offset = decode_sib_address(2);
1073 displacement = (s32)fetch_long_imm();
1074 DECODE_PRINTF2("[%d]", displacement);
1075 return offset + displacement;
1076 }
1077 case 5:
1078 DECODE_PRINTF2("%d[EBP]", displacement);
1079 return M.x86.R_EBP + displacement;
1080 case 6:
1081 DECODE_PRINTF2("%d[ESI]", displacement);
1082 return M.x86.R_ESI + displacement;
1083 case 7:
1084 DECODE_PRINTF2("%d[EDI]", displacement);
1085 return M.x86.R_EDI + displacement;
1086 }
Jason Jina63ce952007-07-06 08:34:56 +08001087 } else {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001088 int displacement = (s16)fetch_word_imm();
Jason Jina63ce952007-07-06 08:34:56 +08001089
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001090 /* 16-bit addressing */
1091 switch (rm) {
1092 case 0:
1093 DECODE_PRINTF2("%d[BX+SI]", displacement);
1094 return (M.x86.R_BX + M.x86.R_SI + displacement) & 0xffff;
1095 case 1:
1096 DECODE_PRINTF2("%d[BX+DI]", displacement);
1097 return (M.x86.R_BX + M.x86.R_DI + displacement) & 0xffff;
1098 case 2:
1099 DECODE_PRINTF2("%d[BP+SI]", displacement);
1100 M.x86.mode |= SYSMODE_SEG_DS_SS;
1101 return (M.x86.R_BP + M.x86.R_SI + displacement) & 0xffff;
1102 case 3:
1103 DECODE_PRINTF2("%d[BP+DI]", displacement);
1104 M.x86.mode |= SYSMODE_SEG_DS_SS;
1105 return (M.x86.R_BP + M.x86.R_DI + displacement) & 0xffff;
1106 case 4:
1107 DECODE_PRINTF2("%d[SI]", displacement);
1108 return (M.x86.R_SI + displacement) & 0xffff;
1109 case 5:
1110 DECODE_PRINTF2("%d[DI]", displacement);
1111 return (M.x86.R_DI + displacement) & 0xffff;
1112 case 6:
1113 DECODE_PRINTF2("%d[BP]", displacement);
1114 M.x86.mode |= SYSMODE_SEG_DS_SS;
1115 return (M.x86.R_BP + displacement) & 0xffff;
1116 case 7:
1117 DECODE_PRINTF2("%d[BX]", displacement);
1118 return (M.x86.R_BX + displacement) & 0xffff;
1119 }
Jason Jina63ce952007-07-06 08:34:56 +08001120 }
1121 HALT_SYS();
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001122 return 0; /* SHOULD NOT HAPPEN */
Jason Jina63ce952007-07-06 08:34:56 +08001123}
1124
Jason Jina63ce952007-07-06 08:34:56 +08001125/****************************************************************************
1126PARAMETERS:
1127mod - modifier
1128rm - RM value to decode
1129
1130RETURNS:
1131Offset in memory for the address decoding, multiplexing calls to
1132the decode_rmXX_address functions
1133
1134REMARKS:
1135Return the offset given by "mod" addressing.
1136****************************************************************************/
1137
1138unsigned decode_rmXX_address(int mod, int rm)
1139{
1140 if(mod == 0)
1141 return decode_rm00_address(rm);
1142 if(mod == 1)
1143 return decode_rm01_address(rm);
1144 return decode_rm10_address(rm);
1145}