|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. ! 3: * ! 4: * @APPLE_LICENSE_HEADER_START@ ! 5: * ! 6: * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights ! 7: * Reserved. This file contains Original Code and/or Modifications of ! 8: * Original Code as defined in and that are subject to the Apple Public ! 9: * Source License Version 1.1 (the "License"). You may not use this file ! 10: * except in compliance with the License. Please obtain a copy of the ! 11: * License at http://www.apple.com/publicsource and read it before using ! 12: * this file. ! 13: * ! 14: * The Original Code and all software distributed under the License are ! 15: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER ! 16: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, ! 17: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, ! 18: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the ! 19: * License for the specific language governing rights and limitations ! 20: * under the License. ! 21: * ! 22: * @APPLE_LICENSE_HEADER_END@ ! 23: */ ! 24: ! 25: .file "status.s" ! 26: ! 27: .ident "@(#)kern-fp:status.s 1.1" ! 28: //$tt(*80387 emulator + + + s t a t u s + + + *) ! 29: // ************************************************************************ ! 30: // ! 31: // s t a t u s . m o d ! 32: // =================== ! 33: // ! 34: // ================================================================ ! 35: // intel corporation proprietary information ! 36: // this software is supplied under the terms of a license ! 37: // agreement or non-disclosure agreement with intel corporation ! 38: // and may not be copied nor disclosed except in accordance with ! 39: // the terms of that agreement. ! 40: // ================================================================= ! 41: // ! 42: // function: ! 43: // operation cluster for 80387 status register ! 44: // ! 45: // public procedures: ! 46: // stcw stenv pop_free ! 47: // incr_top decr_top save_status ! 48: // restore_status clear_p_error init ! 49: // clex stsw ldcw ! 50: // get_precision store_precision get_rnd_control ! 51: // store_rnd_control u_masked? z_masked? ! 52: // d_masked? i_masked? o_masked? ! 53: // get_reg_tag affine_infinity? get_top ! 54: // set_p_error p_error? set_u_error ! 55: // set_o_error set_z_error set_i_error ! 56: // i_error? d_error? set_d_error ! 57: // set_z_bit clear_z_bit set_s_bit ! 58: // clear_s_bit set_a_bit clear_a_bits ! 59: // set_c_bit clear_c_bit store_reg_tag ! 60: // set_i_masked? set_d_masked? set_z_masked? ! 61: // clear_cond_bits ! 62: // ! 63: // ************************************************************************ ! 64: // ! 65: //...March 3, 1987... ! 66: // ! 67: .data //a_msr segment rw public ! 68: // ! 69: //...define the 80387 status register... ! 70: // ! 71: //%gs:sr_masks: .byte 0x07f / bit 6 on for d-step 8087 05/21/81 ! 72: //%gs:sr_controls: .byte 0x13 ! 73: //%gs:sr_reserved1: .value 0 / reserveds take care of 386 env ! 74: //%gs:sr_errors: .byte 0 ! 75: //%gs:sr_flags: .byte 0 / bit 2 off for sim286 09/14/83 ! 76: //%gs:sr_reserved2: .value 0 ! 77: //%gs:sr_tags: .value 0x0ffff ! 78: //%gs:sr_reserved3: .value 0 ! 79: //%gs:sr_instr_offset: .long 0 ! 80: //%gs:sr_instr_base: .value 0 ! 81: //%gs:sr_reserved4: .value 0 ! 82: //%gs:sr_mem_offset: .long 0 ! 83: //%gs:sr_mem_base: .value 0 ! 84: //%gs:sr_reserved5: .value 0 ! 85: //%gs:sr_regstack: .value 40 dup(0) ! 86: //#define a_m%gs:sr_data %gs:sr_masks ! 87: //a_msr ends ! 88: // assume %ds:a_msr ! 89: //$nolist ! 90: #include "fp_e80387.h" ! 91: //$list ! 92: // ! 93: // .globl %gs:sr_mem_offset ! 94: // .globl %gs:sr_controls ! 95: // .globl %gs:sr_mem_base ! 96: // .globl a_m%gs:sr_data ! 97: // .globl %gs:sr_regstack ! 98: // .globl %gs:sr_flags ! 99: // .globl %gs:sr_masks ! 100: // .globl %gs:sr_errors ! 101: // .globl %gs:sr_instr_offset ! 102: // .globl %gs:sr_instr_base ! 103: .globl incr_top ! 104: .globl decr_top ! 105: .globl save_status ! 106: .globl pop_free ! 107: .globl ldcw ! 108: .globl stenv ! 109: .globl clex ! 110: .globl stsw ! 111: .globl stcw ! 112: .globl get_precision ! 113: .globl store_precision ! 114: .globl get_rnd_control ! 115: .globl store_rnd_control ! 116: .globl u_masked_ ! 117: .globl d_masked_ ! 118: .globl get_top ! 119: .globl i_masked_ ! 120: .globl o_masked_ ! 121: .globl get_reg_tag ! 122: .globl affine_infinity_ ! 123: .globl set_p_error ! 124: .globl set_u_error ! 125: .globl set_o_error ! 126: .globl init ! 127: .globl clear_p_error ! 128: .globl set_i_error ! 129: .globl set_d_error ! 130: .globl i_error_ ! 131: .globl d_error_ ! 132: .globl p_error_ ! 133: .globl set_z_bit ! 134: .globl clear_z_bit ! 135: .globl set_s_bit ! 136: .globl clear_s_bit ! 137: .globl set_a_bit ! 138: .globl clear_cond_bits ! 139: .globl set_c_bit ! 140: .globl clear_c_bit ! 141: .globl store_reg_tag ! 142: .globl set_i_masked_ ! 143: .globl set_d_masked_ ! 144: .globl set_z_masked_ ! 145: .globl clear_a_bit ! 146: .globl restore_status ! 147: .globl set_stk_u_error ! 148: .globl set_stk_o_error ! 149: .globl correct_tag_word ! 150: .globl free_reg ! 151: // ! 152: .text //a_med segment er public ! 153: // --------to be added for unix ! 154: //.. extrn fpfulong:far,fpfushort:far,fpsulong:far,fpsushort:far ! 155: // ! 156: // ************************************************************************* ! 157: // ! 158: // the routines in this section manipulate the status and control ! 159: // information stored in the 80387 status data segment, a?msr. ! 160: // ! 161: // ************************************************************************ ! 162: // transfer field group: get_precision, store_precision, get_rnd_control ! 163: // store_rnd_control, get_top, get_reg_tag, store_reg_tag ! 164: // ! 165: // inputs: the *get* routines require no input parameters, except for the ! 166: // procedures get_reg_tag and store_reg_tag which expect the ! 167: // register number to be in al and cl, respectively ! 168: // the *store* routines input the value to be stored in al. ! 169: // ! 170: // outputs: get_precison returns the 2-bit precision field in dl. ! 171: // all other routines return justified values in al. ! 172: // ************************************************************************ ! 173: ! 174: ALIGN ! 175: get_precision: //proc ! 176: movb $precision_mask,%dl // load precision field mask ! 177: andb %gs:sr_controls,%dl // mask in precision control ! 178: ret ! 179: //get_precision endp ! 180: // ! 181: ALIGN ! 182: store_precision: //proc ! 183: andb $~precision_mask,%gs:sr_controls // clear precision ! 184: orb %al,%gs:sr_controls // store new precision control ! 185: ret ! 186: //store_precision endp ! 187: // ! 188: ALIGN ! 189: get_rnd_control: //proc ! 190: movb %gs:sr_controls,%al // load control byte ! 191: andb $rnd_control_mask,%al // mask in rounding control ! 192: ret ! 193: //get_rnd_control endp ! 194: // ! 195: ALIGN ! 196: store_rnd_control: //proc ! 197: andb $~rnd_control_mask,%gs:sr_controls // clear old field ! 198: orb %al,%gs:sr_controls // store new rounding control ! 199: ret ! 200: //store_rnd_control endp ! 201: // ! 202: ALIGN ! 203: get_top: //proc ! 204: movb %gs:sr_flags,%al // load status flag byte ! 205: andb $top_mask,%al // mask in top field ! 206: shrb $3,%al // right justify top field ! 207: ret ! 208: //get_top endp ! 209: // ! 210: ALIGN ! 211: get_reg_tag: //proc ! 212: movzbl %al,%eax // form word bit count ! 213: mov %eax,%ecx // store in cx ! 214: shl $1,%ecx // bit count = 2 * reg num ! 215: mov %ecx,%ebx // else, must examine register ! 216: shl $2,%ebx // form index to %gs:sr_regstack ! 217: add %ecx,%ebx // index = 10 * register num ! 218: add $sr_regstack,%ebx // + start of %gs:sr_regstack ! 219: movw %gs:sr_tags,%ax // load tag word ! 220: shrw %cl,%ax // shift to tag of interest ! 221: andb $empty,%al // mask out other tags ! 222: cmpb inv,%al // if tag not = 2, ! 223: jne got_tag // no further decoding needed ! 224: movw %gs:8(%ebx),%ax // load register exponent ! 225: andw $0x7fff,%ax // mask off sign bit ! 226: jnz check_unsupp // if expon /= 0, check unsupported format ! 227: movb denormd,%al // if exponent zero, denormal ! 228: ret ! 229: ALIGN ! 230: check_unsupp: ! 231: mov %gs:4(%ebx),%eax // get top 32 bits of significand ! 232: test $0x080000000,%eax // is highest bit set. ! 233: jnz check_nan // if so, check for nan ! 234: movb unsupp,%al // if not, its an unsupported format. ! 235: ret ! 236: ALIGN ! 237: check_nan: ! 238: and $0x07fffffff,%eax // zero out most significant bit ! 239: or %gs:(%ebx),%eax // or bottom 32 bits into top 32 bits. ! 240: movb infinty,%al // tentatively set tag to infinitys ! 241: jz got_tag // if fraction is 0, its infinity ! 242: movb inv,%al // fraction is non zero, so tag as nan. ! 243: got_tag: ! 244: ret ! 245: //get_reg_tag endp ! 246: // ************************************************************************ ! 247: // test status bit group: u_masked?, z_masked?, d_masked?, i_masked?, ! 248: // o_masked?, affine_infinity?, p_error?, i_error?, d_error?, ! 249: // set_i_masked?, set_d_masked? ! 250: // ! 251: // inputs: no input values are required. ! 252: // ! 253: // outputs: all boolean function return the complemented bit value ! 254: // in the zf. (test with jz on bit = 0.) ! 255: // ************************************************************************ ! 256: ALIGN ! 257: u_masked_: //proc ! 258: testb underflow_mask,%gs:sr_masks // test the u mask ! 259: ret ! 260: //u_masked_ endp ! 261: // ! 262: ALIGN ! 263: set_d_masked_: //proc ! 264: call set_d_error // set the d error ! 265: d_masked_: ! 266: testb denorm_mask,%gs:sr_masks // test the d mask ! 267: ret ! 268: //set_d_masked_ endp ! 269: // ! 270: ALIGN ! 271: set_i_masked_: //proc ! 272: call set_i_error // set the i error ! 273: i_masked_: ! 274: testb invalid_mask,%gs:sr_masks // test the i mask ! 275: ret ! 276: //set_i_masked_ endp ! 277: // ! 278: ALIGN ! 279: o_masked_: //proc ! 280: testb overflow_mask,%gs:sr_masks // test the o mask ! 281: ret ! 282: //o_masked_ endp ! 283: // ! 284: ALIGN ! 285: affine_infinity_: //proc ! 286: testb infinity_control_mask,%gs:sr_controls // test ic ! 287: ret ! 288: //affine_infinity_ endp ! 289: // ! 290: ALIGN ! 291: p_error_: //proc ! 292: testb $inexact_mask,%gs:sr_errors // test the p error ! 293: ret ! 294: //p_error_ endp ! 295: // ! 296: ALIGN ! 297: i_error_: //proc ! 298: testb invalid_mask,%gs:sr_errors // test the i error ! 299: ret ! 300: //i_error_ endp ! 301: // ! 302: ALIGN ! 303: d_error_: //proc ! 304: testb denorm_mask,%gs:sr_errors // test the d error ! 305: ret ! 306: //d_error_ endp ! 307: // ************************************************************************ ! 308: // set and reset bit group: set_p_error, set_u_error, set_o_error ! 309: // set_z_masked?, set_i_error, set_d_error, clear_s_bit, clear_z_bit ! 310: // set_s_bit, set_z_bit, set_a_bit, clear_a_bit, set_c_bit, clear_c_bit ! 311: // clear_cond_bits, clear_p_error, set_stk_u_error, set_stk_o_error ! 312: // ! 313: // inputs: no input values are required. ! 314: // ! 315: // outputs: all procedures set or reset the indicated status bit ! 316: // ************************************************************************ ! 317: ALIGN ! 318: set_stk_u_error: //proc ! 319: orb invalid_mask+zero_mask,%gs:sr_errors ! 320: andb $~a_mask,%gs:sr_flags // clear the a-bit ! 321: ret ! 322: //set_stk_u_error endp ! 323: // ! 324: ALIGN ! 325: set_stk_o_error: //proc ! 326: orb invalid_mask+zero_mask,%gs:sr_errors ! 327: orb $a_mask,%gs:sr_flags // set the a-bit ! 328: ret ! 329: //set_stk_o_error endp ! 330: // ! 331: ALIGN ! 332: set_p_error: //proc ! 333: orb $inexact_mask,%gs:sr_errors // set the p-error ! 334: ret ! 335: //set_p_error endp ! 336: // ! 337: ALIGN ! 338: set_u_error: //proc ! 339: orb underflow_mask,%gs:sr_errors // set the u-error ! 340: ret ! 341: //set_u_error endp ! 342: // ! 343: ALIGN ! 344: set_o_error: //proc ! 345: orb overflow_mask,%gs:sr_errors // set the o-error ! 346: ret ! 347: //set_o_error endp ! 348: // ! 349: ALIGN ! 350: set_i_error: //proc ! 351: orb invalid_mask,%gs:sr_errors // set the i-error ! 352: ret ! 353: //set_i_error endp ! 354: // ! 355: ALIGN ! 356: set_d_error: //proc ! 357: orb denorm_mask,%gs:sr_errors // set the d-error ! 358: ret ! 359: //set_d_error endp ! 360: // ! 361: ALIGN ! 362: set_z_masked_: //proc ! 363: orb zero_divide_mask,%gs:sr_errors // set the z-error ! 364: testb zero_divide_mask,%gs:sr_masks // test the z mask ! 365: ret ! 366: //set_z_masked_ endp ! 367: // ! 368: ALIGN ! 369: set_s_bit: //proc ! 370: orb $sign_mask,%gs:sr_flags // set the s-bit ! 371: ret ! 372: //set_s_bit endp ! 373: // ! 374: ALIGN ! 375: set_z_bit: //proc ! 376: orb $zero_mask,%gs:sr_flags // set the z-bit ! 377: ret ! 378: //set_z_bit endp ! 379: // ! 380: ALIGN ! 381: set_a_bit: //proc ! 382: orb $a_mask,%gs:sr_flags // set the a-bit ! 383: ret ! 384: //set_a_bit endp ! 385: // ! 386: ALIGN ! 387: set_c_bit: //proc ! 388: orb $c_mask,%gs:sr_flags // set the c-bit ! 389: ret ! 390: //set_c_bit endp ! 391: // ! 392: ALIGN ! 393: clear_s_bit: //proc ! 394: andb $~sign_mask,%gs:sr_flags // clear the s-bit ! 395: ret ! 396: //clear_s_bit endp ! 397: // ! 398: ALIGN ! 399: clear_z_bit: //proc ! 400: andb $~zero_mask,%gs:sr_flags // clear the z-bit ! 401: ret ! 402: //clear_z_bit endp ! 403: // ! 404: ALIGN ! 405: clear_a_bit: //proc ! 406: andb $~a_mask,%gs:sr_flags // clear the a-bit ! 407: ret ! 408: //clear_a_bit endp ! 409: // ! 410: ALIGN ! 411: clear_cond_bits: //proc ! 412: andb $~(c_mask+zero_mask+sign_mask+a_mask),%gs:sr_flags ! 413: ret // clear all condition bits ! 414: //clear_cond_bits endp ! 415: // ! 416: ALIGN ! 417: clear_c_bit: //proc ! 418: andb $~c_mask,%gs:sr_flags // clear the c-bit ! 419: ret ! 420: //clear_c_bit endp ! 421: // ! 422: ALIGN ! 423: clear_p_error: //proc ! 424: andb $~inexact_mask ,%gs:sr_errors // clear the p-error ! 425: ret ! 426: //clear_p_error endp ! 427: // ! 428: // ************************************************************************ ! 429: // pop_free: ! 430: // function: ! 431: // pops the stack and/or frees the register(s) as required ! 432: // ! 433: // ************************************************************************ ! 434: ALIGN ! 435: pop_free: //proc ! 436: call i_masked_ // is invalid masked? ! 437: jnz check_op1 // if so, forget error ! 438: call i_error_ // check for i-error ! 439: jnz common_return // if error, dont pop ! 440: ! 441: free_reg: ! 442: check_op1: ! 443: movb op1_use_up(%ebp),%al // pop or free op1 ! 444: call process_use_up ! 445: movb op2_use_up(%ebp),%al // pop or free op2 ! 446: process_use_up: ! 447: cmpb pop_stack,%al // is it a pop_stack? ! 448: je pop_it // yes, process it ! 449: xorb free,%al // no, is it free reg? ! 450: jnz exit_process // no, done with use_up ! 451: call get_top // yes, get top pointer ! 452: addb reg_num(%ebp),%al // convert relative num ! 453: andb $0x07,%al // to absolute reg num ! 454: empty_reg_tag: ! 455: movb %al,%cl // cl = reg number ! 456: movb $empty,%al // al = new tag value ! 457: store_reg_tag: ! 458: shlb $1,%cl // bit count = 2 * reg num ! 459: rorw %cl,%gs:sr_tags // rotate tag to low bits ! 460: andb $~empty,%gs:sr_tags // clear old reg num tag ! 461: andb $empty,%al // clear bits 2-7 of new tag ! 462: orb %al,%gs:sr_tags // store new reg num tag and ! 463: rolw %cl,%gs:sr_tags // rotate the tag word back ! 464: exit_process: ! 465: ret ! 466: pop_it: ! 467: call get_top // pop the stack once ! 468: // the following six instructions have been commented out to prevent ! 469: // an invalid operation from being signaled when the 87 tos is subject ! 470: // to a freep st(i) (*6 in the 80387 t-spec). in other words, it will ! 471: // be o.k. to free st(0) and decrement stackpointer, so it will also be ! 472: // o.k. to free an already empty st(0). ! 473: // call get_reg_tag ; get register tag ! 474: // cmp al,empty ; is the top empty? ! 475: // jne pop_ok ; no, stack may be popped ! 476: // call set_i_masked? ; yes, stack error ! 477: // jz exit_process ; abort if unmasked ! 478: //pop_ok: ! 479: // call get_top ! 480: call empty_reg_tag //set tag of top empty ! 481: //pop_free endp ; enter incr_top ! 482: // ! 483: // ************************************************************************** ! 484: // incr_top: ! 485: // function: ! 486: // increments stack pointer ! 487: // ! 488: // ************************************************************************** ! 489: FALLSTHRU ! 490: incr_top: //proc ! 491: movb $0x08,%cl // load increment top constant ! 492: jmp adjust_top // merge with decr_top ! 493: ALIGN ! 494: //incr_top endp ! 495: // ************************************************************************** ! 496: // decr_top: ! 497: // function: ! 498: // decrements stack pointer ! 499: // ! 500: // ************************************************************************** ! 501: ALIGN ! 502: decr_top: //proc ! 503: movb $0x38,%cl // load decrement top constant ! 504: adjust_top: ! 505: movb %gs:sr_flags,%al // get old top ! 506: andb $top_mask,%al ! 507: xorb %al,%gs:sr_flags // clear old top field ! 508: addb %cl,%al // increment/decrement top ! 509: andb $top_mask,%al // mask off bits 6-7 ! 510: orb %al,%gs:sr_flags // store new top field ! 511: common_return: ! 512: ret ! 513: //decr_top endp ! 514: // ! 515: // ****************************************************************************** ! 516: // restore_status: ! 517: // function: ! 518: // implements the 80387 ldenv instruction. ! 519: // restores status register from memory. ! 520: // ! 521: // ********************************************************************** ! 522: ALIGN ! 523: restore_status: //proc ! 524: push %ds // save %ds ! 525: push %gs ! 526: pop %es // load destination base ! 527: lds mem_operand_pointer(%ebp),%esi // load environment pointer ! 528: mov $sr_masks,%edi // load dest offset ! 529: mov $0x0007,%ecx // load environment from memory ! 530: cmpb $1,oprnd_siz32(%ebp) //is it a 32 bit operand ! 531: jne restore_status16 //no restore 16 bit status ! 532: FAST_MOVSL_ES ! 533: pop %ds ! 534: orb $0x40,%gs:sr_masks // set stack mask ! 535: jmp correct_tag_word ! 536: ALIGN ! 537: restore_status16: //16 bit protected mode ! 538: movsw // mov words ! 539: inc %edi ! 540: inc %edi ! 541: loop restore_status16 ! 542: // --------- ! 543: ! 544: ! 545: //------------------------------------------------------------------------ ! 546: //.. pushad ! 547: //.. push ds ! 548: //..restore_status32: ! 549: //.. push esi ! 550: //.. call fpfulong ! 551: //.. pop esi ! 552: //.. stosd ! 553: //.. add esi,4 ! 554: //.. loop restore_status32 ! 555: //.. pop ds ! 556: //.. popad ! 557: //.. cld ! 558: //.. ret ! 559: //..restore_status16: ! 560: //.. pushad ! 561: //.. push ds ! 562: //..restor_loop: ! 563: //.. push esi ! 564: //.. call fpfushort ! 565: //.. pop esi ! 566: //.. stosw ! 567: //.. add esi,2 ! 568: //.. add edi,2 ! 569: //.. loop restor_loop ! 570: //.. pop ds ! 571: //.. popad ! 572: //.. cld ! 573: //--------------------------------------------------------------------- ! 574: pop %ds ! 575: orb $0x40,%gs:sr_masks // set stack mask ! 576: correct_tag_word: ! 577: mov $8,%ecx ! 578: xor %ebx,%ebx ! 579: set_tags_loop: //looping through physical locations of 0-7 regs ! 580: mov $10,%eax ! 581: mul %ebx ! 582: mov $sr_regstack,%esi ! 583: add %eax,%esi ! 584: mov $0x00000003,%eax ! 585: and %gs:sr_tags,%eax ! 586: cmp $3,%eax ! 587: je loop_back ! 588: movw %gs:8(%esi),%ax ! 589: andw $0x7fff,%ax // strip off sign bit ! 590: jz expon_zero // branch if exponent 0 ! 591: testb $0x80,%gs:7(%esi) ! 592: jnz max_expon_ ! 593: movb $2,%dl // we have an ! 594: jmp set_tag // unsupported format ! 595: ALIGN ! 596: max_expon_: ! 597: cmpw $0x7fff,%ax // check for invalid ! 598: je not_validx // or infinity ! 599: movb $0,%dl // operand is valid ! 600: jmp set_tag ! 601: ALIGN ! 602: not_validx: ! 603: movb $2,%dl ! 604: jmp set_tag ! 605: ALIGN ! 606: expon_zero: ! 607: mov %gs:4(%esi),%eax ! 608: or %gs:(%esi),%eax ! 609: movb $1,%dl // set tag to special ! 610: jz set_tag // if number is +/- 0 ! 611: movb $2,%dl // set tag to denormd ! 612: set_tag: ! 613: andb $~empty,%gs:sr_tags // clear old reg num tag ! 614: orb %dl,%gs:sr_tags // store new reg num tag and ! 615: loop_back: ! 616: rorw $2,%gs:sr_tags // get next two bits ! 617: inc %ebx ! 618: loop set_tags_loop ! 619: ret ! 620: //restore_status endp ! 621: // ************************************************************************** ! 622: // init: ! 623: // function: ! 624: // implements 80387 init instruction. intializes ! 625: // status register including mode word and error mask. ! 626: // ! 627: // *********************************************************************** ! 628: ALIGN ! 629: init: //proc ! 630: movl $0x137f,%eax // initialize mode word ! 631: movw %ax,%gs:sr_masks ! 632: movl $0xffffffff,%ax // ax = 0ffffh ! 633: movw %ax,%gs:sr_tags // register tags = empty ! 634: xor %eax,%eax // clear a reg ! 635: movw %ax,%gs:sr_errors // clear the error flags ! 636: // and %gs:sr_flags,not top_mask ; top of stack = 0, cbit=0 ! 637: ret ! 638: //init endp ! 639: // *********************************************************************** ! 640: // ldcw: ! 641: // function: ! 642: // implements 80387 ldcw instruction. 80387 control word ! 643: // loaded (from memory location specified in instruction). ! 644: // ! 645: // *********************************************************************** ! 646: ALIGN ! 647: ldcw: //proc ! 648: les mem_operand_pointer(%ebp),%ebx //get new mode word ! 649: movw %es:(%ebx),%ax ! 650: //.. ! 651: //.. pushad ! 652: //.. push es ! 653: //.. push ebx ! 654: //.. call fpfushort ! 655: //.. pop ebx ! 656: //.. pop es ! 657: //.. popad ! 658: //.. cld ! 659: //.. ! 660: orw $0x40,%ax // set stack mask ! 661: movw %ax,%gs:sr_masks // store in status reg ! 662: ret ! 663: //ldcw endp ! 664: // ********************************************************************** ! 665: // stenv: ! 666: // function: ! 667: // implements 80387 fstenv instruction. 80387 environmemt ! 668: // stored (in memory location specified in the instruction). ! 669: // ! 670: // ********************************************************************** ! 671: ALIGN ! 672: stenv: //proc ! 673: call save_status // store status to memory ! 674: orb $0x07f,%gs:sr_masks // set all individual masks ! 675: ret ! 676: //stenv endp ! 677: // ********************************************************************** ! 678: // clex: ! 679: // function: ! 680: // clears all 80387 errors set in status register ! 681: // ! 682: // ********************************************************************** ! 683: ALIGN ! 684: clex: //proc ! 685: movb $0,%gs:sr_errors // clear error byte ! 686: ret ! 687: //clex endp ! 688: // ********************************************************************** ! 689: // stsw ! 690: // function: ! 691: // stores status word in memory location. (i.e., implements ! 692: // fstsw instruction.) also implements 'fstsw ax'. ! 693: // ! 694: // ********************************************************************** ! 695: ALIGN ! 696: stsw: //proc ! 697: movb op2_location(%ebp),%al // load op2 location ! 698: cmpb $reg,%al // is this fstsw ax? ! 699: movw %gs:sr_errors,%ax // get status word ! 700: je stsw_ax // branch on fstsw ax ! 701: store_word: ! 702: les mem_operand_pointer(%ebp),%ebx ! 703: movw %ax,%es:(%ebx) // store status to memory ! 704: ! 705: //.. pushad ! 706: //.. push es ! 707: //.. push ebx ! 708: //.. push ax ! 709: //.. call fpsushort ! 710: //.. add esp,12 ! 711: //.. popad ! 712: //.. cld ! 713: //.. ! 714: ret ! 715: stsw_ax: ! 716: movw %ax,saved_eax(%ebp) // store into register ax ! 717: // above instruction left for completeness but the ax ! 718: // really has to be restored to the EAX above the global ! 719: // re-entrant segment ! 720: // movl %eax, (offset_eax)(%ebp) ! 721: ret ! 722: //stsw endp ! 723: // ********************************************************************* ! 724: // stcw: ! 725: // function: ! 726: // stores control word in memory location. (i.e., implements ! 727: // fstcw instruction.) ! 728: // ! 729: // ********************************************************************* ! 730: ALIGN ! 731: stcw: //proc ! 732: movw %gs:sr_masks,%ax //get control word ! 733: andw $0x1f7f,%ax ! 734: orw $0x1040,%ax //set/reset reserved bits ! 735: jmp store_word //store it ! 736: ALIGN ! 737: //stcw endp ! 738: // ********************************************************************* ! 739: // save_status: ! 740: // function: ! 741: // saves status register to location specified by ! 742: // memory operand pointer(in es:di) ! 743: // ! 744: // ********************************************************************* ! 745: ALIGN ! 746: save_status: //proc ! 747: push %ds // save %ds ! 748: push %gs ! 749: pop %ds // and set it to address sr_masks ! 750: andw $0x1f7f,%gs:sr_masks ! 751: orw $0x1040,%gs:sr_masks //set/reset reserved bits ! 752: mov $sr_masks,%esi // load source offset ! 753: les mem_operand_pointer(%ebp),%edi // load destination pointer ! 754: mov $0x0007,%ecx ! 755: cmpb $1,oprnd_siz32(%ebp) ! 756: jne save_status16 ! 757: FAST_MOVSL_ES ! 758: pop %ds // restore %ds ! 759: ret ! 760: ALIGN ! 761: save_status16: //16 bit protected mode ! 762: movsw // mov words ! 763: inc %esi ! 764: inc %esi ! 765: loop save_status16 ! 766: //------------------------------------------------------------------------ ! 767: //.. pushad ! 768: //.. push es ! 769: //..save_status32: ! 770: //.. push edi ! 771: //.. push dword ptr (esi) ! 772: //.. call fpsulong ! 773: //.. add esp,8 ! 774: //.. add esi,4 ! 775: //.. add edi,4 ! 776: //.. loop save_status32 ! 777: //.. pop es ! 778: //.. popad ! 779: //.. cld ! 780: //.. ret ! 781: //..save_status16: ! 782: //.. pushad ! 783: //.. push es ! 784: //..save_loop: ! 785: //.. push edi ! 786: //.. push word ptr (esi) ! 787: //.. call fpsushort ! 788: //.. add esp,8 ! 789: //.. add edi,2 ! 790: //.. add esi,4 ! 791: //.. loop save_loop ! 792: //.. pop es ! 793: //.. popad ! 794: //.. cld ! 795: pop %ds // restore %ds ! 796: ret ! 797: //save_status endp ! 798: // ! 799: //a_med ends ! 800: // ! 801: // end
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.