Annotation of kernel/machdep/i386/fp_emul/fp_trans.s, revision 1.1.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.