1 /*---------------------------------------------------------------------------+
4 | The entry functions for wm-FPU-emu |
6 | Copyright (C) 1992,1993,1994,1996,1997 |
7 | W. Metzenthen, 22 Parker St, Ormond, Vic 3163, Australia |
8 | E-mail billm@suburbia.net |
10 | See the files "README" and "COPYING" for further copyright and warranty |
13 +---------------------------------------------------------------------------*/
15 /*---------------------------------------------------------------------------+
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 +---------------------------------------------------------------------------*/
22 /*---------------------------------------------------------------------------+
23 | math_emulate(), restore_i387_soft() and save_i387_soft() are the only |
24 | entry points for wm-FPU-emu. |
25 +---------------------------------------------------------------------------*/
27 #include <linux/signal.h>
28 #include <linux/regset.h>
30 #include <asm/uaccess.h>
31 #include <asm/traps.h>
34 #include <asm/fpu/api.h>
36 #include "fpu_system.h"
38 #include "exception.h"
39 #include "control_w.h"
42 #define __BAD__ FPU_illegal /* Illegal on an 80486, causes SIGILL */
44 #ifndef NO_UNDOC_CODE /* Un-documented FPU op-codes supported by default. */
46 /* WARNING: These codes are not documented by Intel in their 80486 manual
47 and may not work on FPU clones or later Intel FPUs. */
49 /* Changes to support the un-doc codes provided by Linus Torvalds. */
51 #define _d9_d8_ fstp_i /* unofficial code (19) */
52 #define _dc_d0_ fcom_st /* unofficial code (14) */
53 #define _dc_d8_ fcompst /* unofficial code (1c) */
54 #define _dd_c8_ fxch_i /* unofficial code (0d) */
55 #define _de_d0_ fcompst /* unofficial code (16) */
56 #define _df_c0_ ffreep /* unofficial code (07) ffree + pop */
57 #define _df_c8_ fxch_i /* unofficial code (0f) */
58 #define _df_d0_ fstp_i /* unofficial code (17) */
59 #define _df_d8_ fstp_i /* unofficial code (1f) */
61 static FUNC
const st_instr_table
[64] = {
62 fadd__
, fld_i_
, __BAD__
, __BAD__
, fadd_i
, ffree_
, faddp_
, _df_c0_
,
63 fmul__
, fxch_i
, __BAD__
, __BAD__
, fmul_i
, _dd_c8_
, fmulp_
, _df_c8_
,
64 fcom_st
, fp_nop
, __BAD__
, __BAD__
, _dc_d0_
, fst_i_
, _de_d0_
, _df_d0_
,
65 fcompst
, _d9_d8_
, __BAD__
, __BAD__
, _dc_d8_
, fstp_i
, fcompp
, _df_d8_
,
66 fsub__
, FPU_etc
, __BAD__
, finit_
, fsubri
, fucom_
, fsubrp
, fstsw_
,
67 fsubr_
, fconst
, fucompp
, __BAD__
, fsub_i
, fucomp
, fsubp_
, __BAD__
,
68 fdiv__
, FPU_triga
, __BAD__
, __BAD__
, fdivri
, __BAD__
, fdivrp
, __BAD__
,
69 fdivr_
, FPU_trigb
, __BAD__
, __BAD__
, fdiv_i
, __BAD__
, fdivp_
, __BAD__
,
72 #else /* Support only documented FPU op-codes */
74 static FUNC
const st_instr_table
[64] = {
75 fadd__
, fld_i_
, __BAD__
, __BAD__
, fadd_i
, ffree_
, faddp_
, __BAD__
,
76 fmul__
, fxch_i
, __BAD__
, __BAD__
, fmul_i
, __BAD__
, fmulp_
, __BAD__
,
77 fcom_st
, fp_nop
, __BAD__
, __BAD__
, __BAD__
, fst_i_
, __BAD__
, __BAD__
,
78 fcompst
, __BAD__
, __BAD__
, __BAD__
, __BAD__
, fstp_i
, fcompp
, __BAD__
,
79 fsub__
, FPU_etc
, __BAD__
, finit_
, fsubri
, fucom_
, fsubrp
, fstsw_
,
80 fsubr_
, fconst
, fucompp
, __BAD__
, fsub_i
, fucomp
, fsubp_
, __BAD__
,
81 fdiv__
, FPU_triga
, __BAD__
, __BAD__
, fdivri
, __BAD__
, fdivrp
, __BAD__
,
82 fdivr_
, FPU_trigb
, __BAD__
, __BAD__
, fdiv_i
, __BAD__
, fdivp_
, __BAD__
,
85 #endif /* NO_UNDOC_CODE */
87 #define _NONE_ 0 /* Take no special action */
88 #define _REG0_ 1 /* Need to check for not empty st(0) */
89 #define _REGI_ 2 /* Need to check for not empty st(0) and st(rm) */
90 #define _REGi_ 0 /* Uses st(rm) */
91 #define _PUSH_ 3 /* Need to check for space to push onto stack */
92 #define _null_ 4 /* Function illegal or not implemented */
93 #define _REGIi 5 /* Uses st(0) and st(rm), result to st(rm) */
94 #define _REGIp 6 /* Uses st(0) and st(rm), result to st(rm) then pop */
95 #define _REGIc 0 /* Compare st(0) and st(rm) */
96 #define _REGIn 0 /* Uses st(0) and st(rm), but handle checks later */
100 /* Un-documented FPU op-codes supported by default. (see above) */
102 static u_char
const type_table
[64] = {
103 _REGI_
, _NONE_
, _null_
, _null_
, _REGIi
, _REGi_
, _REGIp
, _REGi_
,
104 _REGI_
, _REGIn
, _null_
, _null_
, _REGIi
, _REGI_
, _REGIp
, _REGI_
,
105 _REGIc
, _NONE_
, _null_
, _null_
, _REGIc
, _REG0_
, _REGIc
, _REG0_
,
106 _REGIc
, _REG0_
, _null_
, _null_
, _REGIc
, _REG0_
, _REGIc
, _REG0_
,
107 _REGI_
, _NONE_
, _null_
, _NONE_
, _REGIi
, _REGIc
, _REGIp
, _NONE_
,
108 _REGI_
, _NONE_
, _REGIc
, _null_
, _REGIi
, _REGIc
, _REGIp
, _null_
,
109 _REGI_
, _NONE_
, _null_
, _null_
, _REGIi
, _null_
, _REGIp
, _null_
,
110 _REGI_
, _NONE_
, _null_
, _null_
, _REGIi
, _null_
, _REGIp
, _null_
113 #else /* Support only documented FPU op-codes */
115 static u_char
const type_table
[64] = {
116 _REGI_
, _NONE_
, _null_
, _null_
, _REGIi
, _REGi_
, _REGIp
, _null_
,
117 _REGI_
, _REGIn
, _null_
, _null_
, _REGIi
, _null_
, _REGIp
, _null_
,
118 _REGIc
, _NONE_
, _null_
, _null_
, _null_
, _REG0_
, _null_
, _null_
,
119 _REGIc
, _null_
, _null_
, _null_
, _null_
, _REG0_
, _REGIc
, _null_
,
120 _REGI_
, _NONE_
, _null_
, _NONE_
, _REGIi
, _REGIc
, _REGIp
, _NONE_
,
121 _REGI_
, _NONE_
, _REGIc
, _null_
, _REGIi
, _REGIc
, _REGIp
, _null_
,
122 _REGI_
, _NONE_
, _null_
, _null_
, _REGIi
, _null_
, _REGIp
, _null_
,
123 _REGI_
, _NONE_
, _null_
, _null_
, _REGIi
, _null_
, _REGIp
, _null_
126 #endif /* NO_UNDOC_CODE */
128 #ifdef RE_ENTRANT_CHECKING
129 u_char emulating
= 0;
130 #endif /* RE_ENTRANT_CHECKING */
132 static int valid_prefix(u_char
*Byte
, u_char __user
** fpu_eip
,
133 overrides
* override
);
135 void math_emulate(struct math_emu_info
*info
)
137 u_char FPU_modrm
, byte1
;
139 fpu_addr_modes addr_modes
;
143 u_char loaded_tag
, st0_tag
;
144 void __user
*data_address
;
145 struct address data_sel_off
;
146 struct address entry_sel_off
;
147 unsigned long code_base
= 0;
148 unsigned long code_limit
= 0; /* Initialized to stop compiler warnings */
149 struct desc_struct code_descriptor
;
150 struct fpu
*fpu
= ¤t
->thread
.fpu
;
152 if (!fpu
->fpstate_active
) {
153 if (fpstate_alloc_init(fpu
)) {
154 do_group_exit(SIGKILL
);
159 #ifdef RE_ENTRANT_CHECKING
161 printk("ERROR: wm-FPU-emu is not RE-ENTRANT!\n");
164 #endif /* RE_ENTRANT_CHECKING */
168 FPU_ORIG_EIP
= FPU_EIP
;
170 if ((FPU_EFLAGS
& 0x00020000) != 0) {
171 /* Virtual 8086 mode */
172 addr_modes
.default_mode
= VM86
;
173 FPU_EIP
+= code_base
= FPU_CS
<< 4;
174 code_limit
= code_base
+ 0xffff; /* Assumes code_base <= 0xffff0000 */
175 } else if (FPU_CS
== __USER_CS
&& FPU_DS
== __USER_DS
) {
176 addr_modes
.default_mode
= 0;
177 } else if (FPU_CS
== __KERNEL_CS
) {
178 printk("math_emulate: %04x:%08lx\n", FPU_CS
, FPU_EIP
);
179 panic("Math emulation needed in kernel");
182 if ((FPU_CS
& 4) != 4) { /* Must be in the LDT */
183 /* Can only handle segmented addressing via the LDT
184 for now, and it must be 16 bit */
185 printk("FPU emulator: Unsupported addressing mode\n");
186 math_abort(FPU_info
, SIGILL
);
189 code_descriptor
= LDT_DESCRIPTOR(FPU_CS
);
190 if (SEG_D_SIZE(code_descriptor
)) {
191 /* The above test may be wrong, the book is not clear */
192 /* Segmented 32 bit protected mode */
193 addr_modes
.default_mode
= SEG32
;
195 /* 16 bit protected mode */
196 addr_modes
.default_mode
= PM16
;
198 FPU_EIP
+= code_base
= SEG_BASE_ADDR(code_descriptor
);
199 code_limit
= code_base
200 + (SEG_LIMIT(code_descriptor
) +
201 1) * SEG_GRANULARITY(code_descriptor
)
203 if (code_limit
< code_base
)
204 code_limit
= 0xffffffff;
207 FPU_lookahead
= !(FPU_EFLAGS
& X86_EFLAGS_TF
);
209 if (!valid_prefix(&byte1
, (u_char __user
**) & FPU_EIP
,
210 &addr_modes
.override
)) {
211 RE_ENTRANT_CHECK_OFF
;
213 ("FPU emulator: Unknown prefix byte 0x%02x, probably due to\n"
214 "FPU emulator: self-modifying code! (emulation impossible)\n",
217 EXCEPTION(EX_INTERNAL
| 0x126);
218 math_abort(FPU_info
, SIGILL
);
221 do_another_FPU_instruction
:
225 FPU_EIP
++; /* We have fetched the prefix and first code bytes. */
227 if (addr_modes
.default_mode
) {
228 /* This checks for the minimum instruction bytes.
229 We also need to check any extra (address mode) code access. */
230 if (FPU_EIP
> code_limit
)
231 math_abort(FPU_info
, SIGSEGV
);
234 if ((byte1
& 0xf8) != 0xd8) {
235 if (byte1
== FWAIT_OPCODE
) {
236 if (partial_status
& SW_Summary
)
237 goto do_the_FPU_interrupt
;
242 EXCEPTION(EX_INTERNAL
| 0x128);
243 math_abort(FPU_info
, SIGILL
);
244 #endif /* PARANOID */
247 RE_ENTRANT_CHECK_OFF
;
248 FPU_code_access_ok(1);
249 FPU_get_user(FPU_modrm
, (u_char __user
*) FPU_EIP
);
253 if (partial_status
& SW_Summary
) {
254 /* Ignore the error for now if the current instruction is a no-wait
255 control instruction */
256 /* The 80486 manual contradicts itself on this topic,
257 but a real 80486 uses the following instructions:
258 fninit, fnstenv, fnsave, fnstsw, fnstenv, fnclex.
260 code
= (FPU_modrm
<< 8) | byte1
;
261 if (!((((code
& 0xf803) == 0xe003) || /* fnclex, fninit, fnstsw */
262 (((code
& 0x3003) == 0x3001) && /* fnsave, fnstcw, fnstenv,
264 ((code
& 0xc000) != 0xc000))))) {
266 * We need to simulate the action of the kernel to FPU
269 do_the_FPU_interrupt
:
271 FPU_EIP
= FPU_ORIG_EIP
; /* Point to current FPU instruction. */
273 RE_ENTRANT_CHECK_OFF
;
274 current
->thread
.trap_nr
= X86_TRAP_MF
;
275 current
->thread
.error_code
= 0;
276 send_sig(SIGFPE
, current
, 1);
281 entry_sel_off
.offset
= FPU_ORIG_EIP
;
282 entry_sel_off
.selector
= FPU_CS
;
283 entry_sel_off
.opcode
= (byte1
<< 8) | FPU_modrm
;
284 entry_sel_off
.empty
= 0;
286 FPU_rm
= FPU_modrm
& 7;
288 if (FPU_modrm
< 0300) {
289 /* All of these instructions use the mod/rm byte to get a data address */
291 if ((addr_modes
.default_mode
& SIXTEEN
)
292 ^ (addr_modes
.override
.address_size
== ADDR_SIZE_PREFIX
))
294 FPU_get_address_16(FPU_modrm
, &FPU_EIP
,
295 &data_sel_off
, addr_modes
);
298 FPU_get_address(FPU_modrm
, &FPU_EIP
, &data_sel_off
,
301 if (addr_modes
.default_mode
) {
302 if (FPU_EIP
- 1 > code_limit
)
303 math_abort(FPU_info
, SIGSEGV
);
307 unsigned short status1
= partial_status
;
310 st0_tag
= FPU_gettag0();
312 /* Stack underflow has priority */
314 if (addr_modes
.default_mode
& PROTECTED
) {
315 /* This table works for 16 and 32 bit protected mode */
317 data_sizes_16
[(byte1
>> 1) & 3])
318 math_abort(FPU_info
, SIGSEGV
);
321 unmasked
= 0; /* Do this here to stop compiler warnings. */
322 switch ((byte1
>> 1) & 3) {
325 FPU_load_single((float __user
*)
328 loaded_tag
= unmasked
& 0xff;
333 FPU_load_int32((long __user
*)
339 FPU_load_double((double __user
*)
342 loaded_tag
= unmasked
& 0xff;
346 default: /* Used here to suppress gcc warnings. */
348 FPU_load_int16((short __user
*)
354 /* No more access to user memory, it is safe
355 to use static data now */
357 /* NaN operands have the next priority. */
358 /* We have to delay looking at st(0) until after
359 loading the data, because that data might contain an SNaN */
360 if (((st0_tag
== TAG_Special
) && isNaN(st0_ptr
))
361 || ((loaded_tag
== TAG_Special
)
362 && isNaN(&loaded_data
))) {
363 /* Restore the status word; we might have loaded a
365 partial_status
= status1
;
366 if ((FPU_modrm
& 0x30) == 0x10) {
368 EXCEPTION(EX_Invalid
);
369 setcc(SW_C3
| SW_C2
| SW_C0
);
370 if ((FPU_modrm
& 0x08)
373 FPU_pop(); /* fcomp, masked, so we pop. */
375 if (loaded_tag
== TAG_Special
)
380 /* This is not really needed, but gives behaviour
381 identical to an 80486 */
382 if ((FPU_modrm
& 0x28) == 0x20)
389 #endif /* PECULIAR_486 */
390 /* fadd, fdivr, fmul, or fsubr */
396 goto reg_mem_instr_done
;
399 if (unmasked
&& !((FPU_modrm
& 0x30) == 0x10)) {
400 /* Is not a comparison instruction. */
401 if ((FPU_modrm
& 0x38) == 0x38) {
403 if ((st0_tag
== TAG_Zero
) &&
404 ((loaded_tag
== TAG_Valid
)
410 if (FPU_divide_by_zero
415 /* We use the fact here that the unmasked
416 exception in the loaded data was for a
418 /* Restore the state of the denormal op bit */
432 goto reg_mem_instr_done
;
435 switch ((FPU_modrm
>> 3) & 7) {
438 FPU_add(&loaded_data
, loaded_tag
, 0,
443 FPU_mul(&loaded_data
, loaded_tag
, 0,
447 FPU_compare_st_data(&loaded_data
,
451 if (!FPU_compare_st_data
452 (&loaded_data
, loaded_tag
)
458 FPU_sub(LOADED
| loaded_tag
,
464 FPU_sub(REV
| LOADED
| loaded_tag
,
470 FPU_div(LOADED
| loaded_tag
,
476 if (st0_tag
== TAG_Zero
)
477 partial_status
= status1
; /* Undo any denorm tag,
478 zero-divide has priority. */
479 FPU_div(REV
| LOADED
| loaded_tag
,
485 if ((FPU_modrm
& 0x30) == 0x10) {
486 /* The instruction is fcom or fcomp */
487 EXCEPTION(EX_StackUnder
);
488 setcc(SW_C3
| SW_C2
| SW_C0
);
489 if ((FPU_modrm
& 0x08)
490 && (control_word
& CW_Invalid
))
491 FPU_pop(); /* fcomp */
493 FPU_stack_underflow();
496 operand_address
= data_sel_off
;
499 FPU_load_store(((FPU_modrm
& 0x38) | (byte1
& 6))
500 >> 1, addr_modes
, data_address
))) {
501 operand_address
= data_sel_off
;
506 /* None of these instructions access user memory */
507 u_char instr_index
= (FPU_modrm
& 0x38) | (byte1
& 7);
510 /* This is supposed to be undefined, but a real 80486 seems
512 operand_address
.offset
= 0;
513 operand_address
.selector
= FPU_DS
;
514 #endif /* PECULIAR_486 */
517 st0_tag
= FPU_gettag0();
518 switch (type_table
[(int)instr_index
]) {
519 case _NONE_
: /* also _REGIc: _REGIn */
522 if (!NOT_EMPTY_ST0
) {
523 FPU_stack_underflow();
524 goto FPU_instruction_done
;
528 if (!NOT_EMPTY_ST0
|| !NOT_EMPTY(FPU_rm
)) {
529 FPU_stack_underflow_i(FPU_rm
);
530 goto FPU_instruction_done
;
534 if (!NOT_EMPTY_ST0
|| !NOT_EMPTY(FPU_rm
)) {
535 FPU_stack_underflow_pop(FPU_rm
);
536 goto FPU_instruction_done
;
540 if (!NOT_EMPTY_ST0
|| !NOT_EMPTY(FPU_rm
)) {
541 FPU_stack_underflow();
542 goto FPU_instruction_done
;
545 case _PUSH_
: /* Only used by the fld st(i) instruction */
549 goto FPU_instruction_done
;
551 EXCEPTION(EX_INTERNAL
| 0x111);
552 goto FPU_instruction_done
;
554 (*st_instr_table
[(int)instr_index
]) ();
556 FPU_instruction_done
:
561 instruction_address
= entry_sel_off
;
566 RE_ENTRANT_CHECK_OFF
;
571 if (FPU_lookahead
&& !need_resched()) {
572 FPU_ORIG_EIP
= FPU_EIP
- code_base
;
573 if (valid_prefix(&byte1
, (u_char __user
**) & FPU_EIP
,
574 &addr_modes
.override
))
575 goto do_another_FPU_instruction
;
578 if (addr_modes
.default_mode
)
579 FPU_EIP
-= code_base
;
581 RE_ENTRANT_CHECK_OFF
;
584 /* Support for prefix bytes is not yet complete. To properly handle
585 all prefix bytes, further changes are needed in the emulator code
586 which accesses user address space. Access to separate segments is
587 important for msdos emulation. */
588 static int valid_prefix(u_char
*Byte
, u_char __user
**fpu_eip
,
589 overrides
* override
)
592 u_char __user
*ip
= *fpu_eip
;
594 *override
= (overrides
) {
595 0, 0, PREFIX_DEFAULT
}; /* defaults */
597 RE_ENTRANT_CHECK_OFF
;
598 FPU_code_access_ok(1);
599 FPU_get_user(byte
, ip
);
604 case ADDR_SIZE_PREFIX
:
605 override
->address_size
= ADDR_SIZE_PREFIX
;
609 override
->operand_size
= OP_SIZE_PREFIX
;
613 override
->segment
= PREFIX_CS_
;
616 override
->segment
= PREFIX_ES_
;
619 override
->segment
= PREFIX_SS_
;
622 override
->segment
= PREFIX_FS_
;
625 override
->segment
= PREFIX_GS_
;
628 override
->segment
= PREFIX_DS_
;
631 /* lock is not a valid prefix for FPU instructions,
632 let the cpu handle it to generate a SIGILL. */
633 /* case PREFIX_LOCK: */
635 /* rep.. prefixes have no meaning for FPU instructions */
641 RE_ENTRANT_CHECK_OFF
;
642 FPU_code_access_ok(1);
643 FPU_get_user(byte
, ip
);
650 if ((byte
& 0xf8) == 0xd8) {
655 /* Not a valid sequence of prefix bytes followed by
656 an FPU instruction. */
657 *Byte
= byte
; /* Needed for error message. */
664 void math_abort(struct math_emu_info
*info
, unsigned int signal
)
666 FPU_EIP
= FPU_ORIG_EIP
;
667 current
->thread
.trap_nr
= X86_TRAP_MF
;
668 current
->thread
.error_code
= 0;
669 send_sig(signal
, current
, 1);
670 RE_ENTRANT_CHECK_OFF
;
671 __asm__("movl %0,%%esp ; ret": :"g"(((long)info
) - 4));
673 printk("ERROR: wm-FPU-emu math_abort failed!\n");
674 #endif /* PARANOID */
677 #define S387 ((struct i387_soft_struct *)s387)
678 #define sstatus_word() \
679 ((S387->swd & ~SW_Top & 0xffff) | ((S387->ftop << SW_Top_Shift) & SW_Top))
681 int fpregs_soft_set(struct task_struct
*target
,
682 const struct user_regset
*regset
,
683 unsigned int pos
, unsigned int count
,
684 const void *kbuf
, const void __user
*ubuf
)
686 struct i387_soft_struct
*s387
= &target
->thread
.fpu
.state
->soft
;
687 void *space
= s387
->st_space
;
689 int offset
, other
, i
, tags
, regnr
, tag
, newtop
;
691 RE_ENTRANT_CHECK_OFF
;
692 ret
= user_regset_copyin(&pos
, &count
, &kbuf
, &ubuf
, s387
, 0,
693 offsetof(struct i387_soft_struct
, st_space
));
699 S387
->ftop
= (S387
->swd
>> SW_Top_Shift
) & 7;
700 offset
= (S387
->ftop
& 7) * 10;
703 RE_ENTRANT_CHECK_OFF
;
705 /* Copy all registers in stack order. */
706 ret
= user_regset_copyin(&pos
, &count
, &kbuf
, &ubuf
,
707 space
+ offset
, 0, other
);
709 ret
= user_regset_copyin(&pos
, &count
, &kbuf
, &ubuf
,
714 /* The tags may need to be corrected now. */
717 for (i
= 0; i
< 8; i
++) {
718 regnr
= (i
+ newtop
) & 7;
719 if (((tags
>> ((regnr
& 7) * 2)) & 3) != TAG_Empty
) {
720 /* The loaded data over-rides all other cases. */
722 FPU_tagof((FPU_REG
*) ((u_char
*) S387
->st_space
+
724 tags
&= ~(3 << (regnr
* 2));
725 tags
|= (tag
& 3) << (regnr
* 2);
733 int fpregs_soft_get(struct task_struct
*target
,
734 const struct user_regset
*regset
,
735 unsigned int pos
, unsigned int count
,
736 void *kbuf
, void __user
*ubuf
)
738 struct i387_soft_struct
*s387
= &target
->thread
.fpu
.state
->soft
;
739 const void *space
= s387
->st_space
;
741 int offset
= (S387
->ftop
& 7) * 10, other
= 80 - offset
;
743 RE_ENTRANT_CHECK_OFF
;
746 S387
->cwd
&= ~0xe080;
747 /* An 80486 sets nearly all of the reserved bits to 1. */
748 S387
->cwd
|= 0xffff0040;
749 S387
->swd
= sstatus_word() | 0xffff0000;
750 S387
->twd
|= 0xffff0000;
751 S387
->fcs
&= ~0xf8000000;
752 S387
->fos
|= 0xffff0000;
753 #endif /* PECULIAR_486 */
755 ret
= user_regset_copyout(&pos
, &count
, &kbuf
, &ubuf
, s387
, 0,
756 offsetof(struct i387_soft_struct
, st_space
));
758 /* Copy all registers in stack order. */
760 ret
= user_regset_copyout(&pos
, &count
, &kbuf
, &ubuf
,
761 space
+ offset
, 0, other
);
763 ret
= user_regset_copyout(&pos
, &count
, &kbuf
, &ubuf
,