~ubuntu-branches/debian/stretch/uswsusp/stretch

« back to all changes in this revision

Viewing changes to suspend-cvs20060928/vbetool/x86emu/decode.c

  • Committer: Bazaar Package Importer
  • Author(s): Christian Perrier
  • Date: 2008-08-20 09:09:13 UTC
  • mfrom: (0.1.2 upstream)
  • Revision ID: james.westby@ubuntu.com-20080820090913-0eahue1zo8egcxls
Tags: 0.8-1.1
* Non-maintainer upload to fix pending l10n issues.
* Remove extra and useless debian/po/ff/ directory
* Debconf translation updates:
  - Japanese. Closes: #489939
  - German. Closes: #493747
  - French. Closes: #493771
  - Romanian. Closes: #493772
  - Galician. Closes: #494050
  - Finnish. Closes: #494087
  - Italian. Closes: #494096
  - Basque. Closes: #494277
  - Basque. Closes: #494277
  - Czech. Closes: #494410
  - Swedish. Closes: #494412
  - Russian. Closes: #495412
  - Portuguese. Closes: #495451
  - Spanish. Closes: #495499
  - Slovak. Closes: #495516

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(                     
107
 
                                X86EMU_trace_regs();)
108
 
                                return;
109
 
            }
110
 
                        if (((M.x86.intr & INTR_SYNCH) && (M.x86.intno == 0 || M.x86.intno == 2)) ||
111
 
                                !ACCESS_FLAG(F_IF)) {
112
 
                                x86emu_intr_handle();
113
 
                        }
114
 
                }
115
 
                if ((M.x86.R_CS == 0) && (M.x86.R_IP == 0)) {
116
 
DB(                             
117
 
                                X86EMU_trace_regs();)
118
 
                                return;
119
 
                }
120
 
 
121
 
                op1 = (*sys_rdb)(((u32)M.x86.R_CS << 4) + (M.x86.R_IP++));
122
 
                /*X86EMU_trace_regs();*/
123
 
                (*x86emu_optab[op1])(op1);
124
 
    }
125
 
}
126
 
 
127
 
/****************************************************************************
128
 
REMARKS:
129
 
Halts the system by setting the halted system flag.
130
 
****************************************************************************/
131
 
void X86EMU_halt_sys(void)
132
 
{
133
 
        M.x86.intr |= INTR_HALTED;
134
 
}
135
 
 
136
 
/****************************************************************************
137
 
PARAMETERS:
138
 
mod             - Mod value from decoded byte
139
 
regh    - Reg h value from decoded byte
140
 
regl    - Reg l value from decoded byte
141
 
 
142
 
REMARKS:
143
 
Raise the specified interrupt to be handled before the execution of the
144
 
next instruction.
145
 
 
146
 
NOTE: Do not inline this function, as (*sys_rdb) is already inline!
147
 
****************************************************************************/
148
 
void fetch_decode_modrm(
149
 
        int *mod,
150
 
        int *regh,
151
 
        int *regl)
152
 
{
153
 
        int fetched;
154
 
 
155
 
DB(     if (CHECK_IP_FETCH())
156
 
          x86emu_check_ip_access();)
157
 
        fetched = (*sys_rdb)(((u32)M.x86.R_CS << 4) + (M.x86.R_IP++));
158
 
        INC_DECODED_INST_LEN(1);
159
 
        *mod  = (fetched >> 6) & 0x03;
160
 
        *regh = (fetched >> 3) & 0x07;
161
 
    *regl = (fetched >> 0) & 0x07;
162
 
}
163
 
 
164
 
/****************************************************************************
165
 
RETURNS:
166
 
Immediate byte value read from instruction queue
167
 
 
168
 
REMARKS:
169
 
This function returns the immediate byte from the instruction queue, and
170
 
moves the instruction pointer to the next value.
171
 
 
172
 
NOTE: Do not inline this function, as (*sys_rdb) is already inline!
173
 
****************************************************************************/
174
 
u8 fetch_byte_imm(void)
175
 
{
176
 
        u8 fetched;
177
 
 
178
 
DB(     if (CHECK_IP_FETCH())
179
 
                x86emu_check_ip_access();)
180
 
        fetched = (*sys_rdb)(((u32)M.x86.R_CS << 4) + (M.x86.R_IP++));
181
 
        INC_DECODED_INST_LEN(1);
182
 
        return fetched;
183
 
}
184
 
 
185
 
/****************************************************************************
186
 
RETURNS:
187
 
Immediate word value read from instruction queue
188
 
 
189
 
REMARKS:
190
 
This function returns the immediate byte from the instruction queue, and
191
 
moves the instruction pointer to the next value.
192
 
 
193
 
NOTE: Do not inline this function, as (*sys_rdw) is already inline!
194
 
****************************************************************************/
195
 
u16 fetch_word_imm(void)
196
 
{
197
 
        u16     fetched;
198
 
 
199
 
DB(     if (CHECK_IP_FETCH())
200
 
                x86emu_check_ip_access();)
201
 
        fetched = (*sys_rdw)(((u32)M.x86.R_CS << 4) + (M.x86.R_IP));
202
 
        M.x86.R_IP += 2;
203
 
        INC_DECODED_INST_LEN(2);
204
 
        return fetched;
205
 
}
206
 
 
207
 
/****************************************************************************
208
 
RETURNS:
209
 
Immediate lone value read from instruction queue
210
 
 
211
 
REMARKS:
212
 
This function returns the immediate byte from the instruction queue, and
213
 
moves the instruction pointer to the next value.
214
 
 
215
 
NOTE: Do not inline this function, as (*sys_rdw) is already inline!
216
 
****************************************************************************/
217
 
u32 fetch_long_imm(void)
218
 
{
219
 
        u32 fetched;
220
 
 
221
 
DB(     if (CHECK_IP_FETCH())
222
 
          x86emu_check_ip_access();)
223
 
        fetched = (*sys_rdl)(((u32)M.x86.R_CS << 4) + (M.x86.R_IP));
224
 
        M.x86.R_IP += 4;
225
 
        INC_DECODED_INST_LEN(4);
226
 
        return fetched;
227
 
}
228
 
 
229
 
/****************************************************************************
230
 
RETURNS:
231
 
Value of the default data segment
232
 
 
233
 
REMARKS:
234
 
Inline function that returns the default data segment for the current
235
 
instruction.
236
 
 
237
 
On the x86 processor, the default segment is not always DS if there is
238
 
no segment override. Address modes such as -3[BP] or 10[BP+SI] all refer to
239
 
addresses relative to SS (ie: on the stack). So, at the minimum, all
240
 
decodings of addressing modes would have to set/clear a bit describing
241
 
whether the access is relative to DS or SS.  That is the function of the
242
 
cpu-state-varible M.x86.mode. There are several potential states:
243
 
 
244
 
        repe prefix seen  (handled elsewhere)
245
 
        repne prefix seen  (ditto)
246
 
 
247
 
        cs segment override
248
 
        ds segment override
249
 
        es segment override
250
 
        fs segment override
251
 
        gs segment override
252
 
        ss segment override
253
 
 
254
 
        ds/ss select (in absense of override)
255
 
 
256
 
Each of the above 7 items are handled with a bit in the mode field.
257
 
****************************************************************************/
258
 
_INLINE u32 get_data_segment(void)
259
 
{
260
 
#define GET_SEGMENT(segment)
261
 
        switch (M.x86.mode & SYSMODE_SEGMASK) {
262
 
          case 0:                                       /* default case: use ds register */
263
 
          case SYSMODE_SEGOVR_DS:
264
 
          case SYSMODE_SEGOVR_DS | SYSMODE_SEG_DS_SS:
265
 
                return  M.x86.R_DS;
266
 
          case SYSMODE_SEG_DS_SS:       /* non-overridden, use ss register */
267
 
                return  M.x86.R_SS;
268
 
          case SYSMODE_SEGOVR_CS:
269
 
          case SYSMODE_SEGOVR_CS | SYSMODE_SEG_DS_SS:
270
 
                return  M.x86.R_CS;
271
 
          case SYSMODE_SEGOVR_ES:
272
 
          case SYSMODE_SEGOVR_ES | SYSMODE_SEG_DS_SS:
273
 
                return  M.x86.R_ES;
274
 
          case SYSMODE_SEGOVR_FS:
275
 
          case SYSMODE_SEGOVR_FS | SYSMODE_SEG_DS_SS:
276
 
                return  M.x86.R_FS;
277
 
          case SYSMODE_SEGOVR_GS:
278
 
          case SYSMODE_SEGOVR_GS | SYSMODE_SEG_DS_SS:
279
 
                return  M.x86.R_GS;
280
 
          case SYSMODE_SEGOVR_SS:
281
 
          case SYSMODE_SEGOVR_SS | SYSMODE_SEG_DS_SS:
282
 
                return  M.x86.R_SS;
283
 
          default:
284
 
#ifdef  DEBUG
285
 
                printk("error: should not happen:  multiple overrides.\n");
286
 
#endif
287
 
                HALT_SYS();
288
 
                return 0;
289
 
        }
290
 
}
291
 
 
292
 
/****************************************************************************
293
 
PARAMETERS:
294
 
offset  - Offset to load data from
295
 
 
296
 
RETURNS:
297
 
Byte value read from the absolute memory location.
298
 
 
299
 
NOTE: Do not inline this function as (*sys_rdX) is already inline!
300
 
****************************************************************************/
301
 
u8 fetch_data_byte(
302
 
        uint offset)
303
 
{
304
 
#ifdef DEBUG
305
 
        if (CHECK_DATA_ACCESS())
306
 
                x86emu_check_data_access((u16)get_data_segment(), offset);
307
 
#endif
308
 
        return (*sys_rdb)((get_data_segment() << 4) + offset);
309
 
}
310
 
 
311
 
/****************************************************************************
312
 
PARAMETERS:
313
 
offset  - Offset to load data from
314
 
 
315
 
RETURNS:
316
 
Word value read from the absolute memory location.
317
 
 
318
 
NOTE: Do not inline this function as (*sys_rdX) is already inline!
319
 
****************************************************************************/
320
 
u16 fetch_data_word(
321
 
        uint offset)
322
 
{
323
 
#ifdef DEBUG
324
 
        if (CHECK_DATA_ACCESS())
325
 
                x86emu_check_data_access((u16)get_data_segment(), offset);
326
 
#endif
327
 
        return (*sys_rdw)((get_data_segment() << 4) + offset);
328
 
}
329
 
 
330
 
/****************************************************************************
331
 
PARAMETERS:
332
 
offset  - Offset to load data from
333
 
 
334
 
RETURNS:
335
 
Long value read from the absolute memory location.
336
 
 
337
 
NOTE: Do not inline this function as (*sys_rdX) is already inline!
338
 
****************************************************************************/
339
 
u32 fetch_data_long(
340
 
        uint offset)
341
 
{
342
 
#ifdef DEBUG
343
 
        if (CHECK_DATA_ACCESS())
344
 
                x86emu_check_data_access((u16)get_data_segment(), offset);
345
 
#endif
346
 
        return (*sys_rdl)((get_data_segment() << 4) + offset);
347
 
}
348
 
 
349
 
/****************************************************************************
350
 
PARAMETERS:
351
 
segment - Segment to load data from
352
 
offset  - Offset to load data from
353
 
 
354
 
RETURNS:
355
 
Byte value read from the absolute memory location.
356
 
 
357
 
NOTE: Do not inline this function as (*sys_rdX) is already inline!
358
 
****************************************************************************/
359
 
u8 fetch_data_byte_abs(
360
 
        uint segment,
361
 
        uint offset)
362
 
{
363
 
#ifdef DEBUG
364
 
        if (CHECK_DATA_ACCESS())
365
 
                x86emu_check_data_access(segment, offset);
366
 
#endif
367
 
        return (*sys_rdb)(((u32)segment << 4) + offset);
368
 
}
369
 
 
370
 
/****************************************************************************
371
 
PARAMETERS:
372
 
segment - Segment to load data from
373
 
offset  - Offset to load data from
374
 
 
375
 
RETURNS:
376
 
Word value read from the absolute memory location.
377
 
 
378
 
NOTE: Do not inline this function as (*sys_rdX) is already inline!
379
 
****************************************************************************/
380
 
u16 fetch_data_word_abs(
381
 
        uint segment,
382
 
        uint offset)
383
 
{
384
 
#ifdef DEBUG
385
 
        if (CHECK_DATA_ACCESS())
386
 
                x86emu_check_data_access(segment, offset);
387
 
#endif
388
 
        return (*sys_rdw)(((u32)segment << 4) + offset);
389
 
}
390
 
 
391
 
/****************************************************************************
392
 
PARAMETERS:
393
 
segment - Segment to load data from
394
 
offset  - Offset to load data from
395
 
 
396
 
RETURNS:
397
 
Long value read from the absolute memory location.
398
 
 
399
 
NOTE: Do not inline this function as (*sys_rdX) is already inline!
400
 
****************************************************************************/
401
 
u32 fetch_data_long_abs(
402
 
        uint segment,
403
 
        uint offset)
404
 
{
405
 
#ifdef DEBUG
406
 
        if (CHECK_DATA_ACCESS())
407
 
                x86emu_check_data_access(segment, offset);
408
 
#endif
409
 
        return (*sys_rdl)(((u32)segment << 4) + offset);
410
 
}
411
 
 
412
 
/****************************************************************************
413
 
PARAMETERS:
414
 
offset  - Offset to store data at
415
 
val             - Value to store
416
 
 
417
 
REMARKS:
418
 
Writes a word value to an segmented memory location. The segment used is
419
 
the current 'default' segment, which may have been overridden.
420
 
 
421
 
NOTE: Do not inline this function as (*sys_wrX) is already inline!
422
 
****************************************************************************/
423
 
void store_data_byte(
424
 
        uint offset,
425
 
        u8 val)
426
 
{
427
 
#ifdef DEBUG
428
 
        if (CHECK_DATA_ACCESS())
429
 
                x86emu_check_data_access((u16)get_data_segment(), offset);
430
 
#endif
431
 
        (*sys_wrb)((get_data_segment() << 4) + offset, val);
432
 
}
433
 
 
434
 
/****************************************************************************
435
 
PARAMETERS:
436
 
offset  - Offset to store data at
437
 
val             - Value to store
438
 
 
439
 
REMARKS:
440
 
Writes a word value to an segmented memory location. The segment used is
441
 
the current 'default' segment, which may have been overridden.
442
 
 
443
 
NOTE: Do not inline this function as (*sys_wrX) is already inline!
444
 
****************************************************************************/
445
 
void store_data_word(
446
 
        uint offset,
447
 
        u16 val)
448
 
{
449
 
#ifdef DEBUG
450
 
        if (CHECK_DATA_ACCESS())
451
 
                x86emu_check_data_access((u16)get_data_segment(), offset);
452
 
#endif
453
 
        (*sys_wrw)((get_data_segment() << 4) + offset, val);
454
 
}
455
 
 
456
 
/****************************************************************************
457
 
PARAMETERS:
458
 
offset  - Offset to store data at
459
 
val             - Value to store
460
 
 
461
 
REMARKS:
462
 
Writes a long value to an segmented memory location. The segment used is
463
 
the current 'default' segment, which may have been overridden.
464
 
 
465
 
NOTE: Do not inline this function as (*sys_wrX) is already inline!
466
 
****************************************************************************/
467
 
void store_data_long(
468
 
        uint offset,
469
 
        u32 val)
470
 
{
471
 
#ifdef DEBUG
472
 
        if (CHECK_DATA_ACCESS())
473
 
                x86emu_check_data_access((u16)get_data_segment(), offset);
474
 
#endif
475
 
        (*sys_wrl)((get_data_segment() << 4) + offset, val);
476
 
}
477
 
 
478
 
/****************************************************************************
479
 
PARAMETERS:
480
 
segment - Segment to store data at
481
 
offset  - Offset to store data at
482
 
val             - Value to store
483
 
 
484
 
REMARKS:
485
 
Writes a byte value to an absolute memory location.
486
 
 
487
 
NOTE: Do not inline this function as (*sys_wrX) is already inline!
488
 
****************************************************************************/
489
 
void store_data_byte_abs(
490
 
        uint segment,
491
 
        uint offset,
492
 
        u8 val)
493
 
{
494
 
#ifdef DEBUG
495
 
        if (CHECK_DATA_ACCESS())
496
 
                x86emu_check_data_access(segment, offset);
497
 
#endif
498
 
        (*sys_wrb)(((u32)segment << 4) + offset, val);
499
 
}
500
 
 
501
 
/****************************************************************************
502
 
PARAMETERS:
503
 
segment - Segment to store data at
504
 
offset  - Offset to store data at
505
 
val             - Value to store
506
 
 
507
 
REMARKS:
508
 
Writes a word value to an absolute memory location.
509
 
 
510
 
NOTE: Do not inline this function as (*sys_wrX) is already inline!
511
 
****************************************************************************/
512
 
void store_data_word_abs(
513
 
        uint segment,
514
 
        uint offset,
515
 
        u16 val)
516
 
{
517
 
#ifdef DEBUG
518
 
        if (CHECK_DATA_ACCESS())
519
 
                x86emu_check_data_access(segment, offset);
520
 
#endif
521
 
        (*sys_wrw)(((u32)segment << 4) + offset, val);
522
 
}
523
 
 
524
 
/****************************************************************************
525
 
PARAMETERS:
526
 
segment - Segment to store data at
527
 
offset  - Offset to store data at
528
 
val             - Value to store
529
 
 
530
 
REMARKS:
531
 
Writes a long value to an absolute memory location.
532
 
 
533
 
NOTE: Do not inline this function as (*sys_wrX) is already inline!
534
 
****************************************************************************/
535
 
void store_data_long_abs(
536
 
        uint segment,
537
 
        uint offset,
538
 
        u32 val)
539
 
{
540
 
#ifdef DEBUG
541
 
        if (CHECK_DATA_ACCESS())
542
 
                x86emu_check_data_access(segment, offset);
543
 
#endif
544
 
        (*sys_wrl)(((u32)segment << 4) + offset, val);
545
 
}
546
 
 
547
 
/****************************************************************************
548
 
PARAMETERS:
549
 
reg     - Register to decode
550
 
 
551
 
RETURNS:
552
 
Pointer to the appropriate register
553
 
 
554
 
REMARKS:
555
 
Return a pointer to the register given by the R/RM field of the
556
 
modrm byte, for byte operands. Also enables the decoding of instructions.
557
 
****************************************************************************/
558
 
u8* decode_rm_byte_register(
559
 
        int reg)
560
 
{
561
 
        switch (reg) {
562
 
      case 0:
563
 
                DECODE_PRINTF("AL");
564
 
                return &M.x86.R_AL;
565
 
          case 1:
566
 
                DECODE_PRINTF("CL");
567
 
                return &M.x86.R_CL;
568
 
          case 2:
569
 
                DECODE_PRINTF("DL");
570
 
                return &M.x86.R_DL;
571
 
          case 3:
572
 
                DECODE_PRINTF("BL");
573
 
                return &M.x86.R_BL;
574
 
          case 4:
575
 
                DECODE_PRINTF("AH");
576
 
                return &M.x86.R_AH;
577
 
          case 5:
578
 
                DECODE_PRINTF("CH");
579
 
                return &M.x86.R_CH;
580
 
          case 6:
581
 
                DECODE_PRINTF("DH");
582
 
                return &M.x86.R_DH;
583
 
          case 7:
584
 
                DECODE_PRINTF("BH");
585
 
                return &M.x86.R_BH;
586
 
        }
587
 
        HALT_SYS();
588
 
        return NULL;                /* NOT REACHED OR REACHED ON ERROR */
589
 
}
590
 
 
591
 
/****************************************************************************
592
 
PARAMETERS:
593
 
reg     - Register to decode
594
 
 
595
 
RETURNS:
596
 
Pointer to the appropriate register
597
 
 
598
 
REMARKS:
599
 
Return a pointer to the register given by the R/RM field of the
600
 
modrm byte, for word operands.  Also enables the decoding of instructions.
601
 
****************************************************************************/
602
 
u16* decode_rm_word_register(
603
 
        int reg)
604
 
{
605
 
        switch (reg) {
606
 
          case 0:
607
 
                DECODE_PRINTF("AX");
608
 
                return &M.x86.R_AX;
609
 
          case 1:
610
 
                DECODE_PRINTF("CX");
611
 
                return &M.x86.R_CX;
612
 
          case 2:
613
 
                DECODE_PRINTF("DX");
614
 
                return &M.x86.R_DX;
615
 
          case 3:
616
 
                DECODE_PRINTF("BX");
617
 
                return &M.x86.R_BX;
618
 
          case 4:
619
 
                DECODE_PRINTF("SP");
620
 
                return &M.x86.R_SP;
621
 
          case 5:
622
 
                DECODE_PRINTF("BP");
623
 
                return &M.x86.R_BP;
624
 
          case 6:
625
 
                DECODE_PRINTF("SI");
626
 
                return &M.x86.R_SI;
627
 
          case 7:
628
 
                DECODE_PRINTF("DI");
629
 
                return &M.x86.R_DI;
630
 
        }
631
 
        HALT_SYS();
632
 
    return NULL;                /* NOTREACHED OR REACHED ON ERROR */
633
 
}
634
 
 
635
 
/****************************************************************************
636
 
PARAMETERS:
637
 
reg     - Register to decode
638
 
 
639
 
RETURNS:
640
 
Pointer to the appropriate register
641
 
 
642
 
REMARKS:
643
 
Return a pointer to the register given by the R/RM field of the
644
 
modrm byte, for dword operands.  Also enables the decoding of instructions.
645
 
****************************************************************************/
646
 
u32* decode_rm_long_register(
647
 
        int reg)
648
 
{
649
 
    switch (reg) {
650
 
      case 0:
651
 
                DECODE_PRINTF("EAX");
652
 
                return &M.x86.R_EAX;
653
 
          case 1:
654
 
                DECODE_PRINTF("ECX");
655
 
                return &M.x86.R_ECX;
656
 
          case 2:
657
 
                DECODE_PRINTF("EDX");
658
 
                return &M.x86.R_EDX;
659
 
          case 3:
660
 
                DECODE_PRINTF("EBX");
661
 
                return &M.x86.R_EBX;
662
 
          case 4:
663
 
                DECODE_PRINTF("ESP");
664
 
                return &M.x86.R_ESP;
665
 
          case 5:
666
 
                DECODE_PRINTF("EBP");
667
 
                return &M.x86.R_EBP;
668
 
          case 6:
669
 
                DECODE_PRINTF("ESI");
670
 
                return &M.x86.R_ESI;
671
 
          case 7:
672
 
                DECODE_PRINTF("EDI");
673
 
                return &M.x86.R_EDI;
674
 
        }
675
 
        HALT_SYS();
676
 
    return NULL;                /* NOTREACHED OR REACHED ON ERROR */
677
 
}
678
 
 
679
 
/****************************************************************************
680
 
PARAMETERS:
681
 
reg     - Register to decode
682
 
 
683
 
RETURNS:
684
 
Pointer to the appropriate register
685
 
 
686
 
REMARKS:
687
 
Return a pointer to the register given by the R/RM field of the
688
 
modrm byte, for word operands, modified from above for the weirdo
689
 
special case of segreg operands.  Also enables the decoding of instructions.
690
 
****************************************************************************/
691
 
u16* decode_rm_seg_register(
692
 
        int reg)
693
 
{
694
 
        switch (reg) {
695
 
          case 0:
696
 
                DECODE_PRINTF("ES");
697
 
                return &M.x86.R_ES;
698
 
          case 1:
699
 
                DECODE_PRINTF("CS");
700
 
                return &M.x86.R_CS;
701
 
          case 2:
702
 
                DECODE_PRINTF("SS");
703
 
                return &M.x86.R_SS;
704
 
          case 3:
705
 
                DECODE_PRINTF("DS");
706
 
                return &M.x86.R_DS;
707
 
          case 4:
708
 
                DECODE_PRINTF("FS");
709
 
                return &M.x86.R_FS;
710
 
          case 5:
711
 
                DECODE_PRINTF("GS");
712
 
                return &M.x86.R_GS;
713
 
          case 6:
714
 
          case 7:
715
 
                DECODE_PRINTF("ILLEGAL SEGREG");
716
 
                break;
717
 
        }
718
 
        printf("reg %d\n", reg);
719
 
                //DECODE_PRINTF("CS");
720
 
                //return &M.x86.R_CS;
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
 
        switch (rm) {
846
 
          case 0:
847
 
                DECODE_PRINTF("[EAX]");
848
 
                return M.x86.R_EAX;
849
 
          case 1:
850
 
                DECODE_PRINTF("[ECX]");
851
 
                return M.x86.R_ECX;
852
 
          case 2:
853
 
                DECODE_PRINTF("[EDX]");
854
 
                return M.x86.R_EDX;
855
 
          case 3:
856
 
                DECODE_PRINTF("[EBX]");
857
 
                return M.x86.R_EBX;
858
 
          case 4:
859
 
                sib = fetch_byte_imm();
860
 
                return decode_sib_address(sib, 0);
861
 
          case 5:
862
 
                offset = fetch_long_imm();
863
 
                DECODE_PRINTF2("[%08x]", offset);
864
 
                return offset;
865
 
          case 6:
866
 
                DECODE_PRINTF("[ESI]");
867
 
                return M.x86.R_ESI;
868
 
          case 7:
869
 
                DECODE_PRINTF("[EDI]");
870
 
                return M.x86.R_EDI;
871
 
        }
872
 
        HALT_SYS();
873
 
    } else {
874
 
        switch (rm) {
875
 
          case 0:
876
 
                DECODE_PRINTF("[BX+SI]");
877
 
                return M.x86.R_BX + M.x86.R_SI;
878
 
          case 1:
879
 
                DECODE_PRINTF("[BX+DI]");
880
 
                return M.x86.R_BX + M.x86.R_DI;
881
 
          case 2:
882
 
                DECODE_PRINTF("[BP+SI]");
883
 
                M.x86.mode |= SYSMODE_SEG_DS_SS;
884
 
                return M.x86.R_BP + M.x86.R_SI;
885
 
          case 3:
886
 
                DECODE_PRINTF("[BP+DI]");
887
 
                M.x86.mode |= SYSMODE_SEG_DS_SS;
888
 
                return M.x86.R_BP + M.x86.R_DI;
889
 
          case 4:
890
 
                DECODE_PRINTF("[SI]");
891
 
                return M.x86.R_SI;
892
 
          case 5:
893
 
                DECODE_PRINTF("[DI]");
894
 
                return M.x86.R_DI;
895
 
          case 6:
896
 
                offset = fetch_word_imm();
897
 
                DECODE_PRINTF2("[%04x]", offset);
898
 
                return offset;
899
 
          case 7:
900
 
                DECODE_PRINTF("[BX]");
901
 
                return M.x86.R_BX;
902
 
        }
903
 
        HALT_SYS();
904
 
    }
905
 
    return 0;
906
 
}
907
 
 
908
 
/****************************************************************************
909
 
PARAMETERS:
910
 
rm      - RM value to decode
911
 
 
912
 
RETURNS:
913
 
Offset in memory for the address decoding
914
 
 
915
 
REMARKS:
916
 
Return the offset given by mod=01 addressing.  Also enables the
917
 
decoding of instructions.
918
 
****************************************************************************/
919
 
u32 decode_rm01_address(
920
 
        int rm)
921
 
{
922
 
    int displacement = 0;
923
 
    int sib;
924
 
 
925
 
    /* Fetch disp8 if no SIB byte */
926
 
    if (!((M.x86.mode & SYSMODE_PREFIX_ADDR) && (rm == 4)))
927
 
        displacement = (s8)fetch_byte_imm();
928
 
 
929
 
    if (M.x86.mode & SYSMODE_PREFIX_ADDR) {
930
 
        switch (rm) {
931
 
          case 0:
932
 
                DECODE_PRINTF2("%d[EAX]", displacement);
933
 
                return M.x86.R_EAX + displacement;
934
 
          case 1:
935
 
                DECODE_PRINTF2("%d[ECX]", displacement);
936
 
                return M.x86.R_ECX + displacement;
937
 
          case 2:
938
 
                DECODE_PRINTF2("%d[EDX]", displacement);
939
 
                return M.x86.R_EDX + displacement;
940
 
          case 3:
941
 
                DECODE_PRINTF2("%d[EBX]", displacement);
942
 
                return M.x86.R_EBX + displacement;
943
 
          case 4:
944
 
                sib = fetch_byte_imm();
945
 
                displacement = (s8)fetch_byte_imm();
946
 
                DECODE_PRINTF2("%d", displacement);
947
 
                return decode_sib_address(sib, 1) + displacement;
948
 
          case 5:
949
 
                DECODE_PRINTF2("%d[EBP]", displacement);
950
 
                return M.x86.R_EBP + displacement;
951
 
          case 6:
952
 
                DECODE_PRINTF2("%d[ESI]", displacement);
953
 
                return M.x86.R_ESI + displacement;
954
 
          case 7:
955
 
                DECODE_PRINTF2("%d[EDI]", displacement);
956
 
                return M.x86.R_EDI + displacement;
957
 
        }
958
 
        HALT_SYS();
959
 
    } else {
960
 
        switch (rm) {
961
 
          case 0:
962
 
                DECODE_PRINTF2("%d[BX+SI]", displacement);
963
 
                return M.x86.R_BX + M.x86.R_SI + displacement;
964
 
          case 1:
965
 
                DECODE_PRINTF2("%d[BX+DI]", displacement);
966
 
                return M.x86.R_BX + M.x86.R_DI + displacement;
967
 
          case 2:
968
 
                DECODE_PRINTF2("%d[BP+SI]", displacement);
969
 
                M.x86.mode |= SYSMODE_SEG_DS_SS;
970
 
                return M.x86.R_BP + M.x86.R_SI + displacement;
971
 
          case 3:
972
 
                DECODE_PRINTF2("%d[BP+DI]", displacement);
973
 
                M.x86.mode |= SYSMODE_SEG_DS_SS;
974
 
                return M.x86.R_BP + M.x86.R_DI + displacement;
975
 
          case 4:
976
 
                DECODE_PRINTF2("%d[SI]", displacement);
977
 
                return M.x86.R_SI + displacement;
978
 
          case 5:
979
 
                DECODE_PRINTF2("%d[DI]", displacement);
980
 
                return M.x86.R_DI + displacement;
981
 
          case 6:
982
 
                DECODE_PRINTF2("%d[BP]", displacement);
983
 
                M.x86.mode |= SYSMODE_SEG_DS_SS;
984
 
                return M.x86.R_BP + displacement;
985
 
          case 7:
986
 
                DECODE_PRINTF2("%d[BX]", displacement);
987
 
                return M.x86.R_BX + displacement;
988
 
        }
989
 
        HALT_SYS();
990
 
    }
991
 
    return 0;                   /* SHOULD NOT HAPPEN */
992
 
}
993
 
 
994
 
/****************************************************************************
995
 
PARAMETERS:
996
 
rm      - RM value to decode
997
 
 
998
 
RETURNS:
999
 
Offset in memory for the address decoding
1000
 
 
1001
 
REMARKS:
1002
 
Return the offset given by mod=10 addressing.  Also enables the
1003
 
decoding of instructions.
1004
 
****************************************************************************/
1005
 
u32 decode_rm10_address(
1006
 
        int rm)
1007
 
{
1008
 
    u32 displacement = 0;
1009
 
    int sib;
1010
 
 
1011
 
    /* Fetch disp16 if 16-bit addr mode */
1012
 
    if (!(M.x86.mode & SYSMODE_PREFIX_ADDR))
1013
 
        displacement = (u16)fetch_word_imm();
1014
 
    else {
1015
 
        /* Fetch disp32 if no SIB byte */
1016
 
        if (rm != 4)
1017
 
            displacement = (u32)fetch_long_imm();
1018
 
    }
1019
 
 
1020
 
    if (M.x86.mode & SYSMODE_PREFIX_ADDR) {
1021
 
      switch (rm) {
1022
 
          case 0:
1023
 
                DECODE_PRINTF2("%08x[EAX]", displacement);
1024
 
                return M.x86.R_EAX + displacement;
1025
 
          case 1:
1026
 
                DECODE_PRINTF2("%08x[ECX]", displacement);
1027
 
                return M.x86.R_ECX + displacement;
1028
 
          case 2:
1029
 
                DECODE_PRINTF2("%08x[EDX]", displacement);
1030
 
                M.x86.mode |= SYSMODE_SEG_DS_SS;
1031
 
                return M.x86.R_EDX + displacement;
1032
 
          case 3:
1033
 
                DECODE_PRINTF2("%08x[EBX]", displacement);
1034
 
                return M.x86.R_EBX + displacement;
1035
 
          case 4:
1036
 
                sib = fetch_byte_imm();
1037
 
                displacement = (u32)fetch_long_imm();
1038
 
                DECODE_PRINTF2("%08x", displacement);
1039
 
                return decode_sib_address(sib, 2) + displacement;
1040
 
                break;
1041
 
          case 5:
1042
 
                DECODE_PRINTF2("%08x[EBP]", displacement);
1043
 
                return M.x86.R_EBP + displacement;
1044
 
          case 6:
1045
 
                DECODE_PRINTF2("%08x[ESI]", displacement);
1046
 
                return M.x86.R_ESI + displacement;
1047
 
          case 7:
1048
 
                DECODE_PRINTF2("%08x[EDI]", displacement);
1049
 
                return M.x86.R_EDI + displacement;
1050
 
        }
1051
 
        HALT_SYS();
1052
 
    } else {
1053
 
      switch (rm) {
1054
 
          case 0:
1055
 
                DECODE_PRINTF2("%04x[BX+SI]", displacement);
1056
 
                return M.x86.R_BX + M.x86.R_SI + displacement;
1057
 
          case 1:
1058
 
                DECODE_PRINTF2("%04x[BX+DI]", displacement);
1059
 
                return M.x86.R_BX + M.x86.R_DI + displacement;
1060
 
          case 2:
1061
 
                DECODE_PRINTF2("%04x[BP+SI]", displacement);
1062
 
                M.x86.mode |= SYSMODE_SEG_DS_SS;
1063
 
                return M.x86.R_BP + M.x86.R_SI + displacement;
1064
 
          case 3:
1065
 
                DECODE_PRINTF2("%04x[BP+DI]", displacement);
1066
 
                M.x86.mode |= SYSMODE_SEG_DS_SS;
1067
 
                return M.x86.R_BP + M.x86.R_DI + displacement;
1068
 
          case 4:
1069
 
                DECODE_PRINTF2("%04x[SI]", displacement);
1070
 
                return M.x86.R_SI + displacement;
1071
 
          case 5:
1072
 
                DECODE_PRINTF2("%04x[DI]", displacement);
1073
 
                return M.x86.R_DI + displacement;
1074
 
          case 6:
1075
 
                DECODE_PRINTF2("%04x[BP]", displacement);
1076
 
                M.x86.mode |= SYSMODE_SEG_DS_SS;
1077
 
                return M.x86.R_BP + displacement;
1078
 
          case 7:
1079
 
                DECODE_PRINTF2("%04x[BX]", displacement);
1080
 
                return M.x86.R_BX + displacement;
1081
 
        }
1082
 
        HALT_SYS();
1083
 
    }
1084
 
    return 0;
1085
 
    /*NOTREACHED */
1086
 
}