Annotation of kernel/machdep/i386/fp_emul/fp_trans.s, revision 1.1

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.