This source file includes following definitions.
- sib
- vm86_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 };
50
51 #define VM86_REG_(x) (*(unsigned short *) \
52 (reg_offset_vm86[((unsigned)x)]+(char *) FPU_info))
53
54
55
56 static void *sib(int mod, unsigned long *fpu_eip)
57 {
58 unsigned char ss,index,base;
59 long offset;
60
61 RE_ENTRANT_CHECK_OFF;
62 FPU_code_verify_area(1);
63 base = get_fs_byte((char *) (*fpu_eip));
64 RE_ENTRANT_CHECK_ON;
65 (*fpu_eip)++;
66 ss = base >> 6;
67 index = (base >> 3) & 7;
68 base &= 7;
69
70 if ((mod == 0) && (base == 5))
71 offset = 0;
72 else
73 offset = REG_(base);
74
75 if (index == 4)
76 {
77
78
79 if ( ss )
80 EXCEPTION(EX_Invalid);
81 }
82 else
83 {
84 offset += (REG_(index)) << ss;
85 }
86
87 if (mod == 1)
88 {
89
90 RE_ENTRANT_CHECK_OFF;
91 FPU_code_verify_area(1);
92 offset += (signed char) get_fs_byte((char *) (*fpu_eip));
93 RE_ENTRANT_CHECK_ON;
94 (*fpu_eip)++;
95 }
96 else if (mod == 2 || base == 5)
97 {
98
99 RE_ENTRANT_CHECK_OFF;
100 FPU_code_verify_area(4);
101 offset += (signed) get_fs_long((unsigned long *) (*fpu_eip));
102 RE_ENTRANT_CHECK_ON;
103 (*fpu_eip) += 4;
104 }
105
106 return (void *) offset;
107 }
108
109
110 static unsigned long vm86_segment(unsigned char segment)
111 {
112 segment--;
113 #ifdef PARANOID
114 if ( segment > PREFIX_SS_ )
115 {
116 EXCEPTION(EX_INTERNAL|0x130);
117 math_abort(FPU_info,SIGSEGV);
118 }
119 #endif PARANOID
120 return (unsigned long)VM86_REG_(segment) << 4;
121 }
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141 void get_address(unsigned char FPU_modrm, unsigned long *fpu_eip,
142 fpu_addr_modes addr_modes)
143 {
144 unsigned char mod;
145 long *cpu_reg_ptr;
146 int offset = 0;
147
148 #ifndef PECULIAR_486
149
150 FPU_data_selector = FPU_DS;
151 #endif PECULIAR_486
152
153
154
155 #define FPU_WRITE_BIT 0x10
156 if ( !addr_modes.vm86 && (FPU_modrm & FPU_WRITE_BIT)
157 && (addr_modes.override.segment == PREFIX_CS_) )
158 {
159 math_abort(FPU_info,SIGSEGV);
160 }
161
162 mod = (FPU_modrm >> 6) & 3;
163
164 if (FPU_rm == 4 && mod != 3)
165 {
166 FPU_data_address = sib(mod, fpu_eip);
167 return;
168 }
169
170 cpu_reg_ptr = & REG_(FPU_rm);
171 switch (mod)
172 {
173 case 0:
174 if (FPU_rm == 5)
175 {
176
177 RE_ENTRANT_CHECK_OFF;
178 FPU_code_verify_area(4);
179 offset = get_fs_long((unsigned long *) (*fpu_eip));
180 (*fpu_eip) += 4;
181 RE_ENTRANT_CHECK_ON;
182 FPU_data_address = (void *) offset;
183 return;
184 }
185 else
186 {
187 FPU_data_address = (void *)*cpu_reg_ptr;
188
189 return;
190 }
191 case 1:
192
193 RE_ENTRANT_CHECK_OFF;
194 FPU_code_verify_area(1);
195 offset = (signed char) get_fs_byte((char *) (*fpu_eip));
196 RE_ENTRANT_CHECK_ON;
197 (*fpu_eip)++;
198 break;
199 case 2:
200
201 RE_ENTRANT_CHECK_OFF;
202 FPU_code_verify_area(4);
203 offset = (signed) get_fs_long((unsigned long *) (*fpu_eip));
204 (*fpu_eip) += 4;
205 RE_ENTRANT_CHECK_ON;
206 break;
207 case 3:
208
209 EXCEPTION(EX_Invalid);
210 }
211
212 if ( addr_modes.vm86 )
213 {
214 offset += vm86_segment(addr_modes.override.segment);
215 }
216
217 FPU_data_address = offset + (char *)*cpu_reg_ptr;
218 }
219
220
221 void get_address_16(unsigned char FPU_modrm, unsigned long *fpu_eip,
222 fpu_addr_modes addr_modes)
223 {
224 unsigned char mod;
225 int offset = 0;
226
227 #ifndef PECULIAR_486
228
229 FPU_data_selector = FPU_DS;
230 #endif PECULIAR_486
231
232
233
234 #define FPU_WRITE_BIT 0x10
235 if ( !addr_modes.vm86 && (FPU_modrm & FPU_WRITE_BIT)
236 && (addr_modes.override.segment == PREFIX_CS_) )
237 {
238 math_abort(FPU_info,SIGSEGV);
239 }
240
241 mod = (FPU_modrm >> 6) & 3;
242
243 switch (mod)
244 {
245 case 0:
246 if (FPU_rm == 6)
247 {
248
249 RE_ENTRANT_CHECK_OFF;
250 FPU_code_verify_area(2);
251 offset = (unsigned short)get_fs_word((unsigned short *) (*fpu_eip));
252 (*fpu_eip) += 2;
253 RE_ENTRANT_CHECK_ON;
254 goto add_segment;
255 }
256 break;
257 case 1:
258
259 RE_ENTRANT_CHECK_OFF;
260 FPU_code_verify_area(1);
261 offset = (signed char) get_fs_byte((signed char *) (*fpu_eip));
262 RE_ENTRANT_CHECK_ON;
263 (*fpu_eip)++;
264 break;
265 case 2:
266
267 RE_ENTRANT_CHECK_OFF;
268 FPU_code_verify_area(2);
269 offset = (unsigned) get_fs_word((unsigned short *) (*fpu_eip));
270 (*fpu_eip) += 2;
271 RE_ENTRANT_CHECK_ON;
272 break;
273 case 3:
274
275 EXCEPTION(EX_Invalid);
276 break;
277 }
278 switch ( FPU_rm )
279 {
280 case 0:
281 offset += FPU_info->___ebx + FPU_info->___esi;
282 break;
283 case 1:
284 offset += FPU_info->___ebx + FPU_info->___edi;
285 break;
286 case 2:
287 offset += FPU_info->___ebp + FPU_info->___esi;
288 break;
289 case 3:
290 offset += FPU_info->___ebp + FPU_info->___edi;
291 break;
292 case 4:
293 offset += FPU_info->___esi;
294 break;
295 case 5:
296 offset += FPU_info->___edi;
297 break;
298 case 6:
299 offset += FPU_info->___ebp;
300 break;
301 case 7:
302 offset += FPU_info->___ebx;
303 break;
304 }
305
306 add_segment:
307 offset &= 0xffff;
308
309 if ( addr_modes.vm86 )
310 {
311 offset += vm86_segment(addr_modes.override.segment);
312 }
313
314 FPU_data_address = (void *)offset ;
315 }
316