|
|
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 "trans.s" ! 26: ! 27: .ident "@(#)kern-fp:trans.s 1.1" ! 28: // ***************************************************************************** ! 29: // ! 30: // t r a n s . m o d ! 31: // ================= ! 32: // ! 33: // =============================================================== ! 34: // intel corporation proprietary information ! 35: // this software is supplied under the terms of a license ! 36: // agreement or non-disclosure agreement with intel corporation ! 37: // and may not be copied nor disclosed except in accordance with ! 38: // the terms of that agreement. ! 39: // =============================================================== ! 40: // ! 41: // public procedures: ! 42: // arctan, exp, log, splog, tan, move_10_bytes ! 43: // move_constant, test_5w, ,test_6w, test_4w, test_3w, clear_5w, clear_6w ! 44: // set_5w, set_6w,set_4w, set_3w, left_shift_result_cl ! 45: // left_shift_frac1_cl, left_shift_frac2_cl ! 46: // right_shift_result_cl,right_shift_frac1_cl ! 47: // right_shift_frac2_cl,right_shift,left_shift ! 48: // sticky_right_shift,addition_normalize ! 49: // subtraction_normalize,one_left_normalize ! 50: // gradual_underflow,left_shift_frac1_1,sin,cos,sincos ! 51: // ! 52: // ***************************************************************************** ! 53: // ! 54: // ! 55: //...october 16, 1986... ! 56: // ! 57: //$nolist ! 58: #include "fp_e80387.h" ! 59: //$list ! 60: .text //a_med segment er public ! 61: // ! 62: // extrn put_si_result,do_exchange,addx,subx ! 63: // extrn divx,divid,round,underflow_response ! 64: // extrn log_divx,decompose,mult,mulx ! 65: // extrn overflow_response,sp_subadd,stack_full_ ! 66: // extrn pop_free,put_op1_result,set_p_error ! 67: // extrn set_u_error,get_precision,do_exchange_leave_a_bit ! 68: // ! 69: .globl two_arg_trans ! 70: .globl exp ! 71: .globl log ! 72: .globl splog ! 73: .globl move_10_bytes ! 74: .globl tan ! 75: .globl move_constant ! 76: .globl test_5w ! 77: .globl test_6w ! 78: .globl test_4w ! 79: .globl test_3w ! 80: .globl clear_5w ! 81: .globl clear_6w ! 82: .globl set_5w ! 83: .globl set_6w ! 84: .globl set_4w ! 85: .globl set_3w ! 86: .globl left_shift_frac1_cl ! 87: .globl left_shift_result_cl ! 88: .globl left_shift_frac2_cl ! 89: .globl right_shift_frac1_cl ! 90: .globl right_shift_frac2_cl ! 91: .globl right_shift_result_cl ! 92: .globl right_shift ! 93: .globl left_shift ! 94: .globl gradual_underflow ! 95: .globl addition_normalize ! 96: .globl sticky_right_shift ! 97: .globl one_left_normalize ! 98: .globl subtraction_normalize ! 99: .globl left_shift_frac1_1 ! 100: .globl sin ! 101: .globl cos ! 102: .globl sincos ! 103: // ! 104: // ! 105: add_half_pattern: ! 106: .value 0x80,0,0,0,0 ! 107: add_half_pattern_1: ! 108: .value 0x8000,0,0,0,0 ! 109: constant_ln2_ov_6: ! 110: .value 0,0,0,0x1ff5,0x0ec98 ! 111: constant_2_ov_ln2: ! 112: .value 0x0bbc0,0x17f0,0x295c,0x0aa3b,0x00b8 ! 113: constant_one: ! 114: .value 0,0,0,0,0x100 ! 115: constant_six: ! 116: .value 0,0,0,0,0x0c000 ! 117: constant_sqrt_of_2: ! 118: .value 0x8400,0x0de64,0x33f9,0x04f3,0x0b5 ! 119: constant_3_ov_ln2: ! 120: .value 0,0x0f48d,0x0511,0x0ac5f,0x8a7f ! 121: constant_one_1: ! 122: .value 0,0,0,0,0x8000 ! 123: // ! 124: // this constant has been decreased by 1 to compensate ! 125: // for the bits lost during right shift. ! 126: // ! 127: constant_c0h: ! 128: .value 0x0ff00,0x0ffff,0x0ffff,0x0ffff,0x0bf ! 129: // ! 130: log_constant: ! 131: .value 0x09fa0,0x0d687,0x039fb,0x0c01a,0x095 //1 ! 132: .value 0x0f260,0x0dc57,0x05e68,0x0d3c2,0x0a4 //2 ! 133: .value 0x0fd20,0x0b43c,0x0cfde,0x000d1,0x0ae //3 ! 134: .value 0x0e680,0x098b3,0x0d648,0x01fb7,0x0b3 //4 ! 135: .value 0x089c0,0x0ec39,0x0ac77,0x0d69b,0x0b5 //5 ! 136: .value 0x05380,0x0914c,0x02e16,0x03cb4,0x0b7 //6 ! 137: .value 0x0fc80,0x0428b,0x0b778,0x0f285,0x0b7 //7 ! 138: .value 0x056e0,0x063ba,0x06bd5,0x04e23,0x0b8 //8 ! 139: .value 0x031e0,0x0ab26,0x0f853,0x07c1f,0x0b8 //9 ! 140: .value 0x0fd60,0x0a2a0,0x0ba1f,0x09329,0x0b8 //a ! 141: .value 0x057c0,0x0be18,0x07bca,0x09eb1,0x0b8 //b ! 142: .value 0x070a0,0x0fe44,0x0150d,0x0a476,0x0b8 //c ! 143: .value 0x0aa60,0x09b1b,0x08fd2,0x0a758,0x0b8 //d ! 144: .value 0x09460,0x09ae9,0x0d8be,0x0a8c9,0x0b8 //e ! 145: .value 0x03380,0x02572,0x08017,0x0a982,0x0b8 //f ! 146: // ! 147: tan_constant: ! 148: .value 0x034c0,0x068c2,0x0a221,0x00fda,0x0c9 //0 ! 149: .value 0x04580,0x0da7b,0x02b0d,0x06338,0x0ed //1 ! 150: .value 0x01560,0x006eb,0x0c964,0x0dbaf,0x0fa //2 ! 151: .value 0x032c0,0x07b6e,0x0d561,0x0add4,0x0fe //3 ! 152: .value 0x036c0,0x0ef4e,0x0b967,0x0aadd,0x0ff //4 ! 153: .value 0x04280,0x0b125,0x0dd4b,0x0eaad,0x0ff //5 ! 154: .value 0x0bbe0,0x094d5,0x0dddb,0x0faaa,0x0ff //6 ! 155: .value 0x06800,0x0d4b9,0x0addd,0x0feaa,0x0ff //7 ! 156: .value 0x04bc0,0x0ddb9,0x0aadd,0x0ffaa,0x0ff //8 ! 157: .value 0x04ba0,0x0dddd,0x0aaad,0x0ffea,0x0ff //9 ! 158: .value 0x0dba0,0x0dddd,0x0aaaa,0x0fffa,0x0ff //a ! 159: .value 0x0dde0,0x0addd,0x0aaaa,0x0fffe,0x0ff //b ! 160: .value 0x0dde0,0x0aadd,0x0aaaa,0x0ffff,0x0ff //c ! 161: .value 0x0dde0,0x0aaad,0x0eaaa,0x0ffff,0x0ff //d ! 162: .value 0x0dde0,0x0aaaa,0x0faaa,0x0ffff,0x0ff //e ! 163: .value 0x0ade0,0x0aaaa,0x0feaa,0x0ffff,0x0ff //f ! 164: // ! 165: // ******************************************************************************* ! 166: // ! 167: at_case_table: ! 168: .long at_round,case_1,case_2,case_3 ! 169: // ! 170: two_arg_trans_table: ! 171: .long at_non_0,log,splog ! 172: // ! 173: //...the following jump tables refer to the following op1/op2 cases ! 174: // ! 175: // (where v=valid, z=zero, f=infinity, and d=denormal): ! 176: // v/v,v/z,v/f,v/d,z/v,z/z,z/f,z/d,f/v,f/z,f/f,f/d,d/v,d/z,d/f and d/d, ! 177: // in that order .. ! 178: // ! 179: // arctan2_table is first ! 180: // ! 181: special_table: ! 182: .long handle_non_special_cases,sign_y_hapi ! 183: .long sign_y_pi_or_0,only_op2_denormd ! 184: .long sign_y_pi_or_0,at_both_0 ! 185: .long sign_y_pi_or_0,derror_sign_y_pi_or_0 ! 186: .long sign_y_hapi,sign_y_hapi ! 187: .long handle_non_special_cases,derror_sign_y_hapi ! 188: .long only_op1_denormd,derror_sign_y_hapi ! 189: .long derror_sign_y_pi_or_0,both_ops_denormd ! 190: // ! 191: // log_table is second, 64 bytes after arctan2_table ! 192: // ! 193: .long handle_non_special_cases,op2_signed_by_op1_vs_1 ! 194: .long inv_or_op2_signed_by_op1_vs_1,only_op2_denormd ! 195: .long zerror_flip_sign_y_inf,op_unsupp ! 196: .long zerror_flip_sign_op2,zerror_flip_sign_y_inf ! 197: .long sign_y_op1,op_unsupp ! 198: .long op2,derror_sign_y_op1 ! 199: .long only_op1_denormd,derror_flip_sign_op2 ! 200: .long derror_flip_sign_op2,both_ops_denormd ! 201: // ! 202: // splog_table is third (and last), 128 bytes after arctan2_table ! 203: // ! 204: .long handle_non_special_cases,exor_signed_op2 ! 205: .long exor_signed_op2,only_op2_denormd ! 206: .long exor_signed_op1,exor_signed_op2 ! 207: .long op_unsupp,derror_exor_signed_op1 ! 208: .long sign_y_op1,op_unsupp ! 209: .long op2,derror_sign_y_op1 ! 210: .long only_op1_denormd,derror_exor_signed_op2 ! 211: .long derror_exor_signed_op2,both_ops_denormd ! 212: // ! 213: // ***************************************************************************** ! 214: // ! 215: // *********************************************************************** ! 216: // atan_core: ! 217: // ********* ! 218: // ! 219: // function: ! 220: // calculates arc tangent of (y/x), where ! 221: // 0 < y/x < 1 ; op2 = x, op1 = y. ! 222: // ! 223: // inputs: ! 224: // assumes that operand1 and operand2 are set up. ! 225: // ! 226: // outputs: ! 227: // result in global record 12; possible underflow ! 228: // and inexact errors. ! 229: // ! 230: // data accessed: ! 231: // - expon1 word_frac1 ! 232: // - lsb_frac1 msb_frac1 ! 233: // - offset_operand1 expon2 ! 234: // - lsb_frac2 offset_operand2 ! 235: // - offset_result result_sign ! 236: // - result_tag result_expon ! 237: // - result_word_frac msb_result ! 238: // - offset_of_result_frac offset_cop ! 239: // - offset_dop siso ! 240: // ! 241: // data changed: ! 242: // - expon1 frac1 ! 243: // - frac2 result_sign ! 244: // - result_expon result_frac ! 245: // - siso ! 246: // ! 247: // procedures called: ! 248: // put_si_result right_shift left_shift ! 249: // move_10_bytes move_constant addx ! 250: //subx mulx accel_divx (replaces divx) ! 251: // divid one_left_normalize round ! 252: // addition_normalize underflow_response pop_free ! 253: // test_5w set_p_error set_u_error ! 254: // ! 255: // ********************************************************************** ! 256: ALIGN ! 257: atan_core: //proc ! 258: push %gs:sr_masks // save precision control ! 259: // and dword ptr %gs:sr_masks, 0fffff3ffh; set rounding control to nearest ! 260: orl $0x0300,%gs:sr_masks // set precision control to prec64 ! 261: orb $inexact_mask,%gs:sr_errors // always inexact ! 262: movb positive,result_sign(%ebp)// result is always positive ! 263: movw $0,siso // clear siso ! 264: mov dword_expon2,%eax ! 265: sub dword_expon1,%eax ! 266: mov %eax,dword_exp_tmp ! 267: cmp $15,%eax ! 268: jle atn_pseudo_div ! 269: cmp $63,%eax ! 270: // ! 271: //tiny argument ! 272: // ! 273: jg atn_divide ! 274: jmp atn_rat_appx ! 275: ALIGN ! 276: atn_divide: ! 277: call divid // floating-point divide ! 278: // ! 279: //post operation rounding ! 280: // ! 281: call post_op_round // d.e. precision rounding ! 282: // ! 283: //error check ! 284: // ! 285: mov dword_result_expon,%eax ! 286: cmp $0,%eax ! 287: jg atn_put_atn_f ! 288: jl atn_put_atn // underflow of core has occurred. ! 289: mov $offset_result+frac64,%edi ! 290: call test_4w // note that ax is 0 here. ! 291: jnz atn_put_atn // underflow of core has occurred. ! 292: atn_zero: ! 293: movb special,result_tag(%ebp) ! 294: jmp atn_put_atn ! 295: ALIGN ! 296: // ! 297: atn_pseudo_div: ! 298: call right_shift_frac2_8 ! 299: call right_shift_frac1_8 ! 300: atn_loop_back_1: ! 301: call subx ! 302: shlw $1,siso ! 303: cmpb $0,msb_result ! 304: jnz atn_shift_left ! 305: call move_result_cop // cop is 67 bits temp ! 306: mov $offset_operand1,%edi ! 307: call right_shift_dword_exp_tmp ! 308: call addx ! 309: call move_result_frac1 ! 310: mov $add_half_pattern,%esi ! 311: call add_frac2 // add 1/2 round ! 312: call move_result_frac2 ! 313: andl $0x0ff000000,dword_frac2(%ebp) // frac2 = 64 bits x ! 314: call move_cop_frac1 // frac1 = 67 bits y ! 315: incw siso ! 316: cmpb $0,msb_result ! 317: je atn_shift_left ! 318: mov $1,%ecx ! 319: call right_shift_frac2_cl ! 320: andl $0x0ff000000,dword_frac2(%ebp) ! 321: jmp atn_merge_0 ! 322: ALIGN ! 323: atn_shift_left: ! 324: call left_shift_frac1_1 ! 325: atn_merge_0: ! 326: incl dword_exp_tmp ! 327: cmp $15,dword_exp_tmp ! 328: jna atn_loop_back_1 ! 329: mov $7,%ecx ! 330: call left_shift_frac1_cl ! 331: andl $0x0e0000000,dword_frac1(%ebp) ! 332: movl $15,dword_exp_tmp ! 333: call left_shift_frac2_8 ! 334: atn_rat_appx: ! 335: // the following call used to be to divx instead of accel_divx: ! 336: call accel_divx // y/x --> z (67) ! 337: call move_result_frac1 ! 338: mov $9,%ecx ! 339: call right_shift_frac1_cl ! 340: andl $0x0ffe00000,dword_frac1(%ebp) ! 341: call move_result_frac2 ! 342: call right_shift_frac2_8 ! 343: andl $0x0ffe00000,dword_frac2(%ebp) ! 344: andl $0x0e0000000,result_dword_frac(%ebp)// mask result frac ! 345: call move_result_cop ! 346: call addx ! 347: call move_result_dop //dop = new y (67) ! 348: call move_cop_frac1 ! 349: call move_cop_frac2 ! 350: mov $30,%ecx ! 351: call right_shift_frac1_cl // perform short multiply ! 352: movl $0,dword_frac1(%ebp) ! 353: mov $30,%ecx ! 354: call left_shift_frac1_cl ! 355: call mulx ! 356: mov $offset_result,%edi ! 357: call right_shift_dword_exp_tmp ! 358: movb $0x0c0,msb_result ! 359: call move_result_frac2 // new x (64) ! 360: andl $0x0e0000000,dword_frac2(%ebp) ! 361: cmpb $0,msb_dop ! 362: movb $1,%al ! 363: mov $7,%ecx ! 364: jne atn_merge_1 ! 365: movb $0,%al ! 366: mov $8,%ecx ! 367: atn_merge_1: ! 368: push %eax //save al ! 369: mov $offset_dop+frac80,%edi ! 370: call left_shift ! 371: call move_dop_frac1 ! 372: // the following call used to be to divx instead of accel_divx: ! 373: call accel_divx ! 374: andl $0x0e0000000,result_dword_frac(%ebp)// theta is here ! 375: pop %eax ! 376: shrb $1,%al ! 377: mov $7,%ecx ! 378: jnb atn_merge_2 ! 379: mov $6,%ecx ! 380: atn_merge_2: ! 381: call right_shift_result_cl ! 382: call move_result_frac1 ! 383: atn_loop_back_2: ! 384: shrw $1,siso ! 385: jnb atn_q_bit_not_set ! 386: mov $10,%eax ! 387: mull dword_exp_tmp ! 388: add $tan_constant,%eax ! 389: mov %eax,%esi ! 390: call add_frac2 ! 391: call move_result_frac1 ! 392: atn_q_bit_not_set: ! 393: cmpw $0,siso ! 394: jz atn_end_loop ! 395: mov $1,%ecx ! 396: call right_shift_frac1_cl ! 397: andl $0x0ffe00000,dword_frac1(%ebp) ! 398: decl dword_exp_tmp ! 399: jmp atn_loop_back_2 ! 400: ALIGN ! 401: atn_end_loop: ! 402: cmpb $0,msb_frac1 ! 403: mov $8,%ecx ! 404: je atn_merge_3 ! 405: mov $7,%ecx ! 406: decl dword_exp_tmp ! 407: atn_merge_3: ! 408: call left_shift_frac1_cl ! 409: movl $0x3ffe,dword_expon1 ! 410: mov dword_exp_tmp,%eax ! 411: sub %eax,dword_expon1 ! 412: mov $offset_operand1,%edi ! 413: call one_left_normalize ! 414: call move_frac1_result// added when add_half1_frac below was cut ! 415: mov dword_expon1,%eax ! 416: mov %eax,dword_result_expon ! 417: // call add_half1_frac2 ! 418: atn_put_atn_f: ! 419: movb valid,result_tag(%ebp) // valid result ! 420: atn_put_atn: ! 421: pop %gs:sr_masks // restore precision control ! 422: ret ! 423: //atan_core endp ! 424: // ! 425: // ! 426: // ******************************************************************************* ! 427: // ! 428: ALIGN ! 429: move_unpacked_0_to_edi: //proc ! 430: ! 431: movl $0,(%ebp,%edi) ! 432: movl $0,frac64(%ebp,%edi) ! 433: movl $0,frac32(%ebp,%edi) ! 434: movl $0x10000*SPECIAL+POSITIVE,sign(%ebp,%edi) ! 435: movl $0,expon(%ebp,%edi) ! 436: ret ! 437: ! 438: //move_unpacked_0_to_edi endp ! 439: // ! 440: // ******************************************************************************* ! 441: // ! 442: ALIGN ! 443: move_unpacked_hapi_to_edi: //proc ! 444: ! 445: movl $0,(%ebp,%edi) ! 446: movl $0x2168c235,frac64(%ebp,%edi) ! 447: movl $0x0c90fdaa2,frac32(%ebp,%edi) ! 448: movl $0x10000*VALID+POSITIVE,sign(%ebp,%edi) ! 449: movl $0x3fff,expon(%ebp,%edi) ! 450: ret ! 451: ! 452: //move_unpacked_hapi_to_edi endp ! 453: // ! 454: // ******************************************************************************* ! 455: // ! 456: // ! 457: // ******************************************************************************* ! 458: ! 459: ALIGN ! 460: at_non_0: //proc ! 461: ! 462: movb sign1(%ebp),%dl ! 463: movb sign2(%ebp),%dh ! 464: movb positive,sign1(%ebp) ! 465: movb positive,sign2(%ebp) ! 466: movb %dh,%bl ! 467: and $8,%ebx ! 468: at_cmpr_ops: // this compare assumes same- ! 469: // signed, normalized comparands ! 470: mov dword_expon2,%eax ! 471: cmp dword_expon1,%eax ! 472: jg take_atan ! 473: jl at_switch_ops ! 474: mov dword_frac1+frac32(%ebp),%eax ! 475: cmp dword_frac2+frac32(%ebp),%eax ! 476: jg take_atan ! 477: jl at_switch_ops ! 478: mov dword_frac1+frac64(%ebp),%eax ! 479: cmp dword_frac2+frac64(%ebp),%eax ! 480: jg take_atan ! 481: jl at_switch_ops ! 482: at_ops_eql: ! 483: mov $offset_result,%edi ! 484: call move_unpacked_hapi_to_edi ! 485: decl dword_result_expon // make pi/4 ! 486: or %ebx,%ebx ! 487: jz at_sign_adjust ! 488: jmp hapi_to_op1 ! 489: ALIGN ! 490: at_switch_ops: ! 491: push %ebx ! 492: call swap_ops // edx preserved ! 493: pop %ebx ! 494: or $4,%ebx ! 495: take_atan: ! 496: push %ebx // save operand signs ! 497: push %edx // save table index ! 498: call atan_core ! 499: pop %edx ! 500: pop %ebx ! 501: or %ebx,%ebx ! 502: jnz hapi_to_op1 ! 503: at_underflow_: ! 504: mov dword_result_expon,%eax ! 505: cmp $0,%eax ! 506: jg at_round ! 507: jl at_underflow ! 508: cmpb special,result_tag(%ebp) ! 509: je at_round_report ! 510: at_underflow: // underflow ! 511: push %edx // save sign info ! 512: call underflow_response ! 513: pop %edx // restore sign info ! 514: orb underflow_mask,%gs:sr_errors ! 515: jmp at_sign_adjust ! 516: ALIGN ! 517: hapi_to_op1: ! 518: mov $offset_operand1,%edi ! 519: call move_unpacked_hapi_to_edi ! 520: jmp *%cs:at_case_table(%ebx) ! 521: ALIGN ! 522: // ! 523: case_3: ! 524: movb $add_op,operation_type(%ebp) ! 525: jmp at_to_op2 ! 526: ALIGN ! 527: case_2: ! 528: incl dword_expon1 // make pi ! 529: case_1: ! 530: movb $sub_op,operation_type(%ebp) ! 531: at_to_op2: ! 532: push %edx ! 533: // push ebx ! 534: lea dword_frac2(%ebp),%edi ! 535: lea result_dword_frac(%ebp),%esi ! 536: call move_op_to_op ! 537: call subadd ! 538: // pop ebx ! 539: pop %edx ! 540: at_round: ! 541: push %gs:sr_masks ! 542: orl $0x0300,%gs:sr_masks // set precision control to prec64 ! 543: push %edx ! 544: call post_op_round ! 545: pop %edx ! 546: pop %gs:sr_masks ! 547: at_round_report: ! 548: cmpw $0,rnd_history ! 549: je at_sign_adjust ! 550: orb $inexact_mask,%gs:sr_errors ! 551: cmpb true,added_one ! 552: jne at_sign_adjust ! 553: orb $a_mask,%gs:sr_flags ! 554: at_sign_adjust: ! 555: movb %dl,result_sign(%ebp) ! 556: at_exit: ! 557: ret ! 558: ! 559: //at_non_0 endp ! 560: // ! 561: // ******************************************************************************* ! 562: // ! 563: // ! 564: ALIGN ! 565: two_arg_trans: //proc ! 566: ! 567: jz two_arg_special_case_ // branch if no stack error ! 568: call set_stk_u_error // stack underflow occurred ! 569: testb invalid_mask,%gs:sr_masks// if unmasked, just return ! 570: jnz return_indef // else, return indefinite ! 571: two_arg_unmasked_exit: ! 572: ret ! 573: ALIGN ! 574: return_indef: ! 575: call put_indefinite ! 576: jmp get_result_ptr ! 577: ALIGN ! 578: two_arg_special_case_: ! 579: andb $~a_mask,%gs:sr_flags // clear a-bit initially ! 580: movzbl tag1(%ebp),%ebx // both operands valid? ! 581: orb tag2(%ebp),%bl ! 582: jnz two_arg_special_case ! 583: handle_non_special_cases: ! 584: movzbl operation_type(%ebp),%ebx// call log/splog/arctan2 ! 585: subb $arctan_op,%bl // to do the operation ! 586: je main_call // ebx has offset of at_non_0 container ! 587: cmpb $log_op-arctan_op,%bl ! 588: je log_of_neg_num_ ! 589: cmpl $0x3fff,dword_expon1 ! 590: jg op_unsupp ! 591: jl get_splog_offset ! 592: weed_out_neg_1: ! 593: cmpb positive,sign1(%ebp) ! 594: je op_unsupp ! 595: cmpl $0x080000000,dword_frac1+frac32(%ebp) ! 596: jne op_unsupp ! 597: cmp $0,dword_frac1+frac64(%ebp) ! 598: jne op_unsupp ! 599: jmp zerror_flip_sign_y_inf ! 600: ALIGN ! 601: get_splog_offset: ! 602: mov $8,%ebx // ebx has offset of splog container ! 603: jmp main_call ! 604: ALIGN ! 605: log_of_neg_num_: ! 606: cmpb positive,sign1(%ebp) ! 607: jne op_unsupp ! 608: mov $4,%ebx // ebx has offset of log container ! 609: main_call: ! 610: call *%cs:two_arg_trans_table(%ebx) ! 611: get_result_ptr: ! 612: mov $offset_result,%edi ! 613: got_result_ptr: ! 614: mov offset_result_rec,%esi ! 615: jmp put_arith_result ! 616: ALIGN ! 617: // ! 618: both_ops_denormd: ! 619: orb denorm_mask,%gs:sr_errors ! 620: testb denorm_mask,%gs:sr_masks ! 621: jz two_arg_unmasked_exit ! 622: mov $offset_operand1,%edi ! 623: call norm_denorm ! 624: op2_denormd: ! 625: mov $offset_operand2,%edi ! 626: call norm_denorm ! 627: jmp handle_non_special_cases ! 628: ALIGN ! 629: only_op1_denormd: ! 630: orb denorm_mask,%gs:sr_errors ! 631: testb denorm_mask,%gs:sr_masks ! 632: jz two_arg_unmasked_exit ! 633: mov $offset_operand1,%edi ! 634: call norm_denorm ! 635: jmp handle_non_special_cases ! 636: ALIGN ! 637: only_op2_denormd: ! 638: orb denorm_mask,%gs:sr_errors ! 639: testb denorm_mask,%gs:sr_masks ! 640: jz two_arg_unmasked_exit ! 641: jmp op2_denormd ! 642: ALIGN ! 643: // ! 644: two_arg_special_case: ! 645: testb $0x10,%bl // al contains (ebp).tag1 or (ebp).tag2 ! 646: jz op1_nan_ ! 647: op_unsupp: ! 648: orb invalid_mask,%gs:sr_errors// here, at least one op is unsupported. ! 649: testb invalid_mask,%gs:sr_masks ! 650: jz two_arg_unmasked_exit ! 651: jmp return_indef ! 652: ALIGN ! 653: op1_nan_: // here, neither op is unsupported. ! 654: cmpb inv,tag1(%ebp) ! 655: je op1_snan_ ! 656: cmpb inv,tag2(%ebp) ! 657: jne non_nan_supp_ops ! 658: jmp signal_invalid_ ! 659: ALIGN ! 660: op1_snan_: ! 661: testb $0x40,msb_frac1 ! 662: jz invalid_operand ! 663: op2_also_nan_: ! 664: cmpb inv,tag2(%ebp) ! 665: jne jmp_set_up_nan_return ! 666: signal_invalid_: ! 667: testb $0x40,msb_frac2 ! 668: jnz jmp_set_up_nan_return ! 669: invalid_operand: ! 670: orb invalid_mask,%gs:sr_errors// invalid operand sets ! 671: testb invalid_mask,%gs:sr_masks ! 672: jz two_arg_unmasked_exit // i-error, if unmasked ! 673: jmp_set_up_nan_return: ! 674: jmp set_up_nan_return ! 675: ALIGN ! 676: non_nan_supp_ops: ! 677: movb tag1(%ebp),%bh ! 678: movzbl operation_type(%ebp),%eax ! 679: subb $arctan_op,%al ! 680: je get_tag2 // eax now holds base of arctan table ! 681: cmpb $log_op-arctan_op,%al ! 682: je only_neg_0_ok ! 683: cmpl $0x3fff,dword_expon1 ! 684: jl get_splog_table ! 685: je weed_out_neg_1 ! 686: cmpl $0x7fff,dword_expon1 ! 687: jne op_unsupp ! 688: cmpb positive,sign1(%ebp) ! 689: jne op_unsupp ! 690: get_splog_table: ! 691: mov $128,%eax // eax now holds base of splog table ! 692: jmp get_tag2 ! 693: ALIGN ! 694: only_neg_0_ok: ! 695: cmpb positive,sign1(%ebp) ! 696: je log_table_base_to_eax ! 697: cmpb special,%bh ! 698: jne op_unsupp ! 699: log_table_base_to_eax: ! 700: mov $64,%eax // eax now holds base of log table ! 701: get_tag2: ! 702: movb tag2(%ebp),%bl ! 703: testb $0x04,%bh ! 704: jz op2_denorm_ ! 705: movb $3,%bh // indicate op1 is denorm ! 706: op2_denorm_: ! 707: testb $0x04,%bl ! 708: jz get_index ! 709: movb $3,%bl // indicate op2 is denorm ! 710: get_index: ! 711: and $0x0303,%ebx // form index to special operation table ! 712: // bx=4*(4*masked_tag1 + masked_tag2), ! 713: // where masked_tag = 0 for valid, ! 714: shlb $2,%bh //1 for zero, ! 715: //2 for infinity ! 716: addb %bh,%bl //3 for denormd ! 717: xorb %bh,%bh ! 718: shl $2,%ebx ! 719: add_base: ! 720: add %eax,%ebx // (e)bx = case offset ! 721: jmp *%cs:special_table(%ebx) // jump to special case ! 722: ALIGN ! 723: // ! 724: derror_sign_y_pi_or_0: ! 725: orb denorm_mask,%gs:sr_errors ! 726: testb denorm_mask,%gs:sr_masks ! 727: jz two_arg_unmasked_exit // if unmasked, return ! 728: sign_y_pi_or_0: ! 729: cmpb positive,sign2(%ebp) ! 730: je sign_y_0 ! 731: sign_y_pi: ! 732: mov $offset_result,%edi ! 733: call move_unpacked_hapi_to_edi ! 734: incl dword_result_expon // make pi ! 735: jmp at_spcl_sign_adjust ! 736: ALIGN ! 737: ! 738: derror_sign_y_hapi: ! 739: orb denorm_mask,%gs:sr_errors ! 740: testb denorm_mask,%gs:sr_masks ! 741: jz two_arg_unmasked_exit // if unmasked, return ! 742: sign_y_hapi: ! 743: mov $offset_result,%edi ! 744: call move_unpacked_hapi_to_edi ! 745: jmp at_spcl_sign_adjust ! 746: ALIGN ! 747: ! 748: at_both_0: ! 749: cmpb positive,sign2(%ebp) ! 750: jne sign_y_pi ! 751: sign_y_0: ! 752: mov $offset_result,%edi ! 753: call move_unpacked_0_to_edi ! 754: ! 755: at_spcl_sign_adjust: ! 756: movb sign1(%ebp),%dl ! 757: movb %dl,result_sign(%ebp) ! 758: jmp get_result_ptr ! 759: ALIGN ! 760: ! 761: zerror_flip_sign_y_inf: ! 762: orb zero_divide_mask,%gs:sr_errors ! 763: testb zero_divide_mask,%gs:sr_masks ! 764: jz two_arg_unmasked_exit ! 765: flip_sign_y_inf: ! 766: movl $0x080000000,dword_frac1+frac32(%ebp) ! 767: movl $0x10000*INFINITY+POSITIVE,sign1(%ebp) ! 768: movl $0x7fff,dword_expon1 ! 769: flip_sign_y_op1: ! 770: mov $offset_operand1,%edi ! 771: flip_sign_y_to_edi: ! 772: movb sign2(%ebp),%dl ! 773: notb %dl ! 774: movb %dl,sign(%ebp,%edi) ! 775: jmp got_result_ptr ! 776: ALIGN ! 777: ! 778: //zerror_derror_flip_sign_y_inf: ! 779: // or %gs:sr_errors, zero_divide_mask ! 780: // test %gs:sr_masks, zero_divide_mask ! 781: // jz two_arg_unmasked_exit ! 782: // or %gs:sr_errors, denorm_mask ! 783: // test %gs:sr_masks, denorm_mask ! 784: // jz two_arg_unmasked_exit ! 785: // jmp short flip_sign_y_inf ! 786: ! 787: derror_sign_y_op1: ! 788: orb denorm_mask,%gs:sr_errors ! 789: testb denorm_mask,%gs:sr_masks ! 790: jz two_arg_unmasked_exit ! 791: sign_y_op1: ! 792: mov $offset_operand1,%edi ! 793: sign_y_to_edi: ! 794: movb sign2(%ebp),%dl ! 795: movb %dl,sign(%ebp,%edi) ! 796: jmp got_result_ptr ! 797: ALIGN ! 798: ! 799: inv_or_op2_signed_by_op1_vs_1: ! 800: cmpl $0x3fff,dword_expon1 ! 801: jg op2 ! 802: jl flip_sign_op2 ! 803: cmpl $0x80000000,dword_frac1+frac32(%ebp) ! 804: ja op2 ! 805: cmp $0,dword_frac1+frac64(%ebp) ! 806: jne op2 ! 807: jmp op_unsupp ! 808: ALIGN ! 809: ! 810: zerror_flip_sign_op2: ! 811: orb zero_divide_mask,%gs:sr_errors ! 812: testb zero_divide_mask,%gs:sr_masks ! 813: jz two_arg_unmasked_exit ! 814: jmp flip_sign_op2 ! 815: ALIGN ! 816: ! 817: op2_signed_by_op1_vs_1: ! 818: cmpl $0x3fff,dword_expon1 ! 819: jge op2 ! 820: flip_sign_op2: ! 821: notb sign2(%ebp) ! 822: op2: ! 823: mov $offset_operand2,%edi ! 824: jmp got_result_ptr ! 825: ALIGN ! 826: ! 827: derror_flip_sign_op2: ! 828: orb denorm_mask,%gs:sr_errors ! 829: testb denorm_mask,%gs:sr_masks ! 830: jz two_arg_unmasked_exit ! 831: jmp flip_sign_op2 ! 832: ALIGN ! 833: ! 834: derror_exor_signed_op2: ! 835: orb denorm_mask,%gs:sr_errors ! 836: testb denorm_mask,%gs:sr_masks ! 837: jz two_arg_unmasked_exit ! 838: exor_signed_op2: ! 839: movb sign1(%ebp),%dl ! 840: xorb %dl,sign2(%ebp) ! 841: jmp op2 ! 842: ALIGN ! 843: ! 844: derror_exor_signed_op1: ! 845: orb denorm_mask,%gs:sr_errors ! 846: testb denorm_mask,%gs:sr_masks ! 847: jz two_arg_unmasked_exit ! 848: exor_signed_op1: ! 849: movb sign2(%ebp),%dl ! 850: xorb %dl,sign1(%ebp) ! 851: op1: ! 852: mov $offset_operand1,%edi ! 853: jmp got_result_ptr ! 854: ALIGN ! 855: ! 856: //two_arg_trans endp ! 857: // ! 858: ALIGN ! 859: push_5_dw_at_esi: //proc ! 860: ! 861: pop %ebx // ebx <-- return address ! 862: push (%ebp,%esi) ! 863: push frac64(%ebp,%esi) ! 864: push frac32(%ebp,%esi) ! 865: push sign(%ebp,%esi) ! 866: push expon(%ebp,%esi) ! 867: jmp *%ebx ! 868: ! 869: //push_5_dw_at_esi endp ! 870: ! 871: // ********************************************************************** ! 872: // ********************************************************************** ! 873: ! 874: ALIGN ! 875: pop_5_dw_at_esi: //proc ! 876: ! 877: pop %ebx // ebx <-- return address ! 878: pop expon(%ebp,%esi) ! 879: pop sign(%ebp,%esi) ! 880: pop frac32(%ebp,%esi) ! 881: pop frac64(%ebp,%esi) ! 882: pop (%ebp,%esi) ! 883: jmp *%ebx ! 884: ! 885: //pop_5_dw_at_esi endp ! 886: ! 887: // ********************************************************************** ! 888: ALIGN ! 889: move_unpacked_1_to_esi: //proc ! 890: ! 891: movl $0,(%ebp,%esi) ! 892: movl $0,frac64(%ebp,%esi) ! 893: movl $0x080000000,frac32(%ebp,%esi) ! 894: // mov positive+0x10000*valid,sign(%ebp,%esi) ! 895: movl $0x10000*VALID+POSITIVE,sign(%ebp,%esi) ! 896: movl $0x3fff,expon(%ebp,%esi) ! 897: ret ! 898: ! 899: //move_unpacked_1_to_esi endp ! 900: // ********************************************************************** ! 901: // *********************************************************************** ! 902: // exp: ! 903: // *** ! 904: // function: ! 905: // calculates 2**x - 1, where 0 <= x < 1/2. ! 906: // inputs: ! 907: // assumes that operand1 is set up. ! 908: // ! 909: // outputs: ! 910: // result in global record 12; possible underflow ! 911: // and inexact errors. ! 912: // ! 913: // data accessed: ! 914: // - offset_operand1 tag1 ! 915: // - expon1 word_frac1 ! 916: // - lsb_frac1 offset_operand1 ! 917: // - sign2 expon2 ! 918: // - offset_operand2 offset_result ! 919: // - result_tag result_expon ! 920: // - lsb_result msb_result ! 921: // - offset_result siso ! 922: // - offset_cop ! 923: // ! 924: // data changed: ! 925: // - expon1 lsb_frac1 ! 926: // - sign2 expon2 ! 927: // - result_tag msb_result ! 928: // - siso ! 929: // ! 930: // procedures called: ! 931: // put_si_result right_shift left_shift ! 932: // move_10_bytes move_constant addx ! 933: // subx mulx divx ! 934: // addition_normalize round divid ! 935: // log_constant underflow_response set_p_error ! 936: // ! 937: // *********************************************************************** ! 938: ALIGN ! 939: exp_core: //proc ! 940: // ! 941: //pseudo_division ! 942: // ! 943: movw $0,siso // clear siso ! 944: mov $0x3fff,%eax ! 945: sub dword_expon1,%eax // dword_expon1 < 3fffh ! 946: cmp $63,%eax ! 947: jg exp_tiny_argument ! 948: mov %eax,dword_expon1 ! 949: cmp $15,%eax ! 950: ja exp_rat_appx // impossible that eax <= 0 ! 951: call right_shift_frac1_8 ! 952: exp_loop_back_1: ! 953: mov $10,%eax ! 954: mull dword_expon1 ! 955: add $log_constant-10,%eax ! 956: mov %eax,%esi ! 957: call sub_frac2 ! 958: shlw $1,siso ! 959: cmpb $0,msb_result ! 960: jne exp_merge_0 ! 961: call move_result_frac1 ! 962: andl $0x0ffe00000,dword_frac1(%ebp) ! 963: incw siso ! 964: exp_merge_0: ! 965: incl dword_expon1 ! 966: cmp $15,dword_expon1 ! 967: ja exp_branch_1 ! 968: call left_shift_frac1_1 ! 969: jmp exp_loop_back_1 ! 970: ALIGN ! 971: exp_tiny_argument: ! 972: movb positive,sign2(%ebp) ! 973: movl $0x3fff,dword_expon2 ! 974: mov $constant_2_ov_ln2,%esi ! 975: call move_constant_frac2 ! 976: call left_shift_frac2_8 // tiny argument ! 977: call divid // floating-point divide ! 978: call post_op_round ! 979: exp_put_exp_jmp: ! 980: jmp exp_put_exp_f ! 981: ALIGN ! 982: // ! 983: //pre_rat_appx ! 984: // ! 985: exp_branch_1: ! 986: movl $15,dword_expon1 ! 987: call left_shift_frac1_8 ! 988: exp_rat_appx: ! 989: call move_frac1_cop ! 990: // ! 991: //80287 short multiply (does 67-bit by 34-bit multiplication only). ! 992: // ! 993: movb $30,%cl ! 994: call right_shift_frac1_cl ! 995: and $0,dword_frac1(%ebp) ! 996: movb $30,%cl ! 997: call left_shift_frac1_cl ! 998: call mulx ! 999: call move_result_frac1 ! 1000: andl $0x0e0000000,dword_frac1(%ebp) ! 1001: mov $constant_ln2_ov_6,%esi ! 1002: call mul_frac2 ! 1003: mov dword_expon1,%ecx ! 1004: add $10,%ecx ! 1005: call right_shift_result_cl ! 1006: andl $0x0ffe00000,result_dword_frac(%ebp) ! 1007: call move_cop_frac1 ! 1008: call right_shift_frac1_8 ! 1009: call move_result_frac2 ! 1010: call subx ! 1011: mov dword_expon1,%ecx ! 1012: inc %ecx ! 1013: call right_shift_result_cl ! 1014: andl $0x0ffe00000,result_dword_frac(%ebp) ! 1015: call move_result_frac2 ! 1016: mov $constant_2_ov_ln2,%esi ! 1017: call sub_frac1 ! 1018: call move_cop_frac1 ! 1019: call move_result_frac2 ! 1020: call left_shift_frac2_8 ! 1021: // the following call used to be to divx instead of accel_divx: ! 1022: call accel_divx ! 1023: mov $8,%ecx ! 1024: call right_shift_result_cl ! 1025: andl $0x0ffe00000,result_dword_frac(%ebp) ! 1026: ! 1027: // ! 1028: //pseudo_multiply ! 1029: // ! 1030: exp_loop_back_2: ! 1031: shrw $1,siso ! 1032: jnb exp_merge_2 ! 1033: call move_result_frac1 ! 1034: call move_result_frac2 ! 1035: mov dword_expon1,%ecx ! 1036: call right_shift_frac2_cl ! 1037: andl $0x0ffe00000,dword_frac2(%ebp) ! 1038: orw $0x80,8+word_frac2 ! 1039: call addx ! 1040: exp_merge_2: ! 1041: cmpw $0,siso ! 1042: je exp_almost_end ! 1043: call right_shift_result_1 ! 1044: andl $0x0ffe00000,result_dword_frac(%ebp) ! 1045: decl dword_expon1 ! 1046: jmp exp_loop_back_2 ! 1047: ALIGN ! 1048: exp_almost_end: ! 1049: movb $8,%cl ! 1050: cmpb $0,msb_result ! 1051: je exp_merge_3 ! 1052: movb $7,%cl ! 1053: decl dword_expon1 ! 1054: exp_merge_3: ! 1055: call left_shift_result_cl ! 1056: mov $0x3fff,%eax ! 1057: sub dword_expon1,%eax ! 1058: mov %eax,dword_result_expon ! 1059: // mov positive+valid\*0x10000,result_sign(%ebp) ! 1060: movl $0x10000*VALID+POSITIVE,result_sign(%ebp) ! 1061: testb $0x80,msb_result ! 1062: jne exp_add_half_round ! 1063: // ! 1064: //normalize x ! 1065: // ! 1066: movb $1,%cl ! 1067: call left_shift_result_cl ! 1068: decl dword_result_expon ! 1069: exp_add_half_round: ! 1070: call move_result_frac1 ! 1071: call add_half1_frac2 ! 1072: exp_put_exp_f: ! 1073: ret ! 1074: ! 1075: //exp_core endp ! 1076: // ********************************************************************** ! 1077: ALIGN ! 1078: neg_exp_core: //proc ! 1079: notb sign1(%ebp) ! 1080: call exp_core ! 1081: lea result_dword_frac(%ebp),%esi ! 1082: lea dword_frac2(%ebp),%edi ! 1083: call move_op_to_op ! 1084: mov $offset_operand1,%esi ! 1085: call move_unpacked_1_to_esi ! 1086: movb negative,sign1(%ebp) ! 1087: movb $sub_op,operation_type(%ebp) ! 1088: mov $offset_result,%esi ! 1089: call push_5_dw_at_esi ! 1090: call subadd ! 1091: call post_op_round ! 1092: lea result_dword_frac(%ebp),%esi ! 1093: lea dword_frac2(%ebp),%edi ! 1094: call move_op_to_op ! 1095: mov $offset_operand1,%esi ! 1096: call pop_5_dw_at_esi ! 1097: call divid // floating-point divide ! 1098: call post_op_round ! 1099: exp_neg_core_exit: ! 1100: ret ! 1101: ! 1102: //neg_exp_core endp ! 1103: // ********************************************************************** ! 1104: ALIGN ! 1105: exp: //proc ! 1106: call one_result_op1_chk ! 1107: jnz exp_non_zero ! 1108: garb_out: ! 1109: jmp put_op1_result ! 1110: ALIGN ! 1111: // ! 1112: exp_non_zero: ! 1113: cmpl $0x3fff,dword_expon1 ! 1114: jg garb_out ! 1115: jl more_than_half_ ! 1116: more_than_1_: ! 1117: cmpl $0x080000000,dword_frac1+frac32(%ebp) ! 1118: ja garb_out ! 1119: cmp $0,dword_frac1+frac64(%ebp) ! 1120: jne garb_out ! 1121: cmpb positive,sign1(%ebp) ! 1122: je garb_out // answer is 1, already in op1 ! 1123: decl dword_expon1 ! 1124: jmp garb_out // answer is -1/2. ! 1125: ALIGN ! 1126: more_than_half_: ! 1127: orb $inexact_mask,%gs:sr_errors // set inexact error flag ! 1128: push %gs:sr_masks // save precision control ! 1129: orl $0x0300,%gs:sr_masks // set precision control to prec64 ! 1130: andl $0x0fffff3ff,%gs:sr_masks // set rc = to_nearest ! 1131: cmpl $0x3ffe,dword_expon1 ! 1132: je maybe_half ! 1133: cmpb positive,sign1(%ebp) ! 1134: jne tween_neg_half_and_0 ! 1135: jmp tween_0_and_half ! 1136: ALIGN ! 1137: maybe_half: ! 1138: cmpl $0x080000000,dword_frac1+frac32(%ebp) ! 1139: ja tween_half_and_1 ! 1140: cmp $0,dword_frac1+frac64(%ebp) ! 1141: jne tween_half_and_1 ! 1142: cmpb positive,sign1(%ebp) ! 1143: jne tween_neg_half_and_0 ! 1144: tween_0_and_half: ! 1145: call exp_core ! 1146: // ! 1147: //error checking ! 1148: // ! 1149: exp_uflow_: ! 1150: mov dword_result_expon,%ecx ! 1151: cmp $0,%ecx ! 1152: jle exp_underflow ! 1153: movb valid,result_tag(%ebp) //valid result ! 1154: jmp exp_exit ! 1155: ALIGN ! 1156: exp_underflow: ! 1157: call underflow_response ! 1158: orb underflow_mask,%gs:sr_errors ! 1159: exp_exit: ! 1160: cmpb true,added_one ! 1161: jne exp_restore ! 1162: orb $a_mask,%gs:sr_flags ! 1163: exp_restore: ! 1164: pop %gs:sr_masks // restore precision and rounding controls ! 1165: mov $offset_result,%edi ! 1166: jmp put_si_result ! 1167: ALIGN ! 1168: tween_neg_half_and_0: ! 1169: call neg_exp_core ! 1170: jmp exp_uflow_ ! 1171: ALIGN ! 1172: tween_half_and_1: ! 1173: cmpb positive,sign1(%ebp) ! 1174: jne tween_neg_1_and_neg_half ! 1175: mov $offset_operand2,%esi ! 1176: call move_unpacked_1_to_esi ! 1177: movb $sub_op,operation_type(%ebp) ! 1178: call subadd ! 1179: call post_op_round ! 1180: lea result_dword_frac(%ebp),%esi ! 1181: lea dword_frac1(%ebp),%edi ! 1182: call move_op_to_op ! 1183: call neg_exp_core ! 1184: lea result_dword_frac(%ebp),%esi ! 1185: lea dword_frac1(%ebp),%edi ! 1186: call move_op_to_op ! 1187: mov $offset_operand2,%esi ! 1188: call move_unpacked_1_to_esi ! 1189: movb $add_op,operation_type(%ebp) ! 1190: call subadd ! 1191: call post_op_round ! 1192: incl dword_result_expon ! 1193: lea result_dword_frac(%ebp),%esi ! 1194: lea dword_frac1(%ebp),%edi ! 1195: call move_op_to_op ! 1196: mov $offset_operand2,%esi ! 1197: call move_unpacked_1_to_esi ! 1198: movb $sub_op,operation_type(%ebp) ! 1199: call subadd ! 1200: call post_op_round ! 1201: jmp exp_exit ! 1202: ALIGN ! 1203: tween_neg_1_and_neg_half: ! 1204: mov $offset_operand2,%esi ! 1205: call move_unpacked_1_to_esi ! 1206: movb $add_op,operation_type(%ebp) ! 1207: call subadd ! 1208: call post_op_round ! 1209: lea result_dword_frac(%ebp),%esi ! 1210: lea dword_frac1(%ebp),%edi ! 1211: call move_op_to_op ! 1212: call exp_core ! 1213: lea result_dword_frac(%ebp),%esi ! 1214: lea dword_frac1(%ebp),%edi ! 1215: call move_op_to_op ! 1216: mov $offset_operand2,%esi ! 1217: call move_unpacked_1_to_esi ! 1218: movb $add_op,operation_type(%ebp) ! 1219: call subadd ! 1220: call post_op_round ! 1221: lea result_dword_frac(%ebp),%esi ! 1222: lea dword_frac1(%ebp),%edi ! 1223: call move_op_to_op ! 1224: decl dword_expon1 ! 1225: mov $offset_operand2,%esi ! 1226: call move_unpacked_1_to_esi ! 1227: movb $sub_op,operation_type(%ebp) ! 1228: call subadd ! 1229: call post_op_round ! 1230: jmp exp_exit ! 1231: ALIGN ! 1232: ! 1233: //exp endp ! 1234: // *********************************************************************** ! 1235: // ! 1236: // *************************************************************************** ! 1237: // log: ! 1238: // *** ! 1239: // function: ! 1240: // calculates y times log(x) or y times log(1 + x). ! 1241: // ! 1242: // inputs: ! 1243: // assumes that operand1 and operand2 are set up; ! 1244: // op1 = x, op2 = y. ! 1245: // ! 1246: // outputs: ! 1247: // possible underflow, overflow, or inexact errors ! 1248: // ! 1249: // data accessed: ! 1250: // - operation_type offset_result_rec ! 1251: // - sign1 expon1 ! 1252: // - offset_operand1 offset_operand2 ! 1253: // - tag2 sign2 ! 1254: // - expon2 word_frac2 ! 1255: // - msb_frac2 offset_operand2 ! 1256: // - offset_result result_tag ! 1257: // - result_sign result_expon ! 1258: // - result_word_frac msb_result ! 1259: // - msb_result offset_result ! 1260: // - result2_tag result2_sign ! 1261: // - msb_result2 log_loop_ct ! 1262: // - offset_cop offset_dop ! 1263: // - siso ! 1264: // ! 1265: // data changed: ! 1266: // - sign1 sign2 ! 1267: // - msb_frac2 word_frac2 ! 1268: // - result_tag result_sign ! 1269: // - result_frac offset_result ! 1270: // - result2_tag result2_sign ! 1271: // - msb_result2 log_loop_ct ! 1272: // - siso ! 1273: // ! 1274: // procedures called: ! 1275: // put_result right_shift left_shift ! 1276: // move_10_bytes move_constant addx ! 1277: // subx mulx accel_divx (for log_divx) ! 1278: // one_left_normalize addition_normalize log_constant ! 1279: // test_5w subtraction_normalize test_4w ! 1280: // underflow_response overflow_response decompose ! 1281: // pop_free sp_subadd mult ! 1282: // round get_precision set_p_error ! 1283: // ! 1284: // *********************************************************************** ! 1285: ALIGN ! 1286: log: //proc ! 1287: movb valid,result2_tag(%ebp) ! 1288: jmp log_entry ! 1289: ALIGN ! 1290: splog: ! 1291: movb special,result2_tag(%ebp) // flag for special log ! 1292: log_entry: ! 1293: push %gs:sr_masks // save precision control ! 1294: // and dword ptr %gs:sr_masks, 0fffff3ffh; set rounding control to nearest ! 1295: orl $0x0300,%gs:sr_masks // set precision control to prec64 ! 1296: mov $offset_cop+frac80,%edi ! 1297: call move_frac2 // temp store y, cop <- frac(y) ! 1298: movb tag2(%ebp),%al ! 1299: movb %al,lsb_cop ! 1300: mov dword_expon2,%eax // log_loop_ct <- expo(y) ! 1301: mov %eax,log_loop_ct ! 1302: movb sign2(%ebp),%al // lsb_result2 <- sign2 ! 1303: movb %al,lsb_result2 ! 1304: movb positive,result2_sign(%ebp)// used for sign of result ! 1305: cmpb valid,result2_tag(%ebp) // after log core ! 1306: jnz log_special_log // result sign same as result2 ! 1307: call right_shift_frac1_8 ! 1308: mov $constant_sqrt_of_2,%esi ! 1309: call sub_frac2 ! 1310: cmpb $0,msb_result ! 1311: jne log_small_lg ! 1312: jmp log_large_lg ! 1313: ALIGN ! 1314: log_sp_negative_x: ! 1315: call move_frac1_result ! 1316: movb negative,result2_sign(%ebp) ! 1317: jmp log_core ! 1318: ALIGN ! 1319: log_special_log: ! 1320: // mov edi, offset_operand1 ; weed out the special case ! 1321: // call test_6w ; where x = 0. result should ! 1322: // jz log_splog_zero ; be exact signed zero. ! 1323: mov dword_expon1,%eax // log x not 0 ! 1324: mov %eax,dword_result_expon ! 1325: cmpb positive,sign1(%ebp) ! 1326: jne log_sp_negative_x ! 1327: call move_frac1_frac2 ! 1328: mov $0x3fff,%ecx ! 1329: sub dword_expon1,%ecx ! 1330: cmp $72,%ecx ! 1331: jbe log_sp_label_1 ! 1332: mov $72,%ecx ! 1333: log_sp_label_1: ! 1334: call right_shift_frac2_cl ! 1335: movw word_frac2,%cx ! 1336: and $0x1fff,%ecx ! 1337: or %ecx,%edx ! 1338: jz log_non_sticky ! 1339: orw $0x2000,word_frac2 ! 1340: log_non_sticky: ! 1341: orb $0x80,msb_frac2 ! 1342: andl $0x0e0000000,dword_frac2(%ebp) ! 1343: jmp log_div ! 1344: ALIGN ! 1345: // ! 1346: // frac(x) < sqrt(2) ! 1347: // ! 1348: log_small_lg: ! 1349: call left_shift_frac1_8 ! 1350: call move_frac1_result ! 1351: mov $1,%ecx ! 1352: call left_shift_result_cl ! 1353: mov $offset_result+frac80,%edi ! 1354: call test_5w ! 1355: jz log_power_of_two ! 1356: movl $0x3ffe,dword_result_expon ! 1357: mov $offset_result,%edi ! 1358: call subtraction_normalize ! 1359: call move_frac1_frac2 ! 1360: call move_result_frac1 ! 1361: log_div: ! 1362: // the following call used to be to log_divx instead of accel_divx: ! 1363: push log_loop_ct ! 1364: call accel_divx ! 1365: pop log_loop_ct ! 1366: andl $0x0e0000000,result_dword_frac(%ebp)// mask result frac ! 1367: jmp log_merge_lg ! 1368: ALIGN ! 1369: // ! 1370: // x = 2 ** n ! 1371: // ! 1372: log_power_of_two: ! 1373: call decompose ! 1374: log_mul: ! 1375: mov $offset_operand1+frac80,%edi ! 1376: call test_5w ! 1377: jnz log_x_not_0 ! 1378: // call log_round ; round the result ! 1379: log_splog_zero: ! 1380: movb special,tag1(%ebp) // zero tag ! 1381: movb lsb_result2,%al ! 1382: xorb %al,sign1(%ebp) ! 1383: lea dword_frac1(%ebp),%esi ! 1384: lea result_dword_frac(%ebp),%edi ! 1385: call move_op_to_op ! 1386: jmp log_restore_user_controls ! 1387: ALIGN ! 1388: log_x_not_0: ! 1389: // cmp lsb_cop, special ! 1390: // jne log_y_not_zero ! 1391: // ! 1392: //y=0 ! 1393: // ! 1394: // xor eax, eax ! 1395: // mov edi, offset result_dword_frac + 4 ! 1396: // call set_4w ! 1397: // mov dword_result_expon, eax ! 1398: // mov dword ptr (ebp).result_sign, special*10000h ! 1399: // mov al, (ebp).sign1 ! 1400: // xor al, lsb_result2 ! 1401: // mov (ebp).result_sign, al ! 1402: // jmp short log_finish_up ! 1403: //log_y_not_zero: ! 1404: andl $0x0ff000000,dword_cop(%ebp) ! 1405: call move_cop_frac2 // restore y into op2 ! 1406: mov log_loop_ct,%eax ! 1407: mov %eax,dword_expon2 ! 1408: movb lsb_result2,%al ! 1409: movb %al,sign2(%ebp) ! 1410: call mult ! 1411: call post_op_round // round the result ! 1412: // ! 1413: //error checking ! 1414: // ! 1415: mov dword_result_expon,%eax ! 1416: cmp $0x7ffe,%eax ! 1417: jg log_overflow ! 1418: cmp $0,%eax ! 1419: jl log_underflow ! 1420: jg log_set_tag_valid ! 1421: mov $offset_result+frac64,%edi ! 1422: call test_4w // eax = 0 here ! 1423: jnz log_underflow ! 1424: // ! 1425: //zero result ! 1426: // ! 1427: movb special,result_tag(%ebp) ! 1428: jmp log_round_report ! 1429: ALIGN ! 1430: log_set_tag_valid: ! 1431: movb valid,result_tag(%ebp) ! 1432: log_round_report: ! 1433: cmpw $0,rnd_history ! 1434: je log_restore_user_controls ! 1435: orb $inexact_mask,%gs:sr_errors ! 1436: cmpb true,added_one ! 1437: jne log_restore_user_controls ! 1438: orb $a_mask,%gs:sr_flags ! 1439: log_restore_user_controls: ! 1440: pop %gs:sr_masks ! 1441: log_exit: ! 1442: ret ! 1443: ALIGN ! 1444: // ! 1445: log_overflow: ! 1446: call overflow_response ! 1447: jmp log_restore_user_controls ! 1448: ALIGN ! 1449: log_underflow: ! 1450: call underflow_response ! 1451: jmp log_restore_user_controls ! 1452: ALIGN ! 1453: // ! 1454: //frac(x) > sqrt(2) ! 1455: // ! 1456: log_large_lg: ! 1457: incl dword_expon1 ! 1458: call move_frac1_frac2 ! 1459: mov $constant_one,%esi ! 1460: call sub_frac1 ! 1461: mov $7,%ecx ! 1462: call left_shift_result_cl ! 1463: movb negative,result2_sign(%ebp) // set flag for large log ! 1464: movl $0x3fff,dword_result_expon ! 1465: log_merge_lg: ! 1466: mov $offset_result+frac80,%edi // dont normalize a zero ! 1467: call test_5w // is the result zero? ! 1468: jz log_core // yes, no need to normalize ! 1469: mov $offset_result,%edi ! 1470: call subtraction_normalize ! 1471: log_core: ! 1472: call move_result_frac2 ! 1473: movw $0,siso // clear siso ! 1474: mov $0x3fff,%eax ! 1475: sub dword_result_expon,%eax ! 1476: mov %eax,dword_exp_tmp ! 1477: cmp $15,%eax ! 1478: ja log_rat_apx ! 1479: call move_result_frac1 // log pseudo divide ! 1480: mov $7,%ecx ! 1481: add dword_exp_tmp,%ecx ! 1482: call right_shift_frac1_cl ! 1483: call right_shift_frac2_8 ! 1484: call addx ! 1485: cmpb $0,msb_result ! 1486: je log_loop_back_1 ! 1487: andl $0x0ffe00000,result_dword_frac(%ebp) ! 1488: movb $0,msb_result ! 1489: call move_result_frac2 ! 1490: movw $1,siso ! 1491: log_loop_back_1: ! 1492: shlw $1,siso ! 1493: call move_frac2_frac1 ! 1494: mov dword_exp_tmp,%ecx ! 1495: call right_shift_frac1_cl ! 1496: orl $0x00800000,dword_frac1+frac32(%ebp) ! 1497: call addx ! 1498: cmpb $0,msb_result ! 1499: je log_merge_2 ! 1500: andl $0x0ffe00000,result_dword_frac(%ebp) ! 1501: movb $0,msb_result ! 1502: call move_result_frac2 ! 1503: incw siso ! 1504: log_merge_2: ! 1505: mov $1,%ecx ! 1506: call left_shift_frac2_cl ! 1507: incl dword_exp_tmp ! 1508: cmp $15,dword_exp_tmp ! 1509: jbe log_loop_back_1 ! 1510: call left_shift_frac2_8 ! 1511: // ! 1512: //rational approximation ! 1513: // ! 1514: log_rat_apx: ! 1515: orb $inexact_mask,%gs:sr_errors // set p flag ! 1516: call move_frac2_frac1 ! 1517: call mulx ! 1518: mov dword_exp_tmp,%ecx ! 1519: cmp $72,%ecx ! 1520: jbe log_label_4 ! 1521: mov $72,%ecx ! 1522: log_label_4: ! 1523: call right_shift_result_cl ! 1524: andl $0x0e0000000,result_dword_frac(%ebp)// mask result frac ! 1525: call move_result_frac2 ! 1526: call subx ! 1527: call move_result_dop ! 1528: mov dword_exp_tmp,%ecx ! 1529: cmp $72,%ecx ! 1530: jbe log_label_5 ! 1531: mov $72,%ecx ! 1532: log_label_5: ! 1533: call right_shift_frac1_cl ! 1534: andl $0x0e0000000,dword_frac1(%ebp) ! 1535: call move_frac1_frac2 ! 1536: mov $constant_six,%esi ! 1537: call sub_frac1 ! 1538: call move_result_frac1 ! 1539: call move_dop_frac2 ! 1540: mov dword_exp_tmp,%ecx ! 1541: inc %ecx ! 1542: cmp $72,%ecx ! 1543: jbe log_label_6 ! 1544: mov $72,%ecx ! 1545: log_label_6: ! 1546: call right_shift_frac2_cl ! 1547: andl $0x0f0000000,dword_frac2(%ebp) ! 1548: call subx ! 1549: andl $0x0e0000000,result_dword_frac(%ebp)// mask result frac ! 1550: call move_dop_frac1 ! 1551: call move_result_frac2 ! 1552: // the following call used to be to log_divx instead of accel_divx: ! 1553: push log_loop_ct ! 1554: call accel_divx ! 1555: pop log_loop_ct ! 1556: andl $0x0e0000000,result_dword_frac(%ebp)// mask result frac ! 1557: call move_result_frac1 ! 1558: mov $constant_3_ov_ln2,%esi ! 1559: call mul_frac2 ! 1560: mov $7,%ecx ! 1561: call right_shift_result_cl ! 1562: decl dword_exp_tmp ! 1563: log_loop_back_2: ! 1564: shrw $1,siso ! 1565: jnb log_no_carry ! 1566: mov dword_exp_tmp,%esi ! 1567: dec %esi ! 1568: mov $10,%eax ! 1569: mul %esi ! 1570: mov %eax,%esi ! 1571: add $log_constant,%esi ! 1572: call move_constant_frac2 ! 1573: call move_result_frac1 ! 1574: call addx ! 1575: log_no_carry: ! 1576: cmpw $0,siso ! 1577: jz log_end_loop ! 1578: call right_shift_result_1 ! 1579: decl dword_exp_tmp ! 1580: jmp log_loop_back_2 ! 1581: ALIGN ! 1582: log_end_loop: ! 1583: mov $0x4007,%eax //4007 = 3fff + 8 ! 1584: sub dword_exp_tmp,%eax ! 1585: mov %eax,dword_result_expon ! 1586: andl $0x0ffe00000,result_dword_frac(%ebp) ! 1587: mov $offset_result,%edi // dont normalize a zero ! 1588: call test_6w // is the result zero? ! 1589: jz log_end_log_core // yes, no need to normalize ! 1590: mov $offset_result,%edi ! 1591: call subtraction_normalize ! 1592: log_end_log_core: ! 1593: cmpb valid,result2_tag(%ebp) ! 1594: jnz log_special_log_end ! 1595: call decompose ! 1596: call move_result_frac2 ! 1597: mov dword_result_expon,%eax ! 1598: mov %eax,dword_expon2 ! 1599: movb $add_op,operation_type(%ebp) ! 1600: movb result2_sign(%ebp),%al ! 1601: movb %al,sign2(%ebp) ! 1602: call sp_subadd ! 1603: log_merge_4: ! 1604: call move_result_frac1 ! 1605: movb result_sign(%ebp),%al ! 1606: movb %al,sign1(%ebp) ! 1607: mov dword_result_expon,%eax ! 1608: mov %eax,dword_expon1 ! 1609: jmp log_mul ! 1610: ALIGN ! 1611: log_special_log_end: ! 1612: movb result2_sign(%ebp),%al ! 1613: movb %al,result_sign(%ebp) ! 1614: jmp log_merge_4 ! 1615: ALIGN ! 1616: // ! 1617: //do round ; made into common subroutine for all ! 1618: // ! 1619: log_round: ! 1620: movb $1,lsb_result // fixed up such that ! 1621: // call get_precision ! 1622: post_op_round: ! 1623: movb prec64,%dl ! 1624: mov $offset_result,%edi // s = 1 always ! 1625: movb false,%al // not second rounding ! 1626: call round ! 1627: mov $offset_result,%edi ! 1628: movb $4,%ah // fall through ! 1629: //log endp ! 1630: // ! 1631: // ! 1632: // addition_normalize: ! 1633: // ! 1634: // function: ! 1635: // performs normalization after addition if necessary. ! 1636: // ! 1637: // inputs: ! 1638: // carry-out from addition in al upon entry. ! 1639: // fraction offset in di. ! 1640: // ! 1641: // outputs: ! 1642: // increments exponent and shifts 1 bit in from left if al=1. ! 1643: // ! 1644: // data accessed: ! 1645: // ! 1646: // data changed: ! 1647: // ! 1648: // procedures called: ! 1649: // sticky_right_shift ! 1650: // ! 1651: // ************************************************************************* ! 1652: FALLSTHRU ! 1653: addition_normalize: //proc ! 1654: testb $0x01,%al //if low bit of al = 1, ! 1655: jnz right_shift_1 // then shift right 1 ! 1656: ret // else, exit ! 1657: ALIGN ! 1658: right_shift_1: ! 1659: incl expon(%ebp,%edi) //increment exponent ! 1660: movb $1,%cl //shift right 1 bit ! 1661: //addition_normalize endp ; sticky_right_shift ! 1662: // ! 1663: // *********************************************************************** ! 1664: // sticky_right_shift: ! 1665: // ****************** ! 1666: // function: ! 1667: // shifts a 10-byte number right by amount in ! 1668: // cl register. di contains offset of number. ! 1669: // ! 1670: // inputs: ! 1671: // low bit of al contains bit to inject from left. ! 1672: // (for shifts of more than one, the result is undefined ! 1673: // unless al contains zero). ! 1674: // ! 1675: // outputs: ! 1676: // the low-order bit of the number is *sticky*, ie, it is ! 1677: // left as a one if any ones were shifted out. ! 1678: // ! 1679: // data accessed: ! 1680: // ! 1681: // data changed: ! 1682: // ! 1683: // procedures called: ! 1684: // right_shift ! 1685: // ! 1686: // *************************************************************************** ! 1687: FALLSTHRU ! 1688: sticky_right_shift: //proc ! 1689: call right_shift //do right shift ! 1690: and %edx,%edx //edx <> 0 if 1s lost ! 1691: jz sticky_right_shift_done //done if no 1s lost ! 1692: orb $0x01,frac80(%ebp,%edi) //else, set sticky bit ! 1693: sticky_right_shift_done: ! 1694: ret ! 1695: //sticky_right_shift endp ! 1696: // ! 1697: // ************************************************************************ ! 1698: // gradual_underflow: ! 1699: // ! 1700: // function: ! 1701: // changes an *underflowed* number to a legal, ! 1702: // denormalized number. ! 1703: // ! 1704: // input: ! 1705: // address of exponent and fraction in operands or result ! 1706: // (ptr in di register); minimum legal exponent(in ! 1707: // ax register). ! 1708: // ! 1709: // output: ! 1710: // denormalized fraction and adjusted exponent (in input ! 1711: // record) ! 1712: // ! 1713: // data accessed:; - expon word_frac ! 1714: // ! 1715: // data changed: ! 1716: // - expon word_frac ! 1717: // ! 1718: // procedures called: ! 1719: // sticky_right_shift ! 1720: // ! 1721: // *********************************************************************** ! 1722: ALIGN ! 1723: gradual_underflow: //proc ! 1724: mov %eax,%ecx // set exponent to minimum ! 1725: xchg expon(%ebp,%edi),%eax ! 1726: sub %eax,%ecx // form shift amount ! 1727: cmp $67,%ecx // (exponent - minimum exponent) ! 1728: jle do_right_shift ! 1729: mov $67,%ecx // shift amount must be <= 67 ! 1730: do_right_shift: ! 1731: xorb %al,%al // byte to be shifted in from ! 1732: jmp sticky_right_shift // the left ! 1733: ALIGN ! 1734: //gradual_underflow endp ! 1735: ! 1736: ! 1737: // ****************************************************************************** ! 1738: // two_result_op1_chk ! 1739: // ! 1740: // action: ! 1741: // for sincos and (two result) tan, checks the following and responds as ! 1742: // described: ! 1743: // 1. whether fetch_an_op discovered that the source from which ! 1744: // operand1 was to have been taken was empty. if so, sets stack ! 1745: // underflow exception, clears c-flag (indicating not incomplete ! 1746: // reduction), pops the return address of its caller so that it ! 1747: // returns directly to the e80387 executive routine, and, if the ! 1748: // invalid exception is unmasked, makes that return forthwith. ! 1749: // if the invalid exception is masked, this procedure prepares to ! 1750: // return via a jump to put_result by first setting edi so that ! 1751: // the nan indefinite put in operand1 by fetch_an_op will be ! 1752: // returned, and setting esi so that this returned value will be ! 1753: // pushed onto the stack. note that after this push, the former ! 1754: // stack top is unchanged; i.e., if it was empty as stack top, its ! 1755: // still empty as st(1). ! 1756: // 2. if operand1 was fetched from a non-empty source, clears ! 1757: // c-flag (indicating not incomplete reduction) and then checks ! 1758: // whether a push will be to a full position. if so, sets zf so ! 1759: // that return to e80387 executive after popping callers return ! 1760: // address and jumping to put_result does not falsely signal ! 1761: // masked stack underflow instead of correctly signaling stack ! 1762: // overflow. ! 1763: // 3. if push would be to an empty position, initializes the ! 1764: // before_error_signals used by put_result, clears the a-flag, ! 1765: // and checks tag of operand1. ! 1766: // a. if tag is unsupp or infinty, replaces operand1 by ! 1767: // the nan indefinite, then checks whether invalid operation ! 1768: // is masked. if not masked, sets invalid operation exception ! 1769: // flag and pops callers return address so that return is to ! 1770: // e80387 executive. if masked, copies the quiet nan in ! 1771: // operand1 to operand2, sets the signal_i_error? component of ! 1772: // before_error_signals to true, and returns to e80387 ! 1773: // executive by popping callers return address and jumping to ! 1774: // do_exchange. ! 1775: // b. if tag is inv, checks whether the nan in operand1 is ! 1776: // signaling. if not, sets zf, pops callers return address, ! 1777: // sets edi and esi so that jump to put_result causes the ! 1778: // quiet nan in operand1 to be pushed onto 87 stack. if the ! 1779: // nan is signaling, sets its leading fraction bit, thereby ! 1780: // *quieting* it, and proceeds as in *a* above, but with the ! 1781: // *quietized* nan in place of the nan indefinite. ! 1782: // c. if tag is denormd, checks whether denormal exception ! 1783: // is masked. if not masked, sets denormal exception flag and ! 1784: // pops callers return address so that return is to e80387 ! 1785: // executive. if masked, sets the signal_d_error component of ! 1786: // before_error_signals to true, normalizes operand1 and forces ! 1787: // zf = 0 (indicating non-zero operand1) before returning to ! 1788: // caller. ! 1789: // d. if tag is valid or special (signed, true zero), returns ! 1790: // to caller with zf clear or set, respectively. ! 1791: // ! 1792: // ! 1793: // **************************************************************************** ! 1794: ALIGN ! 1795: two_result_op1_chk: //proc ! 1796: jz is_stack_full_ // if no stack underflow, go on ! 1797: call set_stk_u_error // else, prepare for error exit ! 1798: andb $~c_mask,%gs:sr_flags // clear 87 c-flag ! 1799: testb invalid_mask,%gs:sr_masks ! 1800: jnz push_op1 // masked stack error, so return indef ! 1801: unmasked_exit: ! 1802: pop %eax // pop address of transcendental caller so ! 1803: two_res_quik_exit: // return is to e80387 executive procedure. ! 1804: ret ! 1805: ALIGN ! 1806: push_op1: ! 1807: mov $offset_operand1,%edi ! 1808: mov offset_result2_rec,%esi ! 1809: pop %eax // pop address of transcendental caller ! 1810: lahf // save zf to show if masked stack underflow ! 1811: jmp put_result // return is to e80387 executive procedure. ! 1812: ALIGN ! 1813: is_stack_full_: ! 1814: andb $~c_mask,%gs:sr_flags // clear 87 c-flag ! 1815: call stack_full_ ! 1816: jz cntnu_chk ! 1817: set_zf: ! 1818: xor %eax,%eax ! 1819: jmp push_op1 ! 1820: ALIGN ! 1821: cntnu_chk: ! 1822: movl $0,before_error_signals(%ebp) ! 1823: andb $~a_mask,%gs:sr_flags ! 1824: movb tag1(%ebp),%al // load tag for op1 ! 1825: cmpb special,%al ! 1826: jbe ok_op ! 1827: cmpb denormd,%al ! 1828: jb inv_op ! 1829: je signal_d_error // elsif denormalized, then signal d_error ! 1830: mov $offset_operand1,%edi // infinity or unsupported, ! 1831: call set_up_indefinite // set up masked result ! 1832: jmp test_invalid_mask ! 1833: ALIGN ! 1834: inv_op: ! 1835: testb $0x40,msb_frac1 // elsif op1 nan, find what kind ! 1836: jnz set_zf // op1 is a qnan, so load it to tos ! 1837: orb $0x40,msb_frac1 // make nan quiet ! 1838: test_invalid_mask: ! 1839: testb invalid_mask,%gs:sr_masks ! 1840: jnz copy_nan ! 1841: orb invalid_mask,%gs:sr_errors ! 1842: jmp unmasked_exit ! 1843: ALIGN ! 1844: copy_nan: ! 1845: lea dword_frac1(%ebp),%esi // copy op1 to op2 ! 1846: lea dword_frac2(%ebp),%edi ! 1847: call move_op_to_op ! 1848: signal_i_error: ! 1849: movb true,signal_i_error_ ! 1850: pop %eax ! 1851: jmp do_exchange ! 1852: ALIGN ! 1853: signal_d_error: ! 1854: testb denorm_mask,%gs:sr_masks ! 1855: jnz set_up_d_error ! 1856: orb denorm_mask,%gs:sr_errors ! 1857: jmp unmasked_exit ! 1858: ALIGN ! 1859: set_up_d_error: ! 1860: movb true,signal_d_error_// op1 is denormal or pseudo-denormal ! 1861: mov $offset_operand1,%edi ! 1862: call norm_denorm // if d_error masked, make valid ! 1863: or $1,%eax // force zf = 0 ! 1864: ok_op: ! 1865: ret // zf = 1 iff op1 is true zero ! 1866: ! 1867: //two_result_op1_chk endp ! 1868: // ! 1869: // ****************************************************************************** ! 1870: // one_result_op1_chk ! 1871: // ! 1872: // action: ! 1873: // for sin and cos, checks the following and responds as ! 1874: // described: ! 1875: // 1. whether fetch_an_op discovered that the source from which ! 1876: // operand1 was to have been taken was empty. if so, sets stack ! 1877: // underflow exception, clears c-flag (indicating not incomplete ! 1878: // reduction), pops the return address of its caller so that it ! 1879: // returns directly to the e80387 executive routine, and, if the ! 1880: // invalid exception is unmasked, makes that return forthwith. ! 1881: // if the invalid exception is masked, this procedure prepares to ! 1882: // return via a jump to put_result by first setting edi so that ! 1883: // the nan indefinite put in operand1 by fetch_an_op will be ! 1884: // returned, and setting esi so that this returned value will be ! 1885: // pushed onto the stack. note that after this push, the former ! 1886: // stack top is unchanged; i.e., if it was empty as stack top, its ! 1887: // still empty as st(1). ! 1888: // 2. if operand1 was fetched from a non-empty source, clears ! 1889: // c-flag (indicating not incomplete reduction) and then checks ! 1890: // whether a push will be to a full position. if so, sets zf so ! 1891: // that return to e80387 executive after popping callers return ! 1892: // address and jumping to put_result does not falsely signal ! 1893: // masked stack underflow instead of correctly signaling stack ! 1894: // overflow. ! 1895: // 3. if push would be to an empty position, initializes the ! 1896: // before_error_signals used by put_result, clears the a-flag, ! 1897: // and checks tag of operand1. ! 1898: // a. if tag is unsupp or infinty, replaces operand1 by ! 1899: // the nan indefinite, then checks whether invalid operation ! 1900: // is masked. if not masked, sets invalid operation exception ! 1901: // flag and pops callers return address so that return is to ! 1902: // e80387 executive. if masked, copies the quiet nan in ! 1903: // operand1 to operand2, sets the signal_i_error? component of ! 1904: // before_error_signals to true, and returns to e80387 ! 1905: // executive by popping callers return address and jumping to ! 1906: // do_exchange. ! 1907: // b. if tag is inv, checks whether the nan in operand1 is ! 1908: // signaling. if not, sets zf, pops callers return address, ! 1909: // sets edi and esi so that jump to put_result causes the ! 1910: // quiet nan in operand1 to be pushed onto 87 stack. if the ! 1911: // nan is signaling, sets its leading fraction bit, thereby ! 1912: // *quieting* it, and proceeds as in *a* above, but with the ! 1913: // *quietized* nan in place of the nan indefinite. ! 1914: // c. if tag is denormd, checks whether denormal exception ! 1915: // is masked. if not masked, sets denormal exception flag and ! 1916: // pops callers return address so that return is to e80387 ! 1917: // executive. if masked, sets the signal_d_error component of ! 1918: // before_error_signals to true, normalizes operand1 and forces ! 1919: // zf = 0 (indicating non-zero operand1) before returning to ! 1920: // caller. ! 1921: // d. if tag is valid or special (signed, true zero), returns ! 1922: // to caller with zf clear or set, respectively. ! 1923: // ! 1924: // ! 1925: // **************************************************************************** ! 1926: ALIGN ! 1927: one_result_op1_chk: //proc ! 1928: jz check_tag1 // if no stack underflow, go on ! 1929: call set_stk_u_error // else, prepare for error exit ! 1930: andb $~c_mask,%gs:sr_flags // clear 87 c-flag ! 1931: testb invalid_mask,%gs:sr_masks ! 1932: jnz give_op1 // masked stack error, so return indef ! 1933: one_res_unmasked_exit: ! 1934: pop %eax // pop address of transcendental caller so ! 1935: one_res_quik_exit: // return is to e80387 executive procedure. ! 1936: ret ! 1937: ALIGN ! 1938: give_op1: ! 1939: pop %eax // pop address of transcendental caller so ! 1940: jmp put_op1_result // return is to e80387 executive procedure. ! 1941: ALIGN ! 1942: check_tag1: ! 1943: andb $~(a_mask+c_mask),%gs:sr_flags ! 1944: movb tag1(%ebp),%al // load tag for op1 ! 1945: cmpb special,%al ! 1946: jle op1_ok ! 1947: cmpb denormd,%al ! 1948: jl op1_inv ! 1949: je op1_den // elsif denormalized, then signal d_error ! 1950: cmpb $exp_op,operation_type(%ebp) ! 1951: jne one_res_unsup ! 1952: cmpb unsupp,%al ! 1953: je one_res_unsup ! 1954: cmpb positive,sign1(%ebp) // op1 is +/- infinity ! 1955: je give_op1 ! 1956: movl $0x3fff,dword_expon1 ! 1957: jmp give_op1 ! 1958: ALIGN ! 1959: one_res_unsup: ! 1960: mov $offset_operand1,%edi // infinity or unsupported, ! 1961: call set_up_indefinite // set up masked result ! 1962: jmp invalid_masked_ ! 1963: ALIGN ! 1964: op1_inv: ! 1965: testb $0x40,msb_frac1 // elsif op1 nan, find what kind ! 1966: jnz give_op1 // op1 is a qnan, so return it ! 1967: orb $0x40,msb_frac1 // make nan quiet ! 1968: invalid_masked_: ! 1969: orb invalid_mask,%gs:sr_errors ! 1970: testb invalid_mask,%gs:sr_masks ! 1971: jz one_res_unmasked_exit ! 1972: jmp give_op1 ! 1973: ALIGN ! 1974: op1_den: ! 1975: orb denorm_mask,%gs:sr_errors ! 1976: testb denorm_mask,%gs:sr_masks ! 1977: jz one_res_unmasked_exit ! 1978: mov $offset_operand1,%edi ! 1979: call norm_denorm // if d_error masked, make valid ! 1980: or $1,%eax // force zf = 0 ! 1981: op1_ok: ! 1982: ret // zf = 1 iff op1 is true zero ! 1983: ! 1984: //one_result_op1_chk endp ! 1985: // **************************************************************************** ! 1986: ALIGN ! 1987: mod_qrtr_pi: //proc ! 1988: // 87 c-flag has been cleared by this point ! 1989: xor %eax,%eax ! 1990: movb operation_type(%ebp),%al ! 1991: movb sign1(%ebp),%ah ! 1992: mov %eax,trans_info // initialize cofunc_flag false (00h) ! 1993: // and cos_sign positive (00h) ! 1994: movb positive,sign1(%ebp)// take absolute value of op1 ! 1995: movw $0,exp_tmp // initialize q and hi_q to 0. ! 1996: mov dword_expon1,%eax ! 1997: sub $0x3ffe,%eax ! 1998: jl reduction_done ! 1999: cmp $63,%eax ! 2000: jle do_reduction ! 2001: orb $c_mask,%gs:sr_flags // indicate incomplete reduction ! 2002: pop %eax // get rid of callers return address ! 2003: ret ! 2004: ALIGN ! 2005: do_reduction: ! 2006: movl $0x2168c235,dword_frac2+frac64(%ebp) ! 2007: movl $0x0c90fdaa2,dword_frac2+frac32(%ebp) ! 2008: movl $0x10000*VALID+POSITIVE,dword_frac2+sign(%ebp) ! 2009: movl $0x3ffe,dword_expon2 ! 2010: sub %eax,dword_expon1 ! 2011: inc %eax ! 2012: call remrx ! 2013: mov dword_frac1+frac64(%ebp),%eax ! 2014: or dword_frac1+frac32(%ebp),%eax ! 2015: jnz mod_not_0 ! 2016: mov %eax,dword_frac1(%ebp) // here, eax = 0 ! 2017: mov %eax,dword_expon1 ! 2018: movl special,dword_frac1+tag(%ebp) ! 2019: jmp reduce_pi ! 2020: ALIGN ! 2021: mod_not_0: ! 2022: mov $offset_operand1,%edi ! 2023: call subtraction_normalize // returns with zf = 0. ! 2024: reduction_done: ! 2025: orb $inexact_mask,%gs:sr_errors // precision error unless zero mod ! 2026: //check_for_tan_op: ! 2027: // cmpb op_type, tan_op ! 2028: // je reduce_hapi ! 2029: reduce_pi: ! 2030: testb $4,q ! 2031: jz reduce_hapi ! 2032: notw res_signs // flip sign for both sin and cos ! 2033: reduce_hapi: ! 2034: testb $2,q ! 2035: jz reduce_qrpi ! 2036: notb cofunc_flag ! 2037: notb cos_sign ! 2038: // cmpb op_type, tan_op ! 2039: // jne reduce_qrpi ! 2040: // not sin_sign ; use sin_sign as tan_sign ! 2041: reduce_qrpi: ! 2042: testb $1,q ! 2043: jnz last_reduc ! 2044: ret // zf is set here ! 2045: ALIGN ! 2046: last_reduc: ! 2047: notb cofunc_flag // a zero mod will be changed here ! 2048: cmpb special,tag1(%ebp) ! 2049: jne mod_set_inexact ! 2050: cmpb $tan_op,op_type ! 2051: // je complementary_angle ! 2052: jne mod_set_inexact ! 2053: movb $0x80,msb_frac1 ! 2054: movb valid,tag1(%ebp) ! 2055: movl $0x3fff,dword_expon1 ! 2056: mov $offset_operand2,%esi ! 2057: call move_unpacked_1_to_esi ! 2058: add $4,%esp // get rid of return address ! 2059: jmp adjust_sign ! 2060: ALIGN ! 2061: mod_set_inexact: // a zero mod will be changed here ! 2062: orb $inexact_mask,%gs:sr_errors // to qrtr_pi, so precision error ! 2063: complementary_angle: ! 2064: movl $0,dword_frac2(%ebp) ! 2065: movl $0x2168c235,dword_frac2+frac64(%ebp) ! 2066: movl $0x0c90fdaa2,dword_frac2+frac32(%ebp) ! 2067: movl $0x10000*VALID+POSITIVE,dword_frac2+sign(%ebp) ! 2068: movl $0x3ffe,dword_expon2 ! 2069: movb negative,sign1(%ebp) ! 2070: movb $add_op,operation_type(%ebp) ! 2071: call subadd ! 2072: push %gs:sr_masks ! 2073: andl $0x0fffff3ff,%gs:sr_masks // set rc = to_nearest ! 2074: call post_op_round ! 2075: pop %gs:sr_masks ! 2076: lea result_dword_frac(%ebp),%esi ! 2077: lea dword_frac1(%ebp),%edi ! 2078: call move_op_to_op ! 2079: ret ! 2080: //mod_qrtr_pi endp ! 2081: // ! 2082: // ****************************************************************************** ! 2083: ALIGN ! 2084: tan_pseudo_divide: //proc ! 2085: ! 2086: movw $0,siso // clear siso ! 2087: mov %eax,dword_expon1 ! 2088: cmp $16,%eax ! 2089: jg tan_rat_appx ! 2090: decl dword_expon1 // decrement expon1 ! 2091: call right_shift_frac1_8 ! 2092: tan_loop_back_1: ! 2093: mov $10,%eax ! 2094: mull dword_expon1 ! 2095: add $tan_constant,%eax ! 2096: mov %eax,%esi ! 2097: call sub_frac2 ! 2098: shlw $1,siso ! 2099: cmpb $0,msb_result ! 2100: jne tan_merge_0 ! 2101: call move_result_frac1 ! 2102: andl $0x0ffe00000,dword_frac1(%ebp) ! 2103: incw siso ! 2104: tan_merge_0: ! 2105: incl dword_expon1 ! 2106: cmp $15,dword_expon1 ! 2107: ja tan_branch_1 ! 2108: call left_shift_frac1_1 ! 2109: jmp tan_loop_back_1 ! 2110: ALIGN ! 2111: tan_branch_1: ! 2112: call left_shift_frac1_8 ! 2113: movl $0,dword_frac1(%ebp) ! 2114: tan_rat_appx: ! 2115: call move_frac1_cop // cop <- theta, cop tmp ! 2116: call mulx // theta * theta ! 2117: mov dword_expon1,%ecx ! 2118: shl $1,%ecx ! 2119: add $8,%ecx ! 2120: call right_shift_result_cl ! 2121: andl $0x0ff000000,result_dword_frac(%ebp) // 64 bits only ! 2122: call move_result_frac2 ! 2123: mov $constant_c0h,%esi ! 2124: call sub_frac1 // x <- 1.1 - theta*theta ! 2125: call move_cop_frac2 ! 2126: call right_shift_frac2_8 ! 2127: call move_cop_frac1 ! 2128: movb $9,%cl ! 2129: call right_shift_frac1_cl ! 2130: call move_result_cop // cop <- x ! 2131: call addx // y <- y + theta ! 2132: call right_shift_result_1 ! 2133: call move_result_dop // dop <- y, dop ! 2134: decl dword_expon1 // is a 67 bits temp ! 2135: // ! 2136: //pseudo_multiply ! 2137: // ! 2138: tan_loop_back_2: ! 2139: shrw $1,siso ! 2140: jnb tan_merge_2 ! 2141: call move_cop_frac1 // x ! 2142: call move_dop_frac2 // y ! 2143: call addx // x + y ! 2144: call move_result_dop // -> dop ! 2145: mov dword_expon1,%ecx ! 2146: shl $1,%ecx ! 2147: call right_shift_frac2_cl ! 2148: andl $0x0ffe00000,dword_frac2(%ebp) ! 2149: call subx // x - y*2(-2exp) ! 2150: call move_result_cop // -> cop ! 2151: andl $0x0ff000000,dword_cop(%ebp) ! 2152: tan_merge_2: ! 2153: cmpw $0,siso ! 2154: je tan_almost_end ! 2155: movb $1,%cl ! 2156: mov $offset_dop,%edi ! 2157: call right_shift_al0 ! 2158: andl $0x0ffe00000,dword_dop(%ebp) ! 2159: decl dword_expon1 ! 2160: jmp tan_loop_back_2 ! 2161: ALIGN ! 2162: tan_almost_end: ! 2163: movb $8,%cl ! 2164: cmpb $0,msb_dop ! 2165: je tan_merge_3 ! 2166: movb $7,%cl ! 2167: decl dword_expon1 ! 2168: tan_merge_3: ! 2169: mov $offset_dop+frac80,%edi ! 2170: call left_shift ! 2171: call move_dop_frac1 ! 2172: mov $0x3fff,%eax ! 2173: sub dword_expon1,%eax ! 2174: mov %eax,dword_expon1 ! 2175: // ! 2176: //normalize y ! 2177: // ! 2178: mov $offset_operand1,%edi ! 2179: call subtraction_normalize ! 2180: // ! 2181: //now x ! 2182: // ! 2183: call move_cop_frac2 ! 2184: call left_shift_frac2_8 ! 2185: movl $0x3fff,dword_expon2 ! 2186: movl $0x10000*VALID+POSITIVE,sign2(%ebp) ! 2187: // ! 2188: //normalize x ! 2189: // ! 2190: mov $offset_operand2,%edi ! 2191: call subtraction_normalize ! 2192: ret ! 2193: //tan_pseudo_divide endp ! 2194: // ! 2195: // ****************************************************************************** ! 2196: // ! 2197: // tan: ! 2198: // ! 2199: // function: ! 2200: // calculates y and x such that y/x = tan(theta) ! 2201: // ! 2202: // inputs: ! 2203: // assumes that operand1 is set up (theta). ! 2204: // ! 2205: // outputs: ! 2206: // results in result records; y = result, x = result2. ! 2207: // error checking done. ! 2208: // ! 2209: // data accessed: ! 2210: // - result_rec_offset result2_rec_offset ! 2211: // - offset_operand1 expon1 ! 2212: // - word_frac1 lsb_frac1 ! 2213: // - offset_operand1 offset_operand2 ! 2214: // - sign2 tag2 ! 2215: // - expon2 lsb_frac2 ! 2216: // - msb_frac2 offset_operand2 ! 2217: // - lsb_result msb_result ! 2218: // - offset_result siso ! 2219: // - offset_cop lsb_cop ! 2220: // - offset_dop lsb_dop ! 2221: // - msb_dop ! 2222: // ! 2223: // data changed: ! 2224: // - expon1 word_frac1 ! 2225: // - lsb_frac1 sign2 ! 2226: // - tag2 expon2 ! 2227: // - lsb_frac2 msb_result ! 2228: // - lsb_cop lsb_dop ! 2229: // - siso ! 2230: // ! 2231: // procedures called: ! 2232: // do_exchange stack_full? right_shift ! 2233: // left_shift move_10_bytes move_constant ! 2234: // addx subx mulx ! 2235: // subtraction_normalize test_5w set_p_error ! 2236: // ! 2237: // *********************************************************************** ! 2238: ALIGN ! 2239: tan: //proc ! 2240: call two_result_op1_chk ! 2241: get_report: ! 2242: jnz reduce_op1 ! 2243: zero_modulus: ! 2244: mov $offset_operand2,%esi ! 2245: call move_unpacked_1_to_esi ! 2246: jmp do_exchange ! 2247: ALIGN ! 2248: reduce_op1: ! 2249: call mod_qrtr_pi ! 2250: cmpb special,tag1(%ebp) ! 2251: jne tan_tiny_ ! 2252: cmpb true,cofunc_flag ! 2253: jne zero_modulus ! 2254: movl $0,dword_frac1(%ebp) ! 2255: movl $0,dword_frac1+frac64(%ebp) ! 2256: movl $0x080000000,dword_frac1+frac32(%ebp) ! 2257: movl $0x10000*INFINITY+POSITIVE,dword_frac1+sign(%ebp) ! 2258: movl $0x7fff,dword_frac1+expon(%ebp) ! 2259: movb true,signal_z_error_ ! 2260: jmp zero_modulus ! 2261: ALIGN ! 2262: tan_tiny_: ! 2263: mov $0x3fff,%eax ! 2264: sub dword_expon1,%eax ! 2265: cmp $63,%eax ! 2266: jle tan_calc ! 2267: tan_tiny_argument: ! 2268: cmp $0x3fff,%eax ! 2269: jl op2_gets_1 ! 2270: movb sin_sign,%al ! 2271: movb %al,sign1(%ebp) ! 2272: orb underflow_mask,%gs:sr_errors ! 2273: testb underflow_mask,%gs:sr_masks ! 2274: jnz need_grad_uflow ! 2275: addl wrap_around_constant,dword_expon1 ! 2276: jmp zero_modulus ! 2277: ALIGN ! 2278: need_grad_uflow: ! 2279: mov $offset_operand1,%edi ! 2280: mov $1,%eax ! 2281: call gradual_underflow ! 2282: movl $0,dword_expon1 ! 2283: movb denormd,tag1(%ebp) ! 2284: jmp zero_modulus ! 2285: ALIGN ! 2286: op2_gets_1: ! 2287: mov $offset_operand2,%esi ! 2288: call move_unpacked_1_to_esi ! 2289: cmpb true,cofunc_flag ! 2290: jne adjust_sign // straight divide superfluous ! 2291: movw res_signs,%ax ! 2292: movb %al,sign1(%ebp) ! 2293: movb %ah,sign2(%ebp) ! 2294: push %gs:sr_masks ! 2295: // and dword ptr %gs:sr_masks, 0fffff3ffh ; set rc = to_nearest ! 2296: orl $0x0300,%gs:sr_masks // set precision control to prec64 ! 2297: push trans_info ! 2298: jmp reverse_div ! 2299: ALIGN ! 2300: tan_calc: ! 2301: push %gs:sr_masks ! 2302: // and dword ptr %gs:sr_masks, 0fffff3ffh ; set rc = to_nearest ! 2303: orl $0x0300,%gs:sr_masks // set precision control to prec64 ! 2304: push trans_info ! 2305: call tan_pseudo_divide ! 2306: pop trans_info ! 2307: cotan_: ! 2308: movw res_signs,%ax ! 2309: movb %al,sign1(%ebp) ! 2310: movb %ah,sign2(%ebp) ! 2311: push trans_info ! 2312: cmpb true,cofunc_flag ! 2313: jne straight_div ! 2314: reverse_div: ! 2315: call op1_into_op2 ! 2316: jmp get_a_bit ! 2317: ALIGN ! 2318: straight_div: ! 2319: call op2_into_op1 ! 2320: get_a_bit: ! 2321: cmpb true,added_one ! 2322: jne move_tan_result ! 2323: orb $a_mask,%gs:sr_flags ! 2324: move_tan_result: ! 2325: lea result_dword_frac(%ebp),%esi ! 2326: lea dword_frac1(%ebp),%edi ! 2327: call move_op_to_op ! 2328: mov $offset_operand2,%esi ! 2329: call move_unpacked_1_to_esi ! 2330: pop trans_info ! 2331: pop %gs:sr_masks ! 2332: adjust_sign: ! 2333: movb sin_sign,%al ! 2334: xorb cos_sign,%al ! 2335: movb %al,sign1(%ebp) ! 2336: jump_do_exchange: ! 2337: jmp do_exchange_leave_a_bit ! 2338: ALIGN ! 2339: //tan endp ! 2340: // ! 2341: // ********************************************************************** ! 2342: // ! 2343: ALIGN ! 2344: swap_ops: //proc ! 2345: mov $offset_operand1,%esi ! 2346: call push_5_dw_at_esi ! 2347: lea dword_frac2(%ebp),%esi ! 2348: lea dword_frac1(%ebp),%edi ! 2349: call move_op_to_op ! 2350: mov $offset_operand2,%esi ! 2351: call pop_5_dw_at_esi ! 2352: ret ! 2353: //swap_ops endp ! 2354: // ! 2355: // ********************************************************************** ! 2356: // ! 2357: ALIGN ! 2358: op1_into_op2: //proc ! 2359: call swap_ops ! 2360: op2_into_op1: ! 2361: push %gs:sr_masks ! 2362: orl $0x0300,%gs:sr_masks // set precision control to prec64 ! 2363: call divid // floating-point divide ! 2364: call post_op_round ! 2365: pop %gs:sr_masks ! 2366: ret ! 2367: ! 2368: //op1_into_op2 endp ! 2369: // ! 2370: // ********************************************************************** ! 2371: // ! 2372: // ! 2373: ALIGN ! 2374: sin_specific: //proc ! 2375: ! 2376: mov $offset_result,%esi ! 2377: call push_5_dw_at_esi // save (x/y) ! 2378: call op2_into_op1 // result <-- (y/x) ! 2379: lea result_dword_frac(%ebp),%esi ! 2380: lea dword_frac1(%ebp),%edi ! 2381: call move_op_to_op // op1 <-- (y/x) ! 2382: mov $offset_operand2,%esi ! 2383: call pop_5_dw_at_esi // op2 <-- (x/y) ! 2384: orl $0x0f00,%gs:sr_masks // set rc to chop! ! 2385: movb $add_op,operation_type(%ebp) ! 2386: call subadd ! 2387: call post_op_round ! 2388: lea result_dword_frac(%ebp),%esi ! 2389: lea dword_frac2(%ebp),%edi ! 2390: call move_op_to_op // op2 <-- chop(x/y + y/x) ! 2391: mov $offset_operand1,%esi ! 2392: call move_unpacked_1_to_esi // op1 <-- 1 ! 2393: incl dword_expon1 // op1 <-- 2 ! 2394: call op2_into_op1 // res <-- chop{2/chop(x/y + y/x)} ! 2395: ret ! 2396: ! 2397: //sin_specific endp ! 2398: // ! 2399: // ! 2400: // ***************************************************************************** ! 2401: // ! 2402: // sin: ! 2403: // ! 2404: ALIGN ! 2405: sin: //proc ! 2406: call one_result_op1_chk ! 2407: sin_report: ! 2408: jnz sin_reduce_op1 ! 2409: movb $sin_op,op_type ! 2410: movb sign1(%ebp),%al ! 2411: movb %al,sin_sign ! 2412: sin_0_modulus: ! 2413: lea dword_frac1(%ebp),%esi ! 2414: lea result_dword_frac(%ebp),%edi ! 2415: call move_op_to_op ! 2416: jmp check_op_type ! 2417: ALIGN ! 2418: sin_reduce_op1: ! 2419: call mod_qrtr_pi ! 2420: cmpb special,tag1(%ebp) ! 2421: jne sin_tiny_ ! 2422: // testb q, 1 ; was operand (2k+1)*qrtr_pi? ! 2423: // jz sin_cofunc? ; if so, set precision error ! 2424: // orb %gs:sr_errors, inexact_mask ! 2425: //sin_cofunc?: ! 2426: cmpb true,cofunc_flag ! 2427: jne sin_0_modulus ! 2428: jmp cos_0_modulus ! 2429: ALIGN ! 2430: sin_tiny_: ! 2431: cmpb true,cofunc_flag ! 2432: je check_cos_lim ! 2433: check_sin_lim: ! 2434: mov $0x3fff,%eax ! 2435: sub dword_expon1,%eax ! 2436: cmp $30,%eax ! 2437: jl sin_calc ! 2438: jg sin_tiny_argument ! 2439: cmpl $0x08d100000,dword_frac1+frac32(%ebp) ! 2440: ja sin_calc ! 2441: jb sin_0_modulus ! 2442: cmp $0,dword_frac1+frac64(%ebp) ! 2443: je sin_0_modulus ! 2444: sin_tiny_argument: ! 2445: cmp $0x3fff,%eax ! 2446: jl sin_0_modulus ! 2447: orb underflow_mask,%gs:sr_errors ! 2448: testb underflow_mask,%gs:sr_masks ! 2449: jnz sin_grad_uflow ! 2450: addl wrap_around_constant,dword_expon1 ! 2451: jmp sin_0_modulus ! 2452: ALIGN ! 2453: sin_grad_uflow: ! 2454: mov $offset_operand1,%edi ! 2455: mov $1,%eax ! 2456: call gradual_underflow ! 2457: movl $0,dword_expon1 ! 2458: movb denormd,tag1(%ebp) ! 2459: jmp sin_0_modulus ! 2460: ALIGN ! 2461: sin_calc: ! 2462: push trans_info ! 2463: push %gs:sr_masks ! 2464: andl $0x0fffff3ff,%gs:sr_masks // set rc = to_nearest ! 2465: orl $0x0300,%gs:sr_masks // set precision control to prec64 ! 2466: // dec dword_expon1 ; compute tan((op1)/2) ! 2467: inc %eax // eax holds -(true_expon) ! 2468: call tan_pseudo_divide ! 2469: mov $offset_operand1,%esi ! 2470: call push_5_dw_at_esi // save y ! 2471: mov $offset_operand2,%esi ! 2472: call push_5_dw_at_esi // save x ! 2473: call op1_into_op2 // result <-- x/y ! 2474: mov $offset_operand2,%esi ! 2475: call pop_5_dw_at_esi // op2 <-- x ! 2476: mov $offset_operand1,%esi ! 2477: call pop_5_dw_at_esi // op1 <-- y ! 2478: call sin_specific ! 2479: pop %gs:sr_masks ! 2480: pop trans_info ! 2481: andb $~a_mask,%gs:sr_flags ! 2482: cmpb true,added_one ! 2483: jne check_op_type ! 2484: orb $a_mask,%gs:sr_flags ! 2485: jmp check_op_type ! 2486: ALIGN ! 2487: ! 2488: //sin endp ! 2489: // ! 2490: //----------------------------------------------------------------------- ! 2491: // cos: ! 2492: // ! 2493: //----------------------------------------------------------------------- ! 2494: // ! 2495: ALIGN ! 2496: cos_specific: //proc ! 2497: ! 2498: lea dword_frac1(%ebp),%esi ! 2499: lea dword_frac2(%ebp),%edi ! 2500: call move_op_to_op // op2 <-- x/y ! 2501: call mult // res <-- (x/y)**2 ! 2502: call post_op_round ! 2503: lea result_dword_frac(%ebp),%esi ! 2504: lea dword_frac1(%ebp),%edi ! 2505: call move_op_to_op // op1 <-- (x/y)**2 ! 2506: mov $offset_operand2,%esi ! 2507: call move_unpacked_1_to_esi // op2 <-- 1 ! 2508: movb $add_op,operation_type(%ebp) ! 2509: call subadd ! 2510: call post_op_round // res <-- 1 + (x/y)**2 ! 2511: lea result_dword_frac(%ebp),%esi ! 2512: lea dword_frac2(%ebp),%edi ! 2513: call move_op_to_op // op2 <-- 1 + (x/y)**2 ! 2514: mov $offset_operand1,%esi ! 2515: call move_unpacked_1_to_esi // op1 <-- 1 ! 2516: incl dword_expon1 // op1 <-- 2 ! 2517: call op2_into_op1 // res <-- 2/(1 + (x/y)**2) ! 2518: lea result_dword_frac(%ebp),%esi ! 2519: lea dword_frac2(%ebp),%edi ! 2520: call move_op_to_op // op2 <-- 2/(1 + (x/y)**2) ! 2521: mov $offset_operand1,%esi ! 2522: call move_unpacked_1_to_esi // op1 <-- 1 ! 2523: movb $sub_op,operation_type(%ebp) ! 2524: call subadd ! 2525: call post_op_round // res <-- 1 - {2/(1 + (x/y)**2)} ! 2526: ret ! 2527: ! 2528: //cos_specific endp ! 2529: // ! 2530: //----------------------------------------------------------------------- ! 2531: // ! 2532: ALIGN ! 2533: cos: //proc ! 2534: call one_result_op1_chk ! 2535: cos_report: ! 2536: jnz cos_reduce_op1 ! 2537: movb $cos_op,op_type ! 2538: movb positive,cos_sign ! 2539: cos_0_modulus: ! 2540: mov $offset_result,%esi ! 2541: call move_unpacked_1_to_esi ! 2542: check_op_type: ! 2543: cmpb $cos_op,op_type ! 2544: je attach_cos_sign ! 2545: attach_sin_sign: ! 2546: movb sin_sign,%al ! 2547: jmp sign_done ! 2548: ALIGN ! 2549: attach_cos_sign: ! 2550: movb cos_sign,%al ! 2551: sign_done: ! 2552: movb %al,result_sign(%ebp) ! 2553: send_result: ! 2554: mov $offset_result,%edi ! 2555: jmp put_si_result ! 2556: ALIGN ! 2557: cos_reduce_op1: ! 2558: call mod_qrtr_pi ! 2559: cmpb special,tag1(%ebp) ! 2560: jne cos_tiny_ ! 2561: // testb q, 1 ; was operand (2k+1)*qrtr_pi? ! 2562: // jz cos_cofunc? ; if so, set precision error ! 2563: // orb %gs:sr_errors, inexact_mask ! 2564: //cos_cofunc?: ! 2565: cmpb true,cofunc_flag ! 2566: jne cos_0_modulus ! 2567: movl $0,result_dword_frac(%ebp) ! 2568: movl $0,result_dword_frac+frac64(%ebp) ! 2569: movl $0,result_dword_frac+frac32(%ebp) ! 2570: movl $0x10000*SPECIAL+POSITIVE,result_sign(%ebp) ! 2571: movl $0,dword_result_expon ! 2572: jmp attach_cos_sign ! 2573: ALIGN ! 2574: cos_tiny_: ! 2575: cmpb true,cofunc_flag ! 2576: je check_sin_lim ! 2577: check_cos_lim: ! 2578: mov $0x3fff,%eax ! 2579: sub dword_expon1,%eax ! 2580: cmp $62,%eax ! 2581: jl cos_calc ! 2582: jg cos_0_modulus ! 2583: cmpl $0x080000000,dword_frac1+frac32(%ebp) ! 2584: ja cos_calc ! 2585: cmp $0,dword_frac1+frac64(%ebp) ! 2586: je cos_0_modulus ! 2587: cos_calc: ! 2588: push trans_info ! 2589: push %gs:sr_masks ! 2590: andl $0x0fffff3ff,%gs:sr_masks // set rc = to_nearest ! 2591: orl $0x0300,%gs:sr_masks // set precision control to prec64 ! 2592: // dec dword_expon1 ; compute tan((op1)/2) ! 2593: inc %eax // eax holds -(true_expon) ! 2594: call tan_pseudo_divide ! 2595: call op1_into_op2 // result <-- x/y ! 2596: lea result_dword_frac(%ebp),%esi ! 2597: lea dword_frac1(%ebp),%edi ! 2598: call move_op_to_op // op1 <-- x/y ! 2599: call cos_specific // result <-- cos ! 2600: pop %gs:sr_masks ! 2601: pop trans_info ! 2602: andb $~a_mask,%gs:sr_flags ! 2603: cmpb true,added_one ! 2604: jne check_op_type ! 2605: orb $a_mask,%gs:sr_flags ! 2606: jmp check_op_type ! 2607: ! 2608: //cos endp ! 2609: // ! 2610: // ! 2611: // *********************************************************************** ! 2612: // sincos: ! 2613: ! 2614: ALIGN ! 2615: sincos: //proc ! 2616: call two_result_op1_chk ! 2617: combo_get_report: ! 2618: jnz combo_reduce_op1 ! 2619: xor %eax,%eax ! 2620: movb sign1(%ebp),%ah ! 2621: mov %eax,trans_info ! 2622: combo_0_mod: ! 2623: mov $offset_operand2,%esi ! 2624: call move_unpacked_1_to_esi ! 2625: combo_cofunc_: ! 2626: cmpb true,cofunc_flag ! 2627: jne attach_signs ! 2628: switch_ops: ! 2629: call swap_ops ! 2630: attach_signs: ! 2631: movw res_signs,%ax ! 2632: movb %al,sign1(%ebp) ! 2633: movb %ah,sign2(%ebp) ! 2634: results_sent: ! 2635: jmp do_exchange ! 2636: ALIGN ! 2637: combo_reduce_op1: ! 2638: call mod_qrtr_pi ! 2639: cmpb special,tag1(%ebp) ! 2640: // jne combo_tiny? ! 2641: // testb q, 1 ! 2642: jz combo_0_mod ! 2643: // orb %gs:sr_errors, inexact_mask ! 2644: // jmp short combo_0_mod ! 2645: combo_tiny_: ! 2646: mov $0x3fff,%eax ! 2647: sub dword_expon1,%eax ! 2648: cmp $62,%eax ! 2649: jl combo_sin_calc ! 2650: jg combo_tiny_arg ! 2651: cmpl $0x080000000,dword_frac1+frac32(%ebp) ! 2652: ja combo_sin_calc ! 2653: cmp $0,dword_frac1+frac64(%ebp) ! 2654: jne combo_sin_calc ! 2655: combo_tiny_arg: ! 2656: cmp $0x3fff,%eax ! 2657: jl combo_0_mod ! 2658: orb underflow_mask,%gs:sr_errors ! 2659: testb underflow_mask,%gs:sr_masks ! 2660: jnz combo_grad_uflow ! 2661: addl wrap_around_constant,dword_expon1 ! 2662: jmp combo_0_mod ! 2663: ALIGN ! 2664: combo_grad_uflow: ! 2665: mov $offset_operand1,%edi ! 2666: mov $1,%eax ! 2667: call gradual_underflow ! 2668: movl $0,dword_expon1 ! 2669: movb denormd,tag1(%ebp) ! 2670: jmp combo_0_mod ! 2671: ALIGN ! 2672: combo_sin_calc: ! 2673: push trans_info ! 2674: push %gs:sr_masks ! 2675: andl $0x0fffff3ff,%gs:sr_masks // set rc = to_nearest ! 2676: orl $0x0300,%gs:sr_masks // set precision control to prec64 ! 2677: cmp $30,%eax ! 2678: jl push_flags ! 2679: jg force_zf_1 ! 2680: cmpl $0x08d100000,dword_frac1+frac32(%ebp) ! 2681: ja push_flags ! 2682: jb force_zf_1 ! 2683: cmp $0,dword_frac1+frac64(%ebp) ! 2684: jne push_flags ! 2685: force_zf_1: ! 2686: xor %ebx,%ebx // zf set iff arg is tiny for sin ! 2687: mov $offset_operand1,%esi // save tiny op1 as sin(op1) ! 2688: call push_5_dw_at_esi // does not affect flags or eax ! 2689: push_flags: ! 2690: pushf ! 2691: // dec dword_expon1 ; compute tan((op1)/2) ! 2692: inc %eax // eax holds -(true_expon) ! 2693: call tan_pseudo_divide ! 2694: popf ! 2695: jz calc_x_over_y ! 2696: mov $offset_operand1,%esi ! 2697: call push_5_dw_at_esi // save y ! 2698: mov $offset_operand2,%esi ! 2699: call push_5_dw_at_esi // save x ! 2700: calc_x_over_y: ! 2701: pushf ! 2702: call op1_into_op2 // result <-- x/y ! 2703: popf ! 2704: jz save_x_over_y ! 2705: mov $offset_operand2,%esi ! 2706: call pop_5_dw_at_esi // op2 <-- x ! 2707: mov $offset_operand1,%esi ! 2708: call pop_5_dw_at_esi // op1 <-- y ! 2709: save_x_over_y: ! 2710: mov $offset_result,%esi ! 2711: call push_5_dw_at_esi // save x/y ! 2712: jz combo_cos_calc ! 2713: pushf ! 2714: call sin_specific // result <-- sin ! 2715: popf ! 2716: combo_cos_calc: ! 2717: mov $offset_operand1,%esi ! 2718: call pop_5_dw_at_esi // op1 <-- x/y ! 2719: jz tiny_sin_cos_entry ! 2720: mov $offset_result,%esi ! 2721: call push_5_dw_at_esi // save computed sin ! 2722: tiny_sin_cos_entry: ! 2723: call cos_specific // result <-- cos ! 2724: mov $offset_operand1,%esi ! 2725: call pop_5_dw_at_esi // op1 <-- sin ! 2726: lea result_dword_frac(%ebp),%esi ! 2727: lea dword_frac2(%ebp),%edi ! 2728: call move_op_to_op // op2 <-- cos ! 2729: pop %gs:sr_masks ! 2730: pop trans_info ! 2731: jmp combo_cofunc_ ! 2732: ! 2733: //sincos endp ! 2734: // ! 2735: // ! 2736: // *********************************************************************** ! 2737: // test_5w, test_4w, test_3w ! 2738: // ! 2739: // function: ! 2740: // test 3, 4, or 5 consecutive words for zero ! 2741: // ! 2742: // inputs: ! 2743: // least significant word pointed to by ss:(bp + di) ! 2744: // ax must be clear upon entry for test_4w and test_3w ! 2745: // ! 2746: // outputs: ! 2747: // if variable = 0, ax = 00000h; zf = 1 ! 2748: // otherwise, ax = 0ffffh; zf = 0 ! 2749: // ! 2750: // data accessed: ! 2751: // ! 2752: // data changed: ! 2753: // ! 2754: // ************************************************************************* ! 2755: ALIGN ! 2756: test_5w: //proc ! 2757: movw 8(%ebp,%edi),%ax // dump the data into ax ! 2758: test_4w: ! 2759: orw 6(%ebp,%edi),%ax ! 2760: test_3w: ! 2761: orw 4(%ebp,%edi),%ax ! 2762: orw 2(%ebp,%edi),%ax ! 2763: orw (%ebp,%edi),%ax ! 2764: jnz its_not_zero // branch if the number is nonzero ! 2765: ret // return with ax = 00000h, zf = 1 ! 2766: ALIGN ! 2767: its_not_zero: ! 2768: movw $0x0ffff,%ax // return with ax = 0ffffh, zf = 0 ! 2769: ret ! 2770: //test_5w endp ! 2771: // ! 2772: ALIGN ! 2773: test_6w: //proc ! 2774: mov (%ebp,%edi),%eax // dump the data into ax ! 2775: or 4(%ebp,%edi),%eax ! 2776: or 8(%ebp,%edi),%eax ! 2777: jnz non_0 // branch if the number is nonzero ! 2778: ret // return with eax = 000000000h, zf = 1 ! 2779: ALIGN ! 2780: non_0: ! 2781: mov $0x0ffffffff,%eax // return with eax = 0ffffffffh, zf = 0 ! 2782: ret ! 2783: //test_6w endp ! 2784: // ! 2785: // *********************************************************************** ! 2786: // clear_5w, set_5w, set__4w, set_3w ! 2787: // ! 2788: // function: ! 2789: // sets 3, 4, or 5 consecutive words to zero or given value ! 2790: // ! 2791: // inputs: ! 2792: // least significant word pointed to by ss:(ebp + edi) ! 2793: // ax contains value given to store for set routines ! 2794: // ! 2795: // outputs: ! 2796: // ax contains zero for the clear_5w routine ! 2797: // eax * * * * clear_6w * ! 2798: // data accessed: ! 2799: // ! 2800: // data changed: ! 2801: // ! 2802: // ************************************************************************* ! 2803: ALIGN ! 2804: clear_6w: //proc ! 2805: xor %eax,%eax ! 2806: set_6w: ! 2807: mov %eax,(%ebp,%edi) // store the value in eax ! 2808: mov %eax,4(%ebp,%edi) ! 2809: mov %eax,8(%ebp,%edi) ! 2810: ret ! 2811: ALIGN ! 2812: //clear_6w endp ! 2813: // ! 2814: ALIGN ! 2815: clear_5w: //proc ! 2816: xorw %ax,%ax ! 2817: set_5w: ! 2818: movw %ax,8(%ebp,%edi) // store the value in ax ! 2819: set_4w: ! 2820: movw %ax,6(%ebp,%edi) ! 2821: set_3w: ! 2822: movw %ax,4(%ebp,%edi) ! 2823: movw %ax,2(%ebp,%edi) ! 2824: movw %ax,(%ebp,%edi) ! 2825: ret ! 2826: //clear_5w endp ! 2827: // ! 2828: // ! 2829: // common entries to shift and move subroutines ! 2830: // ! 2831: // right_shift group ! 2832: // ! 2833: right_shift_dword_exp_tmp: ! 2834: mov dword_exp_tmp,%ecx ! 2835: shlb $1,%cl ! 2836: jmp right_shift_al0 ! 2837: ALIGN ! 2838: right_shift_result_1: ! 2839: movb $1,%cl ! 2840: right_shift_result_cl: ! 2841: mov $offset_result,%edi ! 2842: jmp right_shift_al0 ! 2843: ALIGN ! 2844: right_shift_frac2_8: ! 2845: movb $8,%cl ! 2846: right_shift_frac2_cl: ! 2847: mov $offset_operand2,%edi ! 2848: jmp right_shift_al0 ! 2849: ALIGN ! 2850: right_shift_frac1_8: ! 2851: movb $8,%cl ! 2852: right_shift_frac1_cl: ! 2853: mov $offset_operand1,%edi ! 2854: right_shift_al0: ! 2855: movb $0,%al ! 2856: // ********************************************************************** ! 2857: // right_shift: ! 2858: // ! 2859: // function: ! 2860: // shifts a 12-byte number right by amount in ecx register. ! 2861: // ! 2862: // inputs: ! 2863: // low bit of al contains bit to inject from left. ! 2864: // edi contains the offset of the least significant byte ! 2865: // of the 12-byte number. ! 2866: // ! 2867: // outputs: ! 2868: // on return, edx is non-zero if any ones have been shifted out. ! 2869: // edi has the same value it had upon entry. ! 2870: // data accessed: ! 2871: // ! 2872: // data changed: ! 2873: // ! 2874: // *************************************************************************** ! 2875: FALLSTHRU ! 2876: right_shift: //proc ! 2877: xor %edx,%edx // initialize edx, the *sticky word* ! 2878: rorb $1,%al // move lsb to msb ! 2879: movsbl %al,%eax // transmit sign to ah and hi_word(eax) ! 2880: push %eax // stack insert bit replica ! 2881: movb $2,%ch // one less than # of dwords to get bit-shifted ! 2882: cmpb $32,%cl // does shift_count exceed 31? ! 2883: jb bits_shft_rt // if not, just do the bit shifting; ! 2884: cmpb $96,%cl // does shift_count exceed 95? ! 2885: jb dwords_shft_rt // if not, proceed with dword shifts; ! 2886: je get_out_shfts // else, if shift_count exceeds 96 ! 2887: orw %ax,%dx // then bit shifted in is also shifted out ! 2888: get_out_shfts: ! 2889: or (%ebp,%edi),%edx // all 3 dwords are *shifted out,* ! 2890: or 4(%ebp,%edi),%edx // and ord to edx ! 2891: or 8(%ebp,%edi),%edx ! 2892: movb %ah,%al // copy insert bit throughout eax ! 2893: mov %eax,(%ebp,%edi) // ! 2894: mov %eax,4(%ebp,%edi) // ! 2895: mov %eax,8(%ebp,%edi) // replace all 96 bits by insert bit. ! 2896: pop %eax ! 2897: ret ! 2898: ALIGN ! 2899: // ! 2900: dwords_shft_rt: ! 2901: push %ds // save a?msr ! 2902: push %ss // copy stack segment ! 2903: pop %ds // to ds ! 2904: // push %ss ! 2905: // pop %es // and es ! 2906: add %ebp,%edi ! 2907: mov %edi,%esi ! 2908: movb %cl,%bl // save bit_shft_count in bl ! 2909: and $0x60,%ecx // get dword_shft_count ! 2910: shr $5,%ecx // normalize dword_shft_count ! 2911: movb %cl,%al // save dword_shft_count in al ! 2912: dword_shft_chk: ! 2913: or (%esi),%edx ! 2914: add $4,%esi ! 2915: LOOP(dword_shft_chk) ! 2916: movl $3,%cx ! 2917: subb %al,%cl ! 2918: movb %cl,%bh ! 2919: push %eax ! 2920: FAST_MOVSL ! 2921: pop %eax ! 2922: movb %al,%cl ! 2923: movb %ah,%al ! 2924: FAST_STOSL ! 2925: sub $12,%edi // adjust edi ! 2926: sub %ebp,%edi // to value it had at entry ! 2927: pop %ds ! 2928: movw %bx,%cx ! 2929: bits_shft_rt: ! 2930: pop %eax ! 2931: push %edi ! 2932: push %eax ! 2933: mov (%ebp,%edi),%eax ! 2934: xor %ebx,%ebx ! 2935: shrdl %cl,%eax,%ebx // cl is interpreted mod 32 ! 2936: or %ebx,%edx ! 2937: bit_shft_loop: ! 2938: mov 4(%ebp,%edi),%eax ! 2939: shrdl %cl,%eax,(%ebp,%edi) ! 2940: add $4,%edi ! 2941: decb %ch ! 2942: jnz bit_shft_loop ! 2943: pop %eax ! 2944: movb %ah,%al ! 2945: shrdl %cl,%eax,(%ebp,%edi) ! 2946: pop %edi ! 2947: right_shift_done: ! 2948: clc ! 2949: ret ! 2950: ALIGN ! 2951: // ! 2952: //right_shift endp ! 2953: // ! 2954: // ! 2955: // left_shift group ! 2956: // ! 2957: left_shift_result_cl: ! 2958: mov $offset_result+frac80,%edi ! 2959: jmp left_shift ! 2960: ALIGN ! 2961: left_shift_frac2_8: ! 2962: movb $8,%cl ! 2963: left_shift_frac2_cl: ! 2964: mov $offset_operand2+frac80,%edi ! 2965: jmp left_shift ! 2966: ALIGN ! 2967: left_shift_frac1_8: ! 2968: movb $8,%cl ! 2969: jmp left_shift_frac1_cl ! 2970: ALIGN ! 2971: left_shift_frac1_1: ! 2972: movb $1,%cl ! 2973: left_shift_frac1_cl: ! 2974: mov $offset_operand1+frac80,%edi ! 2975: // ************************************************************************** ! 2976: // left_shift: ! 2977: // ! 2978: // function: ! 2979: // shifts a 10-byte number left by amount in cl reg. ! 2980: // ! 2981: // input: ! 2982: // di contains offset of low-byte. ! 2983: // ! 2984: // outputs: ! 2985: // bits shifted off the left end are lost. ! 2986: // ! 2987: // data accessed: ! 2988: // ! 2989: // data changed: ! 2990: // ! 2991: // **************************************************************************** ! 2992: FALLSTHRU ! 2993: left_shift: //proc ! 2994: cmpb $80,%cl // more than 80 bits? ! 2995: jle left_count // no, form left count ! 2996: movb $80,%cl // yes, 80 is the max ! 2997: left_count: ! 2998: movb %cl,%al // form byte count ! 2999: andb $0x78,%al // = bits 3-6 of amount ! 3000: jz leftover_bits // branch if count < 8 ! 3001: push %ecx // stack bit count ! 3002: push %edi // stack frac offset ! 3003: push %ds // save a?msr ! 3004: cbtw // clear ah ! 3005: shrw $3,%ax // normalize byte count ! 3006: decw %ax ! 3007: mov $0x0009,%ecx // count = 10 - ax ! 3008: add %ecx,%edi ! 3009: movswl %ax,%eax ! 3010: sub %eax,%ecx // dest = ss:bp+si ! 3011: add %ebp,%edi ! 3012: mov %edi,%esi // dest = ss:bp+di ! 3013: sub %eax,%esi ! 3014: dec %esi ! 3015: push %ss // copy ss to ds and es ! 3016: pop %ds ! 3017: // push %ss ! 3018: // pop %es ! 3019: /* Note direction is not appropriate for FAST_MOVSB */ ! 3020: push %eax ! 3021: 1: ! 3022: movb 0(%esi),%al ! 3023: movb %al,0(%edi) ! 3024: dec %esi ! 3025: dec %edi ! 3026: decl %ecx ! 3027: testl %ecx,%ecx ! 3028: jg 1b ! 3029: ! 3030: movb %cl,(%edi) // clear next byte ! 3031: pop %eax ! 3032: mov %eax,%ecx // form zero count ! 3033: mov %edi,%esi // form string offsets ! 3034: dec %edi ! 3035: /* Note direction is not appropriate for FAST_MOVSB */ ! 3036: push %eax ! 3037: 1: ! 3038: movb 0(%esi),%al ! 3039: movb %al,0(%edi) ! 3040: dec %esi ! 3041: dec %edi ! 3042: decl %ecx ! 3043: testl %ecx,%ecx ! 3044: jg 1b ! 3045: ! 3046: pop %eax ! 3047: pop %ds // reload a?msr ! 3048: pop %edi // reload frac offset ! 3049: pop %ecx // reload bit count ! 3050: leftover_bits: ! 3051: and $0x00000007,%ecx // bits 0-2 = bit count ! 3052: jz left_shift_done // exit if all done ! 3053: FALLSTHRU ! 3054: left_shift_bits: ! 3055: shlw $1,(%ebp,%edi) // shift five words ! 3056: rclw $1,2(%ebp,%edi) // one bit left, using ! 3057: rclw $1,4(%ebp,%edi) // the carry flag out ! 3058: rclw $1,6(%ebp,%edi) ! 3059: rclw $1,8(%ebp,%edi) ! 3060: LOOP(left_shift_bits) // loop bit count times ! 3061: left_shift_done: ! 3062: ret ! 3063: //left_shift endp ! 3064: // ! 3065: // ************************************************************************ ! 3066: // one_left_normalize: ! 3067: // ! 3068: // function: ! 3069: // normalizes following a multiplication. ! 3070: // ! 3071: // inputs: ! 3072: // assumes fraction is not zero. di = frac offset. ! 3073: // ! 3074: // outputs: ! 3075: // shifts fraction left and decrements exponent until ! 3076: // fraction normalized, but no more than one left shift. ! 3077: // zf is reset if the fraction is normalized upon return. ! 3078: // ! 3079: // data accessed: ! 3080: // ! 3081: // data changed: ! 3082: // ! 3083: // ************************************************************************** ! 3084: ALIGN ! 3085: one_left_normalize: //proc ! 3086: testb $0x80,frac80+9(%ebp,%edi) //normalized? ! 3087: jnz one_left_norm_done //quit if normalized. ! 3088: push %edi // save frac offset ! 3089: mov $0x00000001,%ecx // load loop count ! 3090: add $2,%edi ! 3091: call left_shift_bits //shift 5 words left 1 ! 3092: pop %edi // reload frac offset ! 3093: decl expon(%ebp,%edi) //decrement exponent ! 3094: testb $0x80,frac80+9(%ebp,%edi) //normalized? ! 3095: one_left_norm_done: ! 3096: ret ! 3097: //one_left_normalize endp ! 3098: // *********************************************************************** ! 3099: // subtraction_normalize: ! 3100: // ! 3101: // function: ! 3102: // normalizes following a subtraction. ! 3103: // ! 3104: // inputs: ! 3105: // assumes fraction is not zero. di = frac offset ! 3106: // ! 3107: // outputs: ! 3108: // shifts fraction left and decrements exponent ! 3109: // until fraction normalized. ! 3110: // ! 3111: // data accessed: ! 3112: // ! 3113: // data changed: ! 3114: // ! 3115: // ************************************************************************* ! 3116: ALIGN ! 3117: subtraction_normalize: //proc ! 3118: call one_left_normalize // normalize one bit ! 3119: jz subtraction_normalize //quit when normalized. ! 3120: ret ! 3121: //subtraction_normalize endp ! 3122: // ! 3123: // ! 3124: // move_10_bytes group ! 3125: // ! 3126: move_frac2_frac1: ! 3127: mov $offset_operand1+2,%edi ! 3128: move_frac2: ! 3129: mov $offset_operand2+2,%esi ! 3130: jmp move_10_bytes ! 3131: ALIGN ! 3132: move_frac1_result: ! 3133: mov $offset_result+2,%edi ! 3134: jmp move_frac1 ! 3135: ALIGN ! 3136: move_frac1_cop: ! 3137: mov $offset_cop+2,%edi ! 3138: call move_frac1 ! 3139: move_frac1_frac2: ! 3140: mov $offset_operand2+2,%edi ! 3141: move_frac1: ! 3142: mov $offset_operand1+2,%esi ! 3143: jmp move_10_bytes ! 3144: ALIGN ! 3145: move_dop_frac2: ! 3146: mov $offset_operand2+2,%edi ! 3147: jmp move_dop ! 3148: ALIGN ! 3149: move_dop_frac1: ! 3150: mov $offset_operand1+2,%edi ! 3151: move_dop: ! 3152: mov $offset_dop+2,%esi ! 3153: jmp move_10_bytes ! 3154: ALIGN ! 3155: move_cop_frac2: ! 3156: mov $offset_operand2+2,%edi ! 3157: jmp move_cop ! 3158: ALIGN ! 3159: move_cop_frac1: ! 3160: mov $offset_operand1+2,%edi ! 3161: move_cop: ! 3162: mov $offset_cop+2,%esi ! 3163: jmp move_10_bytes ! 3164: ALIGN ! 3165: move_result_cop: ! 3166: mov $offset_cop+2,%edi ! 3167: jmp move_result ! 3168: ALIGN ! 3169: move_result_dop: ! 3170: mov $offset_dop+2,%edi ! 3171: jmp move_result ! 3172: ALIGN ! 3173: move_result_frac2: ! 3174: mov $offset_operand2+2,%edi ! 3175: jmp move_result ! 3176: ALIGN ! 3177: move_result_frac1: ! 3178: mov $offset_operand1+2,%edi ! 3179: move_result: ! 3180: mov $offset_result+2,%esi ! 3181: move_10_bytes: ! 3182: add %ebp,%esi // add global record offset ! 3183: push %ds // save a?msr ! 3184: push %ss // load source segment register ! 3185: set_destination: ! 3186: pop %ds ! 3187: // push %ss // load destination segment register ! 3188: // pop %es // into es ! 3189: add %ebp,%edi // add global record offset ! 3190: ! 3191: /* FAST_MOVSW */ ! 3192: movl 0(%esi),%ecx ! 3193: movl %ecx,%ss:0(%edi) ! 3194: movl 4(%esi),%ecx ! 3195: movl %ecx,%ss:4(%edi) ! 3196: movw 8(%esi),%ecx ! 3197: movw %ecx,%ss:8(%edi) ! 3198: // addl $10,%esi ! 3199: // addl $10,%edi ! 3200: // movl $0,%ecx ! 3201: ! 3202: pop %ds // reload a?msr ! 3203: ret ! 3204: ALIGN ! 3205: // ! 3206: // add, sub, mul, move_constant group ! 3207: // ! 3208: add_half1_frac2: ! 3209: mov $add_half_pattern_1,%esi ! 3210: call add_frac2 ! 3211: mov $offset_result,%edi ! 3212: jmp addition_normalize ! 3213: ALIGN ! 3214: add_frac2: ! 3215: call move_constant_frac2 ! 3216: jmp addx ! 3217: ALIGN ! 3218: sub_frac1: ! 3219: mov $offset_operand1+2,%edi ! 3220: sub_constant: ! 3221: call move_constant ! 3222: jmp subx ! 3223: ALIGN ! 3224: sub_frac2: ! 3225: mov $offset_operand2+2,%edi ! 3226: jmp sub_constant ! 3227: ALIGN ! 3228: mul_frac2: ! 3229: call move_constant_frac2 ! 3230: jmp mulx ! 3231: ALIGN ! 3232: move_constant_frac2: ! 3233: mov $offset_operand2+2,%edi ! 3234: move_constant: ! 3235: push %ds // save a?msr ! 3236: push %cs // load code segment base into ds ! 3237: jmp set_destination // move five words ! 3238: ALIGN ! 3239: // .byte 'bernard verreau,san francisco,ca . 1983' ! 3240: // ! 3241: //a_med ends ! 3242: // ! 3243: // end
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.