|
|
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 "lipsq.s" ! 26: ! 27: .ident "@(#)kern-fp:lipsq.s 1.1" ! 28: ! 29: // *************************************************************************** ! 30: // ! 31: // l i p s q . m o d ! 32: // ================= ! 33: // ! 34: // =============================================================== ! 35: // intel corporation proprietary information ! 36: // this software is supplied under the terms of a license ! 37: // agreement or non-disclosure agreement with intel corporation ! 38: // and may not be copied nor disclosed except in accordance with ! 39: // the terms of that agreement. ! 40: // =============================================================== ! 41: // ! 42: // functions: ! 43: // implements the loading of the constants: ! 44: // one, log base 2 of ten, log base 2 of e, pi, ! 45: // log base 10 of 2, log base e of 2, and zero. ! 46: // implements the 80387 square root instruction. ! 47: // implements the 80387 integer part instruction. ! 48: // ! 49: // public procedures: ! 50: // load_con sqrt intpt ! 51: // ! 52: // ***************************************************************************** ! 53: // ! 54: //...september 16, 1983... ! 55: // ! 56: // .file *a_mli* ! 57: // ! 58: //$nolist ! 59: #include "fp_e80387.h" ! 60: //$list ! 61: .text //a_med segment er public ! 62: // ! 63: // extrn put_si_result,sticky_right_shift,round ! 64: // extrn addition_normalize,left_shift,getx ! 65: // extrn set_up_indefinite,clear_6w,set_6w ! 66: // extrn test_4w,left_shift_result_cl ! 67: // extrn left_shift_frac1_cl,left_shift_frac2_cl ! 68: // extrn add_to_frac_2,gradual_underflow ! 69: // extrn subtraction_normalize,put_indefinite ! 70: // extrn i_masked_,set_i_masked_,set_d_masked_ ! 71: // extrn affine_infinity_,get_precision ! 72: // ! 73: .globl load_con ! 74: .globl intpt ! 75: .globl sqrt ! 76: // ! 77: // temp real floating point numbers for push constant instructions ! 78: // ! 79: treal_table: ! 80: .value 0x00000,0x00000,0x00000,0x00000,0x08000,0x03fff //treal_one ! 81: .value 0x04000,0x08afe,0x0cd1b,0x0784b,0x0d49a,0x04000 //treal_l2t ! 82: .value 0x0c000,0x0f0bb,0x05c17,0x03b29,0x0b8aa,0x03fff //treal_l2e ! 83: .value 0x0c000,0x0c234,0x02168,0x0daa2,0x0c90f,0x04000 //treal_pi ! 84: .value 0x0a000,0x0f798,0x0fbcf,0x09a84,0x09a20,0x03ffd //treal_lg2 ! 85: .value 0x0e000,0x079ab,0x0d1cf,0x017f7,0x0b172,0x03ffe //treal_ln2 ! 86: .value 0x00000,0x00000,0x00000,0x00000,0x00000,0x00000 //treal_0 ! 87: //$eject ! 88: // *************************************************************** ! 89: // load_con ! 90: // ****** ! 91: // function: ! 92: // implements the load constants instructions. ! 93: // ! 94: // inputs: ! 95: // offset of fpn pointer in bx register. ! 96: // ! 97: // outputs: ! 98: // constant value on top of stack ! 99: // ! 100: // data accessed: ! 101: // - offset_result ! 102: // ! 103: // data changed: ! 104: // - mem_operand_pointer ! 105: // ! 106: // procedures called: ! 107: // getx ! 108: // ! 109: // ******************************************************************* ! 110: // all load constant instructions use the same entry point. ! 111: // ! 112: ALIGN ! 113: load_con: //proc near ! 114: // ! 115: // the contents of bx is used as an index to treal_table. ! 116: // getx unpacks the extended floating point number and put_result ! 117: // pushes the value to the top of the 80387 stack. ! 118: // ! 119: shrb $1,%bl //take care of extra shi ! 120: mov $0x06,%eax //treal_table ptr = cs: ! 121: mulb %bl // index * 6 - (6 * 2) ! 122: add $(treal_table-(load_1_op*12)),%eax // * (load_1_op) ! 123: mov %eax, %esi ! 124: movl $0, result_dword_frac(%ebp) ! 125: movw %cs:(%esi), %ax ! 126: movw %ax, result_dword_frac+frac80(%ebp) ! 127: mov %cs:2(%esi), %eax ! 128: mov %eax, result_dword_frac+frac64(%ebp) ! 129: mov %cs:6(%esi), %eax ! 130: mov %eax, result_dword_frac+frac32(%ebp) ! 131: movzwl %cs:10(%esi), %eax ! 132: mov %eax, dword_result_expon ! 133: xor %eax, %eax ! 134: mov %eax, result_sign(%ebp) ! 135: movb prec64, %dl ! 136: mov $offset_result, %edi ! 137: call round ! 138: mov $offset_result, %edi ! 139: call addition_normalize ! 140: andb $~a_mask, %gs:sr_flags ! 141: xor %eax, %eax ! 142: mov before_error_signals(%ebp), %eax ! 143: lahf ! 144: mov $offset_result, %edi ! 145: jmp put_si_result ! 146: //load_con endp ! 147: //$eject ! 148: // *********************************************************************** ! 149: // intpt: ! 150: // ***** ! 151: // function: ! 152: // implements 80387 integer part instruction ! 153: // ! 154: // inputs: ! 155: // ! 156: // outputs: ! 157: // ! 158: // data accessed: ! 159: // - offset_result offset_operand1 ! 160: // - tag1 expon1 ! 161: // - word_frac1 ! 162: // ! 163: // data changed: ! 164: // - tag1 expon1 ! 165: // - result ! 166: // ! 167: // procedures called: ! 168: // get_operand gradual_underflow ! 169: // round subtraction_normalize ! 170: // put_si_result test_4w ! 171: // i_masked? set_i_masked? ! 172: // set_d_masked? ! 173: // ! 174: // ************************************************************************** ! 175: ALIGN ! 176: intpt: //proc ! 177: // movb true,%ah / load constant ! 178: jz separate_cases // branch if no stack error ! 179: call set_stk_u_error ! 180: testb invalid_mask, %gs:sr_masks ! 181: jz intpt_done ! 182: jmp put_op1_result //math stack error, so return indef ! 183: ALIGN ! 184: separate_cases: ! 185: andb $~a_mask, %gs:sr_flags //initialize a-bit to zero ! 186: movb tag1(%ebp), %al // load op1 tag ! 187: cmpb valid,%al ! 188: je valid_case ! 189: cmpb denormd,%al ! 190: je denormalized_operand ! 191: cmpb unsupp,%al ! 192: jne check_nan ! 193: movl $offset_operand1, %edi ! 194: call set_up_indefinite ! 195: set_i_err: ! 196: orb invalid_mask, %gs:sr_errors ! 197: testb invalid_mask, %gs:sr_masks ! 198: jz intpt_done ! 199: jmp put_op1_result // masked_i error so return indef ! 200: ALIGN ! 201: intpt_done: ! 202: ret ! 203: ALIGN ! 204: check_nan: ! 205: cmpb inv, %al ! 206: je kind_of_nan_ ! 207: jmp put_op1_result //infinity or zero, same answer ! 208: ALIGN ! 209: kind_of_nan_: ! 210: testb $0x40, msb_frac1 ! 211: jz make_qnan ! 212: jmp put_op1_result // op1 is a qnan so pass it through ! 213: ALIGN ! 214: make_qnan: ! 215: orb $0x40, msb_frac1 //op1 is an snan so make it a qnan ! 216: jmp set_i_err //and signal i_error ! 217: ALIGN ! 218: denormalized_operand: ! 219: orb denorm_mask, %gs:sr_errors ! 220: testb denorm_mask, %gs:sr_masks ! 221: jz intpt_done ! 222: movw $0x0001,expon1(%ebp) //if masked d-error, make valid ! 223: movb valid,tag1(%ebp) ! 224: valid_case: ! 225: movl $0x403e,%eax ! 226: cmpl %eax,dword_expon1 //if expon >=63, then number ! 227: jge give_op1 // is already an integer ! 228: mov $offset_operand1,%edi //gradual uflow until expon=63 ! 229: push %edi ! 230: call gradual_underflow ! 231: pop %edi //round to precision 64 ! 232: movb prec64,%dl ! 233: movb false,%al ! 234: call round ! 235: cmpb true, rnd1_inexact ! 236: jne detect_zero ! 237: orb $inexact_mask, %gs:sr_errors ! 238: cmpb true,added_one ! 239: jne detect_zero ! 240: orb $a_mask, %gs:sr_flags ! 241: detect_zero: ! 242: xor %eax,%eax ! 243: movl $dword_frac1+4,%edi //if fraction = 0, result = 0 ! 244: call test_4w ! 245: jz zero_result ! 246: mov $offset_operand1,%edi //normalize ! 247: call subtraction_normalize ! 248: jmp put_op1_result ! 249: ALIGN ! 250: zero_result: ! 251: movl %eax,dword_expon1 //set result to true zero ! 252: movb special,tag1(%ebp) ! 253: give_op1: ! 254: jmp put_op1_result ! 255: //intpt endp ! 256: //$eject ! 257: // *************************************************************************** ! 258: // sqrtx: ! 259: // ! 260: // function: ! 261: // fractional square root routine. ! 262: // ! 263: // inputs: ! 264: // assumes valid, non-zero,positive, normalized ! 265: // fraction is in frac1. ! 266: // ! 267: // outputs ! 268: // leaves fractional square root in result. ! 269: // ! 270: // data accessed: ! 271: // - offset_operand1 lsb_frac1 ! 272: // - offset_operand2 word_frac2 ! 273: // - offset_result lsb_frac2 ! 274: // - result_word_frac lsb_result ! 275: // - msb_frac1 ! 276: // ! 277: // data changed: ! 278: // - word_frac2 lsb_frac2 ! 279: // - result_word_frac lsb_result ! 280: // ! 281: // procedures called: ! 282: // left_shift_result_cl left_shift_frac1_cl ! 283: // left_shift_frac2_cl clear_6w ! 284: // set_6w add_to_frac_2 ! 285: // ! 286: // *********************************************************************** ! 287: ALIGN ! 288: sqrtx: //proc ! 289: movl $result_dword_frac,%edi //during this computation, ! 290: call clear_6w //the lsb of the result will ! 291: mov $dword_frac2,%edi // hold g and s, and the msb ! 292: call set_6w // will hold carry-out bits ! 293: and $0x000000ff,%ecx //clear high word ! 294: stc //cf holds the quotient bit ! 295: push $65 // iterate 65 times ! 296: pushf // stack the quotient bit ! 297: jmp enter_sqrt_loop ! 298: ALIGN ! 299: sqrt_loop: ! 300: push %ecx ! 301: pushf // stack the q_bit ! 302: movb $1,%cl ! 303: call left_shift_result_cl //shift result left one bit ! 304: popf // inject the new q_bit into ! 305: pushf // the least significant byte ! 306: adcb %cl,%cl ! 307: orb %cl,1+lsb_result ! 308: movb $2,%cl // into the lsb ! 309: call left_shift_frac2_cl //shift frac2 left 2 bits ! 310: enter_sqrt_loop: ! 311: movb msb_frac1,%al //g and s bits of frac2 <-- ! 312: andb $0x0c0,%al // top 2 bits of frac1 ! 313: movb %al,lsb_frac2 ! 314: movb $2,%cl // shift frac1 left 2 ! 315: call left_shift_frac1_cl ! 316: movb $0x0c0,%al ! 317: movb 1+lsb_result,%ah ! 318: popf //test q_bit ! 319: jc q_bit_set ! 320: shl $16,%eax ! 321: call add_to_frac2 //frac2.gs <-- frac2.gs + ! 322: jmp set_q_bit //result.11 ! 323: q_bit_set: ! 324: notb %ah //frac2.gs <-- frac2.gs + ! 325: shl $16,%eax //take care of extra low word ! 326: add %eax,dword_frac2(%ebp) //not(result).11 ! 327: mov result_dword_frac+frac64(%ebp),%eax ! 328: not %eax ! 329: adc %eax,dword_frac2+frac64(%ebp) ! 330: mov result_dword_frac+frac32(%ebp),%eax ! 331: not %eax ! 332: adc %eax,dword_frac2+frac32(%ebp) ! 333: set_q_bit: ! 334: pop %ecx // reload loop count ! 335: loop sqrt_loop // loop until done ! 336: rcrb $1,%cl // set g bit of result to q_bit ! 337: orb %cl,lsb_result ! 338: movw result_word_frac,%ax //frac2 <- frac2 + ! 339: incb %ah // result + 1 ! 340: shl $16,%eax ! 341: call add_to_frac2 ! 342: mov $dword_frac2+frac64,%edi //if frac2 = 0 then ! 343: xor %eax,%eax //s_bit of result = 0, ! 344: call test_4w //otherwise 1. ! 345: orb 1+lsb_frac2,%al ! 346: jz left_adjust_result ! 347: orb $0x40,lsb_result ! 348: left_adjust_result: ! 349: movb $8,%cl //shift result left 8 bits ! 350: jmp left_shift_result_cl // to eliminate carry ! 351: add_to_frac2: ! 352: mov $result_dword_frac,%esi // si points to the addend ! 353: mov $dword_frac2,%edi // di points to the result ! 354: jmp add_to_frac_2 // add result frac to frac2 ! 355: //sqrtx endp ! 356: //$eject ! 357: // *********************************************************************** ! 358: // sqrt: ! 359: // ! 360: // function: ! 361: // implements the 80387 sqrt instruction ! 362: // ! 363: // inputs: ! 364: // assume op1 is set up ! 365: // ! 366: // outputs: ! 367: // result ! 368: // ! 369: // data accessed: ! 370: // - result_record_offset result_expon ! 371: // - offset_operand1 tag1 ! 372: // - sign1 expon1 ! 373: // - msb_frac1 offset_operand1 ! 374: // - offset_result result_sign ! 375: // - result_tag ! 376: // ! 377: // data changed: ! 378: // - expon1 result_sign ! 379: // - result_tag result_expon ! 380: // ! 381: // procedures called: ! 382: // set_up_indefinite sticky_right_shift ! 383: // sqrtx round ! 384: // addition_normalize affine_infinity? ! 385: // set_i_masked? get_precision ! 386: // set_d_masked? put_si_result ! 387: // ! 388: // *********************************************************************** ! 389: ALIGN ! 390: sqrt: //proc ! 391: jz sqrt_cont // if stack error, sqrt done ! 392: call set_stk_u_error ! 393: testb invalid_mask, %gs:sr_masks ! 394: jnz put_op1 //masked stack error, so return indef ! 395: sqrt_done: ! 396: ret ! 397: ALIGN ! 398: sqrt_cont: ! 399: andb $~a_mask, %gs:sr_flags ! 400: movb tag1(%ebp),%al // load tag for op1 ! 401: cmpb valid,%al ! 402: jne op1_denorm_ ! 403: cmpb positive, sign1(%ebp) ! 404: jne i_error ! 405: jmp sqrt_valid_case ! 406: op1_denorm_: ! 407: cmpb denormd,%al //if op1 denormalized, then give ! 408: jne op1_zero_ ! 409: cmpb positive, sign1(%ebp) ! 410: jne i_error ! 411: jmp d_error ! 412: op1_zero_: ! 413: cmpb special,%al //if op1 = 0, then give 0 as the ! 414: je put_op1 //result ! 415: cmpb unsupp,%al ! 416: je i_error ! 417: cmpb inv,%al //if op1 inv, then give i_error ! 418: jne inf_op1 ! 419: jmp kind_of_nan_ ! 420: inf_op1: ! 421: cmpb positive, sign1(%ebp) //infinity case ! 422: je put_op1 // -infinity is invalid ! 423: i_error: ! 424: call set_i_masked_ //denormalized, unnormalized, ! 425: jz sqrt_done // negative, or proj +infinity ! 426: mov $offset_result,%edi ! 427: call set_up_indefinite //if masked i_error, then give ! 428: jmp sqrt_give_result //indefinite ! 429: put_op1: //if op1 = zero, nan, or +inf, ! 430: jmp give_op1 // then give op1 as the result ! 431: d_error: ! 432: call set_d_masked_ //op1 is denormalized ! 433: jz sqrt_done ! 434: movl $offset_operand1, %edi ! 435: call norm_denorm //if d_error masked, make valid ! 436: sqrt_valid_case: ! 437: subl $exponent_bias,dword_expon1 ! 438: testl $0x0001,dword_expon1 ! 439: jz even_expon ! 440: decl dword_expon1 //if expon1 odd, then expon1 <-- ! 441: jmp halve_exponent // expon1 - 1 ! 442: even_expon: ! 443: movb $1,%cl //if expon1 even, then shift ! 444: xorb %al,%al // frac1 right one bit ! 445: mov $offset_operand1,%edi ! 446: call sticky_right_shift ! 447: halve_exponent: ! 448: movl dword_expon1,%eax ! 449: sarl $1,%eax ! 450: addl $exponent_bias,%eax ! 451: movl %eax,dword_result_expon ! 452: call sqrtx // calculate fraction ! 453: sqrt_round_result: ! 454: xorl %eax,%eax // not second rounding ! 455: movl %eax,result_sign(%ebp) // set sign and tag ! 456: movl $offset_result,%edi // round result ! 457: call get_precision ! 458: call round ! 459: mov $offset_result,%edi ! 460: call addition_normalize //(possible renormalize) ! 461: cmpb true, rnd1_inexact ! 462: jne sqrt_give_result ! 463: orb $inexact_mask, %gs:sr_errors ! 464: cmpb true, added_one ! 465: jne sqrt_give_result ! 466: orb $a_mask, %gs:sr_flags ! 467: sqrt_give_result: ! 468: mov $offset_result,%edi ! 469: jmp put_si_result ! 470: //sqrt endp ! 471: // ! 472: //a_med ends ! 473: // ! 474: // end
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.