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