blob: 879f0a06d17367a7611f5ce6dc1086e36ad1abbb [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****************************************************************************/
39
40#include "x86emu/x86emui.h"
41
Jason Jin7ed5cd92007-08-08 08:33:11 +080042#if defined(CONFIG_BIOSEMU)
43
Jason Jina63ce952007-07-06 08:34:56 +080044/*----------------------------- Implementation ----------------------------*/
45
46/****************************************************************************
47REMARKS:
48Handles any pending asychronous interrupts.
49****************************************************************************/
50static void x86emu_intr_handle(void)
51{
Wolfgang Denk96bb2e02007-08-06 02:17:36 +020052 u8 intno;
Jason Jina63ce952007-07-06 08:34:56 +080053
54 if (M.x86.intr & INTR_SYNCH) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +020055 intno = M.x86.intno;
56 if (_X86EMU_intrTab[intno]) {
57 (*_X86EMU_intrTab[intno])(intno);
58 } else {
59 push_word((u16)M.x86.R_FLG);
60 CLEAR_FLAG(F_IF);
61 CLEAR_FLAG(F_TF);
62 push_word(M.x86.R_CS);
63 M.x86.R_CS = mem_access_word(intno * 4 + 2);
64 push_word(M.x86.R_IP);
65 M.x86.R_IP = mem_access_word(intno * 4);
66 M.x86.intr = 0;
67 }
Jason Jina63ce952007-07-06 08:34:56 +080068 }
69}
70
71/****************************************************************************
72PARAMETERS:
73intrnum - Interrupt number to raise
74
75REMARKS:
76Raise the specified interrupt to be handled before the execution of the
77next instruction.
78****************************************************************************/
79void x86emu_intr_raise(
80 u8 intrnum)
81{
82 M.x86.intno = intrnum;
83 M.x86.intr |= INTR_SYNCH;
84}
85
86/****************************************************************************
87REMARKS:
88Main execution loop for the emulator. We return from here when the system
89halts, which is normally caused by a stack fault when we return from the
90original real mode call.
91****************************************************************************/
92void X86EMU_exec(void)
93{
94 u8 op1;
95
96 M.x86.intr = 0;
97 DB(x86emu_end_instr();)
98
99 for (;;) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200100DB( if (CHECK_IP_FETCH())
101 x86emu_check_ip_access();)
102 /* If debugging, save the IP and CS values. */
103 SAVE_IP_CS(M.x86.R_CS, M.x86.R_IP);
104 INC_DECODED_INST_LEN(1);
105 if (M.x86.intr) {
106 if (M.x86.intr & INTR_HALTED) {
107DB( if (M.x86.R_SP != 0) {
108 printk("halted\n");
109 X86EMU_trace_regs();
110 }
111 else {
112 if (M.x86.debug)
113 printk("Service completed successfully\n");
114 })
115 return;
116 }
117 if (((M.x86.intr & INTR_SYNCH) && (M.x86.intno == 0 || M.x86.intno == 2)) ||
118 !ACCESS_FLAG(F_IF)) {
119 x86emu_intr_handle();
120 }
121 }
122 op1 = (*sys_rdb)(((u32)M.x86.R_CS << 4) + (M.x86.R_IP++));
123 (*x86emu_optab[op1])(op1);
124 if (M.x86.debug & DEBUG_EXIT) {
125 M.x86.debug &= ~DEBUG_EXIT;
126 return;
127 }
Jason Jina63ce952007-07-06 08:34:56 +0800128 }
129}
130
131/****************************************************************************
132REMARKS:
133Halts the system by setting the halted system flag.
134****************************************************************************/
135void X86EMU_halt_sys(void)
136{
137 M.x86.intr |= INTR_HALTED;
138}
139
140/****************************************************************************
141PARAMETERS:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200142mod - Mod value from decoded byte
143regh - Reg h value from decoded byte
144regl - Reg l value from decoded byte
Jason Jina63ce952007-07-06 08:34:56 +0800145
146REMARKS:
147Raise the specified interrupt to be handled before the execution of the
148next instruction.
149
150NOTE: Do not inline this function, as (*sys_rdb) is already inline!
151****************************************************************************/
152void fetch_decode_modrm(
153 int *mod,
154 int *regh,
155 int *regl)
156{
157 int fetched;
158
159DB( if (CHECK_IP_FETCH())
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200160 x86emu_check_ip_access();)
Jason Jina63ce952007-07-06 08:34:56 +0800161 fetched = (*sys_rdb)(((u32)M.x86.R_CS << 4) + (M.x86.R_IP++));
162 INC_DECODED_INST_LEN(1);
163 *mod = (fetched >> 6) & 0x03;
164 *regh = (fetched >> 3) & 0x07;
165 *regl = (fetched >> 0) & 0x07;
166}
167
168/****************************************************************************
169RETURNS:
170Immediate byte value read from instruction queue
171
172REMARKS:
173This function returns the immediate byte from the instruction queue, and
174moves the instruction pointer to the next value.
175
176NOTE: Do not inline this function, as (*sys_rdb) is already inline!
177****************************************************************************/
178u8 fetch_byte_imm(void)
179{
180 u8 fetched;
181
182DB( if (CHECK_IP_FETCH())
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200183 x86emu_check_ip_access();)
Jason Jina63ce952007-07-06 08:34:56 +0800184 fetched = (*sys_rdb)(((u32)M.x86.R_CS << 4) + (M.x86.R_IP++));
185 INC_DECODED_INST_LEN(1);
186 return fetched;
187}
188
189/****************************************************************************
190RETURNS:
191Immediate word value read from instruction queue
192
193REMARKS:
194This function returns the immediate byte from the instruction queue, and
195moves the instruction pointer to the next value.
196
197NOTE: Do not inline this function, as (*sys_rdw) is already inline!
198****************************************************************************/
199u16 fetch_word_imm(void)
200{
201 u16 fetched;
202
203DB( if (CHECK_IP_FETCH())
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200204 x86emu_check_ip_access();)
Jason Jina63ce952007-07-06 08:34:56 +0800205 fetched = (*sys_rdw)(((u32)M.x86.R_CS << 4) + (M.x86.R_IP));
206 M.x86.R_IP += 2;
207 INC_DECODED_INST_LEN(2);
208 return fetched;
209}
210
211/****************************************************************************
212RETURNS:
213Immediate lone value read from instruction queue
214
215REMARKS:
216This function returns the immediate byte from the instruction queue, and
217moves the instruction pointer to the next value.
218
219NOTE: Do not inline this function, as (*sys_rdw) is already inline!
220****************************************************************************/
221u32 fetch_long_imm(void)
222{
223 u32 fetched;
224
225DB( if (CHECK_IP_FETCH())
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200226 x86emu_check_ip_access();)
Jason Jina63ce952007-07-06 08:34:56 +0800227 fetched = (*sys_rdl)(((u32)M.x86.R_CS << 4) + (M.x86.R_IP));
228 M.x86.R_IP += 4;
229 INC_DECODED_INST_LEN(4);
230 return fetched;
231}
232
233/****************************************************************************
234RETURNS:
235Value of the default data segment
236
237REMARKS:
238Inline function that returns the default data segment for the current
239instruction.
240
241On the x86 processor, the default segment is not always DS if there is
242no segment override. Address modes such as -3[BP] or 10[BP+SI] all refer to
243addresses relative to SS (ie: on the stack). So, at the minimum, all
244decodings of addressing modes would have to set/clear a bit describing
245whether the access is relative to DS or SS. That is the function of the
246cpu-state-varible M.x86.mode. There are several potential states:
247
248 repe prefix seen (handled elsewhere)
249 repne prefix seen (ditto)
250
251 cs segment override
252 ds segment override
253 es segment override
254 fs segment override
255 gs segment override
256 ss segment override
257
258 ds/ss select (in absense of override)
259
260Each of the above 7 items are handled with a bit in the mode field.
261****************************************************************************/
262_INLINE u32 get_data_segment(void)
263{
264#define GET_SEGMENT(segment)
265 switch (M.x86.mode & SYSMODE_SEGMASK) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200266 case 0: /* default case: use ds register */
Jason Jina63ce952007-07-06 08:34:56 +0800267 case SYSMODE_SEGOVR_DS:
268 case SYSMODE_SEGOVR_DS | SYSMODE_SEG_DS_SS:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200269 return M.x86.R_DS;
270 case SYSMODE_SEG_DS_SS: /* non-overridden, use ss register */
271 return M.x86.R_SS;
Jason Jina63ce952007-07-06 08:34:56 +0800272 case SYSMODE_SEGOVR_CS:
273 case SYSMODE_SEGOVR_CS | SYSMODE_SEG_DS_SS:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200274 return M.x86.R_CS;
Jason Jina63ce952007-07-06 08:34:56 +0800275 case SYSMODE_SEGOVR_ES:
276 case SYSMODE_SEGOVR_ES | SYSMODE_SEG_DS_SS:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200277 return M.x86.R_ES;
Jason Jina63ce952007-07-06 08:34:56 +0800278 case SYSMODE_SEGOVR_FS:
279 case SYSMODE_SEGOVR_FS | SYSMODE_SEG_DS_SS:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200280 return M.x86.R_FS;
Jason Jina63ce952007-07-06 08:34:56 +0800281 case SYSMODE_SEGOVR_GS:
282 case SYSMODE_SEGOVR_GS | SYSMODE_SEG_DS_SS:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200283 return M.x86.R_GS;
Jason Jina63ce952007-07-06 08:34:56 +0800284 case SYSMODE_SEGOVR_SS:
285 case SYSMODE_SEGOVR_SS | SYSMODE_SEG_DS_SS:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200286 return M.x86.R_SS;
Jason Jina63ce952007-07-06 08:34:56 +0800287 default:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200288#ifdef DEBUG
289 printk("error: should not happen: multiple overrides.\n");
Jason Jina63ce952007-07-06 08:34:56 +0800290#endif
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200291 HALT_SYS();
292 return 0;
Jason Jina63ce952007-07-06 08:34:56 +0800293 }
294}
295
296/****************************************************************************
297PARAMETERS:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200298offset - Offset to load data from
Jason Jina63ce952007-07-06 08:34:56 +0800299
300RETURNS:
301Byte value read from the absolute memory location.
302
303NOTE: Do not inline this function as (*sys_rdX) is already inline!
304****************************************************************************/
305u8 fetch_data_byte(
306 uint offset)
307{
308#ifdef DEBUG
309 if (CHECK_DATA_ACCESS())
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200310 x86emu_check_data_access((u16)get_data_segment(), offset);
Jason Jina63ce952007-07-06 08:34:56 +0800311#endif
312 return (*sys_rdb)((get_data_segment() << 4) + offset);
313}
314
315/****************************************************************************
316PARAMETERS:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200317offset - Offset to load data from
Jason Jina63ce952007-07-06 08:34:56 +0800318
319RETURNS:
320Word value read from the absolute memory location.
321
322NOTE: Do not inline this function as (*sys_rdX) is already inline!
323****************************************************************************/
324u16 fetch_data_word(
325 uint offset)
326{
327#ifdef DEBUG
328 if (CHECK_DATA_ACCESS())
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200329 x86emu_check_data_access((u16)get_data_segment(), offset);
Jason Jina63ce952007-07-06 08:34:56 +0800330#endif
331 return (*sys_rdw)((get_data_segment() << 4) + offset);
332}
333
334/****************************************************************************
335PARAMETERS:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200336offset - Offset to load data from
Jason Jina63ce952007-07-06 08:34:56 +0800337
338RETURNS:
339Long value read from the absolute memory location.
340
341NOTE: Do not inline this function as (*sys_rdX) is already inline!
342****************************************************************************/
343u32 fetch_data_long(
344 uint offset)
345{
346#ifdef DEBUG
347 if (CHECK_DATA_ACCESS())
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200348 x86emu_check_data_access((u16)get_data_segment(), offset);
Jason Jina63ce952007-07-06 08:34:56 +0800349#endif
350 return (*sys_rdl)((get_data_segment() << 4) + offset);
351}
352
353/****************************************************************************
354PARAMETERS:
355segment - Segment to load data from
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200356offset - Offset to load data from
Jason Jina63ce952007-07-06 08:34:56 +0800357
358RETURNS:
359Byte value read from the absolute memory location.
360
361NOTE: Do not inline this function as (*sys_rdX) is already inline!
362****************************************************************************/
363u8 fetch_data_byte_abs(
364 uint segment,
365 uint offset)
366{
367#ifdef DEBUG
368 if (CHECK_DATA_ACCESS())
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200369 x86emu_check_data_access(segment, offset);
Jason Jina63ce952007-07-06 08:34:56 +0800370#endif
371 return (*sys_rdb)(((u32)segment << 4) + offset);
372}
373
374/****************************************************************************
375PARAMETERS:
376segment - Segment to load data from
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200377offset - Offset to load data from
Jason Jina63ce952007-07-06 08:34:56 +0800378
379RETURNS:
380Word value read from the absolute memory location.
381
382NOTE: Do not inline this function as (*sys_rdX) is already inline!
383****************************************************************************/
384u16 fetch_data_word_abs(
385 uint segment,
386 uint offset)
387{
388#ifdef DEBUG
389 if (CHECK_DATA_ACCESS())
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200390 x86emu_check_data_access(segment, offset);
Jason Jina63ce952007-07-06 08:34:56 +0800391#endif
392 return (*sys_rdw)(((u32)segment << 4) + offset);
393}
394
395/****************************************************************************
396PARAMETERS:
397segment - Segment to load data from
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200398offset - Offset to load data from
Jason Jina63ce952007-07-06 08:34:56 +0800399
400RETURNS:
401Long value read from the absolute memory location.
402
403NOTE: Do not inline this function as (*sys_rdX) is already inline!
404****************************************************************************/
405u32 fetch_data_long_abs(
406 uint segment,
407 uint offset)
408{
409#ifdef DEBUG
410 if (CHECK_DATA_ACCESS())
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200411 x86emu_check_data_access(segment, offset);
Jason Jina63ce952007-07-06 08:34:56 +0800412#endif
413 return (*sys_rdl)(((u32)segment << 4) + offset);
414}
415
416/****************************************************************************
417PARAMETERS:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200418offset - Offset to store data at
419val - Value to store
Jason Jina63ce952007-07-06 08:34:56 +0800420
421REMARKS:
422Writes a word value to an segmented memory location. The segment used is
423the current 'default' segment, which may have been overridden.
424
425NOTE: Do not inline this function as (*sys_wrX) is already inline!
426****************************************************************************/
427void store_data_byte(
428 uint offset,
429 u8 val)
430{
431#ifdef DEBUG
432 if (CHECK_DATA_ACCESS())
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200433 x86emu_check_data_access((u16)get_data_segment(), offset);
Jason Jina63ce952007-07-06 08:34:56 +0800434#endif
435 (*sys_wrb)((get_data_segment() << 4) + offset, val);
436}
437
438/****************************************************************************
439PARAMETERS:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200440offset - Offset to store data at
441val - Value to store
Jason Jina63ce952007-07-06 08:34:56 +0800442
443REMARKS:
444Writes a word value to an segmented memory location. The segment used is
445the current 'default' segment, which may have been overridden.
446
447NOTE: Do not inline this function as (*sys_wrX) is already inline!
448****************************************************************************/
449void store_data_word(
450 uint offset,
451 u16 val)
452{
453#ifdef DEBUG
454 if (CHECK_DATA_ACCESS())
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200455 x86emu_check_data_access((u16)get_data_segment(), offset);
Jason Jina63ce952007-07-06 08:34:56 +0800456#endif
457 (*sys_wrw)((get_data_segment() << 4) + offset, val);
458}
459
460/****************************************************************************
461PARAMETERS:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200462offset - Offset to store data at
463val - Value to store
Jason Jina63ce952007-07-06 08:34:56 +0800464
465REMARKS:
466Writes a long value to an segmented memory location. The segment used is
467the current 'default' segment, which may have been overridden.
468
469NOTE: Do not inline this function as (*sys_wrX) is already inline!
470****************************************************************************/
471void store_data_long(
472 uint offset,
473 u32 val)
474{
475#ifdef DEBUG
476 if (CHECK_DATA_ACCESS())
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200477 x86emu_check_data_access((u16)get_data_segment(), offset);
Jason Jina63ce952007-07-06 08:34:56 +0800478#endif
479 (*sys_wrl)((get_data_segment() << 4) + offset, val);
480}
481
482/****************************************************************************
483PARAMETERS:
484segment - Segment to store data at
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200485offset - Offset to store data at
486val - Value to store
Jason Jina63ce952007-07-06 08:34:56 +0800487
488REMARKS:
489Writes a byte value to an absolute memory location.
490
491NOTE: Do not inline this function as (*sys_wrX) is already inline!
492****************************************************************************/
493void store_data_byte_abs(
494 uint segment,
495 uint offset,
496 u8 val)
497{
498#ifdef DEBUG
499 if (CHECK_DATA_ACCESS())
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200500 x86emu_check_data_access(segment, offset);
Jason Jina63ce952007-07-06 08:34:56 +0800501#endif
502 (*sys_wrb)(((u32)segment << 4) + offset, val);
503}
504
505/****************************************************************************
506PARAMETERS:
507segment - Segment to store data at
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200508offset - Offset to store data at
509val - Value to store
Jason Jina63ce952007-07-06 08:34:56 +0800510
511REMARKS:
512Writes a word value to an absolute memory location.
513
514NOTE: Do not inline this function as (*sys_wrX) is already inline!
515****************************************************************************/
516void store_data_word_abs(
517 uint segment,
518 uint offset,
519 u16 val)
520{
521#ifdef DEBUG
522 if (CHECK_DATA_ACCESS())
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200523 x86emu_check_data_access(segment, offset);
Jason Jina63ce952007-07-06 08:34:56 +0800524#endif
525 (*sys_wrw)(((u32)segment << 4) + offset, val);
526}
527
528/****************************************************************************
529PARAMETERS:
530segment - Segment to store data at
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200531offset - Offset to store data at
532val - Value to store
Jason Jina63ce952007-07-06 08:34:56 +0800533
534REMARKS:
535Writes a long value to an absolute memory location.
536
537NOTE: Do not inline this function as (*sys_wrX) is already inline!
538****************************************************************************/
539void store_data_long_abs(
540 uint segment,
541 uint offset,
542 u32 val)
543{
544#ifdef DEBUG
545 if (CHECK_DATA_ACCESS())
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200546 x86emu_check_data_access(segment, offset);
Jason Jina63ce952007-07-06 08:34:56 +0800547#endif
548 (*sys_wrl)(((u32)segment << 4) + offset, val);
549}
550
551/****************************************************************************
552PARAMETERS:
553reg - Register to decode
554
555RETURNS:
556Pointer to the appropriate register
557
558REMARKS:
559Return a pointer to the register given by the R/RM field of the
560modrm byte, for byte operands. Also enables the decoding of instructions.
561****************************************************************************/
562u8* decode_rm_byte_register(
563 int reg)
564{
565 switch (reg) {
566 case 0:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200567 DECODE_PRINTF("AL");
568 return &M.x86.R_AL;
Jason Jina63ce952007-07-06 08:34:56 +0800569 case 1:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200570 DECODE_PRINTF("CL");
571 return &M.x86.R_CL;
Jason Jina63ce952007-07-06 08:34:56 +0800572 case 2:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200573 DECODE_PRINTF("DL");
574 return &M.x86.R_DL;
Jason Jina63ce952007-07-06 08:34:56 +0800575 case 3:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200576 DECODE_PRINTF("BL");
577 return &M.x86.R_BL;
Jason Jina63ce952007-07-06 08:34:56 +0800578 case 4:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200579 DECODE_PRINTF("AH");
580 return &M.x86.R_AH;
Jason Jina63ce952007-07-06 08:34:56 +0800581 case 5:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200582 DECODE_PRINTF("CH");
583 return &M.x86.R_CH;
Jason Jina63ce952007-07-06 08:34:56 +0800584 case 6:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200585 DECODE_PRINTF("DH");
586 return &M.x86.R_DH;
Jason Jina63ce952007-07-06 08:34:56 +0800587 case 7:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200588 DECODE_PRINTF("BH");
589 return &M.x86.R_BH;
Jason Jina63ce952007-07-06 08:34:56 +0800590 }
591 HALT_SYS();
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200592 return NULL; /* NOT REACHED OR REACHED ON ERROR */
Jason Jina63ce952007-07-06 08:34:56 +0800593}
594
595/****************************************************************************
596PARAMETERS:
597reg - Register to decode
598
599RETURNS:
600Pointer to the appropriate register
601
602REMARKS:
603Return a pointer to the register given by the R/RM field of the
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200604modrm byte, for word operands. Also enables the decoding of instructions.
Jason Jina63ce952007-07-06 08:34:56 +0800605****************************************************************************/
606u16* decode_rm_word_register(
607 int reg)
608{
609 switch (reg) {
610 case 0:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200611 DECODE_PRINTF("AX");
612 return &M.x86.R_AX;
Jason Jina63ce952007-07-06 08:34:56 +0800613 case 1:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200614 DECODE_PRINTF("CX");
615 return &M.x86.R_CX;
Jason Jina63ce952007-07-06 08:34:56 +0800616 case 2:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200617 DECODE_PRINTF("DX");
618 return &M.x86.R_DX;
Jason Jina63ce952007-07-06 08:34:56 +0800619 case 3:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200620 DECODE_PRINTF("BX");
621 return &M.x86.R_BX;
Jason Jina63ce952007-07-06 08:34:56 +0800622 case 4:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200623 DECODE_PRINTF("SP");
624 return &M.x86.R_SP;
Jason Jina63ce952007-07-06 08:34:56 +0800625 case 5:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200626 DECODE_PRINTF("BP");
627 return &M.x86.R_BP;
Jason Jina63ce952007-07-06 08:34:56 +0800628 case 6:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200629 DECODE_PRINTF("SI");
630 return &M.x86.R_SI;
Jason Jina63ce952007-07-06 08:34:56 +0800631 case 7:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200632 DECODE_PRINTF("DI");
633 return &M.x86.R_DI;
Jason Jina63ce952007-07-06 08:34:56 +0800634 }
635 HALT_SYS();
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200636 return NULL; /* NOTREACHED OR REACHED ON ERROR */
Jason Jina63ce952007-07-06 08:34:56 +0800637}
638
639/****************************************************************************
640PARAMETERS:
641reg - Register to decode
642
643RETURNS:
644Pointer to the appropriate register
645
646REMARKS:
647Return a pointer to the register given by the R/RM field of the
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200648modrm byte, for dword operands. Also enables the decoding of instructions.
Jason Jina63ce952007-07-06 08:34:56 +0800649****************************************************************************/
650u32* decode_rm_long_register(
651 int reg)
652{
653 switch (reg) {
654 case 0:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200655 DECODE_PRINTF("EAX");
656 return &M.x86.R_EAX;
Jason Jina63ce952007-07-06 08:34:56 +0800657 case 1:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200658 DECODE_PRINTF("ECX");
659 return &M.x86.R_ECX;
Jason Jina63ce952007-07-06 08:34:56 +0800660 case 2:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200661 DECODE_PRINTF("EDX");
662 return &M.x86.R_EDX;
Jason Jina63ce952007-07-06 08:34:56 +0800663 case 3:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200664 DECODE_PRINTF("EBX");
665 return &M.x86.R_EBX;
Jason Jina63ce952007-07-06 08:34:56 +0800666 case 4:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200667 DECODE_PRINTF("ESP");
668 return &M.x86.R_ESP;
Jason Jina63ce952007-07-06 08:34:56 +0800669 case 5:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200670 DECODE_PRINTF("EBP");
671 return &M.x86.R_EBP;
Jason Jina63ce952007-07-06 08:34:56 +0800672 case 6:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200673 DECODE_PRINTF("ESI");
674 return &M.x86.R_ESI;
Jason Jina63ce952007-07-06 08:34:56 +0800675 case 7:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200676 DECODE_PRINTF("EDI");
677 return &M.x86.R_EDI;
Jason Jina63ce952007-07-06 08:34:56 +0800678 }
679 HALT_SYS();
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200680 return NULL; /* NOTREACHED OR REACHED ON ERROR */
Jason Jina63ce952007-07-06 08:34:56 +0800681}
682
683/****************************************************************************
684PARAMETERS:
685reg - Register to decode
686
687RETURNS:
688Pointer to the appropriate register
689
690REMARKS:
691Return a pointer to the register given by the R/RM field of the
692modrm byte, for word operands, modified from above for the weirdo
693special case of segreg operands. Also enables the decoding of instructions.
694****************************************************************************/
695u16* decode_rm_seg_register(
696 int reg)
697{
698 switch (reg) {
699 case 0:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200700 DECODE_PRINTF("ES");
701 return &M.x86.R_ES;
Jason Jina63ce952007-07-06 08:34:56 +0800702 case 1:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200703 DECODE_PRINTF("CS");
704 return &M.x86.R_CS;
Jason Jina63ce952007-07-06 08:34:56 +0800705 case 2:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200706 DECODE_PRINTF("SS");
707 return &M.x86.R_SS;
Jason Jina63ce952007-07-06 08:34:56 +0800708 case 3:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200709 DECODE_PRINTF("DS");
710 return &M.x86.R_DS;
Jason Jina63ce952007-07-06 08:34:56 +0800711 case 4:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200712 DECODE_PRINTF("FS");
713 return &M.x86.R_FS;
Jason Jina63ce952007-07-06 08:34:56 +0800714 case 5:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200715 DECODE_PRINTF("GS");
716 return &M.x86.R_GS;
Jason Jina63ce952007-07-06 08:34:56 +0800717 case 6:
718 case 7:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200719 DECODE_PRINTF("ILLEGAL SEGREG");
720 break;
Jason Jina63ce952007-07-06 08:34:56 +0800721 }
722 HALT_SYS();
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200723 return NULL; /* NOT REACHED OR REACHED ON ERROR */
Jason Jina63ce952007-07-06 08:34:56 +0800724}
725
726/****************************************************************************
727PARAMETERS:
728scale - scale value of SIB byte
729index - index value of SIB byte
730
731RETURNS:
732Value of scale * index
733
734REMARKS:
735Decodes scale/index of SIB byte and returns relevant offset part of
736effective address.
737****************************************************************************/
738unsigned decode_sib_si(
739 int scale,
740 int index)
741{
742 scale = 1 << scale;
743 if (scale > 1) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200744 DECODE_PRINTF2("[%d*", scale);
Jason Jina63ce952007-07-06 08:34:56 +0800745 } else {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200746 DECODE_PRINTF("[");
Jason Jina63ce952007-07-06 08:34:56 +0800747 }
748 switch (index) {
749 case 0:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200750 DECODE_PRINTF("EAX]");
751 return M.x86.R_EAX * index;
Jason Jina63ce952007-07-06 08:34:56 +0800752 case 1:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200753 DECODE_PRINTF("ECX]");
754 return M.x86.R_ECX * index;
Jason Jina63ce952007-07-06 08:34:56 +0800755 case 2:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200756 DECODE_PRINTF("EDX]");
757 return M.x86.R_EDX * index;
Jason Jina63ce952007-07-06 08:34:56 +0800758 case 3:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200759 DECODE_PRINTF("EBX]");
760 return M.x86.R_EBX * index;
Jason Jina63ce952007-07-06 08:34:56 +0800761 case 4:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200762 DECODE_PRINTF("0]");
763 return 0;
Jason Jina63ce952007-07-06 08:34:56 +0800764 case 5:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200765 DECODE_PRINTF("EBP]");
766 return M.x86.R_EBP * index;
Jason Jina63ce952007-07-06 08:34:56 +0800767 case 6:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200768 DECODE_PRINTF("ESI]");
769 return M.x86.R_ESI * index;
Jason Jina63ce952007-07-06 08:34:56 +0800770 case 7:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200771 DECODE_PRINTF("EDI]");
772 return M.x86.R_EDI * index;
Jason Jina63ce952007-07-06 08:34:56 +0800773 }
774 HALT_SYS();
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200775 return 0; /* NOT REACHED OR REACHED ON ERROR */
Jason Jina63ce952007-07-06 08:34:56 +0800776}
777
778/****************************************************************************
779PARAMETERS:
780mod - MOD value of preceding ModR/M byte
781
782RETURNS:
783Offset in memory for the address decoding
784
785REMARKS:
786Decodes SIB addressing byte and returns calculated effective address.
787****************************************************************************/
788unsigned decode_sib_address(
789 int mod)
790{
791 int sib = fetch_byte_imm();
792 int ss = (sib >> 6) & 0x03;
793 int index = (sib >> 3) & 0x07;
794 int base = sib & 0x07;
795 int offset = 0;
796 int displacement;
797
798 switch (base) {
799 case 0:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200800 DECODE_PRINTF("[EAX]");
801 offset = M.x86.R_EAX;
802 break;
Jason Jina63ce952007-07-06 08:34:56 +0800803 case 1:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200804 DECODE_PRINTF("[ECX]");
805 offset = M.x86.R_ECX;
806 break;
Jason Jina63ce952007-07-06 08:34:56 +0800807 case 2:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200808 DECODE_PRINTF("[EDX]");
809 offset = M.x86.R_EDX;
810 break;
Jason Jina63ce952007-07-06 08:34:56 +0800811 case 3:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200812 DECODE_PRINTF("[EBX]");
813 offset = M.x86.R_EBX;
814 break;
Jason Jina63ce952007-07-06 08:34:56 +0800815 case 4:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200816 DECODE_PRINTF("[ESP]");
817 offset = M.x86.R_ESP;
818 break;
Jason Jina63ce952007-07-06 08:34:56 +0800819 case 5:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200820 switch (mod) {
821 case 0:
822 displacement = (s32)fetch_long_imm();
823 DECODE_PRINTF2("[%d]", displacement);
824 offset = displacement;
825 break;
826 case 1:
827 displacement = (s8)fetch_byte_imm();
828 DECODE_PRINTF2("[%d][EBP]", displacement);
829 offset = M.x86.R_EBP + displacement;
830 break;
831 case 2:
832 displacement = (s32)fetch_long_imm();
833 DECODE_PRINTF2("[%d][EBP]", displacement);
834 offset = M.x86.R_EBP + displacement;
835 break;
836 default:
837 HALT_SYS();
838 }
839 DECODE_PRINTF("[EAX]");
840 offset = M.x86.R_EAX;
841 break;
Jason Jina63ce952007-07-06 08:34:56 +0800842 case 6:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200843 DECODE_PRINTF("[ESI]");
844 offset = M.x86.R_ESI;
845 break;
Jason Jina63ce952007-07-06 08:34:56 +0800846 case 7:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200847 DECODE_PRINTF("[EDI]");
848 offset = M.x86.R_EDI;
849 break;
Jason Jina63ce952007-07-06 08:34:56 +0800850 default:
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200851 HALT_SYS();
Jason Jina63ce952007-07-06 08:34:56 +0800852 }
853 offset += decode_sib_si(ss, index);
854 return offset;
855
856}
857
858/****************************************************************************
859PARAMETERS:
860rm - RM value to decode
861
862RETURNS:
863Offset in memory for the address decoding
864
865REMARKS:
866Return the offset given by mod=00 addressing. Also enables the
867decoding of instructions.
868
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200869NOTE: The code which specifies the corresponding segment (ds vs ss)
870 below in the case of [BP+..]. The assumption here is that at the
871 point that this subroutine is called, the bit corresponding to
872 SYSMODE_SEG_DS_SS will be zero. After every instruction
873 except the segment override instructions, this bit (as well
874 as any bits indicating segment overrides) will be clear. So
875 if a SS access is needed, set this bit. Otherwise, DS access
876 occurs (unless any of the segment override bits are set).
Jason Jina63ce952007-07-06 08:34:56 +0800877****************************************************************************/
878unsigned decode_rm00_address(
879 int rm)
880{
881 unsigned offset;
882
883 if (M.x86.mode & SYSMODE_PREFIX_ADDR) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200884 /* 32-bit addressing */
885 switch (rm) {
886 case 0:
887 DECODE_PRINTF("[EAX]");
888 return M.x86.R_EAX;
889 case 1:
890 DECODE_PRINTF("[ECX]");
891 return M.x86.R_ECX;
892 case 2:
893 DECODE_PRINTF("[EDX]");
894 return M.x86.R_EDX;
895 case 3:
896 DECODE_PRINTF("[EBX]");
897 return M.x86.R_EBX;
898 case 4:
899 return decode_sib_address(0);
900 case 5:
901 offset = fetch_long_imm();
902 DECODE_PRINTF2("[%08x]", offset);
903 return offset;
904 case 6:
905 DECODE_PRINTF("[ESI]");
906 return M.x86.R_ESI;
907 case 7:
908 DECODE_PRINTF("[EDI]");
909 return M.x86.R_EDI;
910 }
Jason Jina63ce952007-07-06 08:34:56 +0800911 } else {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200912 /* 16-bit addressing */
913 switch (rm) {
914 case 0:
915 DECODE_PRINTF("[BX+SI]");
916 return (M.x86.R_BX + M.x86.R_SI) & 0xffff;
917 case 1:
918 DECODE_PRINTF("[BX+DI]");
919 return (M.x86.R_BX + M.x86.R_DI) & 0xffff;
920 case 2:
921 DECODE_PRINTF("[BP+SI]");
922 M.x86.mode |= SYSMODE_SEG_DS_SS;
923 return (M.x86.R_BP + M.x86.R_SI) & 0xffff;
924 case 3:
925 DECODE_PRINTF("[BP+DI]");
926 M.x86.mode |= SYSMODE_SEG_DS_SS;
927 return (M.x86.R_BP + M.x86.R_DI) & 0xffff;
928 case 4:
929 DECODE_PRINTF("[SI]");
930 return M.x86.R_SI;
931 case 5:
932 DECODE_PRINTF("[DI]");
933 return M.x86.R_DI;
934 case 6:
935 offset = fetch_word_imm();
936 DECODE_PRINTF2("[%04x]", offset);
937 return offset;
938 case 7:
939 DECODE_PRINTF("[BX]");
940 return M.x86.R_BX;
941 }
Jason Jina63ce952007-07-06 08:34:56 +0800942 }
943 HALT_SYS();
944 return 0;
945}
946
947/****************************************************************************
948PARAMETERS:
949rm - RM value to decode
950
951RETURNS:
952Offset in memory for the address decoding
953
954REMARKS:
955Return the offset given by mod=01 addressing. Also enables the
956decoding of instructions.
957****************************************************************************/
958unsigned decode_rm01_address(
959 int rm)
960{
961 int displacement;
962
963 if (M.x86.mode & SYSMODE_PREFIX_ADDR) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200964 /* 32-bit addressing */
965 if (rm != 4)
966 displacement = (s8)fetch_byte_imm();
967 else
968 displacement = 0;
Jason Jina63ce952007-07-06 08:34:56 +0800969
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200970 switch (rm) {
971 case 0:
972 DECODE_PRINTF2("%d[EAX]", displacement);
973 return M.x86.R_EAX + displacement;
974 case 1:
975 DECODE_PRINTF2("%d[ECX]", displacement);
976 return M.x86.R_ECX + displacement;
977 case 2:
978 DECODE_PRINTF2("%d[EDX]", displacement);
979 return M.x86.R_EDX + displacement;
980 case 3:
981 DECODE_PRINTF2("%d[EBX]", displacement);
982 return M.x86.R_EBX + displacement;
983 case 4: {
984 int offset = decode_sib_address(1);
985 displacement = (s8)fetch_byte_imm();
986 DECODE_PRINTF2("[%d]", displacement);
987 return offset + displacement;
988 }
989 case 5:
990 DECODE_PRINTF2("%d[EBP]", displacement);
991 return M.x86.R_EBP + displacement;
992 case 6:
993 DECODE_PRINTF2("%d[ESI]", displacement);
994 return M.x86.R_ESI + displacement;
995 case 7:
996 DECODE_PRINTF2("%d[EDI]", displacement);
997 return M.x86.R_EDI + displacement;
998 }
Jason Jina63ce952007-07-06 08:34:56 +0800999 } else {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001000 /* 16-bit addressing */
1001 displacement = (s8)fetch_byte_imm();
1002 switch (rm) {
1003 case 0:
1004 DECODE_PRINTF2("%d[BX+SI]", displacement);
1005 return (M.x86.R_BX + M.x86.R_SI + displacement) & 0xffff;
1006 case 1:
1007 DECODE_PRINTF2("%d[BX+DI]", displacement);
1008 return (M.x86.R_BX + M.x86.R_DI + displacement) & 0xffff;
1009 case 2:
1010 DECODE_PRINTF2("%d[BP+SI]", displacement);
1011 M.x86.mode |= SYSMODE_SEG_DS_SS;
1012 return (M.x86.R_BP + M.x86.R_SI + displacement) & 0xffff;
1013 case 3:
1014 DECODE_PRINTF2("%d[BP+DI]", displacement);
1015 M.x86.mode |= SYSMODE_SEG_DS_SS;
1016 return (M.x86.R_BP + M.x86.R_DI + displacement) & 0xffff;
1017 case 4:
1018 DECODE_PRINTF2("%d[SI]", displacement);
1019 return (M.x86.R_SI + displacement) & 0xffff;
1020 case 5:
1021 DECODE_PRINTF2("%d[DI]", displacement);
1022 return (M.x86.R_DI + displacement) & 0xffff;
1023 case 6:
1024 DECODE_PRINTF2("%d[BP]", displacement);
1025 M.x86.mode |= SYSMODE_SEG_DS_SS;
1026 return (M.x86.R_BP + displacement) & 0xffff;
1027 case 7:
1028 DECODE_PRINTF2("%d[BX]", displacement);
1029 return (M.x86.R_BX + displacement) & 0xffff;
1030 }
Jason Jina63ce952007-07-06 08:34:56 +08001031 }
1032 HALT_SYS();
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001033 return 0; /* SHOULD NOT HAPPEN */
Jason Jina63ce952007-07-06 08:34:56 +08001034}
1035
1036/****************************************************************************
1037PARAMETERS:
1038rm - RM value to decode
1039
1040RETURNS:
1041Offset in memory for the address decoding
1042
1043REMARKS:
1044Return the offset given by mod=10 addressing. Also enables the
1045decoding of instructions.
1046****************************************************************************/
1047unsigned decode_rm10_address(
1048 int rm)
1049{
1050 if (M.x86.mode & SYSMODE_PREFIX_ADDR) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001051 int displacement;
Jason Jina63ce952007-07-06 08:34:56 +08001052
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001053 /* 32-bit addressing */
1054 if (rm != 4)
1055 displacement = (s32)fetch_long_imm();
1056 else
1057 displacement = 0;
Jason Jina63ce952007-07-06 08:34:56 +08001058
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001059 switch (rm) {
1060 case 0:
1061 DECODE_PRINTF2("%d[EAX]", displacement);
1062 return M.x86.R_EAX + displacement;
1063 case 1:
1064 DECODE_PRINTF2("%d[ECX]", displacement);
1065 return M.x86.R_ECX + displacement;
1066 case 2:
1067 DECODE_PRINTF2("%d[EDX]", displacement);
1068 return M.x86.R_EDX + displacement;
1069 case 3:
1070 DECODE_PRINTF2("%d[EBX]", displacement);
1071 return M.x86.R_EBX + displacement;
1072 case 4: {
1073 int offset = decode_sib_address(2);
1074 displacement = (s32)fetch_long_imm();
1075 DECODE_PRINTF2("[%d]", displacement);
1076 return offset + displacement;
1077 }
1078 case 5:
1079 DECODE_PRINTF2("%d[EBP]", displacement);
1080 return M.x86.R_EBP + displacement;
1081 case 6:
1082 DECODE_PRINTF2("%d[ESI]", displacement);
1083 return M.x86.R_ESI + displacement;
1084 case 7:
1085 DECODE_PRINTF2("%d[EDI]", displacement);
1086 return M.x86.R_EDI + displacement;
1087 }
Jason Jina63ce952007-07-06 08:34:56 +08001088 } else {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001089 int displacement = (s16)fetch_word_imm();
Jason Jina63ce952007-07-06 08:34:56 +08001090
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001091 /* 16-bit addressing */
1092 switch (rm) {
1093 case 0:
1094 DECODE_PRINTF2("%d[BX+SI]", displacement);
1095 return (M.x86.R_BX + M.x86.R_SI + displacement) & 0xffff;
1096 case 1:
1097 DECODE_PRINTF2("%d[BX+DI]", displacement);
1098 return (M.x86.R_BX + M.x86.R_DI + displacement) & 0xffff;
1099 case 2:
1100 DECODE_PRINTF2("%d[BP+SI]", displacement);
1101 M.x86.mode |= SYSMODE_SEG_DS_SS;
1102 return (M.x86.R_BP + M.x86.R_SI + displacement) & 0xffff;
1103 case 3:
1104 DECODE_PRINTF2("%d[BP+DI]", displacement);
1105 M.x86.mode |= SYSMODE_SEG_DS_SS;
1106 return (M.x86.R_BP + M.x86.R_DI + displacement) & 0xffff;
1107 case 4:
1108 DECODE_PRINTF2("%d[SI]", displacement);
1109 return (M.x86.R_SI + displacement) & 0xffff;
1110 case 5:
1111 DECODE_PRINTF2("%d[DI]", displacement);
1112 return (M.x86.R_DI + displacement) & 0xffff;
1113 case 6:
1114 DECODE_PRINTF2("%d[BP]", displacement);
1115 M.x86.mode |= SYSMODE_SEG_DS_SS;
1116 return (M.x86.R_BP + displacement) & 0xffff;
1117 case 7:
1118 DECODE_PRINTF2("%d[BX]", displacement);
1119 return (M.x86.R_BX + displacement) & 0xffff;
1120 }
Jason Jina63ce952007-07-06 08:34:56 +08001121 }
1122 HALT_SYS();
Wolfgang Denk96bb2e02007-08-06 02:17:36 +02001123 return 0; /* SHOULD NOT HAPPEN */
Jason Jina63ce952007-07-06 08:34:56 +08001124}
1125
Jason Jina63ce952007-07-06 08:34:56 +08001126/****************************************************************************
1127PARAMETERS:
1128mod - modifier
1129rm - RM value to decode
1130
1131RETURNS:
1132Offset in memory for the address decoding, multiplexing calls to
1133the decode_rmXX_address functions
1134
1135REMARKS:
1136Return the offset given by "mod" addressing.
1137****************************************************************************/
1138
1139unsigned decode_rmXX_address(int mod, int rm)
1140{
1141 if(mod == 0)
1142 return decode_rm00_address(rm);
1143 if(mod == 1)
1144 return decode_rm01_address(rm);
1145 return decode_rm10_address(rm);
1146}
Jason Jin7ed5cd92007-08-08 08:33:11 +08001147
1148#endif