diff options
author | Ingo Molnar <mingo@elte.hu> | 2008-01-30 07:30:11 -0500 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2008-01-30 07:30:11 -0500 |
commit | 3d0d14f983b55a570b976976284df4c434af3223 (patch) | |
tree | 864f11c0ce5ee1e15acdd196018b79d0d0e2685d /arch/x86/math-emu/get_address.c | |
parent | a4ec1effce83796209a0258602b0cf50026d86f2 (diff) |
x86: lindent arch/i386/math-emu
lindent these files:
errors lines of code errors/KLOC
arch/x86/math-emu/ 2236 9424 237.2
arch/x86/math-emu/ 128 8706 14.7
no other changes. No code changed:
text data bss dec hex filename
5589802 612739 3833856 10036397 9924ad vmlinux.before
5589802 612739 3833856 10036397 9924ad vmlinux.after
the intent of this patch is to ease the automated tracking of kernel
code quality - it's just much easier for us to maintain it if every file
in arch/x86 is supposed to be clean.
NOTE: it is a known problem of lindent that it causes some style damage
of its own, but it's a safe tool (well, except for the gcc array range
initializers extension), so we did the bulk of the changes via lindent,
and did the manual fixups in a followup patch.
the resulting math-emu code has been tested by Thomas Gleixner on a real
386 DX CPU as well, and it works fine.
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Diffstat (limited to 'arch/x86/math-emu/get_address.c')
-rw-r--r-- | arch/x86/math-emu/get_address.c | 650 |
1 files changed, 308 insertions, 342 deletions
diff --git a/arch/x86/math-emu/get_address.c b/arch/x86/math-emu/get_address.c index 2e2c51a8bd3a..d701e2b39e44 100644 --- a/arch/x86/math-emu/get_address.c +++ b/arch/x86/math-emu/get_address.c | |||
@@ -17,7 +17,6 @@ | |||
17 | | other processes using the emulator while swapping is in progress. | | 17 | | other processes using the emulator while swapping is in progress. | |
18 | +---------------------------------------------------------------------------*/ | 18 | +---------------------------------------------------------------------------*/ |
19 | 19 | ||
20 | |||
21 | #include <linux/stddef.h> | 20 | #include <linux/stddef.h> |
22 | 21 | ||
23 | #include <asm/uaccess.h> | 22 | #include <asm/uaccess.h> |
@@ -27,31 +26,30 @@ | |||
27 | #include "exception.h" | 26 | #include "exception.h" |
28 | #include "fpu_emu.h" | 27 | #include "fpu_emu.h" |
29 | 28 | ||
30 | |||
31 | #define FPU_WRITE_BIT 0x10 | 29 | #define FPU_WRITE_BIT 0x10 |
32 | 30 | ||
33 | static int reg_offset[] = { | 31 | static int reg_offset[] = { |
34 | offsetof(struct info,___eax), | 32 | offsetof(struct info, ___eax), |
35 | offsetof(struct info,___ecx), | 33 | offsetof(struct info, ___ecx), |
36 | offsetof(struct info,___edx), | 34 | offsetof(struct info, ___edx), |
37 | offsetof(struct info,___ebx), | 35 | offsetof(struct info, ___ebx), |
38 | offsetof(struct info,___esp), | 36 | offsetof(struct info, ___esp), |
39 | offsetof(struct info,___ebp), | 37 | offsetof(struct info, ___ebp), |
40 | offsetof(struct info,___esi), | 38 | offsetof(struct info, ___esi), |
41 | offsetof(struct info,___edi) | 39 | offsetof(struct info, ___edi) |
42 | }; | 40 | }; |
43 | 41 | ||
44 | #define REG_(x) (*(long *)(reg_offset[(x)]+(u_char *) FPU_info)) | 42 | #define REG_(x) (*(long *)(reg_offset[(x)]+(u_char *) FPU_info)) |
45 | 43 | ||
46 | static int reg_offset_vm86[] = { | 44 | static int reg_offset_vm86[] = { |
47 | offsetof(struct info,___cs), | 45 | offsetof(struct info, ___cs), |
48 | offsetof(struct info,___vm86_ds), | 46 | offsetof(struct info, ___vm86_ds), |
49 | offsetof(struct info,___vm86_es), | 47 | offsetof(struct info, ___vm86_es), |
50 | offsetof(struct info,___vm86_fs), | 48 | offsetof(struct info, ___vm86_fs), |
51 | offsetof(struct info,___vm86_gs), | 49 | offsetof(struct info, ___vm86_gs), |
52 | offsetof(struct info,___ss), | 50 | offsetof(struct info, ___ss), |
53 | offsetof(struct info,___vm86_ds) | 51 | offsetof(struct info, ___vm86_ds) |
54 | }; | 52 | }; |
55 | 53 | ||
56 | #define VM86_REG_(x) (*(unsigned short *) \ | 54 | #define VM86_REG_(x) (*(unsigned short *) \ |
57 | (reg_offset_vm86[((unsigned)x)]+(u_char *) FPU_info)) | 55 | (reg_offset_vm86[((unsigned)x)]+(u_char *) FPU_info)) |
@@ -60,158 +58,141 @@ static int reg_offset_vm86[] = { | |||
60 | #define ___GS ___ds | 58 | #define ___GS ___ds |
61 | 59 | ||
62 | static int reg_offset_pm[] = { | 60 | static int reg_offset_pm[] = { |
63 | offsetof(struct info,___cs), | 61 | offsetof(struct info, ___cs), |
64 | offsetof(struct info,___ds), | 62 | offsetof(struct info, ___ds), |
65 | offsetof(struct info,___es), | 63 | offsetof(struct info, ___es), |
66 | offsetof(struct info,___fs), | 64 | offsetof(struct info, ___fs), |
67 | offsetof(struct info,___GS), | 65 | offsetof(struct info, ___GS), |
68 | offsetof(struct info,___ss), | 66 | offsetof(struct info, ___ss), |
69 | offsetof(struct info,___ds) | 67 | offsetof(struct info, ___ds) |
70 | }; | 68 | }; |
71 | 69 | ||
72 | #define PM_REG_(x) (*(unsigned short *) \ | 70 | #define PM_REG_(x) (*(unsigned short *) \ |
73 | (reg_offset_pm[((unsigned)x)]+(u_char *) FPU_info)) | 71 | (reg_offset_pm[((unsigned)x)]+(u_char *) FPU_info)) |
74 | 72 | ||
75 | |||
76 | /* Decode the SIB byte. This function assumes mod != 0 */ | 73 | /* Decode the SIB byte. This function assumes mod != 0 */ |
77 | static int sib(int mod, unsigned long *fpu_eip) | 74 | static int sib(int mod, unsigned long *fpu_eip) |
78 | { | 75 | { |
79 | u_char ss,index,base; | 76 | u_char ss, index, base; |
80 | long offset; | 77 | long offset; |
81 | 78 | ||
82 | RE_ENTRANT_CHECK_OFF; | 79 | RE_ENTRANT_CHECK_OFF; |
83 | FPU_code_access_ok(1); | 80 | FPU_code_access_ok(1); |
84 | FPU_get_user(base, (u_char __user *) (*fpu_eip)); /* The SIB byte */ | 81 | FPU_get_user(base, (u_char __user *) (*fpu_eip)); /* The SIB byte */ |
85 | RE_ENTRANT_CHECK_ON; | 82 | RE_ENTRANT_CHECK_ON; |
86 | (*fpu_eip)++; | 83 | (*fpu_eip)++; |
87 | ss = base >> 6; | 84 | ss = base >> 6; |
88 | index = (base >> 3) & 7; | 85 | index = (base >> 3) & 7; |
89 | base &= 7; | 86 | base &= 7; |
90 | 87 | ||
91 | if ((mod == 0) && (base == 5)) | 88 | if ((mod == 0) && (base == 5)) |
92 | offset = 0; /* No base register */ | 89 | offset = 0; /* No base register */ |
93 | else | 90 | else |
94 | offset = REG_(base); | 91 | offset = REG_(base); |
95 | 92 | ||
96 | if (index == 4) | 93 | if (index == 4) { |
97 | { | 94 | /* No index register */ |
98 | /* No index register */ | 95 | /* A non-zero ss is illegal */ |
99 | /* A non-zero ss is illegal */ | 96 | if (ss) |
100 | if ( ss ) | 97 | EXCEPTION(EX_Invalid); |
101 | EXCEPTION(EX_Invalid); | 98 | } else { |
102 | } | 99 | offset += (REG_(index)) << ss; |
103 | else | 100 | } |
104 | { | 101 | |
105 | offset += (REG_(index)) << ss; | 102 | if (mod == 1) { |
106 | } | 103 | /* 8 bit signed displacement */ |
107 | 104 | long displacement; | |
108 | if (mod == 1) | 105 | RE_ENTRANT_CHECK_OFF; |
109 | { | 106 | FPU_code_access_ok(1); |
110 | /* 8 bit signed displacement */ | 107 | FPU_get_user(displacement, (signed char __user *)(*fpu_eip)); |
111 | long displacement; | 108 | offset += displacement; |
112 | RE_ENTRANT_CHECK_OFF; | 109 | RE_ENTRANT_CHECK_ON; |
113 | FPU_code_access_ok(1); | 110 | (*fpu_eip)++; |
114 | FPU_get_user(displacement, (signed char __user *) (*fpu_eip)); | 111 | } else if (mod == 2 || base == 5) { /* The second condition also has mod==0 */ |
115 | offset += displacement; | 112 | /* 32 bit displacement */ |
116 | RE_ENTRANT_CHECK_ON; | 113 | long displacement; |
117 | (*fpu_eip)++; | 114 | RE_ENTRANT_CHECK_OFF; |
118 | } | 115 | FPU_code_access_ok(4); |
119 | else if (mod == 2 || base == 5) /* The second condition also has mod==0 */ | 116 | FPU_get_user(displacement, (long __user *)(*fpu_eip)); |
120 | { | 117 | offset += displacement; |
121 | /* 32 bit displacement */ | 118 | RE_ENTRANT_CHECK_ON; |
122 | long displacement; | 119 | (*fpu_eip) += 4; |
123 | RE_ENTRANT_CHECK_OFF; | 120 | } |
124 | FPU_code_access_ok(4); | ||
125 | FPU_get_user(displacement, (long __user *) (*fpu_eip)); | ||
126 | offset += displacement; | ||
127 | RE_ENTRANT_CHECK_ON; | ||
128 | (*fpu_eip) += 4; | ||
129 | } | ||
130 | |||
131 | return offset; | ||
132 | } | ||
133 | 121 | ||
122 | return offset; | ||
123 | } | ||
134 | 124 | ||
135 | static unsigned long vm86_segment(u_char segment, | 125 | static unsigned long vm86_segment(u_char segment, struct address *addr) |
136 | struct address *addr) | ||
137 | { | 126 | { |
138 | segment--; | 127 | segment--; |
139 | #ifdef PARANOID | 128 | #ifdef PARANOID |
140 | if ( segment > PREFIX_SS_ ) | 129 | if (segment > PREFIX_SS_) { |
141 | { | 130 | EXCEPTION(EX_INTERNAL | 0x130); |
142 | EXCEPTION(EX_INTERNAL|0x130); | 131 | math_abort(FPU_info, SIGSEGV); |
143 | math_abort(FPU_info,SIGSEGV); | 132 | } |
144 | } | ||
145 | #endif /* PARANOID */ | 133 | #endif /* PARANOID */ |
146 | addr->selector = VM86_REG_(segment); | 134 | addr->selector = VM86_REG_(segment); |
147 | return (unsigned long)VM86_REG_(segment) << 4; | 135 | return (unsigned long)VM86_REG_(segment) << 4; |
148 | } | 136 | } |
149 | 137 | ||
150 | |||
151 | /* This should work for 16 and 32 bit protected mode. */ | 138 | /* This should work for 16 and 32 bit protected mode. */ |
152 | static long pm_address(u_char FPU_modrm, u_char segment, | 139 | static long pm_address(u_char FPU_modrm, u_char segment, |
153 | struct address *addr, long offset) | 140 | struct address *addr, long offset) |
154 | { | 141 | { |
155 | struct desc_struct descriptor; | 142 | struct desc_struct descriptor; |
156 | unsigned long base_address, limit, address, seg_top; | 143 | unsigned long base_address, limit, address, seg_top; |
157 | 144 | ||
158 | segment--; | 145 | segment--; |
159 | 146 | ||
160 | #ifdef PARANOID | 147 | #ifdef PARANOID |
161 | /* segment is unsigned, so this also detects if segment was 0: */ | 148 | /* segment is unsigned, so this also detects if segment was 0: */ |
162 | if ( segment > PREFIX_SS_ ) | 149 | if (segment > PREFIX_SS_) { |
163 | { | 150 | EXCEPTION(EX_INTERNAL | 0x132); |
164 | EXCEPTION(EX_INTERNAL|0x132); | 151 | math_abort(FPU_info, SIGSEGV); |
165 | math_abort(FPU_info,SIGSEGV); | 152 | } |
166 | } | ||
167 | #endif /* PARANOID */ | 153 | #endif /* PARANOID */ |
168 | 154 | ||
169 | switch ( segment ) | 155 | switch (segment) { |
170 | { | 156 | /* gs isn't used by the kernel, so it still has its |
171 | /* gs isn't used by the kernel, so it still has its | 157 | user-space value. */ |
172 | user-space value. */ | 158 | case PREFIX_GS_ - 1: |
173 | case PREFIX_GS_-1: | 159 | /* N.B. - movl %seg, mem is a 2 byte write regardless of prefix */ |
174 | /* N.B. - movl %seg, mem is a 2 byte write regardless of prefix */ | 160 | savesegment(gs, addr->selector); |
175 | savesegment(gs, addr->selector); | 161 | break; |
176 | break; | 162 | default: |
177 | default: | 163 | addr->selector = PM_REG_(segment); |
178 | addr->selector = PM_REG_(segment); | ||
179 | } | ||
180 | |||
181 | descriptor = LDT_DESCRIPTOR(PM_REG_(segment)); | ||
182 | base_address = SEG_BASE_ADDR(descriptor); | ||
183 | address = base_address + offset; | ||
184 | limit = base_address | ||
185 | + (SEG_LIMIT(descriptor)+1) * SEG_GRANULARITY(descriptor) - 1; | ||
186 | if ( limit < base_address ) limit = 0xffffffff; | ||
187 | |||
188 | if ( SEG_EXPAND_DOWN(descriptor) ) | ||
189 | { | ||
190 | if ( SEG_G_BIT(descriptor) ) | ||
191 | seg_top = 0xffffffff; | ||
192 | else | ||
193 | { | ||
194 | seg_top = base_address + (1 << 20); | ||
195 | if ( seg_top < base_address ) seg_top = 0xffffffff; | ||
196 | } | 164 | } |
197 | access_limit = | ||
198 | (address <= limit) || (address >= seg_top) ? 0 : | ||
199 | ((seg_top-address) >= 255 ? 255 : seg_top-address); | ||
200 | } | ||
201 | else | ||
202 | { | ||
203 | access_limit = | ||
204 | (address > limit) || (address < base_address) ? 0 : | ||
205 | ((limit-address) >= 254 ? 255 : limit-address+1); | ||
206 | } | ||
207 | if ( SEG_EXECUTE_ONLY(descriptor) || | ||
208 | (!SEG_WRITE_PERM(descriptor) && (FPU_modrm & FPU_WRITE_BIT)) ) | ||
209 | { | ||
210 | access_limit = 0; | ||
211 | } | ||
212 | return address; | ||
213 | } | ||
214 | 165 | ||
166 | descriptor = LDT_DESCRIPTOR(PM_REG_(segment)); | ||
167 | base_address = SEG_BASE_ADDR(descriptor); | ||
168 | address = base_address + offset; | ||
169 | limit = base_address | ||
170 | + (SEG_LIMIT(descriptor) + 1) * SEG_GRANULARITY(descriptor) - 1; | ||
171 | if (limit < base_address) | ||
172 | limit = 0xffffffff; | ||
173 | |||
174 | if (SEG_EXPAND_DOWN(descriptor)) { | ||
175 | if (SEG_G_BIT(descriptor)) | ||
176 | seg_top = 0xffffffff; | ||
177 | else { | ||
178 | seg_top = base_address + (1 << 20); | ||
179 | if (seg_top < base_address) | ||
180 | seg_top = 0xffffffff; | ||
181 | } | ||
182 | access_limit = | ||
183 | (address <= limit) || (address >= seg_top) ? 0 : | ||
184 | ((seg_top - address) >= 255 ? 255 : seg_top - address); | ||
185 | } else { | ||
186 | access_limit = | ||
187 | (address > limit) || (address < base_address) ? 0 : | ||
188 | ((limit - address) >= 254 ? 255 : limit - address + 1); | ||
189 | } | ||
190 | if (SEG_EXECUTE_ONLY(descriptor) || | ||
191 | (!SEG_WRITE_PERM(descriptor) && (FPU_modrm & FPU_WRITE_BIT))) { | ||
192 | access_limit = 0; | ||
193 | } | ||
194 | return address; | ||
195 | } | ||
215 | 196 | ||
216 | /* | 197 | /* |
217 | MOD R/M byte: MOD == 3 has a special use for the FPU | 198 | MOD R/M byte: MOD == 3 has a special use for the FPU |
@@ -221,7 +202,6 @@ static long pm_address(u_char FPU_modrm, u_char segment, | |||
221 | ..... ......... ......... | 202 | ..... ......... ......... |
222 | MOD OPCODE(2) R/M | 203 | MOD OPCODE(2) R/M |
223 | 204 | ||
224 | |||
225 | SIB byte | 205 | SIB byte |
226 | 206 | ||
227 | 7 6 5 4 3 2 1 0 | 207 | 7 6 5 4 3 2 1 0 |
@@ -231,208 +211,194 @@ static long pm_address(u_char FPU_modrm, u_char segment, | |||
231 | */ | 211 | */ |
232 | 212 | ||
233 | void __user *FPU_get_address(u_char FPU_modrm, unsigned long *fpu_eip, | 213 | void __user *FPU_get_address(u_char FPU_modrm, unsigned long *fpu_eip, |
234 | struct address *addr, | 214 | struct address *addr, fpu_addr_modes addr_modes) |
235 | fpu_addr_modes addr_modes) | 215 | { |
216 | u_char mod; | ||
217 | unsigned rm = FPU_modrm & 7; | ||
218 | long *cpu_reg_ptr; | ||
219 | int address = 0; /* Initialized just to stop compiler warnings. */ | ||
220 | |||
221 | /* Memory accessed via the cs selector is write protected | ||
222 | in `non-segmented' 32 bit protected mode. */ | ||
223 | if (!addr_modes.default_mode && (FPU_modrm & FPU_WRITE_BIT) | ||
224 | && (addr_modes.override.segment == PREFIX_CS_)) { | ||
225 | math_abort(FPU_info, SIGSEGV); | ||
226 | } | ||
227 | |||
228 | addr->selector = FPU_DS; /* Default, for 32 bit non-segmented mode. */ | ||
229 | |||
230 | mod = (FPU_modrm >> 6) & 3; | ||
231 | |||
232 | if (rm == 4 && mod != 3) { | ||
233 | address = sib(mod, fpu_eip); | ||
234 | } else { | ||
235 | cpu_reg_ptr = ®_(rm); | ||
236 | switch (mod) { | ||
237 | case 0: | ||
238 | if (rm == 5) { | ||
239 | /* Special case: disp32 */ | ||
240 | RE_ENTRANT_CHECK_OFF; | ||
241 | FPU_code_access_ok(4); | ||
242 | FPU_get_user(address, | ||
243 | (unsigned long __user | ||
244 | *)(*fpu_eip)); | ||
245 | (*fpu_eip) += 4; | ||
246 | RE_ENTRANT_CHECK_ON; | ||
247 | addr->offset = address; | ||
248 | return (void __user *)address; | ||
249 | } else { | ||
250 | address = *cpu_reg_ptr; /* Just return the contents | ||
251 | of the cpu register */ | ||
252 | addr->offset = address; | ||
253 | return (void __user *)address; | ||
254 | } | ||
255 | case 1: | ||
256 | /* 8 bit signed displacement */ | ||
257 | RE_ENTRANT_CHECK_OFF; | ||
258 | FPU_code_access_ok(1); | ||
259 | FPU_get_user(address, (signed char __user *)(*fpu_eip)); | ||
260 | RE_ENTRANT_CHECK_ON; | ||
261 | (*fpu_eip)++; | ||
262 | break; | ||
263 | case 2: | ||
264 | /* 32 bit displacement */ | ||
265 | RE_ENTRANT_CHECK_OFF; | ||
266 | FPU_code_access_ok(4); | ||
267 | FPU_get_user(address, (long __user *)(*fpu_eip)); | ||
268 | (*fpu_eip) += 4; | ||
269 | RE_ENTRANT_CHECK_ON; | ||
270 | break; | ||
271 | case 3: | ||
272 | /* Not legal for the FPU */ | ||
273 | EXCEPTION(EX_Invalid); | ||
274 | } | ||
275 | address += *cpu_reg_ptr; | ||
276 | } | ||
277 | |||
278 | addr->offset = address; | ||
279 | |||
280 | switch (addr_modes.default_mode) { | ||
281 | case 0: | ||
282 | break; | ||
283 | case VM86: | ||
284 | address += vm86_segment(addr_modes.override.segment, addr); | ||
285 | break; | ||
286 | case PM16: | ||
287 | case SEG32: | ||
288 | address = pm_address(FPU_modrm, addr_modes.override.segment, | ||
289 | addr, address); | ||
290 | break; | ||
291 | default: | ||
292 | EXCEPTION(EX_INTERNAL | 0x133); | ||
293 | } | ||
294 | |||
295 | return (void __user *)address; | ||
296 | } | ||
297 | |||
298 | void __user *FPU_get_address_16(u_char FPU_modrm, unsigned long *fpu_eip, | ||
299 | struct address *addr, fpu_addr_modes addr_modes) | ||
236 | { | 300 | { |
237 | u_char mod; | 301 | u_char mod; |
238 | unsigned rm = FPU_modrm & 7; | 302 | unsigned rm = FPU_modrm & 7; |
239 | long *cpu_reg_ptr; | 303 | int address = 0; /* Default used for mod == 0 */ |
240 | int address = 0; /* Initialized just to stop compiler warnings. */ | 304 | |
241 | 305 | /* Memory accessed via the cs selector is write protected | |
242 | /* Memory accessed via the cs selector is write protected | 306 | in `non-segmented' 32 bit protected mode. */ |
243 | in `non-segmented' 32 bit protected mode. */ | 307 | if (!addr_modes.default_mode && (FPU_modrm & FPU_WRITE_BIT) |
244 | if ( !addr_modes.default_mode && (FPU_modrm & FPU_WRITE_BIT) | 308 | && (addr_modes.override.segment == PREFIX_CS_)) { |
245 | && (addr_modes.override.segment == PREFIX_CS_) ) | 309 | math_abort(FPU_info, SIGSEGV); |
246 | { | 310 | } |
247 | math_abort(FPU_info,SIGSEGV); | 311 | |
248 | } | 312 | addr->selector = FPU_DS; /* Default, for 32 bit non-segmented mode. */ |
249 | 313 | ||
250 | addr->selector = FPU_DS; /* Default, for 32 bit non-segmented mode. */ | 314 | mod = (FPU_modrm >> 6) & 3; |
251 | 315 | ||
252 | mod = (FPU_modrm >> 6) & 3; | 316 | switch (mod) { |
253 | |||
254 | if (rm == 4 && mod != 3) | ||
255 | { | ||
256 | address = sib(mod, fpu_eip); | ||
257 | } | ||
258 | else | ||
259 | { | ||
260 | cpu_reg_ptr = & REG_(rm); | ||
261 | switch (mod) | ||
262 | { | ||
263 | case 0: | 317 | case 0: |
264 | if (rm == 5) | 318 | if (rm == 6) { |
265 | { | 319 | /* Special case: disp16 */ |
266 | /* Special case: disp32 */ | 320 | RE_ENTRANT_CHECK_OFF; |
267 | RE_ENTRANT_CHECK_OFF; | 321 | FPU_code_access_ok(2); |
268 | FPU_code_access_ok(4); | 322 | FPU_get_user(address, |
269 | FPU_get_user(address, (unsigned long __user *) (*fpu_eip)); | 323 | (unsigned short __user *)(*fpu_eip)); |
270 | (*fpu_eip) += 4; | 324 | (*fpu_eip) += 2; |
271 | RE_ENTRANT_CHECK_ON; | 325 | RE_ENTRANT_CHECK_ON; |
272 | addr->offset = address; | 326 | goto add_segment; |
273 | return (void __user *) address; | 327 | } |
274 | } | 328 | break; |
275 | else | ||
276 | { | ||
277 | address = *cpu_reg_ptr; /* Just return the contents | ||
278 | of the cpu register */ | ||
279 | addr->offset = address; | ||
280 | return (void __user *) address; | ||
281 | } | ||
282 | case 1: | 329 | case 1: |
283 | /* 8 bit signed displacement */ | 330 | /* 8 bit signed displacement */ |
284 | RE_ENTRANT_CHECK_OFF; | 331 | RE_ENTRANT_CHECK_OFF; |
285 | FPU_code_access_ok(1); | 332 | FPU_code_access_ok(1); |
286 | FPU_get_user(address, (signed char __user *) (*fpu_eip)); | 333 | FPU_get_user(address, (signed char __user *)(*fpu_eip)); |
287 | RE_ENTRANT_CHECK_ON; | 334 | RE_ENTRANT_CHECK_ON; |
288 | (*fpu_eip)++; | 335 | (*fpu_eip)++; |
289 | break; | 336 | break; |
290 | case 2: | 337 | case 2: |
291 | /* 32 bit displacement */ | 338 | /* 16 bit displacement */ |
292 | RE_ENTRANT_CHECK_OFF; | 339 | RE_ENTRANT_CHECK_OFF; |
293 | FPU_code_access_ok(4); | 340 | FPU_code_access_ok(2); |
294 | FPU_get_user(address, (long __user *) (*fpu_eip)); | 341 | FPU_get_user(address, (unsigned short __user *)(*fpu_eip)); |
295 | (*fpu_eip) += 4; | 342 | (*fpu_eip) += 2; |
296 | RE_ENTRANT_CHECK_ON; | 343 | RE_ENTRANT_CHECK_ON; |
297 | break; | 344 | break; |
298 | case 3: | 345 | case 3: |
299 | /* Not legal for the FPU */ | 346 | /* Not legal for the FPU */ |
300 | EXCEPTION(EX_Invalid); | 347 | EXCEPTION(EX_Invalid); |
348 | break; | ||
349 | } | ||
350 | switch (rm) { | ||
351 | case 0: | ||
352 | address += FPU_info->___ebx + FPU_info->___esi; | ||
353 | break; | ||
354 | case 1: | ||
355 | address += FPU_info->___ebx + FPU_info->___edi; | ||
356 | break; | ||
357 | case 2: | ||
358 | address += FPU_info->___ebp + FPU_info->___esi; | ||
359 | if (addr_modes.override.segment == PREFIX_DEFAULT) | ||
360 | addr_modes.override.segment = PREFIX_SS_; | ||
361 | break; | ||
362 | case 3: | ||
363 | address += FPU_info->___ebp + FPU_info->___edi; | ||
364 | if (addr_modes.override.segment == PREFIX_DEFAULT) | ||
365 | addr_modes.override.segment = PREFIX_SS_; | ||
366 | break; | ||
367 | case 4: | ||
368 | address += FPU_info->___esi; | ||
369 | break; | ||
370 | case 5: | ||
371 | address += FPU_info->___edi; | ||
372 | break; | ||
373 | case 6: | ||
374 | address += FPU_info->___ebp; | ||
375 | if (addr_modes.override.segment == PREFIX_DEFAULT) | ||
376 | addr_modes.override.segment = PREFIX_SS_; | ||
377 | break; | ||
378 | case 7: | ||
379 | address += FPU_info->___ebx; | ||
380 | break; | ||
301 | } | 381 | } |
302 | address += *cpu_reg_ptr; | ||
303 | } | ||
304 | |||
305 | addr->offset = address; | ||
306 | |||
307 | switch ( addr_modes.default_mode ) | ||
308 | { | ||
309 | case 0: | ||
310 | break; | ||
311 | case VM86: | ||
312 | address += vm86_segment(addr_modes.override.segment, addr); | ||
313 | break; | ||
314 | case PM16: | ||
315 | case SEG32: | ||
316 | address = pm_address(FPU_modrm, addr_modes.override.segment, | ||
317 | addr, address); | ||
318 | break; | ||
319 | default: | ||
320 | EXCEPTION(EX_INTERNAL|0x133); | ||
321 | } | ||
322 | |||
323 | return (void __user *)address; | ||
324 | } | ||
325 | 382 | ||
383 | add_segment: | ||
384 | address &= 0xffff; | ||
326 | 385 | ||
327 | void __user *FPU_get_address_16(u_char FPU_modrm, unsigned long *fpu_eip, | 386 | addr->offset = address; |
328 | struct address *addr, | 387 | |
329 | fpu_addr_modes addr_modes) | 388 | switch (addr_modes.default_mode) { |
330 | { | 389 | case 0: |
331 | u_char mod; | 390 | break; |
332 | unsigned rm = FPU_modrm & 7; | 391 | case VM86: |
333 | int address = 0; /* Default used for mod == 0 */ | 392 | address += vm86_segment(addr_modes.override.segment, addr); |
334 | 393 | break; | |
335 | /* Memory accessed via the cs selector is write protected | 394 | case PM16: |
336 | in `non-segmented' 32 bit protected mode. */ | 395 | case SEG32: |
337 | if ( !addr_modes.default_mode && (FPU_modrm & FPU_WRITE_BIT) | 396 | address = pm_address(FPU_modrm, addr_modes.override.segment, |
338 | && (addr_modes.override.segment == PREFIX_CS_) ) | 397 | addr, address); |
339 | { | 398 | break; |
340 | math_abort(FPU_info,SIGSEGV); | 399 | default: |
341 | } | 400 | EXCEPTION(EX_INTERNAL | 0x131); |
342 | |||
343 | addr->selector = FPU_DS; /* Default, for 32 bit non-segmented mode. */ | ||
344 | |||
345 | mod = (FPU_modrm >> 6) & 3; | ||
346 | |||
347 | switch (mod) | ||
348 | { | ||
349 | case 0: | ||
350 | if (rm == 6) | ||
351 | { | ||
352 | /* Special case: disp16 */ | ||
353 | RE_ENTRANT_CHECK_OFF; | ||
354 | FPU_code_access_ok(2); | ||
355 | FPU_get_user(address, (unsigned short __user *) (*fpu_eip)); | ||
356 | (*fpu_eip) += 2; | ||
357 | RE_ENTRANT_CHECK_ON; | ||
358 | goto add_segment; | ||
359 | } | 401 | } |
360 | break; | 402 | |
361 | case 1: | 403 | return (void __user *)address; |
362 | /* 8 bit signed displacement */ | ||
363 | RE_ENTRANT_CHECK_OFF; | ||
364 | FPU_code_access_ok(1); | ||
365 | FPU_get_user(address, (signed char __user *) (*fpu_eip)); | ||
366 | RE_ENTRANT_CHECK_ON; | ||
367 | (*fpu_eip)++; | ||
368 | break; | ||
369 | case 2: | ||
370 | /* 16 bit displacement */ | ||
371 | RE_ENTRANT_CHECK_OFF; | ||
372 | FPU_code_access_ok(2); | ||
373 | FPU_get_user(address, (unsigned short __user *) (*fpu_eip)); | ||
374 | (*fpu_eip) += 2; | ||
375 | RE_ENTRANT_CHECK_ON; | ||
376 | break; | ||
377 | case 3: | ||
378 | /* Not legal for the FPU */ | ||
379 | EXCEPTION(EX_Invalid); | ||
380 | break; | ||
381 | } | ||
382 | switch ( rm ) | ||
383 | { | ||
384 | case 0: | ||
385 | address += FPU_info->___ebx + FPU_info->___esi; | ||
386 | break; | ||
387 | case 1: | ||
388 | address += FPU_info->___ebx + FPU_info->___edi; | ||
389 | break; | ||
390 | case 2: | ||
391 | address += FPU_info->___ebp + FPU_info->___esi; | ||
392 | if ( addr_modes.override.segment == PREFIX_DEFAULT ) | ||
393 | addr_modes.override.segment = PREFIX_SS_; | ||
394 | break; | ||
395 | case 3: | ||
396 | address += FPU_info->___ebp + FPU_info->___edi; | ||
397 | if ( addr_modes.override.segment == PREFIX_DEFAULT ) | ||
398 | addr_modes.override.segment = PREFIX_SS_; | ||
399 | break; | ||
400 | case 4: | ||
401 | address += FPU_info->___esi; | ||
402 | break; | ||
403 | case 5: | ||
404 | address += FPU_info->___edi; | ||
405 | break; | ||
406 | case 6: | ||
407 | address += FPU_info->___ebp; | ||
408 | if ( addr_modes.override.segment == PREFIX_DEFAULT ) | ||
409 | addr_modes.override.segment = PREFIX_SS_; | ||
410 | break; | ||
411 | case 7: | ||
412 | address += FPU_info->___ebx; | ||
413 | break; | ||
414 | } | ||
415 | |||
416 | add_segment: | ||
417 | address &= 0xffff; | ||
418 | |||
419 | addr->offset = address; | ||
420 | |||
421 | switch ( addr_modes.default_mode ) | ||
422 | { | ||
423 | case 0: | ||
424 | break; | ||
425 | case VM86: | ||
426 | address += vm86_segment(addr_modes.override.segment, addr); | ||
427 | break; | ||
428 | case PM16: | ||
429 | case SEG32: | ||
430 | address = pm_address(FPU_modrm, addr_modes.override.segment, | ||
431 | addr, address); | ||
432 | break; | ||
433 | default: | ||
434 | EXCEPTION(EX_INTERNAL|0x131); | ||
435 | } | ||
436 | |||
437 | return (void __user *)address ; | ||
438 | } | 404 | } |