Annotation of kernel/machdep/i386/fp_emul/fp_lipsq.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   "lipsq.s"
        !            26: 
        !            27:        .ident  "@(#)kern-fp:lipsq.s    1.1"
        !            28: 
        !            29: // ***************************************************************************
        !            30: //
        !            31: //                     l i p s q . 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: //     functions:
        !            43: //             implements the loading of the constants:
        !            44: //              one, log base 2 of ten, log base 2 of e, pi,
        !            45: //              log base 10 of 2, log base e of 2, and zero.
        !            46: //             implements the 80387 square root instruction.
        !            47: //             implements the 80387 integer part instruction.
        !            48: //
        !            49: //     public procedures:
        !            50: //             load_con                sqrt                    intpt
        !            51: //
        !            52: // *****************************************************************************
        !            53: //
        !            54: //...september 16, 1983...
        !            55: //
        !            56: //     .file   *a_mli*
        !            57: //
        !            58: //$nolist
        !            59: #include       "fp_e80387.h"
        !            60: //$list
        !            61:        .text   //a_med segment er      public
        !            62: //
        !            63: //     extrn   put_si_result,sticky_right_shift,round
        !            64: //     extrn   addition_normalize,left_shift,getx
        !            65: //     extrn   set_up_indefinite,clear_6w,set_6w
        !            66: //     extrn   test_4w,left_shift_result_cl
        !            67: //     extrn   left_shift_frac1_cl,left_shift_frac2_cl
        !            68: //     extrn   add_to_frac_2,gradual_underflow
        !            69: //     extrn   subtraction_normalize,put_indefinite
        !            70: //     extrn   i_masked_,set_i_masked_,set_d_masked_
        !            71: //     extrn   affine_infinity_,get_precision
        !            72: //
        !            73:        .globl  load_con
        !            74:        .globl  intpt
        !            75:        .globl  sqrt
        !            76: //
        !            77: //     temp real floating point numbers for push constant instructions
        !            78: //
        !            79: treal_table:
        !            80:        .value  0x00000,0x00000,0x00000,0x00000,0x08000,0x03fff //treal_one
        !            81:        .value  0x04000,0x08afe,0x0cd1b,0x0784b,0x0d49a,0x04000 //treal_l2t
        !            82:        .value  0x0c000,0x0f0bb,0x05c17,0x03b29,0x0b8aa,0x03fff //treal_l2e
        !            83:        .value  0x0c000,0x0c234,0x02168,0x0daa2,0x0c90f,0x04000 //treal_pi
        !            84:        .value  0x0a000,0x0f798,0x0fbcf,0x09a84,0x09a20,0x03ffd //treal_lg2
        !            85:        .value  0x0e000,0x079ab,0x0d1cf,0x017f7,0x0b172,0x03ffe //treal_ln2
        !            86:        .value  0x00000,0x00000,0x00000,0x00000,0x00000,0x00000 //treal_0
        !            87: //$eject
        !            88: // ***************************************************************
        !            89: //                     load_con
        !            90: //                     ******
        !            91: //     function:
        !            92: //             implements the load constants instructions.
        !            93: //
        !            94: //     inputs:
        !            95: //             offset of fpn pointer in bx register.
        !            96: //
        !            97: //     outputs:
        !            98: //             constant value on top of stack
        !            99: //
        !           100: //     data accessed:
        !           101: //             - offset_result
        !           102: //
        !           103: //     data changed:
        !           104: //             - mem_operand_pointer
        !           105: //
        !           106: //     procedures called:
        !           107: //             getx
        !           108: //
        !           109: // *******************************************************************
        !           110: //  all load constant instructions use the same entry point.
        !           111: //
        !           112:        ALIGN
        !           113: load_con:      //proc  near
        !           114: //
        !           115: //   the contents of bx is used as an index to treal_table.
        !           116: //   getx unpacks the extended floating point number and put_result
        !           117: //   pushes the value to the top of the 80387 stack.
        !           118: //
        !           119:        shrb    $1,%bl                          //take care of extra shi
        !           120:        mov     $0x06,%eax                              //treal_table ptr = cs:
        !           121:        mulb    %bl                             // index * 6 - (6 * 2)
        !           122:        add     $(treal_table-(load_1_op*12)),%eax // * (load_1_op)
        !           123:        mov     %eax, %esi
        !           124:        movl    $0, result_dword_frac(%ebp)
        !           125:        movw    %cs:(%esi), %ax
        !           126:        movw    %ax, result_dword_frac+frac80(%ebp)
        !           127:        mov     %cs:2(%esi), %eax
        !           128:        mov     %eax, result_dword_frac+frac64(%ebp)
        !           129:        mov     %cs:6(%esi), %eax
        !           130:        mov     %eax, result_dword_frac+frac32(%ebp)
        !           131:        movzwl  %cs:10(%esi), %eax
        !           132:        mov     %eax, dword_result_expon
        !           133:        xor     %eax, %eax
        !           134:        mov     %eax, result_sign(%ebp)
        !           135:        movb    prec64, %dl
        !           136:        mov     $offset_result, %edi
        !           137:        call    round
        !           138:        mov     $offset_result, %edi
        !           139:        call    addition_normalize
        !           140:        andb    $~a_mask, %gs:sr_flags
        !           141:        xor     %eax, %eax
        !           142:        mov     before_error_signals(%ebp), %eax
        !           143:        lahf
        !           144:        mov     $offset_result, %edi
        !           145:        jmp     put_si_result
        !           146: //load_con     endp
        !           147: //$eject
        !           148: // ***********************************************************************
        !           149: //                     intpt:
        !           150: //                     *****
        !           151: //     function:
        !           152: //             implements 80387 integer part instruction
        !           153: //
        !           154: //     inputs:
        !           155: //
        !           156: //     outputs:
        !           157: //
        !           158: //     data accessed:
        !           159: //             - offset_result                 offset_operand1
        !           160: //             - tag1                          expon1
        !           161: //             - word_frac1
        !           162: //
        !           163: //     data changed:
        !           164: //             - tag1                          expon1
        !           165: //             - result
        !           166: //
        !           167: //     procedures called:
        !           168: //             get_operand                     gradual_underflow
        !           169: //             round                           subtraction_normalize
        !           170: //             put_si_result                   test_4w
        !           171: //             i_masked?                       set_i_masked?
        !           172: //             set_d_masked?
        !           173: //
        !           174: // **************************************************************************
        !           175:        ALIGN
        !           176: intpt: //proc
        !           177: //     movb    true,%ah                        / load constant
        !           178:        jz      separate_cases          // branch if no stack error
        !           179:        call    set_stk_u_error         
        !           180:        testb   invalid_mask, %gs:sr_masks
        !           181:        jz      intpt_done
        !           182:        jmp     put_op1_result          //math stack error, so return indef
        !           183:        ALIGN
        !           184: separate_cases:
        !           185:        andb    $~a_mask, %gs:sr_flags //initialize a-bit to zero
        !           186:        movb    tag1(%ebp), %al         // load op1 tag
        !           187:        cmpb    valid,%al
        !           188:        je      valid_case
        !           189:        cmpb    denormd,%al
        !           190:        je      denormalized_operand
        !           191:        cmpb    unsupp,%al
        !           192:        jne     check_nan
        !           193:        movl    $offset_operand1, %edi
        !           194:        call    set_up_indefinite
        !           195: set_i_err:
        !           196:        orb     invalid_mask, %gs:sr_errors
        !           197:        testb   invalid_mask, %gs:sr_masks
        !           198:        jz      intpt_done
        !           199:        jmp     put_op1_result  // masked_i error so return indef
        !           200:        ALIGN
        !           201: intpt_done:
        !           202:        ret
        !           203:        ALIGN
        !           204: check_nan:
        !           205:        cmpb    inv, %al
        !           206:        je      kind_of_nan_    
        !           207:        jmp     put_op1_result  //infinity or zero, same answer
        !           208:        ALIGN
        !           209: kind_of_nan_:
        !           210:        testb   $0x40, msb_frac1
        !           211:        jz      make_qnan
        !           212:        jmp     put_op1_result  // op1 is a qnan so pass it through
        !           213:        ALIGN
        !           214: make_qnan:
        !           215:        orb     $0x40, msb_frac1 //op1 is an snan so make it a qnan
        !           216:        jmp     set_i_err       //and signal i_error
        !           217:        ALIGN
        !           218: denormalized_operand:
        !           219:        orb     denorm_mask, %gs:sr_errors
        !           220:        testb   denorm_mask, %gs:sr_masks
        !           221:        jz      intpt_done
        !           222:        movw    $0x0001,expon1(%ebp)    //if masked d-error, make valid
        !           223:        movb    valid,tag1(%ebp)
        !           224: valid_case:
        !           225:        movl    $0x403e,%eax
        !           226:        cmpl    %eax,dword_expon1 //if expon >=63, then number
        !           227:        jge     give_op1                // is already an integer
        !           228:        mov     $offset_operand1,%edi   //gradual uflow until expon=63
        !           229:        push    %edi
        !           230:        call    gradual_underflow
        !           231:        pop     %edi                    //round to precision 64
        !           232:        movb    prec64,%dl
        !           233:        movb    false,%al
        !           234:        call    round
        !           235:        cmpb    true, rnd1_inexact
        !           236:        jne     detect_zero
        !           237:        orb     $inexact_mask, %gs:sr_errors
        !           238:        cmpb    true,added_one
        !           239:        jne     detect_zero
        !           240:        orb     $a_mask, %gs:sr_flags
        !           241: detect_zero:
        !           242:        xor     %eax,%eax
        !           243:        movl    $dword_frac1+4,%edi //if fraction = 0, result = 0
        !           244:        call    test_4w
        !           245:        jz      zero_result
        !           246:        mov     $offset_operand1,%edi   //normalize
        !           247:        call    subtraction_normalize
        !           248:        jmp     put_op1_result
        !           249:        ALIGN
        !           250: zero_result:
        !           251:        movl    %eax,dword_expon1               //set result to true zero
        !           252:        movb    special,tag1(%ebp)
        !           253: give_op1:
        !           254:        jmp     put_op1_result
        !           255: //intpt        endp
        !           256: //$eject
        !           257: // ***************************************************************************
        !           258: //                     sqrtx:
        !           259: //
        !           260: //     function:
        !           261: //              fractional square root routine.
        !           262: //
        !           263: //     inputs:
        !           264: //             assumes valid, non-zero,positive, normalized
        !           265: //             fraction is in frac1.
        !           266: //
        !           267: //     outputs
        !           268: //             leaves fractional square root in result.
        !           269: //
        !           270: //     data accessed:
        !           271: //             - offset_operand1               lsb_frac1
        !           272: //             - offset_operand2               word_frac2
        !           273: //             - offset_result                 lsb_frac2
        !           274: //             - result_word_frac              lsb_result
        !           275: //             - msb_frac1
        !           276: //
        !           277: //     data changed:
        !           278: //             - word_frac2                    lsb_frac2
        !           279: //             - result_word_frac              lsb_result
        !           280: //
        !           281: //     procedures called:
        !           282: //             left_shift_result_cl            left_shift_frac1_cl
        !           283: //             left_shift_frac2_cl             clear_6w
        !           284: //             set_6w                          add_to_frac_2
        !           285: //
        !           286: // ***********************************************************************
        !           287:        ALIGN
        !           288: sqrtx: //proc
        !           289:        movl    $result_dword_frac,%edi //during this computation,
        !           290:        call    clear_6w                //the lsb of the result will
        !           291:        mov     $dword_frac2,%edi       // hold g and s, and the msb
        !           292:        call    set_6w                  // will hold carry-out bits
        !           293:        and     $0x000000ff,%ecx                //clear high word
        !           294:        stc                             //cf holds the quotient bit
        !           295:        push    $65                     // iterate 65 times
        !           296:        pushf                           // stack the quotient bit
        !           297:        jmp     enter_sqrt_loop
        !           298:        ALIGN
        !           299: sqrt_loop:
        !           300:        push    %ecx
        !           301:        pushf                           // stack the q_bit
        !           302:        movb    $1,%cl
        !           303:        call    left_shift_result_cl    //shift result left one bit
        !           304:        popf                            // inject the new q_bit into
        !           305:        pushf                           // the least significant byte
        !           306:        adcb    %cl,%cl
        !           307:        orb     %cl,1+lsb_result
        !           308:        movb    $2,%cl                  // into the lsb
        !           309:        call    left_shift_frac2_cl     //shift frac2 left 2 bits
        !           310: enter_sqrt_loop:
        !           311:        movb    msb_frac1,%al           //g and s bits of frac2 <--
        !           312:        andb    $0x0c0,%al                      // top 2 bits of frac1
        !           313:        movb    %al,lsb_frac2
        !           314:        movb    $2,%cl                  // shift frac1 left 2
        !           315:        call    left_shift_frac1_cl
        !           316:        movb    $0x0c0,%al
        !           317:        movb    1+lsb_result,%ah
        !           318:        popf                            //test q_bit
        !           319:        jc      q_bit_set
        !           320:        shl     $16,%eax
        !           321:        call    add_to_frac2            //frac2.gs <-- frac2.gs +
        !           322:        jmp     set_q_bit               //result.11
        !           323: q_bit_set:
        !           324:        notb    %ah                     //frac2.gs <-- frac2.gs +
        !           325:        shl     $16,%eax                        //take care of extra low word
        !           326:        add     %eax,dword_frac2(%ebp)  //not(result).11
        !           327:        mov     result_dword_frac+frac64(%ebp),%eax
        !           328:        not     %eax
        !           329:        adc     %eax,dword_frac2+frac64(%ebp)
        !           330:        mov     result_dword_frac+frac32(%ebp),%eax
        !           331:        not     %eax
        !           332:        adc     %eax,dword_frac2+frac32(%ebp)
        !           333: set_q_bit:
        !           334:        pop     %ecx                    // reload loop count
        !           335:        loop    sqrt_loop               // loop until done
        !           336:        rcrb    $1,%cl                  // set g bit of result to q_bit
        !           337:        orb     %cl,lsb_result
        !           338:        movw    result_word_frac,%ax    //frac2 <- frac2 +
        !           339:        incb    %ah                     // result + 1
        !           340:        shl     $16,%eax
        !           341:        call    add_to_frac2
        !           342:        mov     $dword_frac2+frac64,%edi //if frac2 = 0 then
        !           343:        xor     %eax,%eax                       //s_bit of result = 0,
        !           344:        call    test_4w                 //otherwise 1.
        !           345:        orb     1+lsb_frac2,%al
        !           346:        jz      left_adjust_result
        !           347:        orb     $0x40,lsb_result
        !           348: left_adjust_result:
        !           349:        movb    $8,%cl                  //shift result left 8 bits
        !           350:        jmp     left_shift_result_cl    // to eliminate carry
        !           351: add_to_frac2:
        !           352:        mov     $result_dword_frac,%esi // si points to the addend
        !           353:        mov     $dword_frac2,%edi       // di points to the result
        !           354:        jmp     add_to_frac_2           // add result frac to frac2
        !           355: //sqrtx        endp
        !           356: //$eject
        !           357: // ***********************************************************************
        !           358: //                     sqrt:
        !           359: //
        !           360: //     function:
        !           361: //             implements the 80387 sqrt instruction
        !           362: //
        !           363: //     inputs:
        !           364: //             assume op1 is set up
        !           365: //
        !           366: //     outputs:
        !           367: //             result
        !           368: //
        !           369: //     data accessed:
        !           370: //             - result_record_offset          result_expon
        !           371: //             - offset_operand1               tag1
        !           372: //             - sign1                         expon1
        !           373: //             - msb_frac1                     offset_operand1
        !           374: //             - offset_result                 result_sign
        !           375: //             - result_tag
        !           376: //
        !           377: //     data changed:
        !           378: //             - expon1                        result_sign
        !           379: //             - result_tag                    result_expon
        !           380: //
        !           381: //     procedures called:
        !           382: //             set_up_indefinite               sticky_right_shift
        !           383: //             sqrtx                           round
        !           384: //             addition_normalize              affine_infinity?
        !           385: //             set_i_masked?                   get_precision
        !           386: //             set_d_masked?                   put_si_result
        !           387: //
        !           388: // ***********************************************************************
        !           389:        ALIGN
        !           390: sqrt:  //proc
        !           391:        jz      sqrt_cont               // if stack error, sqrt done
        !           392:        call    set_stk_u_error
        !           393:        testb   invalid_mask, %gs:sr_masks
        !           394:        jnz     put_op1         //masked stack error, so return indef
        !           395: sqrt_done:
        !           396:        ret
        !           397:        ALIGN
        !           398: sqrt_cont:
        !           399:        andb    $~a_mask, %gs:sr_flags
        !           400:        movb    tag1(%ebp),%al          // load tag for op1
        !           401:        cmpb    valid,%al
        !           402:        jne     op1_denorm_
        !           403:        cmpb    positive, sign1(%ebp)
        !           404:        jne     i_error
        !           405:        jmp     sqrt_valid_case
        !           406: op1_denorm_:
        !           407:        cmpb    denormd,%al             //if op1 denormalized, then give
        !           408:        jne     op1_zero_
        !           409:        cmpb    positive, sign1(%ebp)
        !           410:        jne     i_error
        !           411:        jmp     d_error
        !           412: op1_zero_:
        !           413:        cmpb    special,%al             //if op1 = 0, then give 0 as the
        !           414:        je      put_op1                 //result
        !           415:        cmpb    unsupp,%al                      
        !           416:        je      i_error
        !           417:        cmpb    inv,%al                 //if op1 inv, then give i_error
        !           418:        jne     inf_op1
        !           419:        jmp     kind_of_nan_
        !           420: inf_op1:
        !           421:        cmpb    positive, sign1(%ebp)   //infinity case
        !           422:        je      put_op1                 // -infinity is invalid
        !           423: i_error:
        !           424:        call    set_i_masked_           //denormalized, unnormalized,
        !           425:        jz      sqrt_done               // negative, or proj +infinity
        !           426:        mov     $offset_result,%edi
        !           427:        call    set_up_indefinite       //if masked i_error, then give
        !           428:        jmp     sqrt_give_result        //indefinite
        !           429: put_op1:                                       //if op1 = zero, nan, or +inf,
        !           430:        jmp     give_op1                // then give op1 as the result
        !           431: d_error:
        !           432:        call    set_d_masked_           //op1 is denormalized
        !           433:        jz      sqrt_done
        !           434:        movl    $offset_operand1, %edi
        !           435:        call    norm_denorm             //if d_error masked, make valid
        !           436: sqrt_valid_case:
        !           437:        subl    $exponent_bias,dword_expon1
        !           438:        testl   $0x0001,dword_expon1
        !           439:        jz      even_expon
        !           440:        decl    dword_expon1    //if expon1 odd, then expon1 <--
        !           441:        jmp     halve_exponent  // expon1 - 1
        !           442: even_expon:
        !           443:        movb    $1,%cl                  //if expon1 even, then shift
        !           444:        xorb    %al,%al                 // frac1 right one bit
        !           445:        mov     $offset_operand1,%edi
        !           446:        call    sticky_right_shift
        !           447: halve_exponent:
        !           448:        movl    dword_expon1,%eax
        !           449:        sarl    $1,%eax
        !           450:        addl    $exponent_bias,%eax
        !           451:        movl    %eax,dword_result_expon
        !           452:        call    sqrtx                   // calculate fraction
        !           453: sqrt_round_result:
        !           454:        xorl    %eax,%eax                       // not second rounding
        !           455:        movl    %eax,result_sign(%ebp) // set sign and tag
        !           456:        movl    $offset_result,%edi     // round result
        !           457:        call    get_precision
        !           458:        call    round
        !           459:        mov     $offset_result,%edi
        !           460:        call    addition_normalize      //(possible renormalize)
        !           461:        cmpb    true, rnd1_inexact
        !           462:        jne     sqrt_give_result
        !           463:        orb     $inexact_mask, %gs:sr_errors
        !           464:        cmpb    true, added_one
        !           465:        jne     sqrt_give_result
        !           466:        orb     $a_mask, %gs:sr_flags
        !           467: sqrt_give_result:
        !           468:        mov     $offset_result,%edi
        !           469:        jmp     put_si_result
        !           470: //sqrt endp
        !           471: //
        !           472: //a_med        ends
        !           473: //
        !           474: //     end

unix.superglobalmegacorp.com

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