coreboot
coreboot is an Open Source project aimed at replacing the proprietary BIOS found in most computers.
decode.c
Go to the documentation of this file.
1 /****************************************************************************
2 *
3 * Realmode X86 Emulator Library
4 *
5 * Copyright (C) 1991-2004 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 accesses of immediate data via IP. etc.
37 *
38 ****************************************************************************/
39 
40 #include "x86emui.h"
41 
42 /*----------------------------- Implementation ----------------------------*/
43 
44 /****************************************************************************
45 REMARKS:
46 Handles any pending asynchronous interrupts.
47 ****************************************************************************/
48 static void x86emu_intr_handle(void)
49 {
50  u8 intno;
51 
52  if (M.x86.intr & INTR_SYNCH) {
53  intno = M.x86.intno;
54  if (_X86EMU_intrTab[intno]) {
55  (*_X86EMU_intrTab[intno])(intno);
56  } else {
57  push_word((u16)M.x86.R_FLG);
60  push_word(M.x86.R_CS);
61  M.x86.R_CS = mem_access_word(intno * 4 + 2);
62  push_word(M.x86.R_IP);
63  M.x86.R_IP = mem_access_word(intno * 4);
64  M.x86.intr = 0;
65  }
66  }
67 }
68 
69 /****************************************************************************
70 PARAMETERS:
71 intrnum - Interrupt number to raise
72 
73 REMARKS:
74 Raise the specified interrupt to be handled before the execution of the
75 next instruction.
76 ****************************************************************************/
78  u8 intrnum)
79 {
80  printf("%s, raising exception %x\n", __func__, intrnum);
82  M.x86.intno = intrnum;
83  M.x86.intr |= INTR_SYNCH;
84 }
85 
86 /****************************************************************************
87 REMARKS:
88 Main execution loop for the emulator. We return from here when the system
89 halts, which is normally caused by a stack fault when we return from the
90 original real mode call.
91 ****************************************************************************/
92 void X86EMU_exec(void)
93 {
94  u8 op1;
95 
96  M.x86.intr = 0;
98 
99  for (;;) {
100 DB( if (CHECK_IP_FETCH())
102  /* If debugging, save the IP and CS values. */
103  SAVE_IP_CS(M.x86.R_CS, M.x86.R_IP);
105  if (M.x86.intr) {
106  if (M.x86.intr & INTR_HALTED) {
107 DB( if (M.x86.R_SP != 0) {
108  printf("halted\n");
109  X86EMU_trace_regs();
110  }
111  else {
112  if (M.x86.debug)
113  printf("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)) {
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  //}
128  }
129 }
130 
131 /****************************************************************************
132 REMARKS:
133 Halts the system by setting the halted system flag.
134 ****************************************************************************/
135 void X86EMU_halt_sys(void)
136 {
137  M.x86.intr |= INTR_HALTED;
138 }
139 
140 /****************************************************************************
141 PARAMETERS:
142 mod - Mod value from decoded byte
143 regh - Reg h value from decoded byte
144 regl - Reg l value from decoded byte
145 
146 REMARKS:
147 Raise the specified interrupt to be handled before the execution of the
148 next instruction.
149 
150 NOTE: Do not inline this function, as (*sys_rdb) is already inline!
151 ****************************************************************************/
153  int *mod,
154  int *regh,
155  int *regl)
156 {
157  int fetched;
158 
159 DB( if (CHECK_IP_FETCH())
161  fetched = (*sys_rdb)(((u32)M.x86.R_CS << 4) + (M.x86.R_IP++));
163  *mod = (fetched >> 6) & 0x03;
164  *regh = (fetched >> 3) & 0x07;
165  *regl = (fetched >> 0) & 0x07;
166 }
167 
168 /****************************************************************************
169 RETURNS:
170 Immediate byte value read from instruction queue
171 
172 REMARKS:
173 This function returns the immediate byte from the instruction queue, and
174 moves the instruction pointer to the next value.
175 
176 NOTE: Do not inline this function, as (*sys_rdb) is already inline!
177 ****************************************************************************/
179 {
180  u8 fetched;
181 
182 DB( if (CHECK_IP_FETCH())
184  fetched = (*sys_rdb)(((u32)M.x86.R_CS << 4) + (M.x86.R_IP++));
186  return fetched;
187 }
188 
189 /****************************************************************************
190 RETURNS:
191 Immediate word value read from instruction queue
192 
193 REMARKS:
194 This function returns the immediate byte from the instruction queue, and
195 moves the instruction pointer to the next value.
196 
197 NOTE: Do not inline this function, as (*sys_rdw) is already inline!
198 ****************************************************************************/
200 {
201  u16 fetched;
202 
203 DB( if (CHECK_IP_FETCH())
205  fetched = (*sys_rdw)(((u32)M.x86.R_CS << 4) + (M.x86.R_IP));
206  M.x86.R_IP += 2;
208  return fetched;
209 }
210 
211 /****************************************************************************
212 RETURNS:
213 Immediate lone value read from instruction queue
214 
215 REMARKS:
216 This function returns the immediate byte from the instruction queue, and
217 moves the instruction pointer to the next value.
218 
219 NOTE: Do not inline this function, as (*sys_rdw) is already inline!
220 ****************************************************************************/
222 {
223  u32 fetched;
224 
225 DB( if (CHECK_IP_FETCH())
227  fetched = (*sys_rdl)(((u32)M.x86.R_CS << 4) + (M.x86.R_IP));
228  M.x86.R_IP += 4;
230  return fetched;
231 }
232 
233 /****************************************************************************
234 RETURNS:
235 Value of the default data segment
236 
237 REMARKS:
238 Inline function that returns the default data segment for the current
239 instruction.
240 
241 On the x86 processor, the default segment is not always DS if there is
242 no segment override. Address modes such as -3[BP] or 10[BP+SI] all refer to
243 addresses relative to SS (ie: on the stack). So, at the minimum, all
244 decodings of addressing modes would have to set/clear a bit describing
245 whether the access is relative to DS or SS. That is the function of the
246 cpu-state-variable 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 absence of override)
259 
260 Each of the above 7 items are handled with a bit in the mode field.
261 ****************************************************************************/
263 {
264 #define GET_SEGMENT(segment)
265  switch (M.x86.mode & SYSMODE_SEGMASK) {
266  case 0: /* default case: use ds register */
267  case SYSMODE_SEGOVR_DS:
269  return M.x86.R_DS;
270  case SYSMODE_SEG_DS_SS: /* non-overridden, use ss register */
271  return M.x86.R_SS;
272  case SYSMODE_SEGOVR_CS:
274  return M.x86.R_CS;
275  case SYSMODE_SEGOVR_ES:
277  return M.x86.R_ES;
278  case SYSMODE_SEGOVR_FS:
280  return M.x86.R_FS;
281  case SYSMODE_SEGOVR_GS:
283  return M.x86.R_GS;
284  case SYSMODE_SEGOVR_SS:
286  return M.x86.R_SS;
287  default:
288 #ifdef DEBUG
289  printf("error: should not happen: multiple overrides.\n");
290 #endif
291  HALT_SYS();
292  return 0;
293  }
294 }
295 
296 /****************************************************************************
297 PARAMETERS:
298 offset - Offset to load data from
299 
300 RETURNS:
301 Byte value read from the absolute memory location.
302 
303 NOTE: Do not inline this function as (*sys_rdX) is already inline!
304 ****************************************************************************/
306  uint offset)
307 {
308 #ifdef DEBUG
309  if (CHECK_DATA_ACCESS())
311 #endif
312  return (*sys_rdb)((get_data_segment() << 4) + offset);
313 }
314 
315 /****************************************************************************
316 PARAMETERS:
317 offset - Offset to load data from
318 
319 RETURNS:
320 Word value read from the absolute memory location.
321 
322 NOTE: Do not inline this function as (*sys_rdX) is already inline!
323 ****************************************************************************/
325  uint offset)
326 {
327 #ifdef DEBUG
328  if (CHECK_DATA_ACCESS())
330 #endif
331  return (*sys_rdw)((get_data_segment() << 4) + offset);
332 }
333 
334 /****************************************************************************
335 PARAMETERS:
336 offset - Offset to load data from
337 
338 RETURNS:
339 Long value read from the absolute memory location.
340 
341 NOTE: Do not inline this function as (*sys_rdX) is already inline!
342 ****************************************************************************/
344  uint offset)
345 {
346 #ifdef DEBUG
347  if (CHECK_DATA_ACCESS())
349 #endif
350  return (*sys_rdl)((get_data_segment() << 4) + offset);
351 }
352 
353 /****************************************************************************
354 PARAMETERS:
355 segment - Segment to load data from
356 offset - Offset to load data from
357 
358 RETURNS:
359 Byte value read from the absolute memory location.
360 
361 NOTE: Do not inline this function as (*sys_rdX) is already inline!
362 ****************************************************************************/
364  uint segment,
365  uint offset)
366 {
367 #ifdef DEBUG
368  if (CHECK_DATA_ACCESS())
370 #endif
371  return (*sys_rdb)(((u32)segment << 4) + offset);
372 }
373 
374 /****************************************************************************
375 PARAMETERS:
376 segment - Segment to load data from
377 offset - Offset to load data from
378 
379 RETURNS:
380 Word value read from the absolute memory location.
381 
382 NOTE: Do not inline this function as (*sys_rdX) is already inline!
383 ****************************************************************************/
385  uint segment,
386  uint offset)
387 {
388 #ifdef DEBUG
389  if (CHECK_DATA_ACCESS())
391 #endif
392  return (*sys_rdw)(((u32)segment << 4) + offset);
393 }
394 
395 /****************************************************************************
396 PARAMETERS:
397 segment - Segment to load data from
398 offset - Offset to load data from
399 
400 RETURNS:
401 Long value read from the absolute memory location.
402 
403 NOTE: Do not inline this function as (*sys_rdX) is already inline!
404 ****************************************************************************/
406  uint segment,
407  uint offset)
408 {
409 #ifdef DEBUG
410  if (CHECK_DATA_ACCESS())
412 #endif
413  return (*sys_rdl)(((u32)segment << 4) + offset);
414 }
415 
416 /****************************************************************************
417 PARAMETERS:
418 offset - Offset to store data at
419 val - Value to store
420 
421 REMARKS:
422 Writes a word value to an segmented memory location. The segment used is
423 the current 'default' segment, which may have been overridden.
424 
425 NOTE: Do not inline this function as (*sys_wrX) is already inline!
426 ****************************************************************************/
428  uint offset,
429  u8 val)
430 {
431 #ifdef DEBUG
432  if (CHECK_DATA_ACCESS())
434 #endif
435  (*sys_wrb)((get_data_segment() << 4) + offset, val);
436 }
437 
438 /****************************************************************************
439 PARAMETERS:
440 offset - Offset to store data at
441 val - Value to store
442 
443 REMARKS:
444 Writes a word value to an segmented memory location. The segment used is
445 the current 'default' segment, which may have been overridden.
446 
447 NOTE: Do not inline this function as (*sys_wrX) is already inline!
448 ****************************************************************************/
450  uint offset,
451  u16 val)
452 {
453 #ifdef DEBUG
454  if (CHECK_DATA_ACCESS())
456 #endif
457  (*sys_wrw)((get_data_segment() << 4) + offset, val);
458 }
459 
460 /****************************************************************************
461 PARAMETERS:
462 offset - Offset to store data at
463 val - Value to store
464 
465 REMARKS:
466 Writes a long value to an segmented memory location. The segment used is
467 the current 'default' segment, which may have been overridden.
468 
469 NOTE: Do not inline this function as (*sys_wrX) is already inline!
470 ****************************************************************************/
472  uint offset,
473  u32 val)
474 {
475 #ifdef DEBUG
476  if (CHECK_DATA_ACCESS())
478 #endif
479  (*sys_wrl)((get_data_segment() << 4) + offset, val);
480 }
481 
482 /****************************************************************************
483 PARAMETERS:
484 segment - Segment to store data at
485 offset - Offset to store data at
486 val - Value to store
487 
488 REMARKS:
489 Writes a byte value to an absolute memory location.
490 
491 NOTE: Do not inline this function as (*sys_wrX) is already inline!
492 ****************************************************************************/
494  uint segment,
495  uint offset,
496  u8 val)
497 {
498 #ifdef DEBUG
499  if (CHECK_DATA_ACCESS())
501 #endif
502  (*sys_wrb)(((u32)segment << 4) + offset, val);
503 }
504 
505 /****************************************************************************
506 PARAMETERS:
507 segment - Segment to store data at
508 offset - Offset to store data at
509 val - Value to store
510 
511 REMARKS:
512 Writes a word value to an absolute memory location.
513 
514 NOTE: Do not inline this function as (*sys_wrX) is already inline!
515 ****************************************************************************/
517  uint segment,
518  uint offset,
519  u16 val)
520 {
521 #ifdef DEBUG
522  if (CHECK_DATA_ACCESS())
524 #endif
525  (*sys_wrw)(((u32)segment << 4) + offset, val);
526 }
527 
528 /****************************************************************************
529 PARAMETERS:
530 segment - Segment to store data at
531 offset - Offset to store data at
532 val - Value to store
533 
534 REMARKS:
535 Writes a long value to an absolute memory location.
536 
537 NOTE: Do not inline this function as (*sys_wrX) is already inline!
538 ****************************************************************************/
540  uint segment,
541  uint offset,
542  u32 val)
543 {
544 #ifdef DEBUG
545  if (CHECK_DATA_ACCESS())
547 #endif
548  (*sys_wrl)(((u32)segment << 4) + offset, val);
549 }
550 
551 /****************************************************************************
552 PARAMETERS:
553 reg - Register to decode
554 
555 RETURNS:
556 Pointer to the appropriate register
557 
558 REMARKS:
559 Return a pointer to the register given by the R/RM field of the
560 modrm byte, for byte operands. Also enables the decoding of instructions.
561 ****************************************************************************/
563  int reg)
564 {
565  switch (reg) {
566  case 0:
567  DECODE_PRINTF("AL");
568  return &M.x86.R_AL;
569  case 1:
570  DECODE_PRINTF("CL");
571  return &M.x86.R_CL;
572  case 2:
573  DECODE_PRINTF("DL");
574  return &M.x86.R_DL;
575  case 3:
576  DECODE_PRINTF("BL");
577  return &M.x86.R_BL;
578  case 4:
579  DECODE_PRINTF("AH");
580  return &M.x86.R_AH;
581  case 5:
582  DECODE_PRINTF("CH");
583  return &M.x86.R_CH;
584  case 6:
585  DECODE_PRINTF("DH");
586  return &M.x86.R_DH;
587  case 7:
588  DECODE_PRINTF("BH");
589  return &M.x86.R_BH;
590  }
591  HALT_SYS();
592  return NULL; /* NOT REACHED OR REACHED ON ERROR */
593 }
594 
595 /****************************************************************************
596 PARAMETERS:
597 reg - Register to decode
598 
599 RETURNS:
600 Pointer to the appropriate register
601 
602 REMARKS:
603 Return a pointer to the register given by the R/RM field of the
604 modrm byte, for word operands. Also enables the decoding of instructions.
605 ****************************************************************************/
607  int reg)
608 {
609  switch (reg) {
610  case 0:
611  DECODE_PRINTF("AX");
612  return &M.x86.R_AX;
613  case 1:
614  DECODE_PRINTF("CX");
615  return &M.x86.R_CX;
616  case 2:
617  DECODE_PRINTF("DX");
618  return &M.x86.R_DX;
619  case 3:
620  DECODE_PRINTF("BX");
621  return &M.x86.R_BX;
622  case 4:
623  DECODE_PRINTF("SP");
624  return &M.x86.R_SP;
625  case 5:
626  DECODE_PRINTF("BP");
627  return &M.x86.R_BP;
628  case 6:
629  DECODE_PRINTF("SI");
630  return &M.x86.R_SI;
631  case 7:
632  DECODE_PRINTF("DI");
633  return &M.x86.R_DI;
634  }
635  HALT_SYS();
636  return NULL; /* NOTREACHED OR REACHED ON ERROR */
637 }
638 
639 /****************************************************************************
640 PARAMETERS:
641 reg - Register to decode
642 
643 RETURNS:
644 Pointer to the appropriate register
645 
646 REMARKS:
647 Return a pointer to the register given by the R/RM field of the
648 modrm byte, for dword operands. Also enables the decoding of instructions.
649 ****************************************************************************/
651  int reg)
652 {
653  switch (reg) {
654  case 0:
655  DECODE_PRINTF("EAX");
656  return &M.x86.R_EAX;
657  case 1:
658  DECODE_PRINTF("ECX");
659  return &M.x86.R_ECX;
660  case 2:
661  DECODE_PRINTF("EDX");
662  return &M.x86.R_EDX;
663  case 3:
664  DECODE_PRINTF("EBX");
665  return &M.x86.R_EBX;
666  case 4:
667  DECODE_PRINTF("ESP");
668  return &M.x86.R_ESP;
669  case 5:
670  DECODE_PRINTF("EBP");
671  return &M.x86.R_EBP;
672  case 6:
673  DECODE_PRINTF("ESI");
674  return &M.x86.R_ESI;
675  case 7:
676  DECODE_PRINTF("EDI");
677  return &M.x86.R_EDI;
678  }
679  HALT_SYS();
680  return NULL; /* NOTREACHED OR REACHED ON ERROR */
681 }
682 
683 /****************************************************************************
684 PARAMETERS:
685 reg - Register to decode
686 
687 RETURNS:
688 Pointer to the appropriate register
689 
690 REMARKS:
691 Return a pointer to the register given by the R/RM field of the
692 modrm byte, for word operands, modified from above for the weirdo
693 special case of segreg operands. Also enables the decoding of instructions.
694 ****************************************************************************/
696  int reg)
697 {
698  switch (reg) {
699  case 0:
700  DECODE_PRINTF("ES");
701  return &M.x86.R_ES;
702  case 1:
703  DECODE_PRINTF("CS");
704  return &M.x86.R_CS;
705  case 2:
706  DECODE_PRINTF("SS");
707  return &M.x86.R_SS;
708  case 3:
709  DECODE_PRINTF("DS");
710  return &M.x86.R_DS;
711  case 4:
712  DECODE_PRINTF("FS");
713  return &M.x86.R_FS;
714  case 5:
715  DECODE_PRINTF("GS");
716  return &M.x86.R_GS;
717  case 6:
718  case 7:
719  DECODE_PRINTF("ILLEGAL SEGREG");
720  break;
721  }
722  HALT_SYS();
723  return NULL; /* NOT REACHED OR REACHED ON ERROR */
724 }
725 
726 /****************************************************************************
727 PARAMETERS:
728 scale - scale value of SIB byte
729 index - index value of SIB byte
730 
731 RETURNS:
732 Value of scale * index
733 
734 REMARKS:
735 Decodes scale/index of SIB byte and returns relevant offset part of
736 effective address.
737 ****************************************************************************/
738 static unsigned int decode_sib_si(
739  int scale,
740  int index)
741 {
742  scale = 1 << scale;
743  if (scale > 1) {
744  DECODE_PRINTF2("[%d*", scale);
745  } else {
746  DECODE_PRINTF("[");
747  }
748  switch (index) {
749  case 0:
750  DECODE_PRINTF("EAX]");
751  return M.x86.R_EAX * index;
752  case 1:
753  DECODE_PRINTF("ECX]");
754  return M.x86.R_ECX * index;
755  case 2:
756  DECODE_PRINTF("EDX]");
757  return M.x86.R_EDX * index;
758  case 3:
759  DECODE_PRINTF("EBX]");
760  return M.x86.R_EBX * index;
761  case 4:
762  DECODE_PRINTF("0]");
763  return 0;
764  case 5:
765  DECODE_PRINTF("EBP]");
766  return M.x86.R_EBP * index;
767  case 6:
768  DECODE_PRINTF("ESI]");
769  return M.x86.R_ESI * index;
770  case 7:
771  DECODE_PRINTF("EDI]");
772  return M.x86.R_EDI * index;
773  }
774  HALT_SYS();
775  return 0; /* NOT REACHED OR REACHED ON ERROR */
776 }
777 
778 /****************************************************************************
779 PARAMETERS:
780 mod - MOD value of preceding ModR/M byte
781 
782 RETURNS:
783 Offset in memory for the address decoding
784 
785 REMARKS:
786 Decodes SIB addressing byte and returns calculated effective address.
787 ****************************************************************************/
788 static unsigned int 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:
800  DECODE_PRINTF("[EAX]");
801  offset = M.x86.R_EAX;
802  break;
803  case 1:
804  DECODE_PRINTF("[ECX]");
805  offset = M.x86.R_ECX;
806  break;
807  case 2:
808  DECODE_PRINTF("[EDX]");
809  offset = M.x86.R_EDX;
810  break;
811  case 3:
812  DECODE_PRINTF("[EBX]");
813  offset = M.x86.R_EBX;
814  break;
815  case 4:
816  DECODE_PRINTF("[ESP]");
817  offset = M.x86.R_ESP;
818  break;
819  case 5:
820  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;
842  case 6:
843  DECODE_PRINTF("[ESI]");
844  offset = M.x86.R_ESI;
845  break;
846  case 7:
847  DECODE_PRINTF("[EDI]");
848  offset = M.x86.R_EDI;
849  break;
850  default:
851  HALT_SYS();
852  }
853  offset += decode_sib_si(ss, index);
854  return offset;
855 }
856 
857 /****************************************************************************
858 PARAMETERS:
859 rm - RM value to decode
860 
861 RETURNS:
862 Offset in memory for the address decoding
863 
864 REMARKS:
865 Return the offset given by mod=00 addressing. Also enables the
866 decoding of instructions.
867 
868 NOTE: The code which specifies the corresponding segment (ds vs ss)
869  below in the case of [BP+..]. The assumption here is that at the
870  point that this subroutine is called, the bit corresponding to
871  SYSMODE_SEG_DS_SS will be zero. After every instruction
872  except the segment override instructions, this bit (as well
873  as any bits indicating segment overrides) will be clear. So
874  if a SS access is needed, set this bit. Otherwise, DS access
875  occurs (unless any of the segment override bits are set).
876 ****************************************************************************/
877 unsigned int decode_rm00_address(
878  int rm)
879 {
880  unsigned int offset;
881 
882  if (M.x86.mode & SYSMODE_PREFIX_ADDR) {
883  /* 32-bit addressing */
884  switch (rm) {
885  case 0:
886  DECODE_PRINTF("[EAX]");
887  return M.x86.R_EAX;
888  case 1:
889  DECODE_PRINTF("[ECX]");
890  return M.x86.R_ECX;
891  case 2:
892  DECODE_PRINTF("[EDX]");
893  return M.x86.R_EDX;
894  case 3:
895  DECODE_PRINTF("[EBX]");
896  return M.x86.R_EBX;
897  case 4:
898  return decode_sib_address(0);
899  case 5:
901  DECODE_PRINTF2("[%08x]", offset);
902  return offset;
903  case 6:
904  DECODE_PRINTF("[ESI]");
905  return M.x86.R_ESI;
906  case 7:
907  DECODE_PRINTF("[EDI]");
908  return M.x86.R_EDI;
909  }
910  } else {
911  /* 16-bit addressing */
912  switch (rm) {
913  case 0:
914  DECODE_PRINTF("[BX+SI]");
915  return (M.x86.R_BX + M.x86.R_SI) & 0xffff;
916  case 1:
917  DECODE_PRINTF("[BX+DI]");
918  return (M.x86.R_BX + M.x86.R_DI) & 0xffff;
919  case 2:
920  DECODE_PRINTF("[BP+SI]");
921  M.x86.mode |= SYSMODE_SEG_DS_SS;
922  return (M.x86.R_BP + M.x86.R_SI) & 0xffff;
923  case 3:
924  DECODE_PRINTF("[BP+DI]");
925  M.x86.mode |= SYSMODE_SEG_DS_SS;
926  return (M.x86.R_BP + M.x86.R_DI) & 0xffff;
927  case 4:
928  DECODE_PRINTF("[SI]");
929  return M.x86.R_SI;
930  case 5:
931  DECODE_PRINTF("[DI]");
932  return M.x86.R_DI;
933  case 6:
935  DECODE_PRINTF2("[%04x]", offset);
936  return offset;
937  case 7:
938  DECODE_PRINTF("[BX]");
939  return M.x86.R_BX;
940  }
941  }
942  HALT_SYS();
943  return 0;
944 }
945 
946 /****************************************************************************
947 PARAMETERS:
948 rm - RM value to decode
949 
950 RETURNS:
951 Offset in memory for the address decoding
952 
953 REMARKS:
954 Return the offset given by mod=01 addressing. Also enables the
955 decoding of instructions.
956 ****************************************************************************/
957 unsigned int decode_rm01_address(
958  int rm)
959 {
960  int displacement;
961 
962  if (M.x86.mode & SYSMODE_PREFIX_ADDR) {
963  /* 32-bit addressing */
964  if (rm != 4)
965  displacement = (s8)fetch_byte_imm();
966  else
967  displacement = 0;
968 
969  switch (rm) {
970  case 0:
971  DECODE_PRINTF2("%d[EAX]", displacement);
972  return M.x86.R_EAX + displacement;
973  case 1:
974  DECODE_PRINTF2("%d[ECX]", displacement);
975  return M.x86.R_ECX + displacement;
976  case 2:
977  DECODE_PRINTF2("%d[EDX]", displacement);
978  return M.x86.R_EDX + displacement;
979  case 3:
980  DECODE_PRINTF2("%d[EBX]", displacement);
981  return M.x86.R_EBX + displacement;
982  case 4: {
983  int offset = decode_sib_address(1);
984  displacement = (s8)fetch_byte_imm();
985  DECODE_PRINTF2("[%d]", displacement);
986  return offset + displacement;
987  }
988  case 5:
989  DECODE_PRINTF2("%d[EBP]", displacement);
990  return M.x86.R_EBP + displacement;
991  case 6:
992  DECODE_PRINTF2("%d[ESI]", displacement);
993  return M.x86.R_ESI + displacement;
994  case 7:
995  DECODE_PRINTF2("%d[EDI]", displacement);
996  return M.x86.R_EDI + displacement;
997  }
998  } else {
999  /* 16-bit addressing */
1000  displacement = (s8)fetch_byte_imm();
1001  switch (rm) {
1002  case 0:
1003  DECODE_PRINTF2("%d[BX+SI]", displacement);
1004  return (M.x86.R_BX + M.x86.R_SI + displacement) & 0xffff;
1005  case 1:
1006  DECODE_PRINTF2("%d[BX+DI]", displacement);
1007  return (M.x86.R_BX + M.x86.R_DI + displacement) & 0xffff;
1008  case 2:
1009  DECODE_PRINTF2("%d[BP+SI]", displacement);
1010  M.x86.mode |= SYSMODE_SEG_DS_SS;
1011  return (M.x86.R_BP + M.x86.R_SI + displacement) & 0xffff;
1012  case 3:
1013  DECODE_PRINTF2("%d[BP+DI]", displacement);
1014  M.x86.mode |= SYSMODE_SEG_DS_SS;
1015  return (M.x86.R_BP + M.x86.R_DI + displacement) & 0xffff;
1016  case 4:
1017  DECODE_PRINTF2("%d[SI]", displacement);
1018  return (M.x86.R_SI + displacement) & 0xffff;
1019  case 5:
1020  DECODE_PRINTF2("%d[DI]", displacement);
1021  return (M.x86.R_DI + displacement) & 0xffff;
1022  case 6:
1023  DECODE_PRINTF2("%d[BP]", displacement);
1024  M.x86.mode |= SYSMODE_SEG_DS_SS;
1025  return (M.x86.R_BP + displacement) & 0xffff;
1026  case 7:
1027  DECODE_PRINTF2("%d[BX]", displacement);
1028  return (M.x86.R_BX + displacement) & 0xffff;
1029  }
1030  }
1031  HALT_SYS();
1032  return 0; /* SHOULD NOT HAPPEN */
1033 }
1034 
1035 /****************************************************************************
1036 PARAMETERS:
1037 rm - RM value to decode
1038 
1039 RETURNS:
1040 Offset in memory for the address decoding
1041 
1042 REMARKS:
1043 Return the offset given by mod=10 addressing. Also enables the
1044 decoding of instructions.
1045 ****************************************************************************/
1046 unsigned int decode_rm10_address(
1047  int rm)
1048 {
1049  if (M.x86.mode & SYSMODE_PREFIX_ADDR) {
1050  int displacement;
1051 
1052  /* 32-bit addressing */
1053  if (rm != 4)
1054  displacement = (s32)fetch_long_imm();
1055  else
1056  displacement = 0;
1057 
1058  switch (rm) {
1059  case 0:
1060  DECODE_PRINTF2("%d[EAX]", displacement);
1061  return M.x86.R_EAX + displacement;
1062  case 1:
1063  DECODE_PRINTF2("%d[ECX]", displacement);
1064  return M.x86.R_ECX + displacement;
1065  case 2:
1066  DECODE_PRINTF2("%d[EDX]", displacement);
1067  return M.x86.R_EDX + displacement;
1068  case 3:
1069  DECODE_PRINTF2("%d[EBX]", displacement);
1070  return M.x86.R_EBX + displacement;
1071  case 4: {
1072  int offset = decode_sib_address(2);
1073  displacement = (s32)fetch_long_imm();
1074  DECODE_PRINTF2("[%d]", displacement);
1075  return offset + displacement;
1076  }
1077  case 5:
1078  DECODE_PRINTF2("%d[EBP]", displacement);
1079  return M.x86.R_EBP + displacement;
1080  case 6:
1081  DECODE_PRINTF2("%d[ESI]", displacement);
1082  return M.x86.R_ESI + displacement;
1083  case 7:
1084  DECODE_PRINTF2("%d[EDI]", displacement);
1085  return M.x86.R_EDI + displacement;
1086  }
1087  } else {
1088  int displacement = (s16)fetch_word_imm();
1089 
1090  /* 16-bit addressing */
1091  switch (rm) {
1092  case 0:
1093  DECODE_PRINTF2("%d[BX+SI]", displacement);
1094  return (M.x86.R_BX + M.x86.R_SI + displacement) & 0xffff;
1095  case 1:
1096  DECODE_PRINTF2("%d[BX+DI]", displacement);
1097  return (M.x86.R_BX + M.x86.R_DI + displacement) & 0xffff;
1098  case 2:
1099  DECODE_PRINTF2("%d[BP+SI]", displacement);
1100  M.x86.mode |= SYSMODE_SEG_DS_SS;
1101  return (M.x86.R_BP + M.x86.R_SI + displacement) & 0xffff;
1102  case 3:
1103  DECODE_PRINTF2("%d[BP+DI]", displacement);
1104  M.x86.mode |= SYSMODE_SEG_DS_SS;
1105  return (M.x86.R_BP + M.x86.R_DI + displacement) & 0xffff;
1106  case 4:
1107  DECODE_PRINTF2("%d[SI]", displacement);
1108  return (M.x86.R_SI + displacement) & 0xffff;
1109  case 5:
1110  DECODE_PRINTF2("%d[DI]", displacement);
1111  return (M.x86.R_DI + displacement) & 0xffff;
1112  case 6:
1113  DECODE_PRINTF2("%d[BP]", displacement);
1114  M.x86.mode |= SYSMODE_SEG_DS_SS;
1115  return (M.x86.R_BP + displacement) & 0xffff;
1116  case 7:
1117  DECODE_PRINTF2("%d[BX]", displacement);
1118  return (M.x86.R_BX + displacement) & 0xffff;
1119  }
1120  }
1121  HALT_SYS();
1122  return 0; /* SHOULD NOT HAPPEN */
1123 }
1124 
1125 /****************************************************************************
1126 PARAMETERS:
1127 mod - modifier
1128 rm - RM value to decode
1129 
1130 RETURNS:
1131 Offset in memory for the address decoding, multiplexing calls to
1132 the decode_rmXX_address functions
1133 
1134 REMARKS:
1135 Return the offset given by "mod" addressing.
1136 ****************************************************************************/
1137 
1138 unsigned int decode_rmXX_address(int mod, int rm)
1139 {
1140  if (mod == 0)
1141  return decode_rm00_address(rm);
1142  if (mod == 1)
1143  return decode_rm01_address(rm);
1144  return decode_rm10_address(rm);
1145 }
unsigned int decode_rm01_address(int rm)
Definition: decode.c:957
unsigned int decode_rmXX_address(int mod, int rm)
Definition: decode.c:1138
u16 fetch_data_word_abs(uint segment, uint offset)
Definition: decode.c:384
u16 fetch_data_word(uint offset)
Definition: decode.c:324
u8 fetch_data_byte_abs(uint segment, uint offset)
Definition: decode.c:363
void store_data_byte(uint offset, u8 val)
Definition: decode.c:427
unsigned int decode_rm10_address(int rm)
Definition: decode.c:1046
void fetch_decode_modrm(int *mod, int *regh, int *regl)
Definition: decode.c:152
void store_data_word_abs(uint segment, uint offset, u16 val)
Definition: decode.c:516
static unsigned int decode_sib_address(int mod)
Definition: decode.c:788
void X86EMU_halt_sys(void)
Definition: decode.c:135
u16 fetch_word_imm(void)
Definition: decode.c:199
u16 * decode_rm_seg_register(int reg)
Definition: decode.c:695
void x86emu_intr_raise(u8 intrnum)
Definition: decode.c:77
_INLINE u32 get_data_segment(void)
Definition: decode.c:262
void store_data_byte_abs(uint segment, uint offset, u8 val)
Definition: decode.c:493
void store_data_long_abs(uint segment, uint offset, u32 val)
Definition: decode.c:539
u8 fetch_byte_imm(void)
Definition: decode.c:178
u16 * decode_rm_word_register(int reg)
Definition: decode.c:606
u8 fetch_data_byte(uint offset)
Definition: decode.c:305
unsigned int decode_rm00_address(int rm)
Definition: decode.c:877
u8 * decode_rm_byte_register(int reg)
Definition: decode.c:562
void store_data_long(uint offset, u32 val)
Definition: decode.c:471
void X86EMU_exec(void)
Definition: decode.c:92
u32 fetch_data_long_abs(uint segment, uint offset)
Definition: decode.c:405
u32 * decode_rm_long_register(int reg)
Definition: decode.c:650
void store_data_word(uint offset, u16 val)
Definition: decode.c:449
static unsigned int decode_sib_si(int scale, int index)
Definition: decode.c:738
static void x86emu_intr_handle(void)
Definition: decode.c:48
u32 fetch_data_long(uint offset)
Definition: decode.c:343
u32 fetch_long_imm(void)
Definition: decode.c:221
unsigned int uint
Definition: types.h:44
void x86emu_dump_regs(void)
Definition: debug.c:364
#define printf(x...)
Definition: debug.h:47
void x86emu_end_instr(void)
#define SAVE_IP_CS(x, y)
Definition: debug.h:138
#define DB(x)
Definition: debug.h:197
void x86emu_check_data_access(uint s, uint o)
#define CHECK_DATA_ACCESS()
Definition: debug.h:65
#define CHECK_IP_FETCH()
Definition: debug.h:62
#define INC_DECODED_INST_LEN(x)
Definition: debug.h:135
void x86emu_check_ip_access(void)
#define DECODE_PRINTF(x)
Definition: debug.h:136
#define DECODE_PRINTF2(x, y)
Definition: debug.h:137
static size_t offset
Definition: flashconsole.c:16
void(* x86emu_optab[256])(u8)
Definition: ops.c:5224
u16 mem_access_word(int addr)
Definition: prim_ops.c:2381
void push_word(u16 w)
Definition: prim_ops.c:2394
#define F_TF
Definition: regs.h:198
#define INTR_HALTED
Definition: regs.h:260
#define SYSMODE_SEG_DS_SS
Definition: regs.h:222
#define SYSMODE_SEGMASK
Definition: regs.h:240
#define SYSMODE_SEGOVR_GS
Definition: regs.h:227
#define INTR_SYNCH
Definition: regs.h:258
#define M
Definition: regs.h:327
#define F_IF
Definition: regs.h:199
#define SYSMODE_SEGOVR_ES
Definition: regs.h:225
#define SYSMODE_SEGOVR_DS
Definition: regs.h:224
#define SYSMODE_SEGOVR_SS
Definition: regs.h:228
#define SYSMODE_SEGOVR_CS
Definition: regs.h:223
#define SYSMODE_PREFIX_ADDR
Definition: regs.h:232
#define SYSMODE_SEGOVR_FS
Definition: regs.h:226
#define CLEAR_FLAG(flag)
Definition: regs.h:205
#define ACCESS_FLAG(flag)
Definition: regs.h:206
uintptr_t base
Definition: uart.c:17
#define NULL
Definition: stddef.h:19
uint32_t u32
Definition: stdint.h:51
uint16_t u16
Definition: stdint.h:48
int8_t s8
Definition: stdint.h:44
int16_t s16
Definition: stdint.h:47
uint8_t u8
Definition: stdint.h:45
int32_t s32
Definition: stdint.h:50
u8 val
Definition: sys.c:300
#define HALT_SYS()
Definition: x86emu.h:160
X86EMU_intrFuncs _X86EMU_intrTab[256]
Definition: sys.c:57
#define _INLINE
Definition: x86emui.h:52