|
|
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 "reg.s" ! 26: ! 27: .ident "@(#)kern-fp:reg.s 1.1" ! 28: ! 29: // **************************************************************************** ! 30: // ! 31: // r e g . 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 the 80387 register stack. ! 44: // ! 45: // public procedures: ! 46: // put_result stack_full? float_int16 ! 47: // save_regs restore_regs set_up_indefinite ! 48: // getx fetch_an_op exchange exam ! 49: // fxtrac abs_value chsign put_op1_result ! 50: // put_si_result do_exchange ! 51: // ! 52: // internal procedures: ! 53: // extend_single extend_double get_bcd fetch_an_op ! 54: // float16 float32 float64 ! 55: // ! 56: // ***************************************************************************** ! 57: // ! 58: //...March 3, 1987... ! 59: // ! 60: //$nolist ! 61: #include "fp_e80387.h" ! 62: //$list ! 63: //...declare status register segment... ! 64: // ! 65: .data //a_msr segment rw public ! 66: // extrn %gs:sr_masks,%gs:sr_errors,%gs:sr_flags,%gs:sr_regstack ! 67: //a_msr ends ! 68: // ! 69: // assume %ds:a_msr ! 70: // ! 71: .text //a_med segment er public ! 72: // ! 73: // extrn store_reg_tag,decr_top,left_shift ! 74: // extrn subtraction_normalize,clear_6w,test_3w ! 75: // extrn move_op_to_result,save_status,set_z_bit ! 76: // extrn restore_status,init,test_4w,test_6w ! 77: // extrn left_shift_frac2_cl,left_shift_frac1_1 ! 78: // extrn left_shift_result_cl,get_top,set_i_error ! 79: // extrn get_reg_tag,set_s_bit,set_d_error ! 80: // extrn i_masked_,clear_c_bit,clear_cond_bits ! 81: // extrn set_c_bit,set_a_bit,set_i_masked_ ! 82: // extrn move_op_to_op,set_stk_u_error,set_stk_o_error ! 83: // extrn norm_denorm,correct_tag_word ! 84: // --------to be added for unix ! 85: //.. extrn fpfulong:far,fpfushort:far,fpsulong:far,fpsushort:far ! 86: // ! 87: .globl getx ! 88: .globl fetch_an_op ! 89: .globl put_result ! 90: .globl stack_full_ ! 91: .globl fxtrac ! 92: .globl float_int16 ! 93: .globl save ! 94: .globl save_regs ! 95: .globl restore_regs ! 96: .globl restore ! 97: .globl set_up_indefinite ! 98: .globl exchange ! 99: .globl exam ! 100: .globl decompose ! 101: .globl load ! 102: .globl abs_value ! 103: .globl chsign ! 104: .globl put_op1_result ! 105: .globl do_exchange ! 106: .globl put_si_result ! 107: .globl do_exchange_leave_a_bit ! 108: // ! 109: // ***************************************************************************** ! 110: // extend_single: ! 111: // ************** ! 112: // function: ! 113: // retrieves a single real operand from memory, ! 114: // extends its parts, and puts them in the operand ! 115: // ! 116: // inputs: ! 117: // assumes mem_operand_pointer set up ! 118: // edi points to operand1 or operand2 ! 119: // ! 120: // outputs: ! 121: // extended operand in operand ! 122: // ! 123: // data accessed: ! 124: // - mem_operand_pointer ! 125: // ! 126: // data changed: ! 127: // - operands ! 128: // ! 129: // procedures called: ! 130: // set_d_error ! 131: // ! 132: // *************************************************************************** ! 133: ALIGN ! 134: extend_single: //proc ! 135: les mem_operand_pointer(%ebp),%ebx ! 136: xor %eax,%eax ! 137: mov %eax,frac64(%ebp,%edi) //clear low 5 bytes of ! 138: movb %al,frac32(%ebp,%edi) //fraction to 0 ! 139: // ---- replace following line for unix ! 140: mov %es:(%ebx),%eax // move 3 fraction ! 141: ! 142: //.. ! 143: //.. pushad ! 144: //.. push es ! 145: //.. push ebx ! 146: //.. call fpfulong ! 147: //.. add esp,8 ! 148: //.. popad ! 149: //.. cld ! 150: //.. ! 151: mov %eax,frac32+1(%ebp,%edi) // bytes from memory ! 152: sar $23,%eax // get short real exponent in al ! 153: movb %ah,sign(%ebp,%edi) // transfer sign to operand ! 154: and $0x000000ff,%eax // strip sign bits (here, b8-b31) ! 155: movl $0,before_error_signals(%ebp) // initialize all to false ! 156: jnz single_invalid_ ! 157: movb frac64+7(%ebp,%edi),%al // zero or denormalized? ! 158: orw frac64+5(%ebp,%edi),%ax ! 159: jnz single_denormalized ! 160: zero_return: ! 161: movb special,tag(%ebp,%edi) // set tag to special, ! 162: mov %eax,expon(%ebp,%edi) // expon to 0 ! 163: ret ! 164: ALIGN ! 165: single_denormalized: ! 166: movb denormd,tag(%ebp,%edi) // set tag to denormd ! 167: movb true,signal_d_error_ ! 168: testb denorm_mask,%gs:sr_masks // short cut for unmasked d-error ! 169: jnz sngl_d_error_masked ! 170: ret ! 171: ALIGN ! 172: sngl_d_error_masked: ! 173: movl single_exp_offset+1,expon(%ebp,%edi) ! 174: bsrl frac32(%ebp,%edi),%ecx ! 175: sub $31,%ecx ! 176: neg %ecx ! 177: shll %cl,frac32(%ebp,%edi) ! 178: sub %ecx,expon(%ebp,%edi) // adjust exponent ! 179: ret ! 180: ALIGN ! 181: single_invalid_: ! 182: cmpb true,%al ! 183: jne single_operand_is_valid ! 184: movl $0x7fff,expon(%ebp,%edi) //operand is inv/inf ! 185: testl $0x7fffffff,frac32(%ebp,%edi) ! 186: movb infinty,tag(%ebp,%edi) ! 187: jz sngl_exit ! 188: movb inv,tag(%ebp,%edi) //invalid operand ! 189: testb $0x40,msb(%ebp,%edi) ! 190: jnz sngl_qnan ! 191: movb true,signal_i_error_ ! 192: sngl_qnan: ! 193: sngl_exit: ! 194: ret //set tag to invalid ! 195: ALIGN ! 196: single_operand_is_valid: ! 197: movb valid,tag(%ebp,%edi) //set tag to valid ! 198: add single_exp_offset,%eax //single_exp_offset, ! 199: mov %eax,expon(%ebp,%edi) //implicit bit to 1 ! 200: orb $0x80,frac64+7(%ebp,%edi) ! 201: ret ! 202: ALIGN ! 203: //extend_single endp ! 204: // ! 205: // *********************************************************************** ! 206: // extend_double: ! 207: // ************** ! 208: // function: ! 209: // retrieves a double real operand from memory, ! 210: // extends its parts, and puts them in the operand ! 211: // ! 212: // inputs: ! 213: // assumes mem_operand_pointer is set up ! 214: // edi points to operand1 or operand2 ! 215: // ! 216: // outputs: ! 217: // expanded operand in operand ! 218: // ! 219: // data accessed: ! 220: // - mem_operand_pointer ! 221: // ! 222: // data changed: ! 223: // - operand ! 224: // ! 225: // procedures called: ! 226: // ! 227: // ! 228: // ********************************************************************* ! 229: ALIGN ! 230: extend_double: //proc ! 231: // push %ds // save a?msr ! 232: les mem_operand_pointer(%ebp),%ebx ! 233: movb $0,frac64(%ebp,%edi) //clear low byte of ! 234: mov %es:(%ebx),%eax //fraction to 0 ! 235: ! 236: //.. ! 237: //.. pushad ! 238: //.. push ds ! 239: //.. push ebx ! 240: //.. call fpfulong ! 241: //.. pop ebx ! 242: //.. ! 243: mov %eax,frac64+1(%ebp,%edi) //move 7 fraction bytes ! 244: mov %es:4(%ebx),%eax // from memory ! 245: //.. ! 246: //.. push ebx+4 ! 247: //.. call fpfulong ! 248: //.. add esp, 8 ! 249: //.. popad ! 250: //.. cld ! 251: ! 252: // pop %ds // reload a?msr ! 253: mov %eax,frac32+1(%ebp,%edi) ! 254: sar $20,%eax ! 255: cwtd ! 256: movb %dl,sign(%ebp,%edi) // transfer sign to operand ! 257: and $0x000007ff,%eax // strip sign bits (here, ! 258: // b11 - b31) ! 259: movl $0,before_error_signals(%ebp) // initialize both to false ! 260: jnz double_invalid_ ! 261: mov frac64(%ebp,%edi),%eax // exp=0 : is fraction 0? ! 262: or frac32(%ebp,%edi),%eax ! 263: jnz double_denormalized ! 264: jmp zero_return ! 265: ALIGN ! 266: double_denormalized: ! 267: movb denormd,tag(%ebp,%edi) // set tag to denormd ! 268: movb true,signal_d_error_ ! 269: testb denorm_mask,%gs:sr_masks // short cut for unmasked d-error ! 270: jnz dubl_d_error_masked ! 271: ret ! 272: ALIGN ! 273: dubl_d_error_masked: ! 274: movl double_exp_offset+1+3,expon(%ebp,%edi) ! 275: bsrl frac32(%ebp,%edi),%ecx ! 276: jz top_28_zero ! 277: mov frac64(%ebp,%edi),%eax ! 278: sub $31,%ecx ! 279: neg %ecx ! 280: shldl %cl,%eax,frac32(%ebp,%edi) ! 281: shll %cl,frac64(%ebp,%edi) ! 282: dubl_denorm_expon: ! 283: sub %ecx,expon(%ebp,%edi) // adjust exponent ! 284: ret ! 285: ALIGN ! 286: top_28_zero: ! 287: mov frac64(%ebp,%edi),%eax ! 288: bsrl %eax,%ecx ! 289: sub $31,%ecx ! 290: neg %ecx ! 291: shll %cl,%eax ! 292: mov %eax,frac32(%ebp,%edi) ! 293: movl $0,frac64(%ebp,%edi) ! 294: add $32,%ecx ! 295: jmp dubl_denorm_expon ! 296: ALIGN ! 297: double_invalid_: ! 298: cmpw $0x07ff,%ax ! 299: jne double_operand_is_valid ! 300: movl $0x7fff,expon(%ebp,%edi) // operand is nan or ! 301: andl $0x0fffffff,frac32(%ebp,%edi) // inf. set exponent. ! 302: mov frac32(%ebp,%edi),%eax // mask expon bits ! 303: or frac64(%ebp,%edi),%eax ! 304: movb infinty,tag(%ebp,%edi) ! 305: jz dubl_msb_set ! 306: movb inv,tag(%ebp,%edi) // invalid operand ! 307: testb $0x08,msb(%ebp,%edi) ! 308: jnz dubl_qnan ! 309: movb true,signal_i_error_ ! 310: testb invalid_mask,%gs:sr_masks ! 311: jz dubl_exit ! 312: dubl_qnan: ! 313: jmp norm_dubl_sgnfcnd ! 314: ALIGN ! 315: double_operand_is_valid: ! 316: add double_exp_offset,%eax // double_exp_offset ! 317: mov %eax,expon(%ebp,%edi) ! 318: movb valid,tag(%ebp,%edi) // set operand tag ! 319: norm_dubl_sgnfcnd: ! 320: mov frac64(%ebp,%edi),%eax ! 321: .byte 0x0f,0xa4,0x44,0x3d,0x08,0x03 //implements following inst. ! 322: // shldl $3,%eax,frac32(%ebp,%edi) ! 323: shll $3,frac64(%ebp,%edi) ! 324: dubl_msb_set: ! 325: orb $0x80,frac64+7(%ebp,%edi) //set leading bit ! 326: dubl_exit: ! 327: ret ! 328: //extend_double endp ! 329: // ! 330: // **************************************************************************** ! 331: // getx: ! 332: // ***** ! 333: // function: ! 334: // fetches extended-format fp number from memory, unpacks it, ! 335: // and sets its tag ! 336: // ! 337: // inputs: ! 338: // assumes mem_operand_pointer is set up ! 339: // edi points to operand1 or operand2 ! 340: // ! 341: // outputs: ! 342: // if number is valid, then exponent and msb set to all ones ! 343: // ! 344: // data accessed: ! 345: // - mem_operand_pointer extra_word_reg ! 346: // ! 347: // data changed: ! 348: // - operand extra_word_reg ! 349: // ! 350: // procedures called: ! 351: // test_4w test_3w ! 352: // set_d_error ! 353: // ! 354: // **************************************************************************** ! 355: ALIGN ! 356: getx: //proc ! 357: // push %ds // save a?msr ! 358: les mem_operand_pointer(%ebp),%esi // ds:esi ==> memop ! 359: // ! 360: getx_stackreg: ! 361: // push %ss ! 362: // pop %es // es:edi ==> operand ! 363: ! 364: add $frac64,%edi // bump di to frac64 ! 365: push %edi // save operand offset ! 366: lea (%ebp,%edi),%edi ! 367: // mov $0x0002,%ecx // move first four words ! 368: /* FAST_MOVSL */ ! 369: ! 370: movl %es:0(%esi),%ecx ! 371: movl %ecx,%ss:0(%edi) ! 372: movl %es:4(%esi),%ecx ! 373: movl %ecx,%ss:4(%edi) ! 374: // addl $8,%esi ! 375: // movl $0,%ecx ! 376: ! 377: movw %es:8(%esi),%ax // get sign/expon word ! 378: //.. pushad ! 379: //.. push ds ! 380: //..rep_loop: ! 381: //.. push esi ! 382: //.. call fpfulong ! 383: //.. pop esi ! 384: //.. stosd ! 385: //.. add esi,4 ! 386: //.. loop rep_loop ! 387: //.. push esi ! 388: //.. call fpfushort ! 389: //.. add esp,8 ! 390: //.. popad ! 391: //.. cld ! 392: //.. ! 393: pop %edi // reload operand offset ! 394: // pop %ds // reload a?msr ! 395: cwtd // transmit sign to dx ! 396: movb %dl,sign-frac64(%ebp,%edi)// and to operand ! 397: and $0x7fff,%eax // strip off sign bit ! 398: mov %eax,expon-frac64(%ebp,%edi) // store to operand ! 399: movl $0,before_error_signals(%ebp) // initialize both to false ! 400: jz expon_zero // branch if exponent 0 ! 401: testb $0x80,msb-frac64(%ebp,%edi) ! 402: jnz max_expon_ ! 403: movb unsupp,%dl // we have an ! 404: jmp getx_set_tag // unsupported format ! 405: ALIGN ! 406: max_expon_: ! 407: cmpw $0x7fff,%ax // check for invalid ! 408: je not_validx // or infinity ! 409: movb valid,%dl // operand is valid ! 410: getx_set_tag: ! 411: movb %dl,tag-frac64(%ebp,%edi) // set operand tag ! 412: xor %eax,%eax // (for stackreg return) ! 413: ret ! 414: ALIGN ! 415: not_validx: ! 416: movb infinty,%dl ! 417: mov frac32-frac64(%ebp,%edi),%eax ! 418: and $0x07fffffff,%eax ! 419: or (%ebp,%edi),%eax ! 420: jz getx_set_tag ! 421: movb inv,%dl // set tag to invalid ! 422: jmp getx_set_tag ! 423: ALIGN ! 424: expon_zero: ! 425: mov frac32-frac64(%ebp,%edi),%eax ! 426: or (%ebp,%edi),%eax ! 427: movb special,%dl // set tag to special ! 428: jz getx_set_tag // if number is +/- 0 ! 429: movb denormd,%dl // set tag to denormd ! 430: jmp getx_set_tag ! 431: ALIGN ! 432: //getx endp ! 433: // ! 434: // **************************************************************************** ! 435: // fetch_an_op: ! 436: // *********** ! 437: // function: ! 438: // fetches one operand(op1 or op2) and puts its parts ! 439: // in operand1 or operand2 ! 440: // ! 441: // inputs: ! 442: // location of op info in esi ! 443: // location of the operand in edi ! 444: // ! 445: // outputs: ! 446: // operand parts in operand1 or operand2 ! 447: // ! 448: // procedures called: ! 449: // mem_fetch_routine set_up_indefinite ! 450: // get_top ! 451: // getx_stackreg ! 452: // ! 453: // *************************************************************************** ! 454: fetch_location: ! 455: .long from_memory,from_stack_top,from_stack_minus_1 ! 456: .long from_stack_plus_1,from_reg ! 457: mem_fetch_routine: ! 458: .long extend_single,extend_double,float16,float32 ! 459: .long float64,getx,float16,float16,get_bcd ! 460: ALIGN ! 461: fetch_an_op: //proc ! 462: cmpb $null,format(%ebp,%esi)// if format = null, ! 463: je no_stack_error_on_fetch // then no operand to get ! 464: xor %ebx,%ebx ! 465: mov %ebx,(%ebp,%edi) // set low order dword of ! 466: movb location(%ebp,%esi),%bl // fraction to zero ! 467: shl $2,%ebx // handle each operand ! 468: jmp *%cs:fetch_location(%ebx) // location case separate ! 469: ALIGN ! 470: from_memory: ! 471: movb format(%ebp,%esi),%bl // form table offset ! 472: shl $2,%ebx ! 473: call *%cs:mem_fetch_routine(%ebx) // call routine to fetch ! 474: no_stack_error_on_fetch: ! 475: xor %eax,%eax // eax = 00000000h ! 476: ret ! 477: ALIGN ! 478: from_stack_top: ! 479: call get_top // get reg num in al ! 480: unpack_reg: ! 481: call reg_full_ // zf=1 (empty) cx=top ! 482: jz from_stack_plus_1 // error if reg empty ! 483: mov %ebx,%esi // reg_full returns ebx as pointer ! 484: // to stackoffset = ! 485: // (10*regnum) + offset regstack ! 486: // thus, ds:esi ==> regstack ! 487: // ! 488: // push %ds // stack a copy of a?msr ! 489: push %gs // set ds to address register stack ! 490: pop %es ! 491: jmp getx_stackreg // unpack register ! 492: ALIGN ! 493: from_stack_minus_1: ! 494: call get_top ! 495: incw %ax ! 496: jmp unpack_reg ! 497: ALIGN ! 498: from_reg: ! 499: call get_top ! 500: addb reg_num(%ebp),%al ! 501: jmp unpack_reg ! 502: ALIGN ! 503: from_stack_plus_1: ! 504: call set_up_indefinite // store indefinite opr ! 505: incw %ax // indicate stack error on return ! 506: ret ! 507: ! 508: //fetch_an_op endp ! 509: // ! 510: // ************************************************************************* ! 511: // get_bcd: ! 512: // ******** ! 513: // function: ! 514: // fetches a bcd number and converts it to an unpacked ! 515: // tempreal in operand1. ! 516: // inputs: ! 517: // assumes mem_operand_pointer is set up. ! 518: // ignores di and uses operand2 and result fields. ! 519: // ! 520: // outputs: ! 521: // unpacked operand in operand1 ! 522: // ! 523: // data accessed: ! 524: // - mem_operand_pointer expon1 ! 525: // - offset_operand1 sign1 ! 526: // - tag1 word_frac1 ! 527: // - offset_operand1 word_frac2 ! 528: // - lsb__frac2 offset_operand2 ! 529: // - result_word_frac offset_result ! 530: // ! 531: // data changed: ! 532: // - sign1 tag1 ! 533: // - expon1 word_frac1 ! 534: // - word_frac2 result_word_frac ! 535: // ! 536: // procedures called: ! 537: // left_shift move_op_to_result ! 538: // subtraction_normalize test_6w ! 539: // ! 540: // ****************************************************************************** ! 541: ALIGN ! 542: get_bcd: //proc ! 543: // push %ds // save a?msr ! 544: les mem_operand_pointer(%ebp),%esi ! 545: // push %ss // set up destination pointer ! 546: // pop %es ! 547: lea word_frac2,%edi // es:di ==> word_frac2 ! 548: // mov $0x0005,%ecx ! 549: ! 550: /* FAST_MOVSW */ ! 551: movl %es:0(%esi),%ecx ! 552: movl %ecx,%ss:0(%edi) ! 553: movl %es:4(%esi),%ecx ! 554: movl %ecx,%ss:4(%edi) ! 555: movw %es:8(%esi),%cx ! 556: movw %cx,%ss:8(%edi) ! 557: // addl $10,%esi ! 558: // movl $0,%ecx ! 559: ! 560: //.. ! 561: //.. pushad ! 562: //.. push ds ! 563: //..getbcd_loop: ! 564: //.. push esi ! 565: //.. call fpfushort ! 566: //.. pop esi ! 567: //.. stosw ! 568: //.. add esi,2 ! 569: //.. loop getbcd_loop ! 570: //.. pop ds ! 571: //.. popad ! 572: //.. cld ! 573: //.. ! 574: // pop %ds // reload a?msr ! 575: cmpw $0x0ffff,dword_frac1+10(%ebp) ! 576: jne accept_bcd ! 577: mov $offset_operand1,%edi ! 578: call set_up_indefinite ! 579: ret ! 580: ALIGN ! 581: accept_bcd: ! 582: movb msb_frac2,%al // get most significant byte ! 583: cbtw // and transmit sign to ah ! 584: movb %ah,sign1(%ebp) // store sign into operand ! 585: mov $offset_operand1,%edi // set frac1 to 0 ! 586: call clear_6w ! 587: movb $18,%cl //set loop count to 18 digits ! 588: FALLSTHRU ! 589: convert_loop: ! 590: push %ecx ! 591: movb $4,%cl //shift frac2 left 4 bits to ! 592: call left_shift_frac2_cl // the next digit ! 593: and $0x0f,msb_frac2 //clear previous digit ! 594: call left_shift_frac1_1 // frac1 <= 10*frac1 + frac2(9): ! 595: mov $offset_operand1,%esi // 1) frac1 <= frac1 * 2 ! 596: call move_op_to_result // 2) result_frac <= frac1 * 4 ! 597: movb $2,%cl ! 598: call left_shift_result_cl ! 599: // mov ax,(ebp).result_word_frac ; 3) frac1 <-- frac1 + ! 600: // add word_frac1,ax ; result_frac ! 601: // mov ax,(ebp).result_word_frac + 2 ! 602: // adc (ebp).word_frac1 + 2,ax ! 603: // mov ax,(ebp).result_word_frac + 4 ! 604: // adc (ebp).word_frac1 + 4,ax ! 605: // mov ax,(ebp).result_word_frac + 6 ! 606: // adc (ebp).word_frac1 + 6,ax ! 607: // mov ax,(ebp).result_word_frac + 8 ! 608: // adc (ebp).word_frac1 + 8,ax ! 609: // ! 610: mov result_dword_frac(%ebp),%eax // 3) frac1 <-- frac1 + ! 611: xorw %ax,%ax ! 612: add %eax,dword_frac1(%ebp) // result_frac ! 613: mov result_dword_frac+4(%ebp),%eax ! 614: adc %eax,dword_frac1+4(%ebp) ! 615: mov result_dword_frac+8(%ebp),%eax ! 616: adc %eax,dword_frac1+8(%ebp) ! 617: xor %eax,%eax // 4) frac1 <-- frac1 + frac(9) ! 618: movb msb_frac2,%al ! 619: addw %ax,word_frac1 ! 620: movb $0,%al ! 621: adc %eax,dword_frac1+4(%ebp) ! 622: adc %eax,dword_frac1+8(%ebp) ! 623: pop %ecx //and loop ! 624: LOOP(convert_loop) ! 625: mov $dword_frac1,%edi ! 626: call test_6w //frac1 = 0? ! 627: jnz make_floating_point ! 628: mov %eax,dword_expon1 //set expon and tag for zero ! 629: movb special,tag1(%ebp) ! 630: ret ! 631: ALIGN ! 632: make_floating_point: ! 633: movl $0x404e,dword_expon1 //set expon1 and normalize ! 634: mov $offset_operand1,%edi ! 635: call subtraction_normalize ! 636: movb valid,tag1(%ebp) //set tag to valid ! 637: ret ! 638: //get_bcd endp ! 639: // ! 640: // ****************************************************************************** ! 641: // put_result: ! 642: // ! 643: // function: ! 644: // puts result on 80387 stack or in 80387 register. ! 645: // implements 80387 load instruction. ! 646: // ! 647: // inputs: ! 648: // address of data parts (in edi register) ! 649: // address of result info (in esi). ! 650: // (ebp).before_error_signals ! 651: // outputs: ! 652: // stack error indication (in al register). ! 653: // ! 654: // data accessed: ! 655: // ! 656: // data changed: ! 657: // ! 658: // procedures called: ! 659: // decr_top stack_full? ! 660: // set_up_indefinite store_reg_tag ! 661: // get_top ! 662: // ! 663: // *************************************************************************** ! 664: location_case: ! 665: .long push_onto_stack ! 666: .long put_in_stack_top ! 667: .long put_in_stack_top_minus_1 ! 668: .long push_onto_stack ! 669: .long put_in_reg ! 670: // ! 671: ALIGN ! 672: load: //proc ! 673: jz put_zf_in_ah // if zf set, no stack error ! 674: call set_stk_u_error ! 675: testb invalid_mask,%gs:sr_masks // else, stack underflow error ! 676: jnz put_zf_in_ah // if i_error masked, continue ! 677: ret // else, return ! 678: ALIGN ! 679: put_zf_in_ah: // if zf is set here, no stack ! 680: lahf // underflow occurred. however, ! 681: // if zf is clear, stack underflow ! 682: // occurred and invalid is masked. ! 683: jnz put_op1_result ! 684: common_clear_a_bit: ! 685: andb $~a_mask,%gs:sr_flags ! 686: put_op1_result: ! 687: mov $offset_operand1,%edi // edi points to result record ! 688: put_si_result: ! 689: mov offset_result_rec,%esi // merge with put_result ! 690: put_result: ! 691: movzbl location(%ebp,%esi),%ebx //handle cases separately ! 692: shl $2,%ebx ! 693: jmp *%cs:location_case(%ebx) ! 694: ALIGN ! 695: put_in_stack_top_minus_1: ! 696: call get_top // put reg num of top-1 in al ! 697: incw %ax ! 698: jmp mask_top ! 699: ALIGN ! 700: push_onto_stack: ! 701: sahf // zf clear iff stack underflow occurred with ! 702: jnz push_value // invalid exception masked ! 703: call stack_full_ // is top - 1 full? ! 704: jz other_before_error_ // no, so detect other before errors. ! 705: call set_stk_o_error // set invalid error, stack bit, and ! 706: // c1 (a) bit ! 707: testb invalid_mask,%gs:sr_masks ! 708: jz exit_load // unmasked, so done with load ! 709: call set_up_indefinite // push indefinite as the result ! 710: jmp push_value ! 711: ALIGN ! 712: other_before_error_: ! 713: mov before_error_signals(%ebp),%eax ! 714: or %eax,%eax ! 715: jz push_value ! 716: orb %al,%al ! 717: jz check_z_error ! 718: orb invalid_mask,%gs:sr_errors ! 719: testb invalid_mask,%gs:sr_masks ! 720: jz exit_load // unmasked, so done with load ! 721: orb $0x40,msb(%ebp,%edi) ! 722: jmp push_value ! 723: ALIGN ! 724: check_z_error: ! 725: orb %ah,%ah ! 726: jz signal_d_error ! 727: orb zero_divide_mask,%gs:sr_errors ! 728: testb zero_divide_mask,%gs:sr_masks ! 729: jz exit_load // unmasked, so done with load ! 730: jmp push_value ! 731: ALIGN ! 732: signal_d_error: ! 733: orb denorm_mask,%gs:sr_errors ! 734: testb denorm_mask,%gs:sr_masks ! 735: jz exit_load // unmasked, so done with load ! 736: // the following seven instructions were added to cope with a load from ! 737: // memory to (new) 87 stack top of a short_real or long_real operand. ! 738: // otherwise, such loads of a denormal source operand while the denormal ! 739: // exception is masked would incorrectly tag the loaded, normalized ! 740: // temporary_real operand as invalid, instead of valid. the first four ! 741: // of these seven instructions have been commented out, because the ! 742: // executive procedure e80387 in the module *dcode* always initializes ! 743: // the op1_format field, even when its contents are deducible from the ! 744: // operation_type and op1_location fields, so it is enough to check ! 745: // whether the format field is single_real or double_real. ! 746: // cmp (ebp).operation_type, load_op ! 747: // jne push value ! 748: // cmp (ebp).op1_location, memory_opnd ! 749: // jne push_value ! 750: cmpb $double_real,op1_format(%ebp) ! 751: ja push_value ! 752: movb valid,tag(%ebp,%edi) ! 753: push_value: ! 754: call decr_top // decrement top for push ! 755: put_in_stack_top: ! 756: call get_top // put reg num of stack top in al ! 757: jmp mask_top ! 758: ALIGN ! 759: put_in_reg: ! 760: call get_top // put reg num specified in ! 761: addb reg_num(%ebp),%al // instruction in al ! 762: mask_top: ! 763: and $0x0007,%eax ! 764: mov %eax,%ecx // save reg num word in cx ! 765: movb tag(%ebp,%edi),%al // put new tag in al ! 766: call store_reg_tag ! 767: lea frac64(%ebp,%edi),%esi// ds:esi ==> operand frac64 ! 768: mov $sr_regstack,%edi // form offset within %gs:sr_regstack ! 769: add %ecx,%edi // for result (10 * reg num) ! 770: shl $2,%ecx ! 771: add %ecx,%edi // es:edi ==> treal st(reg num) ! 772: // mov $0x02,%ecx // count = 2 dwords ! 773: // push %gs // set segment registers ! 774: // pop %es ! 775: // push %ds ! 776: // push %ss ! 777: // pop %ds ! 778: ! 779: /* FAST_MOVSL */ ! 780: movl %ss:0(%esi),%ecx ! 781: movl %ecx,%gs:0(%edi) ! 782: movl %ss:4(%esi),%ecx ! 783: movl %ecx,%gs:4(%edi) ! 784: // addl $8,%esi ! 785: // addl $8,%edi ! 786: // movl $0,%ecx ! 787: ! 788: movb %ss:8(%esi),%ah // ah = sign of operand ! 789: andw $0x8000,%ax // form tempreal exponent ! 790: orw %ss:12(%esi),%ax ! 791: // pop %ds // reload a?msr into ds ! 792: movw %ax,%gs:8(%edi) // exponent => %gs:sr_regstack ! 793: exit_load: ! 794: ret ! 795: //load endp ! 796: // ! 797: // ***************************************************************************** ! 798: // stack_full?: ! 799: // ! 800: // function: ! 801: // checks stack to see if an attempted push will ! 802: // generate a stack error. ! 803: // ! 804: // inputs: ! 805: // tag for register on top of stack ! 806: // ! 807: // outputs: ! 808: // zf = true if stack is empty; zf = false if stack is full. ! 809: // ! 810: // procedures called: ! 811: // get_top get_reg_tag ! 812: // ! 813: // ***************************************************************************** ! 814: ALIGN ! 815: stack_full_: //proc ! 816: call get_top // determine reg no. of (top-1) ! 817: decw %ax ! 818: reg_full_: ! 819: andb $0x07,%al ! 820: call get_reg_tag ! 821: cmpb $empty,%al // if (top-1) is not empty, ! 822: return: ! 823: ret // then stack is full ! 824: //stack_full_ endp ! 825: // ! 826: // ************************************************************************ ! 827: // decompose: ! 828: // ! 829: // function: ! 830: // decomposes op1 into two parts ! 831: // ! 832: // inputs: ! 833: // assumes op1 is set up, with tag1 /= unsupp and tag1 /= inv ! 834: // ! 835: // outputs: ! 836: // puts the exponent, floated in op1; the fraction in op2 ! 837: // ! 838: // data accessed: ! 839: // - offset_operand sign1 ! 840: // - tag1 expon1 ! 841: // - offset_operand2 sign2 ! 842: // - tag2 expon2 ! 843: // ! 844: // data changed: ! 845: // - sign2 expon2 ! 846: // ! 847: // procedures called: ! 848: // float_int32 move_op_to_op ! 849: // ! 850: // **************************************************************************** ! 851: ALIGN ! 852: decompose: //proc ! 853: lea dword_frac1(%ebp),%esi // move op1 to op2 ! 854: lea dword_frac2(%ebp),%edi ! 855: call move_op_to_op ! 856: cmpb valid,tag1(%ebp) ! 857: jne is_op1_denorm_ ! 858: put_sig_in_op2: ! 859: movl $exponent_bias,dword_expon2 // set op2 exponent=bias ! 860: put_exp_in_op1: ! 861: mov dword_expon1,%eax // float exp into op1 ! 862: unbias_expon: ! 863: sub $exponent_bias,%eax // first unbias it ! 864: mov $offset_operand1,%edi ! 865: jmp float_int32 ! 866: ALIGN ! 867: is_op1_denorm_: ! 868: cmpb denormd,tag1(%ebp) ! 869: jne op1_zero_or_inf ! 870: movb true,signal_d_error_ ! 871: testb denorm_mask,%gs:sr_masks // short cut if unmasked d-error ! 872: jz interim_exit ! 873: mov $offset_operand2,%edi ! 874: call norm_denorm ! 875: mov dword_expon2,%eax ! 876: movl $exponent_bias,dword_expon2 // set op2 exponent=bias ! 877: jmp unbias_expon ! 878: ALIGN ! 879: op1_zero_or_inf: ! 880: cmpb special,tag1(%ebp) ! 881: je op1_zero // op1 and op2 are infinite ! 882: movb positive,sign1(%ebp) ! 883: interim_exit: ! 884: ret ! 885: ALIGN ! 886: op1_zero: ! 887: movb true,signal_z_error_ // if number=0, signal z-error ! 888: testb zero_divide_mask,%gs:sr_masks // if z_error is unmasked ! 889: jz interim_exit // then just return ! 890: make_op1_negative_inf: ! 891: movl $0x07fff,dword_expon1 // else, make op1 -infinity ! 892: movb $0x80,msb_frac1 ! 893: movl infinty*0x10000+NEGATIVE,sign1(%ebp) ! 894: ret ! 895: //decompose endp ! 896: // ! 897: // ************************************************************************** ! 898: // float16: ! 899: // ! 900: // function: ! 901: // retrieves a 16-bit, 2s complement integer from memory, ! 902: // and fills in the operand ! 903: // ! 904: // inputs: ! 905: // assumes mem_operand_pointer is set up ! 906: // edi points to operand1 or operand2 ! 907: // ! 908: // outputs: ! 909: // operand ! 910: // ! 911: // data accessed: ! 912: // - mem_operand_pointer ! 913: // ! 914: // data changed: ! 915: // - operand ! 916: // ! 917: // procedures called: ! 918: // float_int32 ! 919: // ! 920: // *************************************************************************** ! 921: ALIGN ! 922: float16: //proc ! 923: les mem_operand_pointer(%ebp),%ebx // fetch the ! 924: // 16-bit integer ! 925: movw %es:(%ebx),%ax ! 926: //.. ! 927: //.. pushad ! 928: //.. push es ! 929: //.. push ebx ! 930: //.. call fpfushort ! 931: //.. add esp,8 ! 932: //.. popad ! 933: //.. cld ! 934: //.. ! 935: float_int16: ! 936: movswl %ax,%eax ! 937: jmp float_int32 ! 938: ALIGN ! 939: // ! 940: // ! 941: // ! 942: // ***************************************************************************** ! 943: // float32: ! 944: // ! 945: // function: ! 946: // retrieves a 32-bit, 2s complement integer from memory ! 947: // and fills in the operand ! 948: // ! 949: // inputs: ! 950: // assumes mem_operand_pointer is set up ! 951: // edi points to operand1 or operand2 ! 952: // ! 953: // outputs: ! 954: // operand ! 955: // ! 956: // data accessed: ! 957: // - mem_operand_pointer ! 958: // ! 959: // data changed: ! 960: // - operand ! 961: // ! 962: // procedures called: ! 963: // ! 964: // ! 965: // ***************************************************************************** ! 966: float32: ! 967: les mem_operand_pointer(%ebp),%ebx ! 968: ! 969: mov %es:(%ebx),%eax // move from memory to eax ! 970: ! 971: //.. ! 972: //.. pushad ! 973: //.. push es ! 974: //.. push ebx ! 975: //.. call fpfulong ! 976: //.. add esp,8 ! 977: //.. popad ! 978: //.. cld ! 979: ! 980: float_int32: ! 981: mov %eax,%edx // save integer in edx ! 982: xor %eax,%eax // clear low 8 bytes ! 983: mov %eax,(%ebp,%edi) ! 984: mov %eax,frac64(%ebp,%edi) ! 985: or %edx,%eax // if integer is zero, ! 986: jnz get_sign_and_mag_32 // then load +0 ! 987: mov %eax,frac32(%ebp,%edi) ! 988: movb %al,sign(%ebp,%edi) ! 989: movb special,tag(%ebp,%edi) ! 990: mov %eax,expon(%ebp,%edi) ! 991: ret ! 992: ALIGN ! 993: get_sign_and_mag_32: ! 994: cltd // transmit sign to edx ! 995: movb %dl,sign(%ebp,%edi) // and store to operand ! 996: jns positive_int // branch if positive ! 997: neg %eax // negate if negative ! 998: positive_int: ! 999: bsrl %eax,%ecx ! 1000: sub $31,%ecx ! 1001: neg %ecx ! 1002: shl %cl,%eax ! 1003: mov %eax,frac32(%ebp,%edi) // store normalized{abs(int)} ! 1004: mov $0x401e,%eax // load valid exponent ! 1005: sub %ecx,%eax ! 1006: mov %eax,expon(%ebp,%edi) ! 1007: movb valid,tag(%ebp,%edi) ! 1008: ret ! 1009: ALIGN ! 1010: //float16 endp ! 1011: // ! 1012: // ****************************************************************************** ! 1013: // float64: ! 1014: // ! 1015: // function: ! 1016: // retrieves a 64-bit, 2s complement integer from memory ! 1017: // and fills in the operand ! 1018: // ! 1019: // inputs: ! 1020: // assumes mem_operand_pointer is set up ! 1021: // edi points to operand1 or operand2 ! 1022: // ! 1023: // outputs: ! 1024: // operand ! 1025: // ! 1026: // data accessed: ! 1027: // - mem_operand_pointer ! 1028: // ! 1029: // data changed: ! 1030: // - operand ! 1031: // ! 1032: // procedures called: ! 1033: // ! 1034: // ! 1035: // **************************************************************************** ! 1036: ALIGN ! 1037: float64: //proc ! 1038: // push %ds // save a?msr ! 1039: les mem_operand_pointer(%ebp),%esi ! 1040: // push %ss ! 1041: // pop %es // es:edi ==> operand ! 1042: push %edi // save op? offset ! 1043: lea frac64(%ebp,%edi),%edi // set operand offset ! 1044: // mov $0x0002,%ecx // move fraction from ! 1045: ! 1046: /* FAST_MOVSL */ ! 1047: movl %es:0(%esi),%ecx ! 1048: movl %ecx,%ss:0(%edi) ! 1049: movl %es:4(%esi),%ecx ! 1050: movl %ecx,%ss:4(%edi) ! 1051: // addl $8,%esi ! 1052: // addl $8,%edi ! 1053: // movl $0,%ecx ! 1054: ! 1055: //.. ! 1056: //.. pushad ! 1057: //.. push ds ! 1058: //..float64_loop: ! 1059: //.. push esi ! 1060: //.. call fpfulong ! 1061: //.. pop esi ! 1062: //.. add esi,4 ! 1063: //.. stosd ! 1064: //.. loop float64_loop ! 1065: //.. pop ds ! 1066: //.. popad ! 1067: //.. cld ! 1068: //.. ! 1069: pop %edi // reload operand offset ! 1070: // pop %ds // reload a?msr ! 1071: mov frac32(%ebp,%edi),%eax // get long integer sign ! 1072: cltd // transmit sign to edx ! 1073: movb %dl,sign(%ebp,%edi) // and store to operand ! 1074: inc %edx // test for '-' fract ! 1075: jnz detect_zero_64 ! 1076: notl frac64(%ebp,%edi) // '-', so form 2s ! 1077: add $1,frac64(%ebp,%edi) // complement ! 1078: notl frac32(%ebp,%edi) ! 1079: adc $0,frac32(%ebp,%edi) ! 1080: jmp set_expon_64 ! 1081: ALIGN ! 1082: detect_zero_64: ! 1083: or frac64(%ebp,%edi),%eax ! 1084: jnz set_expon_64 ! 1085: mov %eax,expon(%ebp,%edi) // set expon = zero ! 1086: movb special,tag(%ebp,%edi) ! 1087: ret ! 1088: ALIGN ! 1089: set_expon_64: ! 1090: movl $0x403e,expon(%ebp,%edi) //set expon = 63 ! 1091: bsrl frac32(%ebp,%edi),%ecx ! 1092: jz top_32_zero ! 1093: mov frac64(%ebp,%edi),%eax ! 1094: sub $31,%ecx ! 1095: neg %ecx ! 1096: shldl %cl,%eax,frac32(%ebp,%edi) ! 1097: shl %cl,frac64(%ebp,%edi) ! 1098: adjust_norm_expon: ! 1099: sub %ecx,expon(%ebp,%edi) // adjust exponent ! 1100: ret ! 1101: ALIGN ! 1102: top_32_zero: ! 1103: mov frac64(%ebp,%edi),%eax ! 1104: bsrl %eax,%ecx ! 1105: sub $31,%ecx ! 1106: neg %ecx ! 1107: shl %cl,%eax ! 1108: mov %eax,frac32(%ebp,%edi) ! 1109: movl $0,frac64(%ebp,%edi) ! 1110: add $32,%ecx ! 1111: jmp adjust_norm_expon ! 1112: ALIGN ! 1113: //float64 endp ! 1114: // ! 1115: // *************************************************************************** ! 1116: // save: ! 1117: // ! 1118: // function: ! 1119: // implements 80387 save instruction ! 1120: // ! 1121: // inputs: ! 1122: // ! 1123: // outputs: ! 1124: // ! 1125: // data accessed: ! 1126: // - mem_operand_pointer result_rec_offset ! 1127: // ! 1128: // data changed: ! 1129: // ! 1130: // procedures called: ! 1131: // save_status save_regs init ! 1132: // ! 1133: // ************************************************************************** ! 1134: ALIGN ! 1135: save: //proc ! 1136: call save_status ! 1137: call save_regs ! 1138: jmp init // initialize environment ! 1139: //save endp ! 1140: // ! 1141: // ************************************************************************* ! 1142: // save_regs: ! 1143: // ! 1144: // function: ! 1145: // saves all registers in contiguous memory locations. ! 1146: // ! 1147: // inputs: ! 1148: // memory operand pointer (in es:(di)) ! 1149: // ! 1150: // outputs: ! 1151: // ! 1152: // data accessed: ! 1153: // ! 1154: // data changed: ! 1155: // ! 1156: // procedures called: ! 1157: // get_top ! 1158: // ! 1159: // *************************************************************************** ! 1160: ALIGN ! 1161: save_regs: //proc ! 1162: movb $5,%cl // 5 words per register ! 1163: call get_top // ax = top * 5 ! 1164: push %ds // set source seg register ! 1165: push %gs ! 1166: pop %ds ! 1167: mulb %cl ! 1168: movw $40,%cx // number words to move ! 1169: subw %ax,%cx // from top of stack = ! 1170: mov $sr_regstack,%esi // 40 - top*5 ! 1171: push %esi // starting address = ! 1172: cwtl ! 1173: add %eax,%esi // %gs:sr_regstack + top*5 ! 1174: add %eax,%esi // *2 bytes/word ! 1175: movzwl %cx,%ecx ! 1176: FAST_MOVSW ! 1177: movw %ax,%cx // move (top * 5) words ! 1178: pop %esi // load starting address ! 1179: FAST_MOVSW ! 1180: pop %ds // restore %ds ! 1181: ret ! 1182: //save_regs endp ! 1183: // ! 1184: // ***************************************************************************** ! 1185: // restore_regs: ! 1186: // ! 1187: // function: ! 1188: // loads all registers from contiguous memory locations ! 1189: // implements 80387 restore instruction ! 1190: // ! 1191: // inputs: ! 1192: // mem_operand_pointer ! 1193: // ! 1194: // outputs: ! 1195: // loads the %gs:sr_regstack area of a?msr from memory ! 1196: // ! 1197: // data accessed: ! 1198: // ! 1199: // data changed: ! 1200: // - operand ! 1201: // ! 1202: // procedures called: ! 1203: // restore_status get_top ! 1204: // ! 1205: // ************************************************************************* ! 1206: ALIGN ! 1207: restore: //proc ! 1208: call restore_status // this call defines es ! 1209: restore_regs: ! 1210: movb $5,%cl // 5 words per register ! 1211: call get_top ! 1212: push %ds // save a?msr ! 1213: // pop %es ! 1214: // push %ds ! 1215: mulb %cl // ax = top*5 ! 1216: mov $40,%ecx // number words to move ! 1217: subw %ax,%cx // from top of stack = ! 1218: mov $sr_regstack,%edi // 40 - top*5 ! 1219: push %edi // starting address = ! 1220: cwtl ! 1221: add %eax,%edi // %gs:sr_regstack + top*5 ! 1222: add %eax,%edi // *2 bytes/word ! 1223: lds mem_operand_pointer(%ebp),%esi // source is in memory ! 1224: add $14,%esi ! 1225: cmpb $1,oprnd_siz32(%ebp) //is it a 32 bit operand ! 1226: jne status16 //no restore 16 bit status ! 1227: add $14,%esi // skip the environment ! 1228: // --------replace following line for unix ! 1229: status16: ! 1230: FAST_MOVSW ! 1231: ! 1232: //.. ! 1233: //.. pushad ! 1234: //.. push ds ! 1235: //..restor_loop: ! 1236: //.. push esi ! 1237: //.. call fpfushort ! 1238: //.. pop esi ! 1239: //.. stosw ! 1240: //.. add esi,2 ! 1241: //.. loop restor_loop ! 1242: //.. pop ds ! 1243: //.. popad ! 1244: //.. cld ! 1245: //.. ! 1246: movw %ax,%cx ! 1247: pop %edi // load starting address ! 1248: FAST_MOVSW ! 1249: pop %ds // reload a?msr ! 1250: jmp correct_tag_word ! 1251: ! 1252: // ret ! 1253: //restore endp ! 1254: // ! 1255: // ***************************************************************************** ! 1256: // set_up_indefinite: ! 1257: // ! 1258: // function: ! 1259: // puts indefinite in the operand pointed to by edi ! 1260: // ! 1261: // input: ! 1262: // edi points to operand ! 1263: // ! 1264: // output: ! 1265: // indefinite in operand, eax = 0, zf set (zf = 1) ! 1266: // ! 1267: // data accessed: ! 1268: // - operand ! 1269: // ! 1270: // data changed: ! 1271: // - operand ! 1272: // ! 1273: // **************************************************************************** ! 1274: ALIGN ! 1275: set_up_indefinite: //proc ! 1276: xor %eax,%eax ! 1277: mov %eax,frac64(%ebp,%edi) //set up indef fraction ! 1278: movl $0x0c0000000,frac32(%ebp,%edi) ! 1279: movb negative,sign(%ebp,%edi) //set sign negative ! 1280: movl $0x7fff,expon(%ebp,%edi) //set exponent to 7fffh ! 1281: movb inv,tag(%ebp,%edi) //set tag to invalid ! 1282: common_return: ! 1283: ret ! 1284: ALIGN ! 1285: //set_up_indefinite endp ! 1286: // ! 1287: // *********************************************************************** ! 1288: // exchange ! 1289: // ! 1290: // ! 1291: // function: ! 1292: // implements 80387 exchange instruction ! 1293: // ! 1294: // inputs: ! 1295: // operand(s) in operands ! 1296: // ! 1297: // outputs: ! 1298: // result(s) on stack ! 1299: // ! 1300: // data accessed: ! 1301: // - result_rec_offset offset_operand1 ! 1302: // ! 1303: // data changed: ! 1304: // ! 1305: // procedures called: ! 1306: // put_result set_stk_u_error ! 1307: // ! 1308: // ************************************************************************* ! 1309: ALIGN ! 1310: exchange: //proc ! 1311: jz do_exchange // if zf clear, then stack error ! 1312: call set_stk_u_error ! 1313: testb invalid_mask,%gs:sr_masks ! 1314: jz common_return // if unmasked error, do nothing ! 1315: do_exchange: ! 1316: // call common_clear_a_bit / put op1(top) in result(reg) ! 1317: and $~a_mask,%gs:sr_flags ! 1318: do_exchange_leave_a_bit: ! 1319: call put_op1_result ! 1320: set_zf_put_second_result: ! 1321: xor %eax,%eax // set 86 zf ! 1322: lahf // save set zf in ah ! 1323: put_second_result: ! 1324: mov $offset_operand2,%edi // put op2(reg) in res2(top) ! 1325: mov offset_result2_rec,%esi ! 1326: jmp put_result ! 1327: //exchange endp ! 1328: // ! 1329: // *********************************************************************** ! 1330: // exam: ! 1331: // ! 1332: // function: ! 1333: // implements 80387 fxam instruction ! 1334: // ! 1335: // inputs: ! 1336: // operand1 ! 1337: // ! 1338: // outputs: ! 1339: // operand type indicators set ! 1340: // ! 1341: // data accessed: ! 1342: // - tag1 sign1 ! 1343: // - msb_frac1 ! 1344: // ! 1345: // data changed: ! 1346: // ! 1347: // procedures called: ! 1348: // ! 1349: // *********************************************************************** ! 1350: ALIGN ! 1351: exam: //proc ! 1352: jz something_on_stack // branch on no stack error ! 1353: orb $(zero_mask+sign_mask),%gs:sr_flags // set s and z bits ! 1354: andb $~(a_mask+c_mask),%gs:sr_flags // clear a and c bits ! 1355: jmp check_a_bit ! 1356: ALIGN ! 1357: something_on_stack: ! 1358: andb $~(zero_mask+c_mask+a_mask+sign_mask),%gs:sr_flags ! 1359: // clear condition code bits ! 1360: movb tag1(%ebp),%al ! 1361: cmpb unsupp,%al ! 1362: je check_a_bit ! 1363: cmpb inv,%al // remove special cases ! 1364: je check_z_s_a_bits ! 1365: cmpb infinty,%al ! 1366: je set_c_to_one ! 1367: cmpb denormd,%al ! 1368: jne valid_or_zero ! 1369: orb $(zero_mask+c_mask),%gs:sr_flags // set s, z, c to 0, 1, 1 ! 1370: // for denormalized op ! 1371: jmp check_a_bit ! 1372: ALIGN ! 1373: valid_or_zero: ! 1374: testb $0x80,msb_frac1 // for valid or zero, ! 1375: jz check_z_s_a_bits // set c to msb of frac ! 1376: set_c_to_one: ! 1377: orb $c_mask,%gs:sr_flags ! 1378: check_z_s_a_bits: ! 1379: rorb $1,%al // set z-bit to lsb of tag1 ! 1380: jnc check_s_a_bits ! 1381: orb $zero_mask,%gs:sr_flags ! 1382: check_s_a_bits: ! 1383: rorb $1,%al // set s-bit to lsb-1 of tag1 ! 1384: jnc check_a_bit ! 1385: orb $sign_mask,%gs:sr_flags ! 1386: check_a_bit: ! 1387: testb $0x01,sign1(%ebp) // set a-bit to sign bit ! 1388: jz exchange_return ! 1389: orb $a_mask,%gs:sr_flags // set_a_bit ! 1390: exchange_return: ! 1391: ret ! 1392: //exam endp ! 1393: // ! 1394: // *********************************************************************** ! 1395: // fxtrac: ! 1396: // ! 1397: // function: ! 1398: // implements the 80387 fxtrac instruction ! 1399: // ! 1400: // inputs: ! 1401: // ! 1402: // outputs: ! 1403: // decomposed results in results ! 1404: // ! 1405: // data accessed: ! 1406: // - result_rec_offset result2_rec_offset ! 1407: // - offset_operand1 tag1 ! 1408: // - offset_operand2 ! 1409: // ! 1410: // data changed: ! 1411: // ! 1412: // procedures called: ! 1413: // set_up_indefinite decompose ! 1414: // do_exchange ! 1415: // ! 1416: // *********************************************************************** ! 1417: ALIGN ! 1418: fxtrac: //proc ! 1419: jz detect_i_error // branch if no stack error ! 1420: call set_stk_u_error // set invalid error and stack bit, but ! 1421: // clear c1 (a) bit ! 1422: testb invalid_mask,%gs:sr_masks ! 1423: jz quick_out // branch if error unmasked ! 1424: mov $offset_operand2,%edi // for masked invalid error, ! 1425: call set_up_indefinite // set op2 to indefinite ! 1426: orb true,%al // clear zf to indicate that ! 1427: lahf // stack underflow occurred. ! 1428: jmp put_second_result ! 1429: ALIGN ! 1430: detect_i_error: ! 1431: call stack_full_ ! 1432: jz other_i_error_ ! 1433: jmp set_zf_put_second_result ! 1434: ALIGN ! 1435: other_i_error_: ! 1436: andb $~a_mask,%gs:sr_flags // clear a-bit ! 1437: movl $0,before_error_signals(%ebp) // initialize all to zero ! 1438: movb tag1(%ebp),%al // load operand tag ! 1439: cmpb unsupp,%al ! 1440: jne is_op1_nan_ ! 1441: testb invalid_mask,%gs:sr_masks // short cut if unmasked i-error ! 1442: jnz put_indef_in_op1 ! 1443: unmasked_i_error: ! 1444: orb invalid_mask, %gs:sr_errors ! 1445: quick_out: ! 1446: ret // return if unmasked error ! 1447: ALIGN ! 1448: put_indef_in_op1: ! 1449: mov $offset_operand1, %edi ! 1450: call set_up_indefinite ! 1451: jmp masked_i_error ! 1452: ALIGN ! 1453: is_op1_nan_: ! 1454: cmpb inv,%al ! 1455: jne do_decompose ! 1456: testb $0x40,msb_frac1 // is op1 a signaling nan? ! 1457: jnz op1_is_qnan ! 1458: testb invalid_mask,%gs:sr_masks ! 1459: jz unmasked_i_error ! 1460: orb $0x40,msb_frac1 // make op1 a quiet nan ! 1461: masked_i_error: ! 1462: movb true, signal_i_error_ ! 1463: op1_is_qnan: ! 1464: lea dword_frac1(%ebp),%esi // move op1 to op2 ! 1465: lea dword_frac2(%ebp),%edi ! 1466: call move_op_to_op ! 1467: call put_op1_result // no push occurs here ! 1468: jmp set_zf_put_second_result // put both results ! 1469: ALIGN ! 1470: do_decompose: ! 1471: call decompose ! 1472: jmp do_exchange // put both results ! 1473: ALIGN ! 1474: //fxtrac endp ! 1475: // ! 1476: // *********************************************************************** ! 1477: // abs_value: ! 1478: // ! 1479: // function: ! 1480: // implements the 80387 absolute value instruction ! 1481: // ! 1482: // inputs: ! 1483: // assumes operand is set up ! 1484: // ! 1485: // outputs: ! 1486: // absolute value of operand in result ! 1487: // ! 1488: // procedures called: ! 1489: // set_stk_u_error ! 1490: // ! 1491: // *************************************************************************** ! 1492: ALIGN ! 1493: abs_value: //proc ! 1494: jz do_abs_value // branch if no stack error ! 1495: call set_stk_u_error // set invalid error and stack bit, ! 1496: // but clear c1 (a) bit ! 1497: testb invalid_mask,%gs:sr_masks ! 1498: jnz abs_value_result // masked error, so give indef already ! 1499: common_exit: // set up in operand1 by fetch_an_op. ! 1500: ret // unmasked error ! 1501: ALIGN ! 1502: do_abs_value: ! 1503: movb positive,sign1(%ebp)// set sign to positive ! 1504: abs_value_result: ! 1505: jmp common_clear_a_bit // put result on stack ! 1506: //abs_value endp ! 1507: // ! 1508: // *********************************************************************** ! 1509: // chsign: ! 1510: // ! 1511: // function: ! 1512: // implement the 80387 chsign instruction ! 1513: // ! 1514: // inputs: ! 1515: // operand1 ! 1516: // ! 1517: // outputs: ! 1518: // result <== -(operand1) ! 1519: // ! 1520: // procedures called: ! 1521: // set_stk_u_error ! 1522: // ! 1523: // ************************************************************************ ! 1524: ALIGN ! 1525: chsign: //proc ! 1526: jz do_chsign // branch if no stack error ! 1527: call set_stk_u_error // set invalid error and stack bit, but ! 1528: // clear c1 (a) bit ! 1529: testb invalid_mask,%gs:sr_masks ! 1530: jnz chsign_result // put op1, set up as qnan indefinite ! 1531: ret // by fetch_an_op, into result ! 1532: ALIGN ! 1533: do_chsign: ! 1534: notb sign1(%ebp) // complement sign ! 1535: chsign_result: ! 1536: jmp common_clear_a_bit // put op1 into result ! 1537: ALIGN ! 1538: //chsign endp ! 1539: // ! 1540: //a_med ends ! 1541: // ! 1542: // end
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.