Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/arch/x86/math-emu/fpu_entry.c
10818 views
1
/*---------------------------------------------------------------------------+
2
| fpu_entry.c |
3
| |
4
| The entry functions for wm-FPU-emu |
5
| |
6
| Copyright (C) 1992,1993,1994,1996,1997 |
7
| W. Metzenthen, 22 Parker St, Ormond, Vic 3163, Australia |
8
| E-mail [email protected] |
9
| |
10
| See the files "README" and "COPYING" for further copyright and warranty |
11
| information. |
12
| |
13
+---------------------------------------------------------------------------*/
14
15
/*---------------------------------------------------------------------------+
16
| Note: |
17
| The file contains code which accesses user memory. |
18
| Emulator static data may change when user memory is accessed, due to |
19
| other processes using the emulator while swapping is in progress. |
20
+---------------------------------------------------------------------------*/
21
22
/*---------------------------------------------------------------------------+
23
| math_emulate(), restore_i387_soft() and save_i387_soft() are the only |
24
| entry points for wm-FPU-emu. |
25
+---------------------------------------------------------------------------*/
26
27
#include <linux/signal.h>
28
#include <linux/regset.h>
29
30
#include <asm/uaccess.h>
31
#include <asm/desc.h>
32
#include <asm/user.h>
33
#include <asm/i387.h>
34
35
#include "fpu_system.h"
36
#include "fpu_emu.h"
37
#include "exception.h"
38
#include "control_w.h"
39
#include "status_w.h"
40
41
#define __BAD__ FPU_illegal /* Illegal on an 80486, causes SIGILL */
42
43
#ifndef NO_UNDOC_CODE /* Un-documented FPU op-codes supported by default. */
44
45
/* WARNING: These codes are not documented by Intel in their 80486 manual
46
and may not work on FPU clones or later Intel FPUs. */
47
48
/* Changes to support the un-doc codes provided by Linus Torvalds. */
49
50
#define _d9_d8_ fstp_i /* unofficial code (19) */
51
#define _dc_d0_ fcom_st /* unofficial code (14) */
52
#define _dc_d8_ fcompst /* unofficial code (1c) */
53
#define _dd_c8_ fxch_i /* unofficial code (0d) */
54
#define _de_d0_ fcompst /* unofficial code (16) */
55
#define _df_c0_ ffreep /* unofficial code (07) ffree + pop */
56
#define _df_c8_ fxch_i /* unofficial code (0f) */
57
#define _df_d0_ fstp_i /* unofficial code (17) */
58
#define _df_d8_ fstp_i /* unofficial code (1f) */
59
60
static FUNC const st_instr_table[64] = {
61
fadd__, fld_i_, __BAD__, __BAD__, fadd_i, ffree_, faddp_, _df_c0_,
62
fmul__, fxch_i, __BAD__, __BAD__, fmul_i, _dd_c8_, fmulp_, _df_c8_,
63
fcom_st, fp_nop, __BAD__, __BAD__, _dc_d0_, fst_i_, _de_d0_, _df_d0_,
64
fcompst, _d9_d8_, __BAD__, __BAD__, _dc_d8_, fstp_i, fcompp, _df_d8_,
65
fsub__, FPU_etc, __BAD__, finit_, fsubri, fucom_, fsubrp, fstsw_,
66
fsubr_, fconst, fucompp, __BAD__, fsub_i, fucomp, fsubp_, __BAD__,
67
fdiv__, FPU_triga, __BAD__, __BAD__, fdivri, __BAD__, fdivrp, __BAD__,
68
fdivr_, FPU_trigb, __BAD__, __BAD__, fdiv_i, __BAD__, fdivp_, __BAD__,
69
};
70
71
#else /* Support only documented FPU op-codes */
72
73
static FUNC const st_instr_table[64] = {
74
fadd__, fld_i_, __BAD__, __BAD__, fadd_i, ffree_, faddp_, __BAD__,
75
fmul__, fxch_i, __BAD__, __BAD__, fmul_i, __BAD__, fmulp_, __BAD__,
76
fcom_st, fp_nop, __BAD__, __BAD__, __BAD__, fst_i_, __BAD__, __BAD__,
77
fcompst, __BAD__, __BAD__, __BAD__, __BAD__, fstp_i, fcompp, __BAD__,
78
fsub__, FPU_etc, __BAD__, finit_, fsubri, fucom_, fsubrp, fstsw_,
79
fsubr_, fconst, fucompp, __BAD__, fsub_i, fucomp, fsubp_, __BAD__,
80
fdiv__, FPU_triga, __BAD__, __BAD__, fdivri, __BAD__, fdivrp, __BAD__,
81
fdivr_, FPU_trigb, __BAD__, __BAD__, fdiv_i, __BAD__, fdivp_, __BAD__,
82
};
83
84
#endif /* NO_UNDOC_CODE */
85
86
#define _NONE_ 0 /* Take no special action */
87
#define _REG0_ 1 /* Need to check for not empty st(0) */
88
#define _REGI_ 2 /* Need to check for not empty st(0) and st(rm) */
89
#define _REGi_ 0 /* Uses st(rm) */
90
#define _PUSH_ 3 /* Need to check for space to push onto stack */
91
#define _null_ 4 /* Function illegal or not implemented */
92
#define _REGIi 5 /* Uses st(0) and st(rm), result to st(rm) */
93
#define _REGIp 6 /* Uses st(0) and st(rm), result to st(rm) then pop */
94
#define _REGIc 0 /* Compare st(0) and st(rm) */
95
#define _REGIn 0 /* Uses st(0) and st(rm), but handle checks later */
96
97
#ifndef NO_UNDOC_CODE
98
99
/* Un-documented FPU op-codes supported by default. (see above) */
100
101
static u_char const type_table[64] = {
102
_REGI_, _NONE_, _null_, _null_, _REGIi, _REGi_, _REGIp, _REGi_,
103
_REGI_, _REGIn, _null_, _null_, _REGIi, _REGI_, _REGIp, _REGI_,
104
_REGIc, _NONE_, _null_, _null_, _REGIc, _REG0_, _REGIc, _REG0_,
105
_REGIc, _REG0_, _null_, _null_, _REGIc, _REG0_, _REGIc, _REG0_,
106
_REGI_, _NONE_, _null_, _NONE_, _REGIi, _REGIc, _REGIp, _NONE_,
107
_REGI_, _NONE_, _REGIc, _null_, _REGIi, _REGIc, _REGIp, _null_,
108
_REGI_, _NONE_, _null_, _null_, _REGIi, _null_, _REGIp, _null_,
109
_REGI_, _NONE_, _null_, _null_, _REGIi, _null_, _REGIp, _null_
110
};
111
112
#else /* Support only documented FPU op-codes */
113
114
static u_char const type_table[64] = {
115
_REGI_, _NONE_, _null_, _null_, _REGIi, _REGi_, _REGIp, _null_,
116
_REGI_, _REGIn, _null_, _null_, _REGIi, _null_, _REGIp, _null_,
117
_REGIc, _NONE_, _null_, _null_, _null_, _REG0_, _null_, _null_,
118
_REGIc, _null_, _null_, _null_, _null_, _REG0_, _REGIc, _null_,
119
_REGI_, _NONE_, _null_, _NONE_, _REGIi, _REGIc, _REGIp, _NONE_,
120
_REGI_, _NONE_, _REGIc, _null_, _REGIi, _REGIc, _REGIp, _null_,
121
_REGI_, _NONE_, _null_, _null_, _REGIi, _null_, _REGIp, _null_,
122
_REGI_, _NONE_, _null_, _null_, _REGIi, _null_, _REGIp, _null_
123
};
124
125
#endif /* NO_UNDOC_CODE */
126
127
#ifdef RE_ENTRANT_CHECKING
128
u_char emulating = 0;
129
#endif /* RE_ENTRANT_CHECKING */
130
131
static int valid_prefix(u_char *Byte, u_char __user ** fpu_eip,
132
overrides * override);
133
134
void math_emulate(struct math_emu_info *info)
135
{
136
u_char FPU_modrm, byte1;
137
unsigned short code;
138
fpu_addr_modes addr_modes;
139
int unmasked;
140
FPU_REG loaded_data;
141
FPU_REG *st0_ptr;
142
u_char loaded_tag, st0_tag;
143
void __user *data_address;
144
struct address data_sel_off;
145
struct address entry_sel_off;
146
unsigned long code_base = 0;
147
unsigned long code_limit = 0; /* Initialized to stop compiler warnings */
148
struct desc_struct code_descriptor;
149
150
if (!used_math()) {
151
if (init_fpu(current)) {
152
do_group_exit(SIGKILL);
153
return;
154
}
155
}
156
157
#ifdef RE_ENTRANT_CHECKING
158
if (emulating) {
159
printk("ERROR: wm-FPU-emu is not RE-ENTRANT!\n");
160
}
161
RE_ENTRANT_CHECK_ON;
162
#endif /* RE_ENTRANT_CHECKING */
163
164
FPU_info = info;
165
166
FPU_ORIG_EIP = FPU_EIP;
167
168
if ((FPU_EFLAGS & 0x00020000) != 0) {
169
/* Virtual 8086 mode */
170
addr_modes.default_mode = VM86;
171
FPU_EIP += code_base = FPU_CS << 4;
172
code_limit = code_base + 0xffff; /* Assumes code_base <= 0xffff0000 */
173
} else if (FPU_CS == __USER_CS && FPU_DS == __USER_DS) {
174
addr_modes.default_mode = 0;
175
} else if (FPU_CS == __KERNEL_CS) {
176
printk("math_emulate: %04x:%08lx\n", FPU_CS, FPU_EIP);
177
panic("Math emulation needed in kernel");
178
} else {
179
180
if ((FPU_CS & 4) != 4) { /* Must be in the LDT */
181
/* Can only handle segmented addressing via the LDT
182
for now, and it must be 16 bit */
183
printk("FPU emulator: Unsupported addressing mode\n");
184
math_abort(FPU_info, SIGILL);
185
}
186
187
code_descriptor = LDT_DESCRIPTOR(FPU_CS);
188
if (SEG_D_SIZE(code_descriptor)) {
189
/* The above test may be wrong, the book is not clear */
190
/* Segmented 32 bit protected mode */
191
addr_modes.default_mode = SEG32;
192
} else {
193
/* 16 bit protected mode */
194
addr_modes.default_mode = PM16;
195
}
196
FPU_EIP += code_base = SEG_BASE_ADDR(code_descriptor);
197
code_limit = code_base
198
+ (SEG_LIMIT(code_descriptor) +
199
1) * SEG_GRANULARITY(code_descriptor)
200
- 1;
201
if (code_limit < code_base)
202
code_limit = 0xffffffff;
203
}
204
205
FPU_lookahead = !(FPU_EFLAGS & X86_EFLAGS_TF);
206
207
if (!valid_prefix(&byte1, (u_char __user **) & FPU_EIP,
208
&addr_modes.override)) {
209
RE_ENTRANT_CHECK_OFF;
210
printk
211
("FPU emulator: Unknown prefix byte 0x%02x, probably due to\n"
212
"FPU emulator: self-modifying code! (emulation impossible)\n",
213
byte1);
214
RE_ENTRANT_CHECK_ON;
215
EXCEPTION(EX_INTERNAL | 0x126);
216
math_abort(FPU_info, SIGILL);
217
}
218
219
do_another_FPU_instruction:
220
221
no_ip_update = 0;
222
223
FPU_EIP++; /* We have fetched the prefix and first code bytes. */
224
225
if (addr_modes.default_mode) {
226
/* This checks for the minimum instruction bytes.
227
We also need to check any extra (address mode) code access. */
228
if (FPU_EIP > code_limit)
229
math_abort(FPU_info, SIGSEGV);
230
}
231
232
if ((byte1 & 0xf8) != 0xd8) {
233
if (byte1 == FWAIT_OPCODE) {
234
if (partial_status & SW_Summary)
235
goto do_the_FPU_interrupt;
236
else
237
goto FPU_fwait_done;
238
}
239
#ifdef PARANOID
240
EXCEPTION(EX_INTERNAL | 0x128);
241
math_abort(FPU_info, SIGILL);
242
#endif /* PARANOID */
243
}
244
245
RE_ENTRANT_CHECK_OFF;
246
FPU_code_access_ok(1);
247
FPU_get_user(FPU_modrm, (u_char __user *) FPU_EIP);
248
RE_ENTRANT_CHECK_ON;
249
FPU_EIP++;
250
251
if (partial_status & SW_Summary) {
252
/* Ignore the error for now if the current instruction is a no-wait
253
control instruction */
254
/* The 80486 manual contradicts itself on this topic,
255
but a real 80486 uses the following instructions:
256
fninit, fnstenv, fnsave, fnstsw, fnstenv, fnclex.
257
*/
258
code = (FPU_modrm << 8) | byte1;
259
if (!((((code & 0xf803) == 0xe003) || /* fnclex, fninit, fnstsw */
260
(((code & 0x3003) == 0x3001) && /* fnsave, fnstcw, fnstenv,
261
fnstsw */
262
((code & 0xc000) != 0xc000))))) {
263
/*
264
* We need to simulate the action of the kernel to FPU
265
* interrupts here.
266
*/
267
do_the_FPU_interrupt:
268
269
FPU_EIP = FPU_ORIG_EIP; /* Point to current FPU instruction. */
270
271
RE_ENTRANT_CHECK_OFF;
272
current->thread.trap_no = 16;
273
current->thread.error_code = 0;
274
send_sig(SIGFPE, current, 1);
275
return;
276
}
277
}
278
279
entry_sel_off.offset = FPU_ORIG_EIP;
280
entry_sel_off.selector = FPU_CS;
281
entry_sel_off.opcode = (byte1 << 8) | FPU_modrm;
282
entry_sel_off.empty = 0;
283
284
FPU_rm = FPU_modrm & 7;
285
286
if (FPU_modrm < 0300) {
287
/* All of these instructions use the mod/rm byte to get a data address */
288
289
if ((addr_modes.default_mode & SIXTEEN)
290
^ (addr_modes.override.address_size == ADDR_SIZE_PREFIX))
291
data_address =
292
FPU_get_address_16(FPU_modrm, &FPU_EIP,
293
&data_sel_off, addr_modes);
294
else
295
data_address =
296
FPU_get_address(FPU_modrm, &FPU_EIP, &data_sel_off,
297
addr_modes);
298
299
if (addr_modes.default_mode) {
300
if (FPU_EIP - 1 > code_limit)
301
math_abort(FPU_info, SIGSEGV);
302
}
303
304
if (!(byte1 & 1)) {
305
unsigned short status1 = partial_status;
306
307
st0_ptr = &st(0);
308
st0_tag = FPU_gettag0();
309
310
/* Stack underflow has priority */
311
if (NOT_EMPTY_ST0) {
312
if (addr_modes.default_mode & PROTECTED) {
313
/* This table works for 16 and 32 bit protected mode */
314
if (access_limit <
315
data_sizes_16[(byte1 >> 1) & 3])
316
math_abort(FPU_info, SIGSEGV);
317
}
318
319
unmasked = 0; /* Do this here to stop compiler warnings. */
320
switch ((byte1 >> 1) & 3) {
321
case 0:
322
unmasked =
323
FPU_load_single((float __user *)
324
data_address,
325
&loaded_data);
326
loaded_tag = unmasked & 0xff;
327
unmasked &= ~0xff;
328
break;
329
case 1:
330
loaded_tag =
331
FPU_load_int32((long __user *)
332
data_address,
333
&loaded_data);
334
break;
335
case 2:
336
unmasked =
337
FPU_load_double((double __user *)
338
data_address,
339
&loaded_data);
340
loaded_tag = unmasked & 0xff;
341
unmasked &= ~0xff;
342
break;
343
case 3:
344
default: /* Used here to suppress gcc warnings. */
345
loaded_tag =
346
FPU_load_int16((short __user *)
347
data_address,
348
&loaded_data);
349
break;
350
}
351
352
/* No more access to user memory, it is safe
353
to use static data now */
354
355
/* NaN operands have the next priority. */
356
/* We have to delay looking at st(0) until after
357
loading the data, because that data might contain an SNaN */
358
if (((st0_tag == TAG_Special) && isNaN(st0_ptr))
359
|| ((loaded_tag == TAG_Special)
360
&& isNaN(&loaded_data))) {
361
/* Restore the status word; we might have loaded a
362
denormal. */
363
partial_status = status1;
364
if ((FPU_modrm & 0x30) == 0x10) {
365
/* fcom or fcomp */
366
EXCEPTION(EX_Invalid);
367
setcc(SW_C3 | SW_C2 | SW_C0);
368
if ((FPU_modrm & 0x08)
369
&& (control_word &
370
CW_Invalid))
371
FPU_pop(); /* fcomp, masked, so we pop. */
372
} else {
373
if (loaded_tag == TAG_Special)
374
loaded_tag =
375
FPU_Special
376
(&loaded_data);
377
#ifdef PECULIAR_486
378
/* This is not really needed, but gives behaviour
379
identical to an 80486 */
380
if ((FPU_modrm & 0x28) == 0x20)
381
/* fdiv or fsub */
382
real_2op_NaN
383
(&loaded_data,
384
loaded_tag, 0,
385
&loaded_data);
386
else
387
#endif /* PECULIAR_486 */
388
/* fadd, fdivr, fmul, or fsubr */
389
real_2op_NaN
390
(&loaded_data,
391
loaded_tag, 0,
392
st0_ptr);
393
}
394
goto reg_mem_instr_done;
395
}
396
397
if (unmasked && !((FPU_modrm & 0x30) == 0x10)) {
398
/* Is not a comparison instruction. */
399
if ((FPU_modrm & 0x38) == 0x38) {
400
/* fdivr */
401
if ((st0_tag == TAG_Zero) &&
402
((loaded_tag == TAG_Valid)
403
|| (loaded_tag ==
404
TAG_Special
405
&&
406
isdenormal
407
(&loaded_data)))) {
408
if (FPU_divide_by_zero
409
(0,
410
getsign
411
(&loaded_data))
412
< 0) {
413
/* We use the fact here that the unmasked
414
exception in the loaded data was for a
415
denormal operand */
416
/* Restore the state of the denormal op bit */
417
partial_status
418
&=
419
~SW_Denorm_Op;
420
partial_status
421
|=
422
status1 &
423
SW_Denorm_Op;
424
} else
425
setsign(st0_ptr,
426
getsign
427
(&loaded_data));
428
}
429
}
430
goto reg_mem_instr_done;
431
}
432
433
switch ((FPU_modrm >> 3) & 7) {
434
case 0: /* fadd */
435
clear_C1();
436
FPU_add(&loaded_data, loaded_tag, 0,
437
control_word);
438
break;
439
case 1: /* fmul */
440
clear_C1();
441
FPU_mul(&loaded_data, loaded_tag, 0,
442
control_word);
443
break;
444
case 2: /* fcom */
445
FPU_compare_st_data(&loaded_data,
446
loaded_tag);
447
break;
448
case 3: /* fcomp */
449
if (!FPU_compare_st_data
450
(&loaded_data, loaded_tag)
451
&& !unmasked)
452
FPU_pop();
453
break;
454
case 4: /* fsub */
455
clear_C1();
456
FPU_sub(LOADED | loaded_tag,
457
(int)&loaded_data,
458
control_word);
459
break;
460
case 5: /* fsubr */
461
clear_C1();
462
FPU_sub(REV | LOADED | loaded_tag,
463
(int)&loaded_data,
464
control_word);
465
break;
466
case 6: /* fdiv */
467
clear_C1();
468
FPU_div(LOADED | loaded_tag,
469
(int)&loaded_data,
470
control_word);
471
break;
472
case 7: /* fdivr */
473
clear_C1();
474
if (st0_tag == TAG_Zero)
475
partial_status = status1; /* Undo any denorm tag,
476
zero-divide has priority. */
477
FPU_div(REV | LOADED | loaded_tag,
478
(int)&loaded_data,
479
control_word);
480
break;
481
}
482
} else {
483
if ((FPU_modrm & 0x30) == 0x10) {
484
/* The instruction is fcom or fcomp */
485
EXCEPTION(EX_StackUnder);
486
setcc(SW_C3 | SW_C2 | SW_C0);
487
if ((FPU_modrm & 0x08)
488
&& (control_word & CW_Invalid))
489
FPU_pop(); /* fcomp */
490
} else
491
FPU_stack_underflow();
492
}
493
reg_mem_instr_done:
494
operand_address = data_sel_off;
495
} else {
496
if (!(no_ip_update =
497
FPU_load_store(((FPU_modrm & 0x38) | (byte1 & 6))
498
>> 1, addr_modes, data_address))) {
499
operand_address = data_sel_off;
500
}
501
}
502
503
} else {
504
/* None of these instructions access user memory */
505
u_char instr_index = (FPU_modrm & 0x38) | (byte1 & 7);
506
507
#ifdef PECULIAR_486
508
/* This is supposed to be undefined, but a real 80486 seems
509
to do this: */
510
operand_address.offset = 0;
511
operand_address.selector = FPU_DS;
512
#endif /* PECULIAR_486 */
513
514
st0_ptr = &st(0);
515
st0_tag = FPU_gettag0();
516
switch (type_table[(int)instr_index]) {
517
case _NONE_: /* also _REGIc: _REGIn */
518
break;
519
case _REG0_:
520
if (!NOT_EMPTY_ST0) {
521
FPU_stack_underflow();
522
goto FPU_instruction_done;
523
}
524
break;
525
case _REGIi:
526
if (!NOT_EMPTY_ST0 || !NOT_EMPTY(FPU_rm)) {
527
FPU_stack_underflow_i(FPU_rm);
528
goto FPU_instruction_done;
529
}
530
break;
531
case _REGIp:
532
if (!NOT_EMPTY_ST0 || !NOT_EMPTY(FPU_rm)) {
533
FPU_stack_underflow_pop(FPU_rm);
534
goto FPU_instruction_done;
535
}
536
break;
537
case _REGI_:
538
if (!NOT_EMPTY_ST0 || !NOT_EMPTY(FPU_rm)) {
539
FPU_stack_underflow();
540
goto FPU_instruction_done;
541
}
542
break;
543
case _PUSH_: /* Only used by the fld st(i) instruction */
544
break;
545
case _null_:
546
FPU_illegal();
547
goto FPU_instruction_done;
548
default:
549
EXCEPTION(EX_INTERNAL | 0x111);
550
goto FPU_instruction_done;
551
}
552
(*st_instr_table[(int)instr_index]) ();
553
554
FPU_instruction_done:
555
;
556
}
557
558
if (!no_ip_update)
559
instruction_address = entry_sel_off;
560
561
FPU_fwait_done:
562
563
#ifdef DEBUG
564
RE_ENTRANT_CHECK_OFF;
565
FPU_printall();
566
RE_ENTRANT_CHECK_ON;
567
#endif /* DEBUG */
568
569
if (FPU_lookahead && !need_resched()) {
570
FPU_ORIG_EIP = FPU_EIP - code_base;
571
if (valid_prefix(&byte1, (u_char __user **) & FPU_EIP,
572
&addr_modes.override))
573
goto do_another_FPU_instruction;
574
}
575
576
if (addr_modes.default_mode)
577
FPU_EIP -= code_base;
578
579
RE_ENTRANT_CHECK_OFF;
580
}
581
582
/* Support for prefix bytes is not yet complete. To properly handle
583
all prefix bytes, further changes are needed in the emulator code
584
which accesses user address space. Access to separate segments is
585
important for msdos emulation. */
586
static int valid_prefix(u_char *Byte, u_char __user **fpu_eip,
587
overrides * override)
588
{
589
u_char byte;
590
u_char __user *ip = *fpu_eip;
591
592
*override = (overrides) {
593
0, 0, PREFIX_DEFAULT}; /* defaults */
594
595
RE_ENTRANT_CHECK_OFF;
596
FPU_code_access_ok(1);
597
FPU_get_user(byte, ip);
598
RE_ENTRANT_CHECK_ON;
599
600
while (1) {
601
switch (byte) {
602
case ADDR_SIZE_PREFIX:
603
override->address_size = ADDR_SIZE_PREFIX;
604
goto do_next_byte;
605
606
case OP_SIZE_PREFIX:
607
override->operand_size = OP_SIZE_PREFIX;
608
goto do_next_byte;
609
610
case PREFIX_CS:
611
override->segment = PREFIX_CS_;
612
goto do_next_byte;
613
case PREFIX_ES:
614
override->segment = PREFIX_ES_;
615
goto do_next_byte;
616
case PREFIX_SS:
617
override->segment = PREFIX_SS_;
618
goto do_next_byte;
619
case PREFIX_FS:
620
override->segment = PREFIX_FS_;
621
goto do_next_byte;
622
case PREFIX_GS:
623
override->segment = PREFIX_GS_;
624
goto do_next_byte;
625
case PREFIX_DS:
626
override->segment = PREFIX_DS_;
627
goto do_next_byte;
628
629
/* lock is not a valid prefix for FPU instructions,
630
let the cpu handle it to generate a SIGILL. */
631
/* case PREFIX_LOCK: */
632
633
/* rep.. prefixes have no meaning for FPU instructions */
634
case PREFIX_REPE:
635
case PREFIX_REPNE:
636
637
do_next_byte:
638
ip++;
639
RE_ENTRANT_CHECK_OFF;
640
FPU_code_access_ok(1);
641
FPU_get_user(byte, ip);
642
RE_ENTRANT_CHECK_ON;
643
break;
644
case FWAIT_OPCODE:
645
*Byte = byte;
646
return 1;
647
default:
648
if ((byte & 0xf8) == 0xd8) {
649
*Byte = byte;
650
*fpu_eip = ip;
651
return 1;
652
} else {
653
/* Not a valid sequence of prefix bytes followed by
654
an FPU instruction. */
655
*Byte = byte; /* Needed for error message. */
656
return 0;
657
}
658
}
659
}
660
}
661
662
void math_abort(struct math_emu_info *info, unsigned int signal)
663
{
664
FPU_EIP = FPU_ORIG_EIP;
665
current->thread.trap_no = 16;
666
current->thread.error_code = 0;
667
send_sig(signal, current, 1);
668
RE_ENTRANT_CHECK_OFF;
669
__asm__("movl %0,%%esp ; ret": :"g"(((long)info) - 4));
670
#ifdef PARANOID
671
printk("ERROR: wm-FPU-emu math_abort failed!\n");
672
#endif /* PARANOID */
673
}
674
675
#define S387 ((struct i387_soft_struct *)s387)
676
#define sstatus_word() \
677
((S387->swd & ~SW_Top & 0xffff) | ((S387->ftop << SW_Top_Shift) & SW_Top))
678
679
int fpregs_soft_set(struct task_struct *target,
680
const struct user_regset *regset,
681
unsigned int pos, unsigned int count,
682
const void *kbuf, const void __user *ubuf)
683
{
684
struct i387_soft_struct *s387 = &target->thread.fpu.state->soft;
685
void *space = s387->st_space;
686
int ret;
687
int offset, other, i, tags, regnr, tag, newtop;
688
689
RE_ENTRANT_CHECK_OFF;
690
ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, s387, 0,
691
offsetof(struct i387_soft_struct, st_space));
692
RE_ENTRANT_CHECK_ON;
693
694
if (ret)
695
return ret;
696
697
S387->ftop = (S387->swd >> SW_Top_Shift) & 7;
698
offset = (S387->ftop & 7) * 10;
699
other = 80 - offset;
700
701
RE_ENTRANT_CHECK_OFF;
702
703
/* Copy all registers in stack order. */
704
ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
705
space + offset, 0, other);
706
if (!ret && offset)
707
ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
708
space, 0, offset);
709
710
RE_ENTRANT_CHECK_ON;
711
712
/* The tags may need to be corrected now. */
713
tags = S387->twd;
714
newtop = S387->ftop;
715
for (i = 0; i < 8; i++) {
716
regnr = (i + newtop) & 7;
717
if (((tags >> ((regnr & 7) * 2)) & 3) != TAG_Empty) {
718
/* The loaded data over-rides all other cases. */
719
tag =
720
FPU_tagof((FPU_REG *) ((u_char *) S387->st_space +
721
10 * regnr));
722
tags &= ~(3 << (regnr * 2));
723
tags |= (tag & 3) << (regnr * 2);
724
}
725
}
726
S387->twd = tags;
727
728
return ret;
729
}
730
731
int fpregs_soft_get(struct task_struct *target,
732
const struct user_regset *regset,
733
unsigned int pos, unsigned int count,
734
void *kbuf, void __user *ubuf)
735
{
736
struct i387_soft_struct *s387 = &target->thread.fpu.state->soft;
737
const void *space = s387->st_space;
738
int ret;
739
int offset = (S387->ftop & 7) * 10, other = 80 - offset;
740
741
RE_ENTRANT_CHECK_OFF;
742
743
#ifdef PECULIAR_486
744
S387->cwd &= ~0xe080;
745
/* An 80486 sets nearly all of the reserved bits to 1. */
746
S387->cwd |= 0xffff0040;
747
S387->swd = sstatus_word() | 0xffff0000;
748
S387->twd |= 0xffff0000;
749
S387->fcs &= ~0xf8000000;
750
S387->fos |= 0xffff0000;
751
#endif /* PECULIAR_486 */
752
753
ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, s387, 0,
754
offsetof(struct i387_soft_struct, st_space));
755
756
/* Copy all registers in stack order. */
757
if (!ret)
758
ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
759
space + offset, 0, other);
760
if (!ret)
761
ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
762
space, 0, offset);
763
764
RE_ENTRANT_CHECK_ON;
765
766
return ret;
767
}
768
769