Annotation of kernel/machdep/i386/fp_emul/fp_remsc.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   "remsc.s"
                     26: 
                     27:        .ident  "@(#)kern-fp:remsc.s    1.1"
                     28: 
                     29: // ********************************************************************
                     30: //
                     31: //                     r e m s c . 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 80387 fprem  instruction.
                     44: //             implements 80387 fprem1 instruction.
                     45: //             implements 80387 fscale instruction.
                     46: //
                     47: //     public procedures:
                     48: //             remr                    scale
                     49: //             add_to_frac             add_to_frac_2
                     50: //
                     51: //     internal procedures:
                     52: //             remrx
                     53: //
                     54: // ************************************************************************
                     55: //
                     56: //...March 3, 1987...
                     57: //
                     58: //
                     59: //$nolist
                     60: #include       "fp_e80387.h"
                     61: //$list
                     62:        .data   //a_msr segment rw      public
                     63: //     extrn   %gs:sr_masks,%gs:sr_flags,%gs:sr_errors,%gs:sr_controls
                     64: //a_msr        ends
                     65: //
                     66: //     assume  %ds:a_msr
                     67: //
                     68:        .text   //a_med segment er      public
                     69: //
                     70: //     extrn   put_result,set_up_indefinite,test_4w
                     71: //     extrn   subtraction_normalize,move_op_to_result
                     72: //     extrn   underflow_response,right_shift_frac1_cl
                     73: //     extrn   right_shift_frac2_cl,left_shift_frac1_1
                     74: //     extrn   fix32,overflow_response,set_stk_u_error
                     75: //     extrn   subadd,put_arith_result,set_up_nan_return
                     76: //     extrn   test_6w,clear_6w,norm_denorm
                     77: //     extrn   left_shift_frac2_cl
                     78:        .globl  remr
                     79:        .globl  add_to_frac
                     80:        .globl  add_to_frac_2
                     81:        .globl  scale
                     82:        .globl  remrx
                     83: //
                     84: // ***************************************************************************
                     85: //                     remrx:
                     86: //                     ******
                     87: //     function:
                     88: //              fractional remainder.
                     89: //
                     90: //     inputs:
                     91: //             assumes dividend is in op1, divisor is in op2,
                     92: //             number of quotient bits to generate is in ax,
                     93: //             and q is cleared to all zeroes.
                     94: //
                     95: //     outputs:
                     96: //             it returns the fractional remainder in op1, and
                     97: //             the low bits of the quotient in q.
                     98: //
                     99: //     data accessed:
                    100: //             - offset_operand1               offset_operand2
                    101: //             - offset_result
                    102: //
                    103: //     data changed:
                    104: //             - frac1                 frac2
                    105: //
                    106: //     procedures called:
                    107: //             right_shift_frac1_cl    right_shift_frac2_cl
                    108: //             left_shift_frac1_1              add_to_frac             
                    109: //
                    110: // ************************************************************************
                    111:        ALIGN
                    112: remrx: //proc
                    113:        push    %eax                            // save the loop count
                    114:        movb    $1,%cl                  // shift frac1 right 1 bit
                    115:        call    right_shift_frac1_cl
                    116:        movb    $1,%cl                  // shift frac2 right 1 bit
                    117:        call    right_shift_frac2_cl            // returns cf clear, ch = 0
                    118:        mov     $offset_operand2,%esi           // result_frac <--  - frac2
                    119:        mov     $offset_result,%edi
                    120:        movw    $0,(%ebp,%esi)  // clear extra bytes
                    121:        mov     $0x03,%ecx                      // load loop count
                    122:        FALLSTHRU
                    123: complement_frac2:
                    124:        mov     $0x0000,%eax                            // clear ax, leave cf intact
                    125:        sbb     (%ebp,%esi),%eax                        // 0 - frac2
                    126:        mov     %eax,(%ebp,%edi)                        // store into result frac
                    127:        inc     %esi                                            // bump offsets
                    128:        inc     %esi                                    // (doesnt affect cf)
                    129:        inc     %esi
                    130:        inc     %esi
                    131:        inc     %edi
                    132:        inc     %edi
                    133:        inc     %edi
                    134:        inc     %edi
                    135:        LOOP(complement_frac2)          // loop until result = -frac2
                    136:        jmp     enter_loop
                    137:        ALIGN
                    138: form_next_frac1:
                    139:        push    %ecx                                    // stack loop count
                    140:        call    left_shift_frac1_1              // shift frac1 left one bit
                    141:        mov     $offset_operand2,%esi
                    142:        testb   $0x01,q                                 // if lsb of q = 1 then
                    143:        jz      do_add                          // frac1 <-- frac1 + frac2
                    144: enter_loop:
                    145:        mov     $offset_result,%esi             // else, frac1 <-- frac1 - frac2
                    146: do_add:
                    147:        mov     $offset_operand1,%edi
                    148:        call    add_to_frac                     // move carry-out from add
                    149:        rclb    $1,q                            // shift carry-out into q
                    150: //     adc     hi_q,   0               ; hi_q counts non-0 quotient bits
                    151:        pop     %ecx                    // above bit b7 of the quotient.
                    152:        LOOP(form_next_frac1)           // if looping done,
                    153:        testb   $0x01,q                         // then one last iteration
                    154:        jnz     last_shift                      // frac1 <-- frac1 + frac2
                    155:        mov     $offset_operand2,%esi
                    156:        mov     $offset_operand1,%edi
                    157:        call    add_to_frac
                    158: last_shift:
                    159:        jmp     left_shift_frac1_1              // shift frac1 left 1 bit
                    160: //remrx        endp
                    161: //
                    162: // **************************************************************************
                    163: //                     add_to_frac:
                    164: //                     ***********
                    165: //     function:
                    166: //             adds a 10-byte fraction to another 10-byte fraction.
                    167: //
                    168: //     inputs:
                    169: //             ss:ebp+esi points to the source fraction, and ss:ebp+edi points
                    170: //             to the destination fraction.
                    171: //
                    172: //     outputs:
                    173: //             carry flag set if there was a carry out, else reset.
                    174: //
                    175: //     data accessed:
                    176: //
                    177: //     data changed:
                    178: //
                    179: // ***************************************************************************
                    180:        ALIGN
                    181: add_to_frac:   //proc
                    182:        mov     (%ebp,%esi),%eax
                    183:        xorw    %ax,%ax
                    184: add_to_frac_2:
                    185:        add     %eax,(%ebp,%edi)
                    186:        mov     frac64(%ebp,%esi),%eax
                    187:        adc     %eax,frac64(%ebp,%edi)
                    188:        mov     frac32(%ebp,%esi),%eax
                    189:        adc     %eax,frac32(%ebp,%edi)
                    190: simple_return:
                    191:        ret
                    192:        ALIGN
                    193: //add_to_frac  endp
                    194: // *************************************************************************
                    195:        ALIGN
                    196: mov_esi_edi:   //proc
                    197:        add     %ebp, %edi      //add global record offsets
                    198:        add     %ebp, %esi
                    199: //     push    %ds     //save a_msr ??
                    200: //     push    %ss     //load source segment register
                    201: //     pop     %ds
                    202: //     push    %ss     //load destination segment register
                    203: //     pop     %es     //into es
                    204: 
                    205:        /* FAST_MOVSL */
                    206:        movl    %ss:0(%esi),%ecx
                    207:        movl    %ecx,%ss:0(%esi)
                    208:        movl    %ss:4(%esi),%ecx
                    209:        movl    %ecx,%ss:4(%esi)
                    210:        movl    %ss:8(%esi),%ecx
                    211:        movl    %ecx,%ss:8(%esi)
                    212: //     addl    $12,%esi
                    213: //     addl    $12,%edi
                    214: //     movl    $0,%ecx
                    215: 
                    216: //     pop     %ds     //reload a_msr
                    217:        ret
                    218: //mov_esi_edi  endp
                    219: // *************************************************************************
                    220: 
                    221: 
                    222: //
                    223: // ***************************************************************************
                    224: //                     remr:
                    225: //                     *****
                    226: //     function:
                    227: //             80387 remainder instruction
                    228: //
                    229: //     inputs:
                    230: //             assumes the operand records are set up.
                    231: //
                    232: //     outputs:
                    233: //             results in result record.
                    234: //
                    235: //     data accessed:
                    236: //             - result_rec_offset             offset_operand1
                    237: //             - tag1                          expon1
                    238: //             - word_frac1                    tag2
                    239: //             - expon2                        msb_frac2
                    240: //             - offset_result
                    241: //
                    242: //     data changed:
                    243: //             - tag1                          expon1
                    244: //
                    245: //     procedures called:
                    246: //             set_up_indefinite       set_stk_u_error
                    247: //             remrx                           subtraction_normalize
                    248: //             move_op_to_result       underflow_response
                    249: //             put_result                      test_4w
                    250: //             subadd                          mov_esi_edi
                    251: //
                    252: // ***************************************************************************
                    253:        ALIGN
                    254: remr:  //proc
                    255:        lahf                            // save stack empty flag (86 z-flag)
                    256:        andb    $~(a_mask+c_mask),%gs:sr_flags// clear 87 a-flag, and also
                    257:                                        // c-flag for 387 compatibility
                    258:        movw    $0,exp_tmp              // initialize q and hi_q to 0.
                    259:        sahf                            // restore stack empty flag (86 z-flag)
                    260:        jz      catch_special_cases             // branch if no stack error
                    261:        call    set_stk_u_error                 // stack underflow occurred
                    262:        jmp     unmasked_i_error_
                    263:        ALIGN
                    264: catch_special_cases:
                    265:        movb    tag1(%ebp),%al          // both operands valid?
                    266:        orb     tag2(%ebp),%al
                    267:        jnz     special_cases_handler   // no, branch to handler of special cases
                    268: valid_case:
                    269:        mov     dword_expon1,%eax       // eax <- expon_diff = exp1 - exp2
                    270:        sub     dword_expon2,%eax               // if expon_diff < zero,
                    271:        mov     $offset_operand1,%edi           // then op1 is the modulus
                    272:        jl      rem_or_mod_
                    273:        cmp     $63,%eax                        // if expon_diff > 63,
                    274:        jle     calc_exponent                   // then set c-bit for incomplete
                    275:        orb     $c_mask,%gs:sr_flags    // reduction and replace expon_diff
                    276:        or      $32,%eax                // by ((expon_diff or 32) mod 64)
                    277:        and     $63,%eax
                    278: calc_exponent:
                    279:        sub     %eax,dword_expon1               // expon1 <- remainder exponent
                    280:        inc     %eax                    // num_quotient_bits = expon_diff + 1
                    281:        call    remrx                   // calculate remainder fraction
                    282:        xor     %eax,%eax                       // detect zero result
                    283:        mov     $dword_frac1+frac64,%edi
                    284:        call    test_4w
                    285:        jnz     do_normalize
                    286:        testb   $c_mask,%gs:sr_flags            // was reduction complete?
                    287:        jz      remr_zero                       // if so, process q as well
                    288:        movb    %al,q                   // else, make q 0 (value of al)
                    289:        jmp     remr_zero
                    290:        ALIGN
                    291: do_normalize:
                    292:        mov     $offset_operand1,%edi
                    293:        call    subtraction_normalize
                    294: //     mov     (ebp).tag1,     valid   ; unneeded if denormals retagged
                    295: reduction_incomplete_:
                    296:        testb   $c_mask,%gs:sr_flags
                    297:        jz      rem_or_mod_     // rem or mod matters only if complete
                    298:        movb    $0,q                    // if incomplete, make q 0.
                    299:        jmp     check_rem_underflow     // branch to check unmasked underflow
                    300:        ALIGN
                    301: rem_or_mod_:
                    302:        lahf                    //save zf to indicate whether 
                    303:                                //op2 needs restoration
                    304:        cmpb    $rem1_op,operation_type(%ebp)
                    305:        jne     check_rem_underflow
                    306:        sahf            
                    307:        jnz     op2_restored
                    308:        movb    $1, %cl
                    309:        call    left_shift_frac2_cl
                    310: op2_restored:
                    311:        
                    312:        decl    dword_expon2
                    313:        push    sign1(%ebp)
                    314:        movb    positive,sign2(%ebp)
                    315:        movb    positive,sign1(%ebp)
                    316:        movb    $sub_op,operation_type(%ebp)
                    317:        mov     dword_expon1, %eax
                    318:        cmp     dword_expon2, %eax
                    319:        mov     $offset_operand1, %esi
                    320:        jle     save_shiftable_op
                    321:        mov     $offset_operand2, %esi
                    322: save_shiftable_op:
                    323:        mov     $offset_cop, %edi
                    324:        call    mov_esi_edi
                    325:        call    subadd
                    326:        mov     $offset_result,%edi
                    327:        call    test_6w
                    328:        pop     sign1(%ebp)
                    329:        mov     $offset_operand1, %edi
                    330:        jnz     check_sign
                    331: tiebreaker:
                    332:        testb   $1,q
                    333:        jz      check_rem_underflow
                    334:        incb    q
                    335:        notb    sign1(%ebp)
                    336:        jmp     check_rem_underflow
                    337:        ALIGN
                    338: check_sign:
                    339:        mov     $offset_cop, %esi
                    340:        cmpb    positive,result_sign(%ebp)
                    341:        je      restore_op2_
                    342:        call    mov_esi_edi
                    343:        mov     $offset_operand1, %edi
                    344:        jmp     check_rem_underflow
                    345:        ALIGN
                    346: restore_op2_:
                    347:        mov     dword_expon1, %eax
                    348:        cmp     dword_expon2, %eax
                    349:        je      reduce_modulus
                    350:        mov     $offset_operand2, %edi
                    351:        call    mov_esi_edi
                    352: reduce_modulus:
                    353:        incb    q
                    354:        incl    dword_expon2
                    355:        movb    sign1(%ebp),%al
                    356:        movb    %al,sign2(%ebp)
                    357:        call    subadd
                    358:        mov     $offset_result,%edi
                    359: check_rem_underflow:
                    360:        cmp     $0x0001,expon(%ebp,%edi)        // if expon1 < 1, then underflow
                    361:        jge     do_put_result
                    362:        mov     %edi,%esi                       // give std underflow response
                    363:        call    move_op_to_result
                    364:        push    %gs:sr_masks
                    365:        orb     prec64,%gs:sr_controls          // *or* works only because prec64
                    366:        movb    false,rnd1_inexact              // sets all bits in the pc field
                    367:        call    underflow_response
                    368:        pop     %gs:sr_masks
                    369: move_result_to_result:
                    370:        mov     $offset_result,%edi
                    371:        jmp     do_put_result
                    372:        ALIGN
                    373: remr_zero:
                    374:        mov     %eax,dword_expon1               // if remainder fraction = 0,
                    375:        movb    special,tag1(%ebp)                      // then set result to 0
                    376:        cmpb    $rem1_op,operation_type(%ebp)
                    377:        jne     put_op1
                    378:        movb    positive,sign1(%ebp)
                    379:        testb   rnd_down,%gs:sr_controls
                    380:        jz      put_op1
                    381:        testb   rnd_up,%gs:sr_controls
                    382:        jnz     put_op1
                    383:        movb    negative,sign1(%ebp)
                    384: put_op1:
                    385:        mov     $offset_operand1,%edi
                    386: do_put_result:
                    387:        mov     offset_result_rec,%esi
                    388:        call    put_result
                    389:        andb    $~(zero_mask+a_mask+sign_mask),%gs:sr_flags
                    390:        movb    q,%al
                    391:        shlb    $6,%al                  // move 3 low bits of q to
                    392:        jnc     fix_z_bit               // s, z, and a bits
                    393:        orb     $sign_mask,%gs:sr_flags
                    394: fix_z_bit:
                    395:        shlb    $1,%al
                    396:        jnc     fix_a_bit
                    397:        orb     $zero_mask,%gs:sr_flags
                    398: fix_a_bit:
                    399:        shlb    $1,%al
                    400:        jnc     remr_done
                    401:        orb     $a_mask,%gs:sr_flags
                    402: remr_done:
                    403:        ret
                    404:        ALIGN
                    405: special_cases_handler:
                    406:        testb   $0x10,%al       // al contains (ebp).tag1 or (ebp).tag2
                    407:        jz      op1_nan_        // no branch if at least one op unsupported
                    408: invalid_operand:
                    409:        orb     invalid_mask,%gs:sr_errors
                    410: unmasked_i_error_:
                    411:        testb   invalid_mask,%gs:sr_masks// if unmasked, just exit
                    412:        jz      remr_done               // (c-bit remains clear here,
                    413:                                        // to indicate complete reduction.)
                    414:                                        // else, return indefinite
                    415: remr_indef:
                    416:        mov     $offset_operand1,%edi
                    417:        call    set_up_indefinite
                    418: load_esi_for_result:
                    419:        mov     offset_result_rec,%esi
                    420:        jmp     put_arith_result
                    421:        ALIGN
                    422: op1_nan_:                      // here, neither op is unsupported.
                    423:        movb    tag2(%ebp),%al
                    424:        movb    tag1(%ebp),%ah
                    425:        cmpb    inv,%ah
                    426:        je      op1_snan_
                    427:        cmpb    inv,%al
                    428:        jne     non_nan_supp_ops
                    429:        jmp     signal_invalid_
                    430:        ALIGN
                    431: op1_snan_:
                    432:        testb   $0x40,msb_frac1
                    433:        jz      signal_for_snan
                    434: op2_also_nan_:
                    435:        cmpb    inv,%al
                    436:        jne     jmp_set_up_nan_return
                    437: signal_invalid_:
                    438:        testb   $0x40,msb_frac2
                    439:        jnz     jmp_set_up_nan_return
                    440: signal_for_snan:
                    441:        orb     invalid_mask,%gs:sr_errors// set i-error for signaling nan operand
                    442:        testb   invalid_mask,%gs:sr_masks// if unmasked, return forthwith
                    443:        jz      remr_done                               // else, masked, so return max nan.
                    444: jmp_set_up_nan_return:
                    445:        jmp     set_up_nan_return
                    446:        ALIGN
                    447: non_nan_supp_ops:
                    448:        cmpb    $scale_op,operation_type(%ebp)
                    449:        je      scale_non_nan_supp_ops
                    450: rem_non_nan_supp_ops:
                    451:        cmpb    infinty,%ah
                    452:        je      invalid_operand
                    453:        cmpb    special,%al
                    454:        je      invalid_operand
                    455:        cmpb    denormd,%ah
                    456:        jne     op2_denorm_
                    457:        orb     denorm_mask,%gs:sr_errors
                    458:        testb   denorm_mask,%gs:sr_masks
                    459:        jz      remr_done
                    460:        mov     $offset_operand1,%edi
                    461:        cmpb    infinty,%al
                    462:        jne     norm_op1
                    463:        testb   $0x80,msb_frac1
                    464:        jz      op1_true_denormal
                    465:        movl    $1,dword_expon1
                    466:        movb    valid,tag1(%ebp)
                    467:        jmp     load_esi_for_result
                    468:        ALIGN
                    469: op1_true_denormal:
                    470:        testb   underflow_mask,%gs:sr_masks
                    471:        jnz     load_esi_for_result
                    472:        call    norm_denorm
                    473:        addl    wrap_around_constant,dword_expon1// add wrap-around
                    474:        orb     underflow_mask,%gs:sr_errors
                    475:        jmp     load_esi_for_result
                    476:        ALIGN
                    477: norm_op1:
                    478:        push    %eax
                    479:        call    norm_denorm
                    480:        pop     %eax
                    481: op2_denorm_:
                    482:        cmpb    denormd,%al
                    483:        jne     non_error_specials
                    484:        orb     denorm_mask,%gs:sr_errors
                    485:        testb   denorm_mask,%gs:sr_masks
                    486:        jz      remr_done
                    487:        mov     $offset_operand2,%edi
                    488:        push    %eax
                    489:        call    norm_denorm
                    490:        pop     %eax
                    491: non_error_specials:
                    492:        cmpb    special,%ah
                    493:        je      put_op1
                    494: op2_inf_:
                    495:        cmpb    infinty,%al
                    496:        je      put_op1
                    497:        jmp     valid_case
                    498:        ALIGN
                    499: //
                    500: scale_non_nan_supp_ops:
                    501:        cmpb    infinty,%ah
                    502:        jne     scaler_denormd_
                    503:        cmpb    positive,sign1(%ebp)
                    504:        jne     op2_also_inf_
                    505:        cmpb    special,%al
                    506:        je      invalid_operand
                    507:        cmpb    denormd,%al
                    508:        jne     xfer_sign
                    509:        orb     denorm_mask,%gs:sr_errors
                    510:        testb   denorm_mask,%gs:sr_masks
                    511:        jz      exit_scale
                    512: xfer_sign:
                    513:        movb    sign2(%ebp),%al
                    514:        movb    %al,sign1(%ebp)
                    515:        mov     $offset_operand1,%edi
                    516:        jmp     put_scaled_result
                    517:        ALIGN
                    518: op2_also_inf_:
                    519:        cmpb    infinty,%al
                    520:        je      invalid_operand
                    521:        cmpb    denormd,%al
                    522:        jne     zero_op2
                    523:        orb     denorm_mask,%gs:sr_errors
                    524:        testb   denorm_mask,%gs:sr_masks
                    525:        jz      exit_scale
                    526: zero_op2:
                    527:        mov     $offset_operand2,%edi
                    528:        call    clear_6w
                    529:        mov     %eax,dword_expon2               // clear eax
                    530:        movb    special,tag2(%ebp)
                    531:        jmp     put_scaled_result
                    532:        ALIGN
                    533: scaler_denormd_:
                    534:        cmpb    denormd,%ah
                    535:        jne     scalend_denormd_
                    536:        orb     denorm_mask,%gs:sr_errors
                    537:        testb   denorm_mask,%gs:sr_masks
                    538:        jnz     scalend_denormd_
                    539: exit_scale:
                    540:        ret
                    541:        ALIGN
                    542: scalend_denormd_:
                    543:        cmpb    denormd,%al
                    544:        jne     give_op2
                    545:        orb     denorm_mask, %gs:sr_errors
                    546:        testb   denorm_mask, %gs:sr_masks
                    547:        jz      exit_scale
                    548:        cmpb    valid,%ah
                    549:        jne     check_unfl_mask
                    550:        mov     $offset_operand2,%edi
                    551:        call    norm_denorm
                    552:        jmp     valid_scale_case
                    553:        ALIGN
                    554: check_unfl_mask:
                    555:        testb   underflow_mask,%gs:sr_masks
                    556:        jnz     give_op2
                    557:        jmp     scale_underflow
                    558: 
                    559: //remr endp
                    560: //
                    561: //
                    562: // **********************************************************************
                    563: //                     scale:
                    564: //                     ******
                    565: //     function:
                    566: //             emulates the 80387 scale instruction.
                    567: //
                    568: //     inputs:
                    569: //             scale term (scaler) from st(1) in operand1, and 
                    570: //             scalend (*to be scaled*) from st(0) in operand2
                    571: //
                    572: //     outputs:
                    573: //             scaled operand in operand2 record or result_record.
                    574: //             error indicators set.
                    575: //
                    576: //     data accessed:
                    577: //             - result_rec_offset             tag1
                    578: //             - word_frac1                    offset_operand2
                    579: //             - tag2                          expon2
                    580: //             - offset_result                 extra_word_reg
                    581: //
                    582: //     data changed:
                    583: //             - expon2
                    584: //
                    585: //     procedures called:
                    586: //             set_up_indefinite       fix32           put_result
                    587: //             move_op_to_result       underflow_response
                    588: //             overflow_response
                    589: //
                    590: // *************************************************************************
                    591:        ALIGN
                    592: scale: //proc
                    593:        jz      catch_spcl_scale_cases          // branch if no stack error
                    594:        call    set_stk_u_error                 // stack underflow occurred
                    595:        jmp     unmasked_i_error_
                    596:        ALIGN
                    597: catch_spcl_scale_cases:
                    598:        andb    $~(a_mask),%gs:sr_flags// clear 87 a-bit
                    599:        movb    tag1(%ebp),%al          // both operands valid?
                    600:        orb     tag2(%ebp),%al
                    601:        jnz     special_cases_handler   // no, branch to handler of special cases
                    602: valid_scale_case:
                    603:        push    %gs:sr_masks                    // save current rounding controls
                    604:        orb     rnd_to_zero,%gs:sr_controls     // institute round by chopping
                    605:                                        // this *or* works only because
                    606:                                        // rnd_to_zero sets entire rc field
                    607:        call    fix32                   // convert scale factor to int32
                    608:        pop     %gs:sr_masks                    // restore rnd control
                    609:        jz      add_scale_term                          // if zf=1, no overflow in fix32
                    610:        cmpb    positive,sign1(%ebp)
                    611:        je      get_least_sf_xtrm_ovfl
                    612:        jmp     get_grtst_sf_xtrm_unfl
                    613:        ALIGN
                    614: add_scale_term:
                    615:        mov     dword_frac1+frac32(%ebp),%eax   // int32 scale factor
                    616:        cmp     least_sf_xtrm_ovfl,%eax
                    617:        jle     check_xtrm_unfl
                    618: get_least_sf_xtrm_ovfl:
                    619:        mov     least_sf_xtrm_ovfl,%eax
                    620:        jmp     add_int32_to_dword_exp
                    621:        ALIGN
                    622: check_xtrm_unfl:
                    623:        cmp     grtst_sf_xtrm_unfl,%eax
                    624:        jge     add_int32_to_dword_exp
                    625: get_grtst_sf_xtrm_unfl:
                    626:        mov     grtst_sf_xtrm_unfl,%eax
                    627: add_int32_to_dword_exp:
                    628:        add     %eax,dword_expon2               // add scale term to op2s expon
                    629:        cmpl    $0x7ffe,dword_expon2
                    630:        jg      scale_overflow
                    631:        cmp     $1,dword_expon2
                    632:        jl      scale_underflow
                    633: give_op2:
                    634:        mov     $offset_operand2,%edi
                    635: put_scaled_result:
                    636:        mov     offset_result_rec,%esi
                    637:        jmp     put_result
                    638:        ALIGN
                    639: scale_overflow:
                    640:        mov     $offset_operand2,%esi           // move op2 to result
                    641:        call    move_op_to_result
                    642:        call    overflow_response
                    643:        jmp     set_up_result
                    644:        ALIGN
                    645: scale_underflow:
                    646:        mov     $offset_operand2,%esi           // move op2 to result
                    647:        call    move_op_to_result
                    648:        push    %gs:sr_masks
                    649:        orb     prec64,%gs:sr_controls          // *or* works only because prec64
                    650:        movb    false,rnd1_inexact              // sets all bits in the pc field
                    651:        call    underflow_response
                    652:        pop     %gs:sr_masks
                    653: set_up_result:
                    654:        mov     $offset_result,%edi
                    655:        jmp     put_scaled_result
                    656:        ALIGN
                    657: //scale        endp
                    658: //
                    659: //a_med        ends
                    660: //
                    661: //     end

unix.superglobalmegacorp.com

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