|
|
1.1 root 1: /*---------------------------------------------------------------------------+
2: | get_address.c |
3: | |
4: | Get the effective address from an FPU instruction. |
5: | |
6: | Copyright (C) 1992 W. Metzenthen, 22 Parker St, Ormond, Vic 3163, |
7: | Australia. E-mail [email protected] |
8: | |
9: | |
10: +---------------------------------------------------------------------------*/
11:
12: /*---------------------------------------------------------------------------+
13: | Note: |
14: | The file contains code which accesses user memory. |
15: | Emulator static data may change when user memory is accessed, due to |
16: | other processes using the emulator while swapping is in progress. |
17: +---------------------------------------------------------------------------*/
18:
19:
20: #include <linux/stddef.h>
21: #include <asm/segment.h>
22:
23: #include "fpu_system.h"
24: #include "exception.h"
25: #include "fpu_emu.h"
26:
27: #ifdef COHERENT
28: #include <sys/reg.h>
29:
30: #define REG_(x) (*(long *)(reg_offset[(x)]+(char *) emCurrent))
31:
32: static unsigned char reg_offset[] = {
33: (1 + EAX) * sizeof(long),
34: (1 + ECX) * sizeof(long),
35: (1 + EDX) * sizeof(long),
36: (1 + EBX) * sizeof(long),
37: (1 + UESP) * sizeof(long),
38: (1 + EBP) * sizeof(long),
39: (1 + ESI) * sizeof(long),
40: (1 + EDI) * sizeof(long)
41: #else
42: #define REG_(x) (*(long *)(reg_offset[(x)]+(char *) FPU_info))
43:
44: static int reg_offset[] = {
45: offsetof(struct info,___eax),
46: offsetof(struct info,___ecx),
47: offsetof(struct info,___edx),
48: offsetof(struct info,___ebx),
49: offsetof(struct info,___esp),
50: offsetof(struct info,___ebp),
51: offsetof(struct info,___esi),
52: offsetof(struct info,___edi)
53: #endif
54: };
55:
56:
57: void *FPU_data_address;
58:
59:
60: /* Decode the SIB byte. This function assumes mod != 0 */
61: static void *sib(int mod)
62: {
63: unsigned char ss,index,base;
64: long offset;
65:
66: RE_ENTRANT_CHECK_OFF
67: base = get_fs_byte((char *) FPU_EIP); /* The SIB byte */
68: RE_ENTRANT_CHECK_ON
69: FPU_EIP++;
70: ss = base >> 6;
71: index = (base >> 3) & 7;
72: base &= 7;
73:
74: if ((mod == 0) && (base == 5))
75: offset = 0; /* No base register */
76: else
77: offset = REG_(base);
78:
79: if (index == 4)
80: {
81: /* No index register */
82: /* A non-zero ss is illegal */
83: if ( ss )
84: EXCEPTION(EX_Invalid);
85: }
86: else
87: {
88: offset += (REG_(index)) << ss;
89: }
90:
91: if (mod == 1)
92: {
93: /* 8 bit signed displacement */
94: RE_ENTRANT_CHECK_OFF
95: offset += (signed char) get_fs_byte((char *) FPU_EIP);
96: RE_ENTRANT_CHECK_ON
97: FPU_EIP++;
98: }
99: else if (mod == 2 || base == 5) /* The second condition also has mod==0 */
100: {
101: /* 32 bit displacment */
102: RE_ENTRANT_CHECK_OFF
103: offset += (signed) get_fs_long((unsigned long *) FPU_EIP);
104: RE_ENTRANT_CHECK_ON
105: FPU_EIP += 4;
106: }
107:
108: return (void *) offset;
109: }
110:
111:
112: /*
113: MOD R/M byte: MOD == 3 has a special use for the FPU
114: SIB byte used iff R/M = 100b
115:
116: 7 6 5 4 3 2 1 0
117: ..... ......... .........
118: MOD OPCODE(2) R/M
119:
120:
121: SIB byte
122:
123: 7 6 5 4 3 2 1 0
124: ..... ......... .........
125: SS INDEX BASE
126:
127: */
128:
129: void get_address(unsigned char FPU_modrm)
130: {
131: unsigned char mod;
132: long *cpu_reg_ptr;
133: int offset;
134:
135: mod = (FPU_modrm >> 6) & 3;
136:
137: if (FPU_rm == 4 && mod != 3)
138: {
139: FPU_data_address = sib(mod);
140: return;
141: }
142: cpu_reg_ptr = & REG_(FPU_rm);
143:
144: switch (mod)
145: {
146: case 0:
147: if (FPU_rm == 5)
148: {
149: /* Special case: disp32 */
150: RE_ENTRANT_CHECK_OFF
151: offset = get_fs_long((unsigned long *) FPU_EIP);
152: RE_ENTRANT_CHECK_ON
153: FPU_EIP += 4;
154: FPU_data_address = (void *) offset;
155: return;
156: }
157: else
158: {
159: FPU_data_address = (void *)*cpu_reg_ptr; /* Just return the contents
160: of the cpu register */
161: return;
162: }
163: case 1:
164: /* 8 bit signed displacement */
165: RE_ENTRANT_CHECK_OFF
166: offset = (signed char) get_fs_byte((char *) FPU_EIP);
167: RE_ENTRANT_CHECK_ON
168: FPU_EIP++;
169: break;
170: case 2:
171: /* 32 bit displacement */
172: RE_ENTRANT_CHECK_OFF
173: offset = (signed) get_fs_long((unsigned long *) FPU_EIP);
174: RE_ENTRANT_CHECK_ON
175: FPU_EIP += 4;
176: break;
177: case 3:
178: /* Not legal for the FPU */
179: EXCEPTION(EX_Invalid);
180: }
181:
182: FPU_data_address = offset + (char *)*cpu_reg_ptr;
183: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.