Annotation of kernel/machdep/i386/fp_emul/fp_arith.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   "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.