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

1.1     ! root        1: /*
        !             2:  * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
        !             3:  *
        !             4:  * @APPLE_LICENSE_HEADER_START@
        !             5:  * 
        !             6:  * Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
        !             7:  * Reserved.  This file contains Original Code and/or Modifications of
        !             8:  * Original Code as defined in and that are subject to the Apple Public
        !             9:  * Source License Version 1.1 (the "License").  You may not use this file
        !            10:  * except in compliance with the License.  Please obtain a copy of the
        !            11:  * License at http://www.apple.com/publicsource and read it before using
        !            12:  * this file.
        !            13:  * 
        !            14:  * The Original Code and all software distributed under the License are
        !            15:  * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
        !            16:  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
        !            17:  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
        !            18:  * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
        !            19:  * License for the specific language governing rights and limitations
        !            20:  * under the License.
        !            21:  * 
        !            22:  * @APPLE_LICENSE_HEADER_END@
        !            23:  */
        !            24: 
        !            25:        .file   "arith.s"
        !            26: 
        !            27:        .ident  "@(#)kern-fp:arith.s    1.1"
        !            28: //$tt(*80387   emulator        + + + arithmetic + + +*)
        !            29: // ************************************************************************
        !            30: //
        !            31: //                     a r i t h . m o d
        !            32: //                     =================
        !            33: // 
        !            34: //     ===============================================================
        !            35: //               intel corporation proprietary information
        !            36: //    this software  is  supplied  under  the  terms  of  a  license
        !            37: //    agreement  or non-disclosure agreement  with intel corporation
        !            38: //    and  may not be copied  or disclosed except in accordance with
        !            39: //    the terms of that agreement.                                  
        !            40: //     ===============================================================
        !            41: //
        !            42: //     function:
        !            43: //             implements add, subtract, multiply, and divide.
        !            44: //
        !            45: //     public procedures:
        !            46: //             move_op_to_result               overflow_response
        !            47: //             underflow_response              put_max_nan
        !            48: //             put_indefinite                  arith
        !            49: //
        !            50: // *************************************************************************
        !            51: //
        !            52: //...March 3, 1987...
        !            53: //
        !            54: //     .file   *a_mar*
        !            55: #include       "fp_e80387.h"
        !            56: //$eject
        !            57: //...declare status register segment...
        !            58: //
        !            59:        .data   //a_msr segment rw      public
        !            60: //     extrn   sr_masks
        !            61: //a_msr        ends
        !            62: //
        !            63:        .text   //a_med segment er      public
        !            64: //     assume  %ds:a_med
        !            65: //     extrn   addition_normalize,round
        !            66: //     extrn   gradual_underflow,put_result
        !            67: //     extrn   pop_free,subadd,mult
        !            68: //     extrn   divid,set_up_indefinite,test_4w
        !            69: //     extrn   special_round_test,directed_round_test
        !            70: //     extrn   get_precision,u_masked_,set_i_masked_
        !            71: //     extrn   d_masked_,affine_infinity_,i_masked_
        !            72: //     extrn   o_masked_,set_p_error,set_u_error
        !            73: //     extrn   set_o_error,set_z_masked_,set_d_masked_
        !            74: //     extrn   set_stk_u_error,d_error_,get_rnd_control
        !            75: //
        !            76:        .globl  put_indefinite
        !            77:        .globl  move_op_to_result
        !            78:        .globl  put_max_nan
        !            79:        .globl  overflow_response
        !            80:        .globl  underflow_response
        !            81:        .globl  arith
        !            82:        .globl  norm_denorm
        !            83:        .globl put_arith_result
        !            84:        .globl set_up_nan_return
        !            85: //$eject
        !            86: //
        !            87: //...define some floating point constants...
        !            88: //
        !            89: indefinite_pattern:    
        !            90:        .value  0,0,0,0x0c000,0x0ffff
        !            91: infinity_pattern:      
        !            92:        .value  0,0,0,0x8000,0x7fff
        !            93: zero_pattern:  
        !            94:        .value  0,0,0,0,0
        !            95: max_valid_pattern:     
        !            96:        .value  0x0ffff,0x0ffff,0x0ffff,0x0ffff,0x7ffe
        !            97: arith_table:   
        !            98:        .long   subadd,subadd,mult,divid
        !            99: //
        !           100: //...the following jump tables refer to the following op1/op2 cases 
        !           101: //
        !           102: //   (where v=valid, z=zero, f=infinity, and d=denormal):
        !           103: //             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,
        !           104: //      in that order ..
        !           105: //add_table
        !           106: special_table: 
        !           107:        .long   handle_non_special_cases,handle_non_special_cases
        !           108:        .long   second_operand,only_op2_denormd
        !           109:        .long   handle_non_special_cases,handle_non_special_cases
        !           110:        .long   second_operand,only_op2_denormd
        !           111:        .long   first_operand,first_operand
        !           112:        .long   add_sub_infinities,derror_with_first_operand
        !           113:        .long   only_op1_denormd,only_op1_denormd
        !           114:        .long   derror_with_second_operand,both_ops_denormd
        !           115: //sub_table
        !           116:        .long   handle_non_special_cases,handle_non_special_cases
        !           117:        .long   neg_second_operand,only_op2_denormd
        !           118:        .long   handle_non_special_cases,handle_non_special_cases
        !           119:        .long   neg_second_operand,only_op2_denormd
        !           120:        .long   first_operand,first_operand
        !           121:        .long   add_sub_infinities,derror_with_first_operand
        !           122:        .long   only_op1_denormd,only_op1_denormd
        !           123:        .long   derror_with_neg_second_operand,both_ops_denormd
        !           124: //mul_table
        !           125:        .long   handle_non_special_cases,exor_signed_zero
        !           126:        .long   exor_signed_infinity,only_op2_denormd
        !           127:        .long   exor_signed_zero,exor_signed_zero
        !           128:        .long   invalid_error_detected,denormd_exor_signed_zero
        !           129:        .long   exor_signed_infinity,invalid_error_detected
        !           130:        .long   exor_signed_infinity,denormd_exor_signed_infinity
        !           131:        .long   only_op1_denormd,denormd_exor_signed_zero
        !           132:        .long   denormd_exor_signed_infinity,both_ops_denormd
        !           133: //div_table
        !           134:        .long   handle_non_special_cases,divide_by_zero
        !           135:        .long   exor_signed_zero,only_op2_denormd
        !           136:        .long   exor_signed_zero,invalid_error_detected
        !           137:        .long   exor_signed_zero,denormd_exor_signed_zero
        !           138:        .long   exor_signed_infinity,exor_signed_infinity
        !           139:        .long   invalid_error_detected,denormd_exor_signed_infinity
        !           140:        .long   only_op1_denormd,divide_by_zero
        !           141:        .long   denormd_exor_signed_zero,both_ops_denormd
        !           142: //
        !           143: //$eject
        !           144: //                     put_indefinite:
        !           145: //
        !           146: //     function:
        !           147: //             sets unpacked result to indefinite.
        !           148: //
        !           149: //     inputs:
        !           150: //
        !           151: //     outputs:
        !           152: //             result set to indefinite; tag set to invalid.
        !           153: //
        !           154: //     data accessed:
        !           155: //             - result_sign                   result_tag
        !           156: //
        !           157: //     data changed:
        !           158: //             - result
        !           159: //
        !           160:        ALIGN
        !           161: put_indefinite:        //proc
        !           162:        mov     $indefinite_pattern,%esi
        !           163:        movb    negative,result_sign(%ebp)
        !           164: // note that entry points below do not affect result_sign.
        !           165: put_inv_tag:
        !           166:        movb    inv,result_tag(%ebp)    // fall into set_constant_result
        !           167: set_constant_result:
        !           168:        lea     offset_result+4(%ebp),%edi
        !           169: //     push    %ds                       // save a?msr
        !           170: //     push    %cs
        !           171: //     pop     %ds
        !           172: //     push    %ss
        !           173: //     pop     %es
        !           174: 
        !           175:        /* FAST_MOVSL */
        !           176:        movl    %cs:0(%esi),%ecx
        !           177:        movl    %ecx,%ss:0(%edi)
        !           178:        movl    %cs:4(%esi),%ecx
        !           179:        movl    %ecx,%ss:4(%edi)
        !           180: //     addl    $8,%esi
        !           181: 
        !           182:        mov     %ecx,result_dword_frac(%ebp)        // clear ls dword
        !           183:        mov     %cs:8(%esi),%eax                        // move exponent
        !           184:        movw    %ax,result_expon(%ebp)          // to result
        !           185: //     pop     %ds                             // reload a?msr
        !           186:        ret
        !           187: //put_indefinite       endp
        !           188: //$eject
        !           189: //                     move_op_to_result:
        !           190: //
        !           191: //     function:
        !           192: //             moves operand to result.
        !           193: //
        !           194: //     inputs:
        !           195: //             assumes ss:(ebp).esi points to op1 or op2
        !           196: //
        !           197: //     outputs:
        !           198: //             result in result
        !           199: //
        !           200: //     data accessed:
        !           201: //             - expon1                        offset_result
        !           202: //             - result_expon
        !           203: //
        !           204: //     data changed:
        !           205: //             - result
        !           206: //
        !           207:        ALIGN
        !           208: move_op_to_result:     //proc
        !           209: //     push    %ds                                             // save a?msr
        !           210:        add     %ebp,%esi
        !           211: //     push    %ss
        !           212: //     pop     %ds
        !           213: //     push    %ss
        !           214: //     pop     %es
        !           215:        lea     offset_result(%ebp),%edi
        !           216:        mov     $((offset_operand2-offset_operand1)>>2),%ecx
        !           217: 
        !           218:        /* FAST_MOVSL */
        !           219: 1:
        !           220:        movl    %ss:0(%esi),%eax
        !           221:        movl    %eax,%ss:0(%edi)
        !           222:        addl    $4,%esi
        !           223:        addl    $4,%edi
        !           224:        decl    %ecx
        !           225:        testl   %ecx,%ecx
        !           226:        jg      1b
        !           227: 
        !           228: //     pop     %ds                             // reload a?msr
        !           229:        ret
        !           230: //move_op_to_result    endp
        !           231: //$eject
        !           232: //                     overflow_response:
        !           233: //
        !           234: //     function:
        !           235: //             responds to detected overflow.
        !           236: //
        !           237: //     inputs:
        !           238: //
        !           239: //     outputs:
        !           240: //             overflow error indication(s) set when appropriate
        !           241: //             correct masked or unmasked result
        !           242: //
        !           243: //     data accessed:
        !           244: //             - result_sign                   result_tag
        !           245: //             - result_expon                  msb_result
        !           246: //
        !           247: //     data changed:
        !           248: //             - result
        !           249: //
        !           250: //     procedures called:
        !           251: //             special_round_test              set_o_error
        !           252: //             o_masked?                           set_p_error
        !           253: //
        !           254: //
        !           255:        ALIGN
        !           256: overflow_response:     //proc
        !           257:        orb     overflow_mask, %gs:sr_errors    //set overflow error
        !           258:        testb   overflow_mask, %gs:sr_masks
        !           259:        jnz     masked_overflow            // branch if ovflw masked
        !           260: // note that p_error may have been set by the first rounding of the result,
        !           261: // and that rounded result will now have its exponents bias adjusted:
        !           262: reduce_exponent:
        !           263:        subl    wrap_around_constant,dword_result_expon // subtract
        !           264:        cmpl    $0x7fff, dword_result_expon     //wrap around constant
        !           265:        jge     masked_overflow             // bad! should give qnan indefinite
        !           266: unmasked_ov_un_rounds:
        !           267:        cmpb    true, rnd1_inexact      //detect inexact result
        !           268:        jne     give_valid_o_result     // if exact, branch to replace source
        !           269:        orb     $inexact_mask, %gs:sr_errors    // else, set p_error
        !           270:        cmpb    true, added_one //was rounding done by adding one
        !           271:        jne     give_valid_o_result     // if not branch to replace source
        !           272:        orb     $a_mask, %gs:sr_flags   // else set A_bit
        !           273:        jmp     give_valid_o_result
        !           274:        ALIGN
        !           275: masked_overflow:
        !           276:        orb     $inexact_mask, %gs:sr_errors    //set p_error
        !           277:        call    get_rnd_control
        !           278:        cmpb    rnd_to_zero,%al
        !           279:        je      put_max_valid
        !           280:        movb    result_sign(%ebp),%al           // check for special
        !           281:        call    special_round_test                          // rounding case
        !           282:        jnz     put_max_valid
        !           283:        orb     $a_mask, %gs:sr_flags   //set a_bit
        !           284: put_infinity:
        !           285:        mov     $infinity_pattern,%esi
        !           286:        jmp     put_inv_tag
        !           287:        ALIGN
        !           288: put_max_valid:
        !           289: //     mov         (ebp).result_tag,   valid
        !           290:        movl    $0x00007ffe,dword_result_expon
        !           291:        movl    $0,result_dword_frac(%ebp)
        !           292:        movl    $0x0ffffffff,result_dword_frac+frac64(%ebp)
        !           293:        movl    $0x0ffffffff,result_dword_frac+frac32(%ebp)
        !           294:        cmpb    $add_op,operation_type(%ebp)
        !           295:        jl      give_valid_o_result
        !           296:        cmpb    $div_op,operation_type(%ebp)
        !           297:        jg      give_valid_o_result
        !           298:        movb    $precision_mask,%dl     // load precision field mask
        !           299:        andb    %gs:sr_controls,%dl             // mask in precision control
        !           300:        cmpb    prec53,%dl
        !           301:        jg      give_valid_o_result
        !           302:        je      purge_11_bits
        !           303:        movl    $0,result_dword_frac+frac64(%ebp)
        !           304:        movl    $0x0ffffff00,result_dword_frac+frac32(%ebp)
        !           305:        jmp     give_valid_o_result
        !           306:        ALIGN
        !           307: purge_11_bits:
        !           308:        andl    $0x0fffff800,result_dword_frac+frac64(%ebp)
        !           309: 
        !           310: //     mov         esi,    offset max_valid_pattern    ; set result to max
        !           311: //     jmp         set_constant_result                     ; valid number
        !           312: 
        !           313: give_valid_o_result:
        !           314:        movb    valid,result_tag(%ebp)
        !           315:        ret
        !           316: //overflow_response    endp
        !           317: //$eject
        !           318: //                     underflow_response:
        !           319: //
        !           320: //     function:
        !           321: //             responds to a detected underflow 
        !           322: //
        !           323: //     inputs:
        !           324: //
        !           325: //     outputs:
        !           326: //             sets underflow error indication(s) if appropiate
        !           327: //             correct masked or unmasked results in result
        !           328: //
        !           329: //     data accessed:
        !           330: //             - offset_result                 result_sign
        !           331: //             - result_tag                    result_expon
        !           332: //             - result_word_frac
        !           333: //
        !           334: //     data changed:
        !           335: //             - result
        !           336: //
        !           337: //     procedures called:
        !           338: //             directed_round_test             gradual_underflow
        !           339: //             round                               test_4w
        !           340: //             set_u_error                         u_masked?
        !           341: //             get_precision
        !           342: //
        !           343:        ALIGN
        !           344: underflow_response:    //proc
        !           345:        testb   underflow_mask, %gs:sr_masks    //is underflow masked
        !           346:        jnz     do_grad_underflow               // yes, dont set flag
        !           347:        orb     underflow_mask, %gs:sr_errors   //no, set error flag
        !           348: increase_exponent:
        !           349:        addl    wrap_around_constant,dword_result_expon // add wrap-around
        !           350:        cmp     $0, dword_result_expon  //wrap_around constant
        !           351:        jg      unmasked_ov_un_rounds   // bad! shuld give qnan indef
        !           352:        subl    wrap_around_constant, dword_result_expon // subtract
        !           353: do_grad_underflow:
        !           354:        mov     $offset_result,%edi                  // do gradual underflow
        !           355:        mov     $0x0001,%eax                    // minimum expon is 0001
        !           356:        call    gradual_underflow
        !           357:        call    get_precision
        !           358:        movb    true,%al
        !           359:        mov     $offset_result,%edi             // do second round
        !           360:        call    round
        !           361:        cmpw    $0, rnd_history         
        !           362:        je      prepare_zero_expon
        !           363:        orb     underflow_mask + inexact_mask, %gs:sr_errors //set both errors
        !           364:        cmpb    true, added_one         // was rounding done by adding one
        !           365:        jne     prepare_zero_expon      //if not, branch for zero expon
        !           366:        orb     $a_mask, %gs:sr_flags   //else, set a_bit & if incrementing
        !           367:        testb   $0x80, msb_result       //The significand caused the most
        !           368:        jz      prepare_zero_expon      //significant bit of result_frac to
        !           369:        movb    valid, result_tag(%ebp) // be set, tag result *valid* & return
        !           370:        ret
        !           371:        ALIGN
        !           372: prepare_zero_expon:
        !           373:        xor     %eax, %eax
        !           374: clear_expon:
        !           375:        mov     %eax,dword_result_expon         // set exponent to zero
        !           376:        mov     $result_dword_frac+4,%edi
        !           377:        call    test_4w                         // if fraction nonzero,
        !           378:        movb    denormd,result_tag(%ebp)
        !           379:        jnz     accept_tag                      // tag as denormal
        !           380:        movb    special,result_tag(%ebp)        // else, tag as zero
        !           381: accept_tag:
        !           382:        ret
        !           383: //underflow_response   endp
        !           384: //$eject
        !           385: //                     norm_denorm:
        !           386: //
        !           387: //     function:
        !           388: //             normalizes an unpacked operand presumed to have been tagged
        !           389: //             *denormd*.  includes case in which operand is so tagged because
        !           390: //             it was a single or double format denormal, which has already
        !           391: //       been normalized in the course of extending it to unpacked format.
        !           392: //             also includes case in which operand is a pseudo-denormal.
        !           393: //
        !           394: //     inputs:  edi points to the offset of the record to be normalized.
        !           395: //
        !           396: //     outputs:
        !           397: //             8 bytes beginning at (ebp + edi + frac64) are left shifted until
        !           398: //             the bit in position b63 is set.
        !           399: //             the 32 bit exponent field is 1 - shift_count
        !           400: //
        !           401: //     data accessed:
        !           402: //             - dword ptr (ebp + edi + expon)
        !           403: //             - byte ptr (ebp + edi + msb)
        !           404: //             - dword ptr (ebp + edi + frac32),       dword ptr (ebp + edi + frac64)
        !           405: //
        !           406: //     data changed:
        !           407: //             - dword ptr (ebp + edi + expon)
        !           408: //             - byte ptr (ebp + edi + msb)
        !           409: //             - dword ptr (ebp + edi + frac32),       dword ptr (ebp + edi + frac64)
        !           410: //
        !           411: //     procedures called:
        !           412: //
        !           413: //
        !           414:        ALIGN
        !           415: norm_denorm:   //proc
        !           416:        cmp     $0,expon(%ebp,%edi)
        !           417:        jne     norm_denorm_done
        !           418:        movl    $1,expon(%ebp,%edi)
        !           419:        testb   $0x80,msb(%ebp,%edi)
        !           420:        jnz     norm_denorm_done
        !           421: norm_64_bits:
        !           422:        bsrl    frac32(%ebp,%edi),%ecx
        !           423:        jz      top_32_zero
        !           424:        mov     frac64(%ebp,%edi),%eax
        !           425:        sub     $31,%ecx
        !           426:        neg     %ecx
        !           427:        shldl   %cl,%eax,frac32(%ebp,%edi)
        !           428:        shll    %cl,frac64(%ebp,%edi)
        !           429: adjust_dword_expon:
        !           430:        sub     %ecx,expon(%ebp,%edi)   // adjust exponent
        !           431: norm_denorm_done:
        !           432:        ret
        !           433:        ALIGN
        !           434: top_32_zero:
        !           435:        mov     frac64(%ebp,%edi),%eax
        !           436:        bsrl    %eax,%ecx
        !           437:        sub     $31,%ecx
        !           438:        neg     %ecx
        !           439:        shll    %cl,%eax
        !           440:        mov     %eax,frac32(%ebp,%edi)
        !           441:        movl    $0,frac64(%ebp,%edi)
        !           442:        add     $32,%ecx
        !           443:        jmp     adjust_dword_expon
        !           444: //norm_denorm  endp
        !           445: //$eject
        !           446: //
        !           447: //                     arith:
        !           448: //
        !           449: //     function:
        !           450: //             main procedure for implementation of 80387 add, subtract,
        !           451: //             multiply, and divide instructions
        !           452: //
        !           453: //     inputs:
        !           454: //             assumes operation type, operand(s), and unpacked
        !           455: //             status variables are set up
        !           456: //
        !           457: //     outputs
        !           458: //             result of operation in result
        !           459: //
        !           460: //     data accessed:
        !           461: //             - operation_type                offset_operand1
        !           462: //             - sign1                         tag1
        !           463: //             - expon1                        offset_operand2
        !           464: //             - sign2                         tag2
        !           465: //             - expon2                        offset_result
        !           466: //             - result_sign                   result_tag
        !           467: //             - result_expon                  result_word_frac
        !           468: //
        !           469: //     data changed:
        !           470: //             - result
        !           471: //
        !           472: //     procedures called:
        !           473: //             put_indefinite          affine_infinity?
        !           474: //             put_max_valid           move_op_to_result
        !           475: //             overflow_response       underflow_response
        !           476: //             put_max_nan             divid
        !           477: //             set_up_indefinite       round
        !           478: //             addition_normalized     put_result
        !           479: //             pop_free                subadd
        !           480: //             mult                    test_4w
        !           481: //             i_masked?               d_error?
        !           482: //             d_masked?               i_error?
        !           483: //             get_precision           set_i_masked?
        !           484: //             set_z_masked?           set_d_masked?
        !           485: //
        !           486: //
        !           487:        ALIGN
        !           488: arith: //proc
        !           489: //     assume  %ds:a_msr
        !           490:        jz      weed_out_special_cases  // branch if no stack error
        !           491:        call    set_stk_u_error                 // stack underflow occurred
        !           492:        testb   invalid_mask,%gs:sr_masks
        !           493:        jz      go_home                                 // if unmasked, return
        !           494:        call    put_indefinite                  // otherwise, result = indefinite
        !           495:        jmp     finish_up
        !           496:        ALIGN
        !           497: weed_out_special_cases:
        !           498:        andb    $~a_mask, %gs:sr_flags          //clear a_bit initially
        !           499:        movb    tag1(%ebp),%al                  // both operands valid?
        !           500:        orb     tag2(%ebp),%al
        !           501:        jnz     special_cases                           // no, special case
        !           502: handle_non_special_cases:
        !           503:        movzbl  operation_type(%ebp),%ebx// call sub/add/mul/div
        !           504:        subb    $add_op,%bl                             // to do the operation
        !           505:        shlw    $2,%bx
        !           506:        call    *%cs:arith_table(%ebx)
        !           507: // the following three instructions are residue of warning mode arithmetic:
        !           508: //             call    i_error?                ; invalid if attempted
        !           509: //             jz              no_invalid_error; division by denormal
        !           510: //             jmp             invalid_error_detected
        !           511: no_invalid_error:
        !           512:        mov     $offset_result,%edi     // round result
        !           513:        call    get_precision                           // (indicate first, not
        !           514:        movb    false,%al                       // second, round)
        !           515:        call    round
        !           516:        mov     $offset_result,%edi     // re-normalize
        !           517: //     movb    $4,%ah                          / (num words in frac=4)
        !           518:        call    addition_normalize                      // (al contains overflow
        !           519:        mov     dword_result_expon,%eax // indication from round)
        !           520:        cmp     $0x7ffe,%eax            // overflow iff
        !           521:        jg      overflow_happened                       // expon > 7ffeh
        !           522:        cmp     $0,%eax                 // check underflow if
        !           523:        jl      underflow_happened                      // expon < 0
        !           524:        call    give_valid_o_result                     // set tag to valid
        !           525:        and     %eax,%eax                               // check underflow if
        !           526:        jnz     report_rounds           // expon = 0 and frac <> 0
        !           527:        mov     $result_dword_frac+4,%edi       //expon=0
        !           528:        call    test_4w
        !           529:        jnz     underflow_happened
        !           530:        movb    special,result_tag(%ebp)        // result is truly zero
        !           531: report_rounds:
        !           532:        cmpb    true, rnd1_inexact      //detect inexact result
        !           533:        jne     finish_up               //if exact, branch
        !           534:        orb     $inexact_mask, %gs:sr_errors  //else, set p_error
        !           535:        cmpb    true, added_one         //was rounding done by adding one
        !           536:        jne     finish_up               //if not, branch
        !           537:        orb     $a_mask, %gs:sr_flags   // else, set a_bit
        !           538: finish_up:
        !           539:        mov     $offset_result,%edi
        !           540:        mov     offset_result_rec,%esi
        !           541:        jmp     put_arith_result
        !           542:        ALIGN
        !           543: //
        !           544: both_ops_denormd:
        !           545:        orb     denorm_mask, %gs:sr_errors 
        !           546:        testb   denorm_mask, %gs:sr_masks
        !           547:        jz      go_home
        !           548:        mov     $offset_operand1,%edi
        !           549:        call    norm_denorm
        !           550: op2_denormd:
        !           551:        mov     $offset_operand2,%edi
        !           552:        call    norm_denorm
        !           553:        jmp     handle_non_special_cases
        !           554:        ALIGN
        !           555: only_op1_denormd:
        !           556:        orb     denorm_mask, %gs:sr_errors 
        !           557:        testb   denorm_mask, %gs:sr_masks
        !           558:        jz      go_home
        !           559:        mov     $offset_operand1,%edi
        !           560:        call    norm_denorm
        !           561:        jmp     handle_non_special_cases
        !           562:        ALIGN
        !           563: only_op2_denormd:
        !           564:        orb     denorm_mask, %gs:sr_errors 
        !           565:        testb   denorm_mask, %gs:sr_masks
        !           566:        jz      go_home
        !           567:        jmp     op2_denormd
        !           568:        ALIGN
        !           569: //
        !           570: overflow_happened:
        !           571:        call    overflow_response       // here, overflow is certain.
        !           572:        jmp     finish_up
        !           573:        ALIGN
        !           574: go_home:
        !           575:        ret
        !           576: underflow_happened:
        !           577:        call    underflow_response
        !           578:        jmp     finish_up
        !           579:        ALIGN
        !           580: special_cases:
        !           581:        testb   $0x10,%al               // al contains (ebp).tag1 or (ebp).tag2
        !           582:        jz      op1_nan_
        !           583:        orb     invalid_mask, %gs:sr_errors 
        !           584:        testb   invalid_mask, %gs:sr_masks
        !           585:        jz      go_home
        !           586:        mov     $offset_operand1,%edi
        !           587:        call    set_up_indefinite
        !           588:        mov     offset_result_rec,%esi
        !           589:        jmp     put_arith_result
        !           590:        ALIGN
        !           591: op1_nan_:                              // here, neither op is unsupported.
        !           592:        cmpb    inv,tag1(%ebp)
        !           593:        je      op1_snan_
        !           594:        cmpb    inv,tag2(%ebp)
        !           595:        jne     non_nan_supp_ops
        !           596:        jmp     signal_invalid_
        !           597:        ALIGN
        !           598: op1_snan_:
        !           599:        testb   $0x40,msb_frac1
        !           600:        jz      invalid_operand
        !           601: op2_also_nan_:
        !           602:        cmpb    inv,tag2(%ebp)
        !           603:        jne     set_up_nan_return
        !           604: signal_invalid_:
        !           605:        testb   $0x40,msb_frac2
        !           606:        jnz     set_up_nan_return
        !           607: invalid_operand:
        !           608:        orb     invalid_mask, %gs:sr_errors 
        !           609:        testb   invalid_mask, %gs:sr_masks
        !           610:        jz      go_home                                 // i-error, if unmasked
        !           611: set_up_nan_return:
        !           612:        mov     offset_result_rec,%esi  // result=max(nan1,nan2)
        !           613:        cmpb    inv, tag1(%ebp)
        !           614:        je      check_tag2
        !           615:        mov     $offset_operand2, %edi
        !           616:        jmp     install_hi_bits
        !           617:        ALIGN
        !           618: check_tag2:
        !           619:        cmpb    inv, tag2(%ebp)
        !           620:        je      put_max_nan
        !           621:        mov     $offset_operand1, %edi
        !           622:        jmp     install_hi_bits
        !           623:        ALIGN
        !           624: put_max_nan:
        !           625:        movb    sign1(%ebp),%al                 // set result to larger
        !           626:        movb    sign2(%ebp),%ah                 // magnitude result
        !           627:        push    %eax                            // save signs
        !           628:        andb    $0x7f,msb_frac1
        !           629:        andb    $0x7f,msb_frac2
        !           630: subtract_fracs:
        !           631:        movb    positive,sign1(%ebp)            // subtract the absolute
        !           632:        movb    positive,sign2(%ebp)            // values of the two ops
        !           633:        movb    $sub_op,operation_type(%ebp)
        !           634:        push    %esi
        !           635:        call    subadd
        !           636:        pop     %esi
        !           637:        pop     %eax
        !           638:        movb    %al,sign1(%ebp)                         // restore sign1 and give
        !           639:        mov     $offset_operand1,%edi   // operand1 as answer
        !           640:        cmpb    positive,result_sign(%ebp)              // if difference is +
        !           641:        je      install_hi_bits
        !           642:        movb    %ah,sign2(%ebp)                         // restore sign2 and give
        !           643:        mov     $offset_operand2,%edi   // operand2 as answer
        !           644: install_hi_bits:
        !           645:        orb     $0x0c0,msb(%ebp,%edi)
        !           646: put_arith_result:
        !           647:        call    put_result
        !           648:        jmp     pop_free
        !           649:        ALIGN
        !           650: non_nan_supp_ops:
        !           651:        movb    tag2(%ebp),%bl
        !           652:        movb    tag1(%ebp),%bh
        !           653:        testb   $0x04,%bh
        !           654:        jz      op2_denorm_
        !           655:        movb    $3,%bh                          // indicate op1 is denorm
        !           656: op2_denorm_:
        !           657:        testb   $0x04,%bl
        !           658:        jz      get_index
        !           659:        movb    $3,%bl                          // indicate op2 is denorm
        !           660: get_index:
        !           661:        and     $0x0303,%ebx    // form index to special operation table
        !           662:                                // bx=4*(4*masked_tag1 + masked_tag2),
        !           663:                                // where masked_tag =   0 for valid,
        !           664:        shlb    $2,%bh          //      1 for zero,
        !           665:                                //2 for infinity
        !           666:        addb    %bh,%bl         //      3 for denormd
        !           667:        xorb    %bh,%bh
        !           668:        shl     $2,%ebx
        !           669:        mov     $0x40fb,%eax            // 64 byte/table -add_op
        !           670:        addb    operation_type(%ebp),%al        // al = normalized type
        !           671:        mulb    %ah                     // (e)ax = operation offset
        !           672:        add     %eax,%ebx               // (e)bx = case offset
        !           673:        jmp     *%cs:special_table(%ebx)                        // jump to special case
        !           674:        ALIGN
        !           675: exit_arith:
        !           676:        ret
        !           677: derror_with_first_operand:
        !           678:        orb     denorm_mask, %gs:sr_errors 
        !           679:        testb   denorm_mask, %gs:sr_masks
        !           680:        jz      exit_arith                      // if unmasked, return
        !           681: first_operand:
        !           682:        mov     $offset_operand1,%esi           // give first operand as
        !           683:        jmp     set_result_to_operand   // result
        !           684:        ALIGN
        !           685: derror_with_neg_second_operand:
        !           686:        orb     denorm_mask, %gs:sr_errors 
        !           687:        testb   denorm_mask, %gs:sr_masks
        !           688:        jz      exit_arith                      // if unmasked, return
        !           689: neg_second_operand:
        !           690:        notb    sign2(%ebp)                     // negate second operand
        !           691:        jmp     second_operand                  // result
        !           692:        ALIGN
        !           693: derror_with_second_operand:
        !           694:        orb     denorm_mask, %gs:sr_errors 
        !           695:        testb   denorm_mask, %gs:sr_masks
        !           696:        jz      exit_arith                      // if unmasked, return
        !           697: second_operand:
        !           698:        mov     $offset_operand2,%esi           //give second operand
        !           699: set_result_to_operand:
        !           700:        call    move_op_to_result
        !           701:        jmp     go_to_finish_up
        !           702:        ALIGN
        !           703: //divide_into_zero:    ; this section, for pseudo-zeroes, was
        !           704: //             xor     ax,ax           ; commented out when they became unsupp.
        !           705: //             mov     edi,offset word_frac2 + 2       ; if frac2 = 0, invalid
        !           706: //             call    test_4w         ; else, zero and xor
        !           707: //             jz      invalid_error_detected          ; signs as the result
        !           708: denormd_exor_signed_zero:
        !           709:        orb     denorm_mask, %gs:sr_errors 
        !           710:        testb   denorm_mask, %gs:sr_masks
        !           711:        jz      exit_arith                              // if unmasked, return
        !           712: exor_signed_zero:
        !           713:        mov     $zero_pattern,%esi
        !           714:        call    set_constant_result
        !           715:        movb    special,result_tag(%ebp)
        !           716:        jmp     set_exor_sign
        !           717:        ALIGN
        !           718: denormd_exor_signed_infinity:
        !           719:        orb     denorm_mask, %gs:sr_errors 
        !           720:        testb   denorm_mask, %gs:sr_masks
        !           721:        jz      exit_arith                              // if unmasked, return
        !           722:        jmp     exor_signed_infinity
        !           723:        ALIGN
        !           724: divide_by_zero:
        !           725:        orb     zero_divide_mask, %gs:sr_errors 
        !           726:        testb   zero_divide_mask, %gs:sr_masks
        !           727:        jz      exit_arith                              // if unmasked, return
        !           728: exor_signed_infinity:
        !           729:        call    put_infinity                    // else, give infinity
        !           730: set_exor_sign:
        !           731:        movb    positive,result_sign(%ebp)      // set sign to exclusive
        !           732:        movb    sign1(%ebp),%ah // or of operand signs
        !           733:        cmpb    sign2(%ebp),%ah
        !           734:        je      go_to_finish_up
        !           735:        notb    result_sign(%ebp)
        !           736: go_to_finish_up:
        !           737:        jmp     finish_up
        !           738:        ALIGN
        !           739: add_sub_infinities:
        !           740:        movb    sign2(%ebp),%ah // add or sub magnitude?
        !           741:        cmpb    $sub_op,operation_type(%ebp)            // add mag if add_op and
        !           742:        jne     add_or_sub_mag_                 // signs same, else sub
        !           743:        notb    %ah                             // comp sign2 if sub
        !           744: add_or_sub_mag_:
        !           745:        cmpb    sign1(%ebp),%ah
        !           746:        je      first_operand           // first op res if add_mag
        !           747: invalid_error_detected:
        !           748:        orb     invalid_mask, %gs:sr_errors 
        !           749:        testb   invalid_mask, %gs:sr_masks
        !           750:        jz      exit_arith
        !           751:        call    put_indefinite                  // if masked, indefinite
        !           752:        jmp     finish_up                       // otherwise, just return
        !           753:        ALIGN
        !           754: //
        !           755: //arith        endp
        !           756: //
        !           757: //a_med        ends
        !           758: //
        !           759: //     end

unix.superglobalmegacorp.com

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