~ubuntu-branches/ubuntu/intrepid/xserver-xgl/intrepid

« back to all changes in this revision

Viewing changes to hw/xfree86/x86emu/decode.c

  • Committer: Bazaar Package Importer
  • Author(s): Matthew Garrett
  • Date: 2006-02-13 14:21:43 UTC
  • Revision ID: james.westby@ubuntu.com-20060213142143-mad6z9xzem7hzxz9
Tags: upstream-7.0.0
ImportĀ upstreamĀ versionĀ 7.0.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/****************************************************************************
 
2
*
 
3
*                                               Realmode X86 Emulator Library
 
4
*
 
5
*               Copyright (C) 1996-1999 SciTech Software, Inc.
 
6
*                                    Copyright (C) David Mosberger-Tang
 
7
*                                          Copyright (C) 1999 Egbert Eich
 
8
*
 
9
*  ========================================================================
 
10
*
 
11
*  Permission to use, copy, modify, distribute, and sell this software and
 
12
*  its documentation for any purpose is hereby granted without fee,
 
13
*  provided that the above copyright notice appear in all copies and that
 
14
*  both that copyright notice and this permission notice appear in
 
15
*  supporting documentation, and that the name of the authors not be used
 
16
*  in advertising or publicity pertaining to distribution of the software
 
17
*  without specific, written prior permission.  The authors makes no
 
18
*  representations about the suitability of this software for any purpose.
 
19
*  It is provided "as is" without express or implied warranty.
 
20
*
 
21
*  THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
 
22
*  INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
 
23
*  EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
 
24
*  CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
 
25
*  USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
 
26
*  OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
 
27
*  PERFORMANCE OF THIS SOFTWARE.
 
28
*
 
29
*  ========================================================================
 
30
*
 
31
* Language:             ANSI C
 
32
* Environment:  Any
 
33
* Developer:    Kendall Bennett
 
34
*
 
35
* Description:  This file includes subroutines which are related to
 
36
*                               instruction decoding and accessess of immediate data via IP.  etc.
 
37
*
 
38
****************************************************************************/
 
39
 
 
40
 
 
41
#include "x86emu/x86emui.h"
 
42
 
 
43
/*----------------------------- Implementation ----------------------------*/
 
44
 
 
45
/****************************************************************************
 
46
REMARKS:
 
47
Handles any pending asychronous interrupts.
 
48
****************************************************************************/
 
49
static void x86emu_intr_handle(void)
 
50
{
 
51
        u8      intno;
 
52
 
 
53
        if (M.x86.intr & INTR_SYNCH) {
 
54
                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
                }
 
67
        }
 
68
}
 
69
 
 
70
/****************************************************************************
 
71
PARAMETERS:
 
72
intrnum - Interrupt number to raise
 
73
 
 
74
REMARKS:
 
75
Raise the specified interrupt to be handled before the execution of the
 
76
next instruction.
 
77
****************************************************************************/
 
78
void x86emu_intr_raise(
 
79
        u8 intrnum)
 
80
{
 
81
        M.x86.intno = intrnum;
 
82
        M.x86.intr |= INTR_SYNCH;
 
83
}
 
84
 
 
85
/****************************************************************************
 
86
REMARKS:
 
87
Main execution loop for the emulator. We return from here when the system
 
88
halts, which is normally caused by a stack fault when we return from the
 
89
original real mode call.
 
90
****************************************************************************/
 
91
void X86EMU_exec(void)
 
92
{
 
93
        u8 op1;
 
94
 
 
95
        M.x86.intr = 0;
 
96
        DB(x86emu_end_instr();)
 
97
 
 
98
    for (;;) {
 
99
DB(             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) {
 
106
DB(             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
        }
 
127
    }
 
128
}
 
129
 
 
130
/****************************************************************************
 
131
REMARKS:
 
132
Halts the system by setting the halted system flag.
 
133
****************************************************************************/
 
134
void X86EMU_halt_sys(void)
 
135
{
 
136
        M.x86.intr |= INTR_HALTED;
 
137
}
 
138
 
 
139
/****************************************************************************
 
140
PARAMETERS:
 
141
mod             - Mod value from decoded byte
 
142
regh    - Reg h value from decoded byte
 
143
regl    - Reg l value from decoded byte
 
144
 
 
145
REMARKS:
 
146
Raise the specified interrupt to be handled before the execution of the
 
147
next instruction.
 
148
 
 
149
NOTE: Do not inline this function, as (*sys_rdb) is already inline!
 
150
****************************************************************************/
 
151
void fetch_decode_modrm(
 
152
        int *mod,
 
153
        int *regh,
 
154
        int *regl)
 
155
{
 
156
        int fetched;
 
157
 
 
158
DB(     if (CHECK_IP_FETCH())
 
159
          x86emu_check_ip_access();)
 
160
        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
/****************************************************************************
 
168
RETURNS:
 
169
Immediate byte value read from instruction queue
 
170
 
 
171
REMARKS:
 
172
This function returns the immediate byte from the instruction queue, and
 
173
moves the instruction pointer to the next value.
 
174
 
 
175
NOTE: Do not inline this function, as (*sys_rdb) is already inline!
 
176
****************************************************************************/
 
177
u8 fetch_byte_imm(void)
 
178
{
 
179
        u8 fetched;
 
180
 
 
181
DB(     if (CHECK_IP_FETCH())
 
182
                x86emu_check_ip_access();)
 
183
        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
/****************************************************************************
 
189
RETURNS:
 
190
Immediate word value read from instruction queue
 
191
 
 
192
REMARKS:
 
193
This function returns the immediate byte from the instruction queue, and
 
194
moves the instruction pointer to the next value.
 
195
 
 
196
NOTE: Do not inline this function, as (*sys_rdw) is already inline!
 
197
****************************************************************************/
 
198
u16 fetch_word_imm(void)
 
199
{
 
200
        u16     fetched;
 
201
 
 
202
DB(     if (CHECK_IP_FETCH())
 
203
                x86emu_check_ip_access();)
 
204
        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
/****************************************************************************
 
211
RETURNS:
 
212
Immediate lone value read from instruction queue
 
213
 
 
214
REMARKS:
 
215
This function returns the immediate byte from the instruction queue, and
 
216
moves the instruction pointer to the next value.
 
217
 
 
218
NOTE: Do not inline this function, as (*sys_rdw) is already inline!
 
219
****************************************************************************/
 
220
u32 fetch_long_imm(void)
 
221
{
 
222
        u32 fetched;
 
223
 
 
224
DB(     if (CHECK_IP_FETCH())
 
225
          x86emu_check_ip_access();)
 
226
        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
/****************************************************************************
 
233
RETURNS:
 
234
Value of the default data segment
 
235
 
 
236
REMARKS:
 
237
Inline function that returns the default data segment for the current
 
238
instruction.
 
239
 
 
240
On the x86 processor, the default segment is not always DS if there is
 
241
no segment override. Address modes such as -3[BP] or 10[BP+SI] all refer to
 
242
addresses relative to SS (ie: on the stack). So, at the minimum, all
 
243
decodings of addressing modes would have to set/clear a bit describing
 
244
whether the access is relative to DS or SS.  That is the function of the
 
245
cpu-state-varible M.x86.mode. There are several potential states:
 
246
 
 
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
 
 
259
Each 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) {
 
265
          case 0:                                       /* default case: use ds register */
 
266
          case SYSMODE_SEGOVR_DS:
 
267
          case SYSMODE_SEGOVR_DS | SYSMODE_SEG_DS_SS:
 
268
                return  M.x86.R_DS;
 
269
          case SYSMODE_SEG_DS_SS:       /* non-overridden, use ss register */
 
270
                return  M.x86.R_SS;
 
271
          case SYSMODE_SEGOVR_CS:
 
272
          case SYSMODE_SEGOVR_CS | SYSMODE_SEG_DS_SS:
 
273
                return  M.x86.R_CS;
 
274
          case SYSMODE_SEGOVR_ES:
 
275
          case SYSMODE_SEGOVR_ES | SYSMODE_SEG_DS_SS:
 
276
                return  M.x86.R_ES;
 
277
          case SYSMODE_SEGOVR_FS:
 
278
          case SYSMODE_SEGOVR_FS | SYSMODE_SEG_DS_SS:
 
279
                return  M.x86.R_FS;
 
280
          case SYSMODE_SEGOVR_GS:
 
281
          case SYSMODE_SEGOVR_GS | SYSMODE_SEG_DS_SS:
 
282
                return  M.x86.R_GS;
 
283
          case SYSMODE_SEGOVR_SS:
 
284
          case SYSMODE_SEGOVR_SS | SYSMODE_SEG_DS_SS:
 
285
                return  M.x86.R_SS;
 
286
          default:
 
287
#ifdef  DEBUG
 
288
                printk("error: should not happen:  multiple overrides.\n");
 
289
#endif
 
290
                HALT_SYS();
 
291
                return 0;
 
292
        }
 
293
}
 
294
 
 
295
/****************************************************************************
 
296
PARAMETERS:
 
297
offset  - Offset to load data from
 
298
 
 
299
RETURNS:
 
300
Byte value read from the absolute memory location.
 
301
 
 
302
NOTE: Do not inline this function as (*sys_rdX) is already inline!
 
303
****************************************************************************/
 
304
u8 fetch_data_byte(
 
305
        uint offset)
 
306
{
 
307
#ifdef DEBUG
 
308
        if (CHECK_DATA_ACCESS())
 
309
                x86emu_check_data_access((u16)get_data_segment(), offset);
 
310
#endif
 
311
        return (*sys_rdb)((get_data_segment() << 4) + offset);
 
312
}
 
313
 
 
314
/****************************************************************************
 
315
PARAMETERS:
 
316
offset  - Offset to load data from
 
317
 
 
318
RETURNS:
 
319
Word value read from the absolute memory location.
 
320
 
 
321
NOTE: Do not inline this function as (*sys_rdX) is already inline!
 
322
****************************************************************************/
 
323
u16 fetch_data_word(
 
324
        uint offset)
 
325
{
 
326
#ifdef DEBUG
 
327
        if (CHECK_DATA_ACCESS())
 
328
                x86emu_check_data_access((u16)get_data_segment(), offset);
 
329
#endif
 
330
        return (*sys_rdw)((get_data_segment() << 4) + offset);
 
331
}
 
332
 
 
333
/****************************************************************************
 
334
PARAMETERS:
 
335
offset  - Offset to load data from
 
336
 
 
337
RETURNS:
 
338
Long value read from the absolute memory location.
 
339
 
 
340
NOTE: Do not inline this function as (*sys_rdX) is already inline!
 
341
****************************************************************************/
 
342
u32 fetch_data_long(
 
343
        uint offset)
 
344
{
 
345
#ifdef DEBUG
 
346
        if (CHECK_DATA_ACCESS())
 
347
                x86emu_check_data_access((u16)get_data_segment(), offset);
 
348
#endif
 
349
        return (*sys_rdl)((get_data_segment() << 4) + offset);
 
350
}
 
351
 
 
352
/****************************************************************************
 
353
PARAMETERS:
 
354
segment - Segment to load data from
 
355
offset  - Offset to load data from
 
356
 
 
357
RETURNS:
 
358
Byte value read from the absolute memory location.
 
359
 
 
360
NOTE: Do not inline this function as (*sys_rdX) is already inline!
 
361
****************************************************************************/
 
362
u8 fetch_data_byte_abs(
 
363
        uint segment,
 
364
        uint offset)
 
365
{
 
366
#ifdef DEBUG
 
367
        if (CHECK_DATA_ACCESS())
 
368
                x86emu_check_data_access(segment, offset);
 
369
#endif
 
370
        return (*sys_rdb)(((u32)segment << 4) + offset);
 
371
}
 
372
 
 
373
/****************************************************************************
 
374
PARAMETERS:
 
375
segment - Segment to load data from
 
376
offset  - Offset to load data from
 
377
 
 
378
RETURNS:
 
379
Word value read from the absolute memory location.
 
380
 
 
381
NOTE: Do not inline this function as (*sys_rdX) is already inline!
 
382
****************************************************************************/
 
383
u16 fetch_data_word_abs(
 
384
        uint segment,
 
385
        uint offset)
 
386
{
 
387
#ifdef DEBUG
 
388
        if (CHECK_DATA_ACCESS())
 
389
                x86emu_check_data_access(segment, offset);
 
390
#endif
 
391
        return (*sys_rdw)(((u32)segment << 4) + offset);
 
392
}
 
393
 
 
394
/****************************************************************************
 
395
PARAMETERS:
 
396
segment - Segment to load data from
 
397
offset  - Offset to load data from
 
398
 
 
399
RETURNS:
 
400
Long value read from the absolute memory location.
 
401
 
 
402
NOTE: Do not inline this function as (*sys_rdX) is already inline!
 
403
****************************************************************************/
 
404
u32 fetch_data_long_abs(
 
405
        uint segment,
 
406
        uint offset)
 
407
{
 
408
#ifdef DEBUG
 
409
        if (CHECK_DATA_ACCESS())
 
410
                x86emu_check_data_access(segment, offset);
 
411
#endif
 
412
        return (*sys_rdl)(((u32)segment << 4) + offset);
 
413
}
 
414
 
 
415
/****************************************************************************
 
416
PARAMETERS:
 
417
offset  - Offset to store data at
 
418
val             - Value to store
 
419
 
 
420
REMARKS:
 
421
Writes a word value to an segmented memory location. The segment used is
 
422
the current 'default' segment, which may have been overridden.
 
423
 
 
424
NOTE: Do not inline this function as (*sys_wrX) is already inline!
 
425
****************************************************************************/
 
426
void store_data_byte(
 
427
        uint offset,
 
428
        u8 val)
 
429
{
 
430
#ifdef DEBUG
 
431
        if (CHECK_DATA_ACCESS())
 
432
                x86emu_check_data_access((u16)get_data_segment(), offset);
 
433
#endif
 
434
        (*sys_wrb)((get_data_segment() << 4) + offset, val);
 
435
}
 
436
 
 
437
/****************************************************************************
 
438
PARAMETERS:
 
439
offset  - Offset to store data at
 
440
val             - Value to store
 
441
 
 
442
REMARKS:
 
443
Writes a word value to an segmented memory location. The segment used is
 
444
the current 'default' segment, which may have been overridden.
 
445
 
 
446
NOTE: Do not inline this function as (*sys_wrX) is already inline!
 
447
****************************************************************************/
 
448
void store_data_word(
 
449
        uint offset,
 
450
        u16 val)
 
451
{
 
452
#ifdef DEBUG
 
453
        if (CHECK_DATA_ACCESS())
 
454
                x86emu_check_data_access((u16)get_data_segment(), offset);
 
455
#endif
 
456
        (*sys_wrw)((get_data_segment() << 4) + offset, val);
 
457
}
 
458
 
 
459
/****************************************************************************
 
460
PARAMETERS:
 
461
offset  - Offset to store data at
 
462
val             - Value to store
 
463
 
 
464
REMARKS:
 
465
Writes a long value to an segmented memory location. The segment used is
 
466
the current 'default' segment, which may have been overridden.
 
467
 
 
468
NOTE: Do not inline this function as (*sys_wrX) is already inline!
 
469
****************************************************************************/
 
470
void store_data_long(
 
471
        uint offset,
 
472
        u32 val)
 
473
{
 
474
#ifdef DEBUG
 
475
        if (CHECK_DATA_ACCESS())
 
476
                x86emu_check_data_access((u16)get_data_segment(), offset);
 
477
#endif
 
478
        (*sys_wrl)((get_data_segment() << 4) + offset, val);
 
479
}
 
480
 
 
481
/****************************************************************************
 
482
PARAMETERS:
 
483
segment - Segment to store data at
 
484
offset  - Offset to store data at
 
485
val             - Value to store
 
486
 
 
487
REMARKS:
 
488
Writes a byte value to an absolute memory location.
 
489
 
 
490
NOTE: Do not inline this function as (*sys_wrX) is already inline!
 
491
****************************************************************************/
 
492
void store_data_byte_abs(
 
493
        uint segment,
 
494
        uint offset,
 
495
        u8 val)
 
496
{
 
497
#ifdef DEBUG
 
498
        if (CHECK_DATA_ACCESS())
 
499
                x86emu_check_data_access(segment, offset);
 
500
#endif
 
501
        (*sys_wrb)(((u32)segment << 4) + offset, val);
 
502
}
 
503
 
 
504
/****************************************************************************
 
505
PARAMETERS:
 
506
segment - Segment to store data at
 
507
offset  - Offset to store data at
 
508
val             - Value to store
 
509
 
 
510
REMARKS:
 
511
Writes a word value to an absolute memory location.
 
512
 
 
513
NOTE: Do not inline this function as (*sys_wrX) is already inline!
 
514
****************************************************************************/
 
515
void store_data_word_abs(
 
516
        uint segment,
 
517
        uint offset,
 
518
        u16 val)
 
519
{
 
520
#ifdef DEBUG
 
521
        if (CHECK_DATA_ACCESS())
 
522
                x86emu_check_data_access(segment, offset);
 
523
#endif
 
524
        (*sys_wrw)(((u32)segment << 4) + offset, val);
 
525
}
 
526
 
 
527
/****************************************************************************
 
528
PARAMETERS:
 
529
segment - Segment to store data at
 
530
offset  - Offset to store data at
 
531
val             - Value to store
 
532
 
 
533
REMARKS:
 
534
Writes a long value to an absolute memory location.
 
535
 
 
536
NOTE: Do not inline this function as (*sys_wrX) is already inline!
 
537
****************************************************************************/
 
538
void store_data_long_abs(
 
539
        uint segment,
 
540
        uint offset,
 
541
        u32 val)
 
542
{
 
543
#ifdef DEBUG
 
544
        if (CHECK_DATA_ACCESS())
 
545
                x86emu_check_data_access(segment, offset);
 
546
#endif
 
547
        (*sys_wrl)(((u32)segment << 4) + offset, val);
 
548
}
 
549
 
 
550
/****************************************************************************
 
551
PARAMETERS:
 
552
reg     - Register to decode
 
553
 
 
554
RETURNS:
 
555
Pointer to the appropriate register
 
556
 
 
557
REMARKS:
 
558
Return a pointer to the register given by the R/RM field of the
 
559
modrm byte, for byte operands. Also enables the decoding of instructions.
 
560
****************************************************************************/
 
561
u8* decode_rm_byte_register(
 
562
        int reg)
 
563
{
 
564
        switch (reg) {
 
565
      case 0:
 
566
                DECODE_PRINTF("AL");
 
567
                return &M.x86.R_AL;
 
568
          case 1:
 
569
                DECODE_PRINTF("CL");
 
570
                return &M.x86.R_CL;
 
571
          case 2:
 
572
                DECODE_PRINTF("DL");
 
573
                return &M.x86.R_DL;
 
574
          case 3:
 
575
                DECODE_PRINTF("BL");
 
576
                return &M.x86.R_BL;
 
577
          case 4:
 
578
                DECODE_PRINTF("AH");
 
579
                return &M.x86.R_AH;
 
580
          case 5:
 
581
                DECODE_PRINTF("CH");
 
582
                return &M.x86.R_CH;
 
583
          case 6:
 
584
                DECODE_PRINTF("DH");
 
585
                return &M.x86.R_DH;
 
586
          case 7:
 
587
                DECODE_PRINTF("BH");
 
588
                return &M.x86.R_BH;
 
589
        }
 
590
        HALT_SYS();
 
591
        return NULL;                /* NOT REACHED OR REACHED ON ERROR */
 
592
}
 
593
 
 
594
/****************************************************************************
 
595
PARAMETERS:
 
596
reg     - Register to decode
 
597
 
 
598
RETURNS:
 
599
Pointer to the appropriate register
 
600
 
 
601
REMARKS:
 
602
Return a pointer to the register given by the R/RM field of the
 
603
modrm byte, for word operands.  Also enables the decoding of instructions.
 
604
****************************************************************************/
 
605
u16* decode_rm_word_register(
 
606
        int reg)
 
607
{
 
608
        switch (reg) {
 
609
          case 0:
 
610
                DECODE_PRINTF("AX");
 
611
                return &M.x86.R_AX;
 
612
          case 1:
 
613
                DECODE_PRINTF("CX");
 
614
                return &M.x86.R_CX;
 
615
          case 2:
 
616
                DECODE_PRINTF("DX");
 
617
                return &M.x86.R_DX;
 
618
          case 3:
 
619
                DECODE_PRINTF("BX");
 
620
                return &M.x86.R_BX;
 
621
          case 4:
 
622
                DECODE_PRINTF("SP");
 
623
                return &M.x86.R_SP;
 
624
          case 5:
 
625
                DECODE_PRINTF("BP");
 
626
                return &M.x86.R_BP;
 
627
          case 6:
 
628
                DECODE_PRINTF("SI");
 
629
                return &M.x86.R_SI;
 
630
          case 7:
 
631
                DECODE_PRINTF("DI");
 
632
                return &M.x86.R_DI;
 
633
        }
 
634
        HALT_SYS();
 
635
    return NULL;                /* NOTREACHED OR REACHED ON ERROR */
 
636
}
 
637
 
 
638
/****************************************************************************
 
639
PARAMETERS:
 
640
reg     - Register to decode
 
641
 
 
642
RETURNS:
 
643
Pointer to the appropriate register
 
644
 
 
645
REMARKS:
 
646
Return a pointer to the register given by the R/RM field of the
 
647
modrm byte, for dword operands.  Also enables the decoding of instructions.
 
648
****************************************************************************/
 
649
u32* decode_rm_long_register(
 
650
        int reg)
 
651
{
 
652
    switch (reg) {
 
653
      case 0:
 
654
                DECODE_PRINTF("EAX");
 
655
                return &M.x86.R_EAX;
 
656
          case 1:
 
657
                DECODE_PRINTF("ECX");
 
658
                return &M.x86.R_ECX;
 
659
          case 2:
 
660
                DECODE_PRINTF("EDX");
 
661
                return &M.x86.R_EDX;
 
662
          case 3:
 
663
                DECODE_PRINTF("EBX");
 
664
                return &M.x86.R_EBX;
 
665
          case 4:
 
666
                DECODE_PRINTF("ESP");
 
667
                return &M.x86.R_ESP;
 
668
          case 5:
 
669
                DECODE_PRINTF("EBP");
 
670
                return &M.x86.R_EBP;
 
671
          case 6:
 
672
                DECODE_PRINTF("ESI");
 
673
                return &M.x86.R_ESI;
 
674
          case 7:
 
675
                DECODE_PRINTF("EDI");
 
676
                return &M.x86.R_EDI;
 
677
        }
 
678
        HALT_SYS();
 
679
    return NULL;                /* NOTREACHED OR REACHED ON ERROR */
 
680
}
 
681
 
 
682
/****************************************************************************
 
683
PARAMETERS:
 
684
reg     - Register to decode
 
685
 
 
686
RETURNS:
 
687
Pointer to the appropriate register
 
688
 
 
689
REMARKS:
 
690
Return a pointer to the register given by the R/RM field of the
 
691
modrm byte, for word operands, modified from above for the weirdo
 
692
special case of segreg operands.  Also enables the decoding of instructions.
 
693
****************************************************************************/
 
694
u16* decode_rm_seg_register(
 
695
        int reg)
 
696
{
 
697
        switch (reg) {
 
698
          case 0:
 
699
                DECODE_PRINTF("ES");
 
700
                return &M.x86.R_ES;
 
701
          case 1:
 
702
                DECODE_PRINTF("CS");
 
703
                return &M.x86.R_CS;
 
704
          case 2:
 
705
                DECODE_PRINTF("SS");
 
706
                return &M.x86.R_SS;
 
707
          case 3:
 
708
                DECODE_PRINTF("DS");
 
709
                return &M.x86.R_DS;
 
710
          case 4:
 
711
                DECODE_PRINTF("FS");
 
712
                return &M.x86.R_FS;
 
713
          case 5:
 
714
                DECODE_PRINTF("GS");
 
715
                return &M.x86.R_GS;
 
716
          case 6:
 
717
          case 7:
 
718
                DECODE_PRINTF("ILLEGAL SEGREG");
 
719
                break;
 
720
        }
 
721
        HALT_SYS();
 
722
        return NULL;                /* NOT REACHED OR REACHED ON ERROR */
 
723
}
 
724
 
 
725
/*
 
726
 *
 
727
 * return offset from the SIB Byte
 
728
 */
 
729
u32 decode_sib_address(int sib, int mod)
 
730
{
 
731
    u32 base = 0, i = 0, scale = 1;
 
732
 
 
733
    switch(sib & 0x07) {
 
734
    case 0:
 
735
        DECODE_PRINTF("[EAX]");
 
736
        base = M.x86.R_EAX;
 
737
        break;
 
738
    case 1:
 
739
        DECODE_PRINTF("[ECX]");
 
740
        base = M.x86.R_ECX;
 
741
        break;
 
742
    case 2:
 
743
        DECODE_PRINTF("[EDX]");
 
744
        base = M.x86.R_EDX;
 
745
        break;
 
746
    case 3:
 
747
        DECODE_PRINTF("[EBX]");
 
748
        base = M.x86.R_EBX;
 
749
        break;
 
750
    case 4:
 
751
        DECODE_PRINTF("[ESP]");
 
752
        base = M.x86.R_ESP;
 
753
        M.x86.mode |= SYSMODE_SEG_DS_SS;
 
754
        break;
 
755
    case 5:
 
756
        if (mod == 0) {
 
757
            base = fetch_long_imm();
 
758
            DECODE_PRINTF2("%08x", base);
 
759
        } else {
 
760
            DECODE_PRINTF("[EBP]");
 
761
            base = M.x86.R_ESP;
 
762
            M.x86.mode |= SYSMODE_SEG_DS_SS;
 
763
        }
 
764
        break;
 
765
    case 6:
 
766
        DECODE_PRINTF("[ESI]");
 
767
        base = M.x86.R_ESI;
 
768
        break;
 
769
    case 7:
 
770
        DECODE_PRINTF("[EDI]");
 
771
        base = M.x86.R_EDI;
 
772
        break;
 
773
    }
 
774
    switch ((sib >> 3) & 0x07) {
 
775
    case 0:
 
776
        DECODE_PRINTF("[EAX");
 
777
        i = M.x86.R_EAX;
 
778
        break;
 
779
    case 1:
 
780
        DECODE_PRINTF("[ECX");
 
781
        i = M.x86.R_ECX;
 
782
        break;
 
783
    case 2:
 
784
        DECODE_PRINTF("[EDX");
 
785
        i = M.x86.R_EDX;
 
786
        break;
 
787
    case 3:
 
788
        DECODE_PRINTF("[EBX");
 
789
        i = M.x86.R_EBX;
 
790
        break;
 
791
    case 4:
 
792
        i = 0;
 
793
        break;
 
794
    case 5:
 
795
        DECODE_PRINTF("[EBP");
 
796
        i = M.x86.R_EBP;
 
797
        break;
 
798
    case 6:
 
799
        DECODE_PRINTF("[ESI");
 
800
        i = M.x86.R_ESI;
 
801
        break;
 
802
    case 7:
 
803
        DECODE_PRINTF("[EDI");
 
804
        i = M.x86.R_EDI;
 
805
        break;
 
806
    }
 
807
    scale = 1 << ((sib >> 6) & 0x03);
 
808
    if (((sib >> 3) & 0x07) != 4) {
 
809
        if (scale == 1) {
 
810
            DECODE_PRINTF("]");
 
811
        } else {
 
812
            DECODE_PRINTF2("*%d]", scale);
 
813
        }
 
814
    }
 
815
    return base + (i * scale);
 
816
}
 
817
 
 
818
/****************************************************************************
 
819
PARAMETERS:
 
820
rm      - RM value to decode
 
821
 
 
822
RETURNS:
 
823
Offset in memory for the address decoding
 
824
 
 
825
REMARKS:
 
826
Return the offset given by mod=00 addressing.  Also enables the
 
827
decoding of instructions.
 
828
 
 
829
NOTE:   The code which specifies the corresponding segment (ds vs ss)
 
830
                below in the case of [BP+..].  The assumption here is that at the
 
831
                point that this subroutine is called, the bit corresponding to
 
832
                SYSMODE_SEG_DS_SS will be zero.  After every instruction
 
833
                except the segment override instructions, this bit (as well
 
834
                as any bits indicating segment overrides) will be clear.  So
 
835
                if a SS access is needed, set this bit.  Otherwise, DS access
 
836
                occurs (unless any of the segment override bits are set).
 
837
****************************************************************************/
 
838
u32 decode_rm00_address(
 
839
        int rm)
 
840
{
 
841
    u32 offset;
 
842
    int sib;
 
843
 
 
844
    if (M.x86.mode & SYSMODE_PREFIX_ADDR) {
 
845
        /* 32-bit addressing */
 
846
        switch (rm) {
 
847
          case 0:
 
848
                DECODE_PRINTF("[EAX]");
 
849
                return M.x86.R_EAX;
 
850
          case 1:
 
851
                DECODE_PRINTF("[ECX]");
 
852
                return M.x86.R_ECX;
 
853
          case 2:
 
854
                DECODE_PRINTF("[EDX]");
 
855
                return M.x86.R_EDX;
 
856
          case 3:
 
857
                DECODE_PRINTF("[EBX]");
 
858
                return M.x86.R_EBX;
 
859
          case 4:
 
860
                sib = fetch_byte_imm();
 
861
                return decode_sib_address(sib, 0);
 
862
          case 5:
 
863
                offset = fetch_long_imm();
 
864
                DECODE_PRINTF2("[%08x]", offset);
 
865
                return offset;
 
866
          case 6:
 
867
                DECODE_PRINTF("[ESI]");
 
868
                return M.x86.R_ESI;
 
869
          case 7:
 
870
                DECODE_PRINTF("[EDI]");
 
871
                return M.x86.R_EDI;
 
872
        }
 
873
        HALT_SYS();
 
874
    } else {
 
875
        /* 16-bit addressing */
 
876
        switch (rm) {
 
877
          case 0:
 
878
                DECODE_PRINTF("[BX+SI]");
 
879
            return (M.x86.R_BX + M.x86.R_SI) & 0xffff;
 
880
          case 1:
 
881
                DECODE_PRINTF("[BX+DI]");
 
882
            return (M.x86.R_BX + M.x86.R_DI) & 0xffff;
 
883
          case 2:
 
884
                DECODE_PRINTF("[BP+SI]");
 
885
                M.x86.mode |= SYSMODE_SEG_DS_SS;
 
886
            return (M.x86.R_BP + M.x86.R_SI) & 0xffff;
 
887
          case 3:
 
888
                DECODE_PRINTF("[BP+DI]");
 
889
                M.x86.mode |= SYSMODE_SEG_DS_SS;
 
890
            return (M.x86.R_BP + M.x86.R_DI) & 0xffff;
 
891
          case 4:
 
892
                DECODE_PRINTF("[SI]");
 
893
                return M.x86.R_SI;
 
894
          case 5:
 
895
                DECODE_PRINTF("[DI]");
 
896
                return M.x86.R_DI;
 
897
          case 6:
 
898
                offset = fetch_word_imm();
 
899
                DECODE_PRINTF2("[%04x]", offset);
 
900
                return offset;
 
901
          case 7:
 
902
                DECODE_PRINTF("[BX]");
 
903
                return M.x86.R_BX;
 
904
        }
 
905
        HALT_SYS();
 
906
    }
 
907
    return 0;
 
908
}
 
909
 
 
910
/****************************************************************************
 
911
PARAMETERS:
 
912
rm      - RM value to decode
 
913
 
 
914
RETURNS:
 
915
Offset in memory for the address decoding
 
916
 
 
917
REMARKS:
 
918
Return the offset given by mod=01 addressing.  Also enables the
 
919
decoding of instructions.
 
920
****************************************************************************/
 
921
u32 decode_rm01_address(
 
922
        int rm)
 
923
{
 
924
    int displacement = 0;
 
925
    int sib;
 
926
 
 
927
    /* Fetch disp8 if no SIB byte */
 
928
    if (!((M.x86.mode & SYSMODE_PREFIX_ADDR) && (rm == 4)))
 
929
        displacement = (s8)fetch_byte_imm();
 
930
 
 
931
    if (M.x86.mode & SYSMODE_PREFIX_ADDR) {
 
932
        /* 32-bit addressing */
 
933
        switch (rm) {
 
934
          case 0:
 
935
                DECODE_PRINTF2("%d[EAX]", displacement);
 
936
                return M.x86.R_EAX + displacement;
 
937
          case 1:
 
938
                DECODE_PRINTF2("%d[ECX]", displacement);
 
939
                return M.x86.R_ECX + displacement;
 
940
          case 2:
 
941
                DECODE_PRINTF2("%d[EDX]", displacement);
 
942
                return M.x86.R_EDX + displacement;
 
943
          case 3:
 
944
                DECODE_PRINTF2("%d[EBX]", displacement);
 
945
                return M.x86.R_EBX + displacement;
 
946
          case 4:
 
947
                sib = fetch_byte_imm();
 
948
                displacement = (s8)fetch_byte_imm();
 
949
                DECODE_PRINTF2("%d", displacement);
 
950
                return decode_sib_address(sib, 1) + displacement;
 
951
          case 5:
 
952
                DECODE_PRINTF2("%d[EBP]", displacement);
 
953
                return M.x86.R_EBP + displacement;
 
954
          case 6:
 
955
                DECODE_PRINTF2("%d[ESI]", displacement);
 
956
                return M.x86.R_ESI + displacement;
 
957
          case 7:
 
958
                DECODE_PRINTF2("%d[EDI]", displacement);
 
959
                return M.x86.R_EDI + displacement;
 
960
        }
 
961
        HALT_SYS();
 
962
    } else {
 
963
        /* 16-bit addressing */
 
964
        switch (rm) {
 
965
          case 0:
 
966
                DECODE_PRINTF2("%d[BX+SI]", displacement);
 
967
            return (M.x86.R_BX + M.x86.R_SI + displacement) & 0xffff;
 
968
          case 1:
 
969
                DECODE_PRINTF2("%d[BX+DI]", displacement);
 
970
            return (M.x86.R_BX + M.x86.R_DI + displacement) & 0xffff;
 
971
          case 2:
 
972
                DECODE_PRINTF2("%d[BP+SI]", displacement);
 
973
                M.x86.mode |= SYSMODE_SEG_DS_SS;
 
974
            return (M.x86.R_BP + M.x86.R_SI + displacement) & 0xffff;
 
975
          case 3:
 
976
                DECODE_PRINTF2("%d[BP+DI]", displacement);
 
977
                M.x86.mode |= SYSMODE_SEG_DS_SS;
 
978
            return (M.x86.R_BP + M.x86.R_DI + displacement) & 0xffff;
 
979
          case 4:
 
980
                DECODE_PRINTF2("%d[SI]", displacement);
 
981
            return (M.x86.R_SI + displacement) & 0xffff;
 
982
          case 5:
 
983
                DECODE_PRINTF2("%d[DI]", displacement);
 
984
            return (M.x86.R_DI + displacement) & 0xffff;
 
985
          case 6:
 
986
                DECODE_PRINTF2("%d[BP]", displacement);
 
987
                M.x86.mode |= SYSMODE_SEG_DS_SS;
 
988
            return (M.x86.R_BP + displacement) & 0xffff;
 
989
          case 7:
 
990
                DECODE_PRINTF2("%d[BX]", displacement);
 
991
            return (M.x86.R_BX + displacement) & 0xffff;
 
992
        }
 
993
        HALT_SYS();
 
994
    }
 
995
    return 0;                   /* SHOULD NOT HAPPEN */
 
996
}
 
997
 
 
998
/****************************************************************************
 
999
PARAMETERS:
 
1000
rm      - RM value to decode
 
1001
 
 
1002
RETURNS:
 
1003
Offset in memory for the address decoding
 
1004
 
 
1005
REMARKS:
 
1006
Return the offset given by mod=10 addressing.  Also enables the
 
1007
decoding of instructions.
 
1008
****************************************************************************/
 
1009
u32 decode_rm10_address(
 
1010
        int rm)
 
1011
{
 
1012
    u32 displacement = 0;
 
1013
    int sib;
 
1014
 
 
1015
    /* Fetch disp16 if 16-bit addr mode */
 
1016
    if (!(M.x86.mode & SYSMODE_PREFIX_ADDR))
 
1017
        displacement = (u16)fetch_word_imm();
 
1018
    else {
 
1019
        /* Fetch disp32 if no SIB byte */
 
1020
        if (rm != 4)
 
1021
            displacement = (u32)fetch_long_imm();
 
1022
    }
 
1023
 
 
1024
    if (M.x86.mode & SYSMODE_PREFIX_ADDR) {
 
1025
        /* 32-bit addressing */
 
1026
      switch (rm) {
 
1027
          case 0:
 
1028
                DECODE_PRINTF2("%08x[EAX]", displacement);
 
1029
                return M.x86.R_EAX + displacement;
 
1030
          case 1:
 
1031
                DECODE_PRINTF2("%08x[ECX]", displacement);
 
1032
                return M.x86.R_ECX + displacement;
 
1033
          case 2:
 
1034
                DECODE_PRINTF2("%08x[EDX]", displacement);
 
1035
                M.x86.mode |= SYSMODE_SEG_DS_SS;
 
1036
                return M.x86.R_EDX + displacement;
 
1037
          case 3:
 
1038
                DECODE_PRINTF2("%08x[EBX]", displacement);
 
1039
                return M.x86.R_EBX + displacement;
 
1040
          case 4:
 
1041
                sib = fetch_byte_imm();
 
1042
                displacement = (u32)fetch_long_imm();
 
1043
                DECODE_PRINTF2("%08x", displacement);
 
1044
                return decode_sib_address(sib, 2) + displacement;
 
1045
                break;
 
1046
          case 5:
 
1047
                DECODE_PRINTF2("%08x[EBP]", displacement);
 
1048
                return M.x86.R_EBP + displacement;
 
1049
          case 6:
 
1050
                DECODE_PRINTF2("%08x[ESI]", displacement);
 
1051
                return M.x86.R_ESI + displacement;
 
1052
          case 7:
 
1053
                DECODE_PRINTF2("%08x[EDI]", displacement);
 
1054
                return M.x86.R_EDI + displacement;
 
1055
        }
 
1056
        HALT_SYS();
 
1057
    } else {
 
1058
        /* 16-bit addressing */
 
1059
      switch (rm) {
 
1060
          case 0:
 
1061
            DECODE_PRINTF2("%04x[BX+SI]", displacement);
 
1062
            return (M.x86.R_BX + M.x86.R_SI + displacement) & 0xffff;
 
1063
          case 1:
 
1064
            DECODE_PRINTF2("%04x[BX+DI]", displacement);
 
1065
            return (M.x86.R_BX + M.x86.R_DI + displacement) & 0xffff;
 
1066
          case 2:
 
1067
                DECODE_PRINTF2("%04x[BP+SI]", displacement);
 
1068
                M.x86.mode |= SYSMODE_SEG_DS_SS;
 
1069
            return (M.x86.R_BP + M.x86.R_SI + displacement) & 0xffff;
 
1070
          case 3:
 
1071
                DECODE_PRINTF2("%04x[BP+DI]", displacement);
 
1072
                M.x86.mode |= SYSMODE_SEG_DS_SS;
 
1073
            return (M.x86.R_BP + M.x86.R_DI + displacement) & 0xffff;
 
1074
          case 4:
 
1075
            DECODE_PRINTF2("%04x[SI]", displacement);
 
1076
            return (M.x86.R_SI + displacement) & 0xffff;
 
1077
          case 5:
 
1078
            DECODE_PRINTF2("%04x[DI]", displacement);
 
1079
            return (M.x86.R_DI + displacement) & 0xffff;
 
1080
          case 6:
 
1081
                DECODE_PRINTF2("%04x[BP]", displacement);
 
1082
                M.x86.mode |= SYSMODE_SEG_DS_SS;
 
1083
            return (M.x86.R_BP + displacement) & 0xffff;
 
1084
          case 7:
 
1085
            DECODE_PRINTF2("%04x[BX]", displacement);
 
1086
            return (M.x86.R_BX + displacement) & 0xffff;
 
1087
        }
 
1088
        HALT_SYS();
 
1089
    }
 
1090
    return 0;
 
1091
    /*NOTREACHED */
 
1092
}