|
|
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 "subadd.s" ! 26: ! 27: .ident "@(#)kern-fp:subadd.s 1.1" ! 28: //$tt(*80387 emulator + + + s u b a d d + + + *) ! 29: // ************************************************************************ ! 30: // ! 31: // s u b a d d . m o d ! 32: // =================== ! 33: // ! 34: // =============================================================== ! 35: // intel corporation proprietary information ! 36: // this software is supplied under the terms of a license ! 37: // agreement or non-disclosure agreement with intel corporation ! 38: // and may not be copied nor disclosed except in accordance with ! 39: // the terms of that agreement. ! 40: // =============================================================== ! 41: // ! 42: // function: ! 43: // performs floating point add, subtract, or compare ! 44: // of unpacked, non-zero, valid numbers. ! 45: // ! 46: // public procedures: ! 47: // addx subx subadd ! 48: // sp_subadd compar mov_neg_frac ! 49: // ! 50: // ************************************************************************** ! 51: // ! 52: //...March 3, 1987... ! 53: // ! 54: //$nolist ! 55: #include "fp_e80387.h" ! 56: //$list ! 57: //...declare status register segment... ! 58: // ! 59: .data //a_msr segment rw public ! 60: // extrn %gs:sr_masks,%gs:sr_flags,%gs:sr_errors ! 61: //a_msr ends ! 62: // ! 63: // assume %ds:a_msr ! 64: .text //a_med segment er public ! 65: // ! 66: // extrn sticky_right_shift,right_shift,test_6w ! 67: // extrn addition_normalize,subtraction_normalize ! 68: // extrn pop_free,clear_6w,get_rnd_control ! 69: // extrn set_i_error,affine_infinity_,set_s_bit ! 70: // extrn clear_s_bit,set_z_bit,clear_z_bit ! 71: // extrn i_error_,set_d_error,set_stk_u_error ! 72: // ! 73: .globl addx ! 74: .globl subx ! 75: .globl subadd ! 76: .globl sp_subadd ! 77: .globl compar ! 78: // ! 79: // *********************************************************************** ! 80: // addx: ! 81: // ***** ! 82: // function: ! 83: // fractional add. result_frac <-- frac1 + frac2. ! 84: // ! 85: // inputs: ! 86: // assumes operand records are set up. ! 87: // ! 88: // outputs: ! 89: // al = 1 if there was a carry-out; al=0 otherwise. ! 90: // ! 91: // data accessed: ! 92: // - word_frac1 word_frac2 ! 93: // - result_word_frac ! 94: // ! 95: // data changed: ! 96: // result_word_frac ! 97: // ! 98: // *********************************************************************** ! 99: ALIGN ! 100: addx: //proc ! 101: ! 102: mov dword_frac1(%ebp),%eax //do fractional add ! 103: xorw %ax,%ax //clear extra word ! 104: add dword_frac2(%ebp),%eax ! 105: mov %eax,result_dword_frac(%ebp) ! 106: mov dword_frac1+4(%ebp),%eax ! 107: adc dword_frac2+4(%ebp),%eax ! 108: mov %eax,result_dword_frac+4(%ebp) ! 109: mov dword_frac1+8(%ebp),%eax ! 110: adc dword_frac2+8(%ebp),%eax ! 111: mov %eax,result_dword_frac+8(%ebp) ! 112: ! 113: movb $0,%al ! 114: rclb $1,%al //put carry into al ! 115: ret ! 116: //addx endp ! 117: // ! 118: // **************************************************************************** ! 119: // subx: ! 120: // **** ! 121: // function: ! 122: // 2s complement fractional subtract. ! 123: // result_frac <-- frac1 - frac2. ! 124: // ! 125: // inputs: ! 126: // assumes operand variables are set up. ! 127: // ! 128: // outputs: ! 129: // al=1 if borrow; al=0 otherwise. ! 130: // ! 131: // data accessed: ! 132: // - word_frac1 word_frac2 ! 133: // - result_word_frac ! 134: // ! 135: // data changed: ! 136: // - result_word_frac ! 137: // ! 138: // *************************************************************************** ! 139: ALIGN ! 140: subx: //proc ! 141: ! 142: mov dword_frac1(%ebp),%eax // fractional subtract ! 143: andl $0x0ffff0000,dword_frac2(%ebp) // clear low word ! 144: sub dword_frac2(%ebp),%eax ! 145: mov %eax,result_dword_frac(%ebp) ! 146: mov dword_frac1+4(%ebp),%eax ! 147: sbb dword_frac2+4(%ebp),%eax ! 148: mov %eax,result_dword_frac+4(%ebp) ! 149: mov dword_frac1+8(%ebp),%eax ! 150: sbb dword_frac2+8(%ebp),%eax ! 151: mov %eax,result_dword_frac+8(%ebp) ! 152: movb $0,%al //set al to borrow ! 153: rclb $1,%al ! 154: ret ! 155: //subx endp ! 156: // ! 157: // *************************************************************************** ! 158: // subadd: ! 159: // ******* ! 160: // function: ! 161: // floating point add or subtract.calculates unpacked result. ! 162: // sp_subadd is the entry point for log functions. ! 163: // ! 164: // inputs: ! 165: // assumes operands are unpacked, valid, non-zero. ! 166: // ! 167: // outputs: ! 168: // ! 169: // data accessed: ! 170: // - operation_type sign1 ! 171: // - expon1 msb_frac ! 172: // - offset_operand1 sign2 ! 173: // - expon2 msb_frac2 ! 174: // - offset_operand2 offset_result ! 175: // - result_sign result_expon ! 176: // - result_word_frac ! 177: // ! 178: // data changed: ! 179: // - result_sign result_expon ! 180: // - result_word_frac ! 181: // ! 182: // procedures called: ! 183: // sticky_right_shift right_shift ! 184: // addition_normlized subtraction_normalize ! 185: // addx subx ! 186: // test_6w get_rnd_control ! 187: // ! 188: // ************************************************************************ ! 189: ALIGN ! 190: subadd: //proc ! 191: mov $sticky_right_shift,%esi // load shift proc ptr ! 192: jmp form_expon_difference // merge with sp_subadd ! 193: ALIGN ! 194: sp_subadd: ! 195: mov $sp_right_shift,%esi // load shift proc ptr ! 196: form_expon_difference: ! 197: mov dword_expon1,%ecx ! 198: sub dword_expon2,%ecx ! 199: js expon2_larger ! 200: cmp $67,%ecx //set cl to shift amount = ! 201: jbe adjust_frac2 //min(67,expon1-expon2) ! 202: mov $67,%ecx ! 203: adjust_frac2: ! 204: movb $0x00,%al //al = bit to inject from left ! 205: mov $offset_operand2,%edi ! 206: push %esi ! 207: call *%esi //shift op2 fraction ! 208: pop %esi ! 209: mov expon1(%ebp),%eax //set result expon to expon1 ! 210: mov %eax,result_expon(%ebp) ! 211: cmpb special, tag1(%ebp) ! 212: je determine_operation_true ! 213: testb $0x80,msb_frac1 ! 214: jnz determine_operation_true // branch if frac1 is normal ! 215: jmp frac2_normal_ // test frac2 ! 216: ALIGN ! 217: expon2_larger: ! 218: neg %ecx //set cl to shift amount ! 219: cmp $67,%ecx ! 220: jbe adjust_frac1 ! 221: mov $67,%ecx ! 222: adjust_frac1: ! 223: push %ecx //save shift amount ! 224: movb $0x00,%al //al = bit to inject ! 225: mov $offset_operand1,%edi ! 226: call *%esi ! 227: mov expon2(%ebp),%eax //set result expon to expon2 ! 228: mov %eax,result_expon(%ebp) ! 229: pop %ecx ! 230: frac2_normal_: ! 231: cmpb special, tag2(%ebp) ! 232: je determine_operation_true ! 233: movb false,%al ! 234: testb $0x80,msb_frac2 // set al to true if frac2 is ! 235: jz determine_operation // normalized ! 236: determine_operation_true: ! 237: movb true,%al ! 238: determine_operation: ! 239: cmpb $sub_op,operation_type(%ebp) //if op=sub_op, negate op2 ! 240: jne add_or_sub_ ! 241: notb sign2(%ebp) ! 242: add_or_sub_: ! 243: movb sign1(%ebp),%ah ! 244: cmpb sign2(%ebp),%ah ! 245: jne do_subtraction ! 246: call addx //do fractional add ! 247: mov $offset_result,%edi ! 248: call addition_normalize //normalize result after add ! 249: movb sign1(%ebp),%al ! 250: movb %al,result_sign(%ebp) //set result sign to sign1 ! 251: testb $0x80, msb_result ! 252: jnz add_done ! 253: mov $offset_result, %edi ! 254: call test_6w ! 255: jnz norm_result ! 256: add_done: ! 257: ret ! 258: ALIGN ! 259: do_subtraction: ! 260: push %eax //save normalization indicator ! 261: movb sign1(%ebp),%al //initially, set sign to sign1 ! 262: movb %al,result_sign(%ebp) ! 263: call subx //do fractional subtract ! 264: mov $offset_result,%edi ! 265: cmpb $0,%al ! 266: mov $0,%eax ! 267: je detect_zero ! 268: ! 269: notl (%ebp,%edi) //form 2s comp of result_frac ! 270: add $1,(%ebp,%edi) ! 271: notl 4(%ebp,%edi) ! 272: adc %eax,4(%ebp,%edi) ! 273: notl 8(%ebp,%edi) ! 274: adc %eax,8(%ebp,%edi) ! 275: notb result_sign(%ebp) //and complement result_sign ! 276: detect_zero: ! 277: call test_6w //find true zero result ! 278: jnz do_norm_ // if not zero, test for denorm ! 279: call get_rnd_control // sign is + unless rnd down ! 280: xorb rnd_down,%al ! 281: decw %ax ! 282: cbtw ! 283: movb %ah,result_sign(%ebp) ! 284: pop %eax //if al=true, then result should ! 285: cmpb true,%al // be true zero ! 286: jne subtract_done ! 287: movw $0,result_expon(%ebp) ! 288: ret ! 289: ALIGN ! 290: do_norm_: ! 291: pop %eax //if al=false, dont normalize ! 292: cmpb true,%al // the result ! 293: jne subtract_done ! 294: norm_result: ! 295: mov $offset_result,%edi ! 296: call subtraction_normalize //normalize the result ! 297: subtract_done: ! 298: ret ! 299: ALIGN ! 300: sp_right_shift: ! 301: call right_shift ! 302: mov (%ebp,%edi),%eax // ss:ebp+edi -> dword_frac after call ! 303: and $0x1fffffff,%eax // mask dword fraction ! 304: or %eax,%edx // or it to the right_shift output ! 305: jz sp_nonsticky // if zero, it must be nonsticky ! 306: orl $0x20000000,(%ebp,%edi) // if nonzero, set bit of dword_frac ! 307: sp_nonsticky: ! 308: andl $0x0e0000000,(%ebp,%edi) // now mask off most of dword_frac ! 309: ret ! 310: //subadd endp ! 311: // ! 312: // *********************************************************************** ! 313: // compar: ! 314: // ******* ! 315: // ! 316: // function: ! 317: // main procedure for compare and test instructions. ! 318: // ! 319: // inputs: ! 320: // op1 and op2 operand records. ! 321: // ! 322: // outputs: ! 323: // sets zero and sign status bits to indicate the result ! 324: // of the compare. sets the invalid and denorm error bits ! 325: // if these errors are detected. ! 326: // ! 327: // data accessed: ! 328: // - operation_type tag1 ! 329: // - expon1 tag2 ! 330: // - expon2 result_sign ! 331: // - result_word_frac ! 332: // ! 333: // data changed: ! 334: // ! 335: // procedures called: ! 336: // pop_free subadd ! 337: // test_6w clear_6w ! 338: // set_s_bit clear_s_bit ! 339: // set_z_bit clear_z_bit ! 340: // ! 341: // *************************************************************************** ! 342: ALIGN ! 343: compar: //proc ! 344: jz no_stack_error // branch if no stack error ! 345: andb $~a_mask,%gs:sr_flags // clear a-bit ! 346: orb invalid_mask+zero_mask,%gs:sr_errors// clears zf, to 0 ! 347: jmp invalid_error_signal ! 348: ALIGN ! 349: no_stack_error: ! 350: movl $0,before_error_signals(%ebp) ! 351: andb $~(a_mask+c_mask),%gs:sr_flags ! 352: cmpb $test_op,operation_type(%ebp) // if not test_op, then ! 353: jne set_up_check // its compar_op or ucom_op ! 354: movb positive,sign2(%ebp) // for test_op, set operand2 ! 355: movb special,tag2(%ebp) // to zero ! 356: mov $dword_frac2,%edi ! 357: call clear_6w // returns with eax = 0 ! 358: mov %eax,dword_expon2 ! 359: set_up_check: ! 360: movb tag1(%ebp),%al // both operands valid? ! 361: orb tag2(%ebp),%al ! 362: jz ordered_cases // yes, ops are ordered. ! 363: cmpb special,%al // one op is zero, and the ! 364: je ordered_cases // other is zero or valid. ! 365: testb $0x10,%al // is either op unsupported? ! 366: jnz invalid_error_detected ! 367: op1_nan_: ! 368: movb tag1(%ebp),%al // al = value of tag1 ! 369: movb tag2(%ebp),%ah // ah = value of tag2 ! 370: cmpb inv,%al ! 371: je op1_snan_ ! 372: cmpb inv,%ah ! 373: jne non_nan_supp_ops ! 374: jmp signal_invalid_ ! 375: ALIGN ! 376: op1_snan_: ! 377: testb $0x40,msb_frac1 ! 378: jz invalid_error_detected ! 379: op2_also_nan_: ! 380: cmpb inv,%ah ! 381: jne set_up_nan_return ! 382: signal_invalid_: ! 383: testb $0x40,msb_frac2 ! 384: jz invalid_error_detected ! 385: set_up_nan_return: ! 386: cmpb $ucom_op,operation_type(%ebp) // if ucom_op, then ! 387: je set_uncertain // no invalid signal. ! 388: jmp invalid_error_detected ! 389: ALIGN ! 390: non_nan_supp_ops: ! 391: cmpb denormd,tag1(%ebp) ! 392: jne op2_denormd_ ! 393: movb true,signal_d_error_ ! 394: cmp $0,expon1(%ebp) ! 395: jne op2_denormd_ ! 396: movl $1,expon1(%ebp) ! 397: op2_denormd_: ! 398: cmpb denormd,tag2(%ebp) ! 399: jne ordered_cases ! 400: movb true,signal_d_error_ ! 401: cmp $0,expon2(%ebp) ! 402: jne ordered_cases ! 403: movl $1,expon2(%ebp) ! 404: ordered_cases: ! 405: movb $sub_op,operation_type(%ebp) // subtract op2 from op1 ! 406: call subadd ! 407: mov $offset_result,%edi // detect a zero fraction ! 408: call test_6w // in result ! 409: jz operands_equal ! 410: andb $~(zero_mask+sign_mask),%gs:sr_flags // set zero to false ! 411: testb $0x01,result_sign(%ebp) // set sign to result ! 412: jz finish_up ! 413: orb $sign_mask,%gs:sr_flags ! 414: finish_up: ! 415: cmp $0,before_error_signals(%ebp) ! 416: jne check_i_error ! 417: jmp pop_free ! 418: ALIGN ! 419: check_i_error: ! 420: cmpb false,signal_i_error_ // recall that false = 00h ! 421: je set_denorm_error ! 422: test_invalid_mask: ! 423: testb invalid_mask,%gs:sr_masks ! 424: jz unmasked_exit ! 425: jmp pop_free ! 426: ALIGN ! 427: unmasked_exit: ! 428: ret ! 429: ALIGN ! 430: check_d_error: ! 431: cmpb false,signal_d_error_ // recall that false = 00h ! 432: jne set_denorm_error ! 433: jmp pop_free ! 434: ALIGN ! 435: set_denorm_error: ! 436: orb denorm_mask,%gs:sr_errors ! 437: test_denorm_mask: ! 438: testb denorm_mask,%gs:sr_masks ! 439: jz unmasked_exit ! 440: jmp pop_free ! 441: ALIGN ! 442: ! 443: invalid_error_detected: ! 444: orb invalid_mask,%gs:sr_errors ! 445: invalid_error_signal: ! 446: movl $0x000000ff,before_error_signals(%ebp) ! 447: jmp set_uncertain ! 448: ALIGN ! 449: ! 450: also_d_error_: ! 451: cmpb denormd,tag1(%ebp) ! 452: je d_error_also ! 453: cmpb denormd,tag2(%ebp) ! 454: jne set_uncertain ! 455: d_error_also: ! 456: movb true, signal_d_error_ ! 457: set_uncertain: ! 458: orb $(sign_mask + c_mask), %gs:sr_flags ! 459: jmp zero_true // set zero to true ! 460: ALIGN ! 461: operands_equal: ! 462: andb $~sign_mask,%gs:sr_flags // set sign positive ! 463: zero_true: ! 464: orb $zero_mask,%gs:sr_flags ! 465: jmp finish_up ! 466: //compar endp ! 467: // ! 468: //a_med ends ! 469: // ! 470: // end
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.