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