This source file includes following definitions.
- sib
- mode16_segment
- get_address
- get_address_16
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 #include <linux/stddef.h>
22
23 #include <asm/segment.h>
24
25 #include "fpu_system.h"
26 #include "exception.h"
27 #include "fpu_emu.h"
28
29 static int reg_offset[] = {
30 offsetof(struct info,___eax),
31 offsetof(struct info,___ecx),
32 offsetof(struct info,___edx),
33 offsetof(struct info,___ebx),
34 offsetof(struct info,___esp),
35 offsetof(struct info,___ebp),
36 offsetof(struct info,___esi),
37 offsetof(struct info,___edi)
38 };
39
40 #define REG_(x) (*(long *)(reg_offset[(x)]+(char *) FPU_info))
41
42 static int reg_offset_vm86[] = {
43 offsetof(struct info,___cs),
44 offsetof(struct info,___vm86_ds),
45 offsetof(struct info,___vm86_es),
46 offsetof(struct info,___vm86_fs),
47 offsetof(struct info,___vm86_gs),
48 offsetof(struct info,___ss),
49 offsetof(struct info,___vm86_ds)
50 };
51
52 #define VM86_REG_(x) (*(unsigned short *) \
53 (reg_offset_vm86[((unsigned)x)]+(char *) FPU_info))
54
55 static int reg_offset_p286[] = {
56 offsetof(struct info,___cs),
57 offsetof(struct info,___ds),
58 offsetof(struct info,___es),
59 offsetof(struct info,___fs),
60 offsetof(struct info,___gs),
61 offsetof(struct info,___ss),
62 offsetof(struct info,___ds)
63 };
64
65 #define P286_REG_(x) (*(unsigned short *) \
66 (reg_offset_p286[((unsigned)x)]+(char *) FPU_info))
67
68
69
70 static void *sib(int mod, unsigned long *fpu_eip)
71 {
72 unsigned char ss,index,base;
73 long offset;
74
75 RE_ENTRANT_CHECK_OFF;
76 FPU_code_verify_area(1);
77 base = get_fs_byte((char *) (*fpu_eip));
78 RE_ENTRANT_CHECK_ON;
79 (*fpu_eip)++;
80 ss = base >> 6;
81 index = (base >> 3) & 7;
82 base &= 7;
83
84 if ((mod == 0) && (base == 5))
85 offset = 0;
86 else
87 offset = REG_(base);
88
89 if (index == 4)
90 {
91
92
93 if ( ss )
94 EXCEPTION(EX_Invalid);
95 }
96 else
97 {
98 offset += (REG_(index)) << ss;
99 }
100
101 if (mod == 1)
102 {
103
104 RE_ENTRANT_CHECK_OFF;
105 FPU_code_verify_area(1);
106 offset += (signed char) get_fs_byte((char *) (*fpu_eip));
107 RE_ENTRANT_CHECK_ON;
108 (*fpu_eip)++;
109 }
110 else if (mod == 2 || base == 5)
111 {
112
113 RE_ENTRANT_CHECK_OFF;
114 FPU_code_verify_area(4);
115 offset += (signed) get_fs_long((unsigned long *) (*fpu_eip));
116 RE_ENTRANT_CHECK_ON;
117 (*fpu_eip) += 4;
118 }
119
120 return (void *) offset;
121 }
122
123
124 static unsigned long mode16_segment(fpu_addr_modes addr_modes)
125 {
126 int segment = addr_modes.override.segment - 1;
127
128 #ifdef PARANOID
129 if ( segment > PREFIX_SS_ )
130 {
131 EXCEPTION(EX_INTERNAL|0x130);
132 math_abort(FPU_info,SIGSEGV);
133 }
134 #endif PARANOID
135 if ( addr_modes.vm86 )
136 return (unsigned long)VM86_REG_(segment) << 4;
137 else if ( addr_modes.p286 )
138 return (unsigned long)LDT_BASE_ADDR(P286_REG_(segment));
139 return 0;
140 }
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160 void get_address(unsigned char FPU_modrm, unsigned long *fpu_eip,
161 fpu_addr_modes addr_modes)
162 {
163 unsigned char mod;
164 long *cpu_reg_ptr;
165 int offset = 0;
166
167 #ifndef PECULIAR_486
168
169 FPU_data_selector = FPU_DS;
170 #endif PECULIAR_486
171
172
173
174 #define FPU_WRITE_BIT 0x10
175 if ( !addr_modes.vm86 && (FPU_modrm & FPU_WRITE_BIT)
176 && (addr_modes.override.segment == PREFIX_CS_) )
177 {
178 math_abort(FPU_info,SIGSEGV);
179 }
180
181 mod = (FPU_modrm >> 6) & 3;
182
183 if (FPU_rm == 4 && mod != 3)
184 {
185 FPU_data_address = sib(mod, fpu_eip);
186 return;
187 }
188
189 cpu_reg_ptr = & REG_(FPU_rm);
190 switch (mod)
191 {
192 case 0:
193 if (FPU_rm == 5)
194 {
195
196 RE_ENTRANT_CHECK_OFF;
197 FPU_code_verify_area(4);
198 offset = get_fs_long((unsigned long *) (*fpu_eip));
199 (*fpu_eip) += 4;
200 RE_ENTRANT_CHECK_ON;
201 FPU_data_address = (void *) offset;
202 return;
203 }
204 else
205 {
206 FPU_data_address = (void *)*cpu_reg_ptr;
207
208 return;
209 }
210 case 1:
211
212 RE_ENTRANT_CHECK_OFF;
213 FPU_code_verify_area(1);
214 offset = (signed char) get_fs_byte((char *) (*fpu_eip));
215 RE_ENTRANT_CHECK_ON;
216 (*fpu_eip)++;
217 break;
218 case 2:
219
220 RE_ENTRANT_CHECK_OFF;
221 FPU_code_verify_area(4);
222 offset = (signed) get_fs_long((unsigned long *) (*fpu_eip));
223 (*fpu_eip) += 4;
224 RE_ENTRANT_CHECK_ON;
225 break;
226 case 3:
227
228 EXCEPTION(EX_Invalid);
229 }
230
231 if ( addr_modes.mode16 )
232 {
233 offset += mode16_segment(addr_modes);
234 }
235
236 FPU_data_address = offset + (char *)*cpu_reg_ptr;
237 }
238
239
240 void get_address_16(unsigned char FPU_modrm, unsigned long *fpu_eip,
241 fpu_addr_modes addr_modes)
242 {
243 unsigned char mod;
244 int offset = 0;
245
246 #ifndef PECULIAR_486
247
248 FPU_data_selector = FPU_DS;
249 #endif PECULIAR_486
250
251
252
253 #define FPU_WRITE_BIT 0x10
254 if ( !addr_modes.vm86 && (FPU_modrm & FPU_WRITE_BIT)
255 && (addr_modes.override.segment == PREFIX_CS_) )
256 {
257 math_abort(FPU_info,SIGSEGV);
258 }
259
260 mod = (FPU_modrm >> 6) & 3;
261
262 switch (mod)
263 {
264 case 0:
265 if (FPU_rm == 6)
266 {
267
268 RE_ENTRANT_CHECK_OFF;
269 FPU_code_verify_area(2);
270 offset = (unsigned short)get_fs_word((unsigned short *) (*fpu_eip));
271 (*fpu_eip) += 2;
272 RE_ENTRANT_CHECK_ON;
273 goto add_segment;
274 }
275 break;
276 case 1:
277
278 RE_ENTRANT_CHECK_OFF;
279 FPU_code_verify_area(1);
280 offset = (signed char) get_fs_byte((signed char *) (*fpu_eip));
281 RE_ENTRANT_CHECK_ON;
282 (*fpu_eip)++;
283 break;
284 case 2:
285
286 RE_ENTRANT_CHECK_OFF;
287 FPU_code_verify_area(2);
288 offset = (unsigned) get_fs_word((unsigned short *) (*fpu_eip));
289 (*fpu_eip) += 2;
290 RE_ENTRANT_CHECK_ON;
291 break;
292 case 3:
293
294 EXCEPTION(EX_Invalid);
295 break;
296 }
297 switch ( FPU_rm )
298 {
299 case 0:
300 offset += FPU_info->___ebx + FPU_info->___esi;
301 break;
302 case 1:
303 offset += FPU_info->___ebx + FPU_info->___edi;
304 break;
305 case 2:
306 offset += FPU_info->___ebp + FPU_info->___esi;
307 if ( addr_modes.override.segment == PREFIX_DEFAULT )
308 addr_modes.override.segment = PREFIX_SS_;
309 break;
310 case 3:
311 offset += FPU_info->___ebp + FPU_info->___edi;
312 if ( addr_modes.override.segment == PREFIX_DEFAULT )
313 addr_modes.override.segment = PREFIX_SS_;
314 break;
315 case 4:
316 offset += FPU_info->___esi;
317 break;
318 case 5:
319 offset += FPU_info->___edi;
320 break;
321 case 6:
322 offset += FPU_info->___ebp;
323 if ( addr_modes.override.segment == PREFIX_DEFAULT )
324 addr_modes.override.segment = PREFIX_SS_;
325 break;
326 case 7:
327 offset += FPU_info->___ebx;
328 break;
329 }
330
331 add_segment:
332 offset &= 0xffff;
333
334 if ( addr_modes.mode16 )
335 {
336 offset += mode16_segment(addr_modes);
337 }
338
339 FPU_data_address = (void *)offset ;
340 }