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

unix.superglobalmegacorp.com

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