Annotation of kernel/machdep/i386/fp_emul/fp_store.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 "store.s"
        !            26: 
        !            27:        .ident  "@(#)kern-fp:store.s    1.1"
        !            28: 
        !            29: //$tt(*80387   emulator+++s    t       o       r       e+++*)
        !            30: // ***************************************************************************
        !            31: //
        !            32: //                     s t o r e . m o d 
        !            33: //                     ==================
        !            34: //
        !            35: //     =============================================================
        !            36: //               intel corporation proprietary information
        !            37: //    this software  is  supplied  under  the  terms  of  a  license
        !            38: //    agreement  or non-disclosure agreement  with intel corporation
        !            39: //    and  may not be copied nor disclosed except in accordance with
        !            40: //    the terms of that agreement.                                  
        !            41: //     ===============================================================
        !            42: //
        !            43: //     function:
        !            44: //             implements 80387 store, fix, and storex instructions.
        !            45: //
        !            46: //     public procedures:
        !            47: //             store   fix16   fix32   fix64   move_op_to_op
        !            48: //
        !            49: //     internal procedures:
        !            50: //             extended_store          bcd_store
        !            51: //             single_real_store       double_real_store
        !            52: //             store_valid             int64_store
        !            53: //             int16_store             int32_store
        !            54: //
        !            55: // ************************************************************************
        !            56: //
        !            57: //...december 12, 1986..
        !            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   pop_free,clear_6w,test_3w,subadd
        !            71: //     extrn   gradual_underflow,right_shift_frac2_cl
        !            72: //     extrn   special_round_test,directed_round_test
        !            73: //     extrn   right_shift_result_cl,set_up_indefinite
        !            74: //     extrn   right_shift_frac1_cl,sticky_right_shift
        !            75: //     extrn   left_shift_frac1_cl,left_shift_result_cl
        !            76: //     extrn   put_op1_result,divid,addition_normalize
        !            77: //     extrn   round,get_precision,get_rnd_control
        !            78: //     extrn   store_precision,set_i_error,i_masked_
        !            79: //     extrn   set_o_error,o_masked_,set_p_error
        !            80: //     extrn   set_u_error,test_4w,subtraction_normalize
        !            81: //     extrn   p_error_,clear_p_error,add_to_frac
        !            82: //     extrn   move_constant,set_stk_u_error,norm_denorm
        !            83: //     extrn   %gs:sr_mem_offset
        !            84: //     --------to be added for unix
        !            85: //..           extrn   fpfulong:far,fpfushort:far,fpsulong:far,fpsushort:far
        !            86: //
        !            87:        .globl  store
        !            88:        .globl  fix16
        !            89:        .globl  fix32
        !            90:        .globl  fix64
        !            91:        .globl  move_op_to_op
        !            92: //
        !            93: store_routine: 
        !            94:        .long   single_real_store,double_real_store,int16_store
        !            95:        .long   int32_store,int64_store,extended_store
        !            96:        .long   int16_store,int16_store,bcd_store
        !            97: //
        !            98: // *************************************************************************
        !            99: //                     store:
        !           100: //                     ******
        !           101: //     function:
        !           102: //             implements all store instructions .
        !           103: //
        !           104: //     inputs:
        !           105: //             operand1; format of result.
        !           106: //
        !           107: //     outputs:
        !           108: //             operand in *result_format* stored in memory
        !           109: //             destination pointed to by es:di.
        !           110: //
        !           111: //     data accessed:
        !           112: //             - result_rec_offset     result_format
        !           113: //             - offset_operand1
        !           114: //
        !           115: //     data changed:
        !           116: //             - result record
        !           117: //
        !           118: //     procedures called:
        !           119: //             set_up_indefinite       store routine (result format)
        !           120: //             i_masked?
        !           121: //
        !           122: // ****************************************************************************
        !           123:        ALIGN
        !           124: store: //proc
        !           125:        jz      no_unmasked_stack_error         // branch if no stack error
        !           126:        call    set_stk_u_error                 // stack underflow occurred
        !           127:        testb   invalid_mask,%gs:sr_masks       // if unmasked, just exit
        !           128:        jz      return                          // else, store indef set up
        !           129: no_unmasked_stack_error:                       // in operand1 by fetch_an_op
        !           130:        andb    $~a_mask,%gs:sr_flags   // clear a-bit
        !           131: get_result_loc:
        !           132:        cmpb    $reg,result_location(%ebp)
        !           133:        jne     store_to_memory                         // branch if memop
        !           134:        call    put_op1_result                          // give opnd1 as result
        !           135:        jmp     pop_free
        !           136:        ALIGN
        !           137: store_to_memory:
        !           138:        movzbl  result_format(%ebp),%ebx// call a different rtn
        !           139:        shll    $2,%ebx                                 // for each of the
        !           140:        cmp     $8,%ebx
        !           141:        jge     go_to_storer                    // do store of temporary real
        !           142:        cmpb    unsupp,tag1(%ebp)               // detect unsupported pattern
        !           143:        jne     go_to_storer
        !           144:        orb     invalid_mask,%gs:sr_errors      // set i_error
        !           145:        testb   invalid_mask,%gs:sr_masks       // if unmasked, just exit
        !           146:        jz      return                                  // else, set up indef in
        !           147:        mov     $offset_operand1,%edi           // operand1. 
        !           148:        call    set_up_indefinite
        !           149: go_to_storer:
        !           150:        jmp     *%cs:store_routine(%ebx)                        // output formats
        !           151: //store        endp
        !           152: //
        !           153: // ****************************************************************************
        !           154: //                     move_op_to_op:
        !           155: //
        !           156: //     function:
        !           157: //             moves operand record (op1,op2,result_op,result2_op) to
        !           158: //             another op.
        !           159: //
        !           160: //     inputs:
        !           161: //             ss:esi points to the source, and
        !           162: //             ss:edi points to the destination
        !           163: //     outputs:
        !           164: //             operand record in destination
        !           165: //
        !           166: //     data accessed:
        !           167: //             operand or result variables
        !           168: //
        !           169: //     data changed:
        !           170: //             operand or result variables
        !           171: //
        !           172: // *****************************************************************************
        !           173:        ALIGN
        !           174: move_op_to_op: //proc
        !           175: //     push    %ds                     // save a?msr
        !           176: //     push    %ss
        !           177: //     pop     %ds
        !           178:        push    %ss
        !           179:        pop     %es
        !           180:        mov     $((sign2-sign1)>> 2),%ecx / set record length
        !           181: 
        !           182:        /* FAST_MOVSL */
        !           183:        push    %eax
        !           184: 1:
        !           185:        movl    %ss:0(%esi),%eax
        !           186:        movl    %eax,%es:0(%edi)
        !           187:        addl    $4,%esi 
        !           188:        addl    $4,%edi 
        !           189:        decl    %ecx    
        !           190:        testl   %ecx,%ecx
        !           191:        jg      1b
        !           192: 
        !           193:        pop     %eax
        !           194: //     pop     %ds                     // reload a?msr
        !           195: return:
        !           196:        ret
        !           197: //move_op_to_op        endp
        !           198: //
        !           199: // ***************************************************************************
        !           200: //                     extended_store:
        !           201: //                     ***************
        !           202: //     function:
        !           203: //             stores into double extended format.
        !           204: //
        !           205: //     inputs:
        !           206: //             operand1
        !           207: //
        !           208: //     outputs:
        !           209: //             double extended operand in memory.
        !           210: //             stack popped if indicated
        !           211: //
        !           212: //     data accessed:
        !           213: //             - mem_operand_pointer           sign1
        !           214: //             - expon1                        word_frac1
        !           215: //
        !           216: //     data changed:
        !           217: //
        !           218: //     procedures called:
        !           219: //             pop_free
        !           220: //
        !           221: // *****************************************************************************
        !           222:        ALIGN
        !           223: extended_store:        //proc
        !           224:        les     mem_operand_pointer(%ebp),%edi  //move frac to memory
        !           225: //     push    %ds                             // save a?msr
        !           226: //     push    %ss
        !           227: //     pop     %ds                             // set up source pointer
        !           228:        lea     2+word_frac1,%esi
        !           229:        
        !           230:        /* FAST_MOVSL */
        !           231:        movl    %ss:0(%esi),%ecx
        !           232:        movl    %ecx,%es:0(%edi)
        !           233:        movl    %ss:4(%esi),%ecx
        !           234:        movl    %ecx,%es:4(%edi)
        !           235: //     addl    $8,%esi
        !           236: //     addl    $8,%edi
        !           237: //     movl    $0,%ecx
        !           238: 
        !           239: //     pop     %ds                                             // reload a?msr
        !           240:        movb    sign1(%ebp),%ah                 // merge sign & exponent
        !           241:        andw    $0x8000,%ax                             // and move to memory
        !           242:        orw     expon1(%ebp),%ax
        !           243:        movw    %ax,%es:8(%edi)
        !           244: 
        !           245: //..
        !           246: //..           pushad
        !           247: //..           push    es
        !           248: //..           push    edi
        !           249: //..           push    ax
        !           250: //..           call    fpsushort
        !           251: //..           add     esp,12
        !           252: //..           popad
        !           253: //..           cld
        !           254:        jmp     pop_free                                        // pop stack, if needed
        !           255: //extended_store       endp
        !           256: //
        !           257: // ****************************************************************************
        !           258: //                     bcd_store:
        !           259: //                     **********
        !           260: //     function:
        !           261: //             stores into bcd format
        !           262: //
        !           263: //     inputs:
        !           264: //             operand1
        !           265: //
        !           266: //     outputs:
        !           267: //             bcd operand in memory; stack popped
        !           268: //
        !           269: //     data accessed:
        !           270: //             - mem_operand_pointer           operation_type
        !           271: //             - offset_operand1               sign1
        !           272: //             - tag1                          word_frac1
        !           273: //             - msb_frac1                     offset_operand1
        !           274: //             - offset_operand2               sign2
        !           275: //             - expon2                        word_frac2
        !           276: //             - offset_operand2               offset_result
        !           277: //             - result_expon                  result_word_frac
        !           278: //             - msb_result                    offset_result
        !           279: //
        !           280: //     data changed:
        !           281: //             - operation_type                word_frac1
        !           282: //             - msb_frac1                     sign2
        !           283: //             - expon2                        word_frac2
        !           284: //             - result_word_frac              msb_result
        !           285: //
        !           286: //     procedures called:
        !           287: //             move_op_to_op                   right_shift_frac1_cl
        !           288: //             right_shift_frac2_cl    right_shift_result_cl
        !           289: //             left_shift_frac1_cl             left_shift_result_cl
        !           290: //             divid                                   clear_6w
        !           291: //             pop_free                                test_4w
        !           292: //             add_to_frac                             move_constant
        !           293: //
        !           294: // **************************************************************************
        !           295: ten_18:        
        !           296:        .value  0x0000,0x0000,0x0000,0x7640,0x6b3a,0x0de0b// frac for 10**18
        !           297: //
        !           298:        ALIGN
        !           299: bcd_store:     //proc
        !           300:        push    %gs:sr_masks                            // save current precision
        !           301:        orb     prec64,%gs:sr_controls                  // and set to 64-bit
        !           302:        cmpb    special,tag1(%ebp)                      // separate bcd cases
        !           303:        jne     finite_value_
        !           304:        jmp     store_signed_bcd
        !           305:        ALIGN
        !           306: finite_value_:
        !           307:        cmpl    $0x07fff,dword_expon1            // is it a finite number?
        !           308:        jne     check_bcd_denorm                        // yes, branch to valid
        !           309: invalid_bcd:
        !           310:        orb     invalid_mask,%gs:sr_errors      // set i_error
        !           311:        testb   invalid_mask,%gs:sr_masks       // is i_error unmasked?
        !           312:        jnz     store_bcd_indef
        !           313:        jmp     bcd_store_done                  // no, so exit at once
        !           314:        ALIGN
        !           315: store_bcd_indef:                               // yes, store bcd_indef
        !           316:        movl    $0, dword_frac1+frac80(%ebp)    // clear low frac
        !           317:        movl    $0x80000000, dword_frac1+6(%ebp)// set only ms bit of hi frac
        !           318:        movw    $0x0ffff, 8+word_frac1          //set msw to all ones,
        !           319:        jmp     store_bcd_result                // and give as answer
        !           320:        ALIGN
        !           321: check_bcd_denorm:
        !           322:        cmpb    denormd,tag1(%ebp)                      // separate bcd cases
        !           323:        jne     round_to_int
        !           324:        movl    $0x0001,dword_expon1    // if masked d-error, make valid
        !           325:        movb    valid,tag1(%ebp)
        !           326: round_to_int:
        !           327:        mov     $0x403e,%eax
        !           328:        cmp     %eax,dword_expon1               // if expon >= 63, then number
        !           329:        jge     invalid_bcd                     // is already too big for bcd
        !           330:        mov     $offset_operand1,%edi   // gradual uflow until expon=63
        !           331:        push    %edi
        !           332:        call    gradual_underflow
        !           333:        pop     %edi                            // round to precision 64
        !           334:        movb    prec64,%dl
        !           335:        movb    false,%al
        !           336:        call    round
        !           337: detect_zero:
        !           338:        xor     %eax,%eax
        !           339:        mov     $dword_frac1+4,%edi     // if fraction = 0, result = 0
        !           340:        call    test_4w
        !           341:        jnz     below_10_to_18_
        !           342:        mov     %eax,dword_expon1               // set result to true zero
        !           343:        movb    special,tag1(%ebp)
        !           344:        jmp     store_bcd_round_data
        !           345:        ALIGN
        !           346: below_10_to_18_:
        !           347:        mov     4(%ebp,%edi),%edx
        !           348:        cmp     $0x0de0b6b3,%edx
        !           349:        ja      invalid_bcd
        !           350:        mov     (%ebp,%edi),%eax
        !           351:        jb      divide_by_10_to_9
        !           352:        cmp     $0x0a7640000,%eax
        !           353:        jae     invalid_bcd
        !           354: divide_by_10_to_9:
        !           355:        movl    $0,4(%ebp,%edi) // clear high dword of frac1
        !           356:        movl    $0,(%ebp,%edi)// clear  low dword of 8 byte frac1 
        !           357:        sub     $2,%edi                 // make edi point to 10 byte frac1
        !           358:        mov     $0x3b9aca00,%ebx                // ten to the 9th, as hex ordinal
        !           359:        div     %ebx
        !           360:        push    %eax                                            // save quotient
        !           361:        mov     $4,%ecx
        !           362:        mov     $100,%ebx
        !           363:        FALLSTHRU
        !           364: next_pair_nibbles:
        !           365:        mov     %edx,%eax
        !           366:        xor     %edx,%edx
        !           367:        div     %ebx
        !           368:        xchgl   %edx,%eax
        !           369:        aam
        !           370: second_half_loop_start:
        !           371:        shlb    $4,%ah
        !           372:        orb     %ah,%al
        !           373:        movb    %al,(%ebp,%edi)
        !           374:        inc     %edi
        !           375:        LOOP(next_pair_nibbles)
        !           376: do_second_half_:
        !           377:        pop     %eax
        !           378:        or      %eax,%eax                                       // is eax 0?
        !           379:        movb    %dl,(%ebp,%edi)
        !           380:        jz      store_bcd_round_data
        !           381:        push    %edx
        !           382:        xor     %edx,%edx
        !           383:        mov     $10,%ecx
        !           384:        div     %ecx
        !           385:        xchgl   %edx,%eax
        !           386:        pop     %ecx
        !           387:        movb    %al, %ah
        !           388:        movb    %cl, %al
        !           389:        push    $0
        !           390:        mov     $5, %ecx
        !           391:        jmp     second_half_loop_start
        !           392:        ALIGN
        !           393: store_bcd_round_data:
        !           394:        cmpb    true,rnd1_inexact
        !           395:        jne     store_signed_bcd
        !           396:        orb     $inexact_mask,%gs:sr_errors
        !           397:        cmpb    true,added_one
        !           398:        jne     store_signed_bcd
        !           399:        orb     $a_mask,%gs:sr_flags
        !           400: store_signed_bcd:
        !           401:        movb    sign1(%ebp),%ah                 // set sign in bcd number
        !           402:        andb    $0x080,%ah
        !           403:        movb    %ah,msb_frac1
        !           404: store_bcd_result:
        !           405:        les     %gs:sr_mem_offset,%edi  //move frac1 to memory
        !           406: //     push    %ds                             // save a?msr
        !           407: //     push    %ss
        !           408: //     pop     %ds
        !           409:        lea     word_frac1,%esi
        !           410: 
        !           411:        /* FAST_MOVSL */
        !           412:        movl    %ss:0(%esi),%ecx
        !           413:        movl    %ecx,%es:0(%edi)
        !           414:        movl    %ss:4(%esi),%ecx
        !           415:        movl    %ecx,%es:4(%edi)
        !           416:        movw    %ss:8(%esi),%cx
        !           417:        movw    %cx,%es:8(%edi)
        !           418: //     addl    $10,%esi
        !           419: //     addl    $10,%edi
        !           420: //     movl    $0,%ecx
        !           421: 
        !           422: //     pop     %ds                                     // reload a?msr
        !           423:        call    pop_free
        !           424: bcd_store_done:
        !           425:        pop     %gs:sr_masks                            // restore old setting
        !           426:        ret
        !           427: //bcd_store    endp
        !           428: //
        !           429: // *****************************************************************************
        !           430: //                     single_real_store:
        !           431: //                     ******************
        !           432: //     function:
        !           433: //             implements store to single-precision real format
        !           434: //
        !           435: //     inputs:
        !           436: //             operand1
        !           437: //
        !           438: //     outputs:
        !           439: //             single_precision real in memory;
        !           440: //             stack popped if indicated.
        !           441: //
        !           442: //     data accessed:
        !           443: //             - mem_operand_pointer           offset_operand1
        !           444: //             - sign1                         tag1
        !           445: //             - expon1                        word_frac
        !           446: //             - msb_frac1
        !           447: //
        !           448: //     data changed:
        !           449: //
        !           450: //     procedures called:
        !           451: //             round                           store_valid
        !           452: //             addition_normalized             special_round_test
        !           453: //             directed_round_test             gradual_underflow
        !           454: //             pop_free                        test_3w
        !           455: //             u_masked?                       set_o_error
        !           456: //             o_masked?                       set_p_error
        !           457: //             set_u_error                     set_i_masked?
        !           458: //             store_denormd
        !           459: //
        !           460: // ************************************************************************
        !           461:        ALIGN
        !           462: single_real_store:     //proc
        !           463:        push    $pop_free                               // return to pop_free
        !           464:        les     mem_operand_pointer(%ebp),%edi  //set es:di to memop
        !           465:        mov     low_extended_expon_for_single,%esi
        !           466:        movb    prec24,%dl                              // 24-bit precision
        !           467:        movb    tag1(%ebp),%al                  // load op1 tag
        !           468:        cmpb    valid,%al
        !           469:        je      single_valid                            // detect valid, infinity,
        !           470:        cmpb    denormd,%al                             // denormd, invalid, and
        !           471:        je      single_denormd                          // special cases
        !           472:        cmpb    inv,%al                                 // check whether op1 is nan
        !           473:        jne     single_special                          // branch unless op1 is nan
        !           474:        testb   $0x40,msb_frac1                         // check whether nan is quiet
        !           475:        jnz     single_special                          // branch if nan is quiet
        !           476:        orb     invalid_mask,%gs:sr_errors      // set i_error for snan
        !           477:        testb   invalid_mask,%gs:sr_masks       // if unmasked, just exit
        !           478:        jz      special_return                          // else, change to qnan
        !           479:        orb     $0x40,msb_frac1
        !           480: single_special:
        !           481:        mov     dword_frac1+frac32+1(%ebp),%ecx
        !           482:        and     $0x807fffff,%ecx
        !           483:        movzbl  expon1(%ebp),%eax
        !           484:        shl     $23,%eax
        !           485:        or      %ecx,%eax
        !           486:        mov     %eax,%es:(%edi)
        !           487: //..
        !           488: //..           pushad
        !           489: //..           push    es
        !           490: //..           push    edi
        !           491: //..           push    eax
        !           492: //..           call    fpsulong
        !           493: //..           add             esp,    12
        !           494: //..           popad
        !           495: //..           cld
        !           496: //..
        !           497: special_return:
        !           498:        ret
        !           499:        ALIGN
        !           500: 
        !           501: single_denormd:
        !           502:        mov     $offset_operand1,%edi   // op1 is denormal or pseudo-denormal
        !           503:        call    norm_denorm             // dont set d_error; just normalize
        !           504: single_valid:
        !           505:        mov     high_extended_expon_for_single,%edi // load parameter
        !           506:        call    store_valid
        !           507:        les     mem_operand_pointer(%ebp),%edi  // es:edi --> memop
        !           508:        jz      single_infinity         // zf = 1 => store infinity
        !           509:        js      single_max                      // sf = 1 => store max
        !           510:        jc      single_qnan                     // cf = 1 => store qnan
        !           511: single_store:
        !           512:        mov     dword_frac1+frac32+1(%ebp),%eax
        !           513:        and     $0x80ffffff,%eax
        !           514:        test    $0x00ffffff,%eax
        !           515:        jz      single_store_it
        !           516:        and     $0x807fffff,%eax
        !           517:        movzbl  expon1(%ebp),%ecx
        !           518:        addb    $0x80,%cl
        !           519:        shl     $23,%ecx
        !           520:        or      %ecx,%eax
        !           521: single_store_it:
        !           522:        mov     %eax,%es:(%edi)
        !           523: //..
        !           524: //..           pushad
        !           525: //..           push    es
        !           526: //..           push    edi
        !           527: //..           push    eax
        !           528: //..           call    fpsulong
        !           529: //..           add     esp,12
        !           530: //..           popad
        !           531: //..           cld
        !           532: //..
        !           533:        ret                                     //do needed pop or free
        !           534:        ALIGN
        !           535: 
        !           536: single_max:
        !           537:        mov     $0x7fffff7f,%eax
        !           538:        jmp     single_sign_on
        !           539:        ALIGN
        !           540: single_infinity:
        !           541:        mov     $0x8000007f,%eax
        !           542: single_sign_on:
        !           543:        orb     sign1(%ebp),%al
        !           544:        ror     $8,%eax
        !           545:        jmp     single_store_it
        !           546:        ALIGN
        !           547: single_qnan:
        !           548:        movl    $0xffffffff,%es:(%edi)
        !           549:        pop     %eax                            // skip pop or free
        !           550:        ret                                     //   since this happens on error
        !           551:        ALIGN
        !           552: 
        !           553: store_valid:
        !           554:        push    %edi                            // stack high_expon
        !           555:        push    %esi                            // stack low_expon
        !           556:        push    %edx                            // stack prec control
        !           557:        movb    false,%al                       // not second rounding
        !           558:        mov     $offset_operand1,%edi   // round to prec (dl)
        !           559: //     push    edi                                     ; round preserves edi
        !           560:        call    round
        !           561: //             pop             edi
        !           562:        call    addition_normalize              // and renormalize
        !           563:        pop     %edx                            // unstack prec control
        !           564:        pop     %esi                            // unstack low_expon
        !           565:        pop     %edi                            // unstack high_expon
        !           566:        cmp     %esi,dword_expon1               // is underflow possible?
        !           567:        jl      store_underflow_        // < low_expon, so underflow possible
        !           568:        je      decrement_exponent              // no, = low_expon?
        !           569:        cmp     %edi,dword_expon1               // no, > high_expon?
        !           570:        jle     do_store_valid                  // no, store number
        !           571:        orb     overflow_mask,%gs:sr_errors     // set o_error
        !           572:        testb   overflow_mask,%gs:sr_masks      // if unmasked, violate ieee standard
        !           573:        jnz     masked_overflow         // and abort without rounding source
        !           574: unmasked_ov_underflow:
        !           575: //
        !           576: // the commentized instructions immediately following are appropriate for
        !           577: // unmasked over/underflow response in accord with the ieee standard.  on the
        !           578: // 80387, unmasked over/underflows on conversion leave for the trap handler the
        !           579: // source operand, unmodified by rounding, exponent rebiasing, or anything else.
        !           580: // therefore, to report that preliminary rounding was inexact or achieved by
        !           581: // increasing the source seems inconsistent with the 80387s philosophy
        !           582: // of entering an over/underflow trap handler with the 80387s state changed
        !           583: // only insofar as the over/underflow flag has been set, so skip that report.
        !           584: //
        !           585: //     cmp     rnd1_inexact,   true            ; detect inexact result
        !           586: //     jne     move_op1_to_87_tos              ; if exact, branch to replace source
        !           587: //     or      %gs:sr_errors,  inexact_mask    ; else, set i_error
        !           588: //     cmp     added_one,      true            ; was rounding done by adding one?
        !           589: //     jne     move_op1_to_87_tos              ; if not, branch to replace source
        !           590: //     or      %gs:sr_flags,   a_mask          ; else, set a_bit
        !           591: //move_op1_to_87_tos:
        !           592: //     mov     (ebp).result_location,  stack_top
        !           593: //     pop     %edi            ; discard callers return address
        !           594: //     pop     %edi            ; discard pop_free address
        !           595: //     jmp     put_op1_result
        !           596: //
        !           597: // Instead, we return a special error condition (sf=0 zf=0 cf=1)
        !           598: // to our caller, to cause a quiet NaN to be generated, as the 80387 does.
        !           599:        movb    $1, %ah
        !           600:        sahf
        !           601:        ret
        !           602:        ALIGN
        !           603: 
        !           604: masked_overflow:
        !           605:        orb     $inexact_mask,%gs:sr_errors     // set inexact_error
        !           606:        movb    %gs:sr_controls,%al                     // load control byte
        !           607:        andb    $rnd_control_mask,%al   // mask in rounding control
        !           608:        movb    rnd_up,%ah
        !           609:        cmpb    %al,%ah
        !           610:        js      store_valid_done                // branch if zf = 0 & sf = 1
        !           611:        movb    sign1(%ebp),%al                         // get sign of op1
        !           612:        call    special_round_test                      // after round test, cf=0
        !           613:        pushf                           //  (zf=0 sf=1)/(zf=1 sf=0)
        !           614:        js      pop_store_valid_done            // sf = 1 => store max
        !           615:        orb     $a_mask,%gs:sr_flags                    // set a_bit
        !           616: pop_store_valid_done:
        !           617:        popf                                            // reload flags
        !           618: store_valid_done:
        !           619:        ret                                                                     // exit
        !           620:        ALIGN
        !           621: store_underflow_:
        !           622:        testb   underflow_mask,%gs:sr_masks     // if underflow masked,
        !           623:        jnz     check_masked_underflow  // then branch to check for inexact
        !           624:        orb     underflow_mask,%gs:sr_errors// else, set u_error
        !           625: //
        !           626: // after the underflow exception has been set, the response to unmasked
        !           627: // underflow ought to be the same as that to unmasked overflow.
        !           628:        jmp     unmasked_ov_underflow
        !           629:        ALIGN
        !           630: 
        !           631: check_masked_underflow:
        !           632:        mov     $offset_operand1,%edi           // load op1 offset
        !           633:        mov     %esi,%eax                               // load low exponent
        !           634:        push    %edi                                    // save op1 offset
        !           635:        push    %edx                                    // save prec control
        !           636:        call    gradual_underflow                       // do gradual underflow
        !           637:        pop     %edx                                    // reload prec control
        !           638:        pop     %edi                                    // reload op1 offset
        !           639:        movb    true,%al                                // perform second round
        !           640:        call    round
        !           641:        cmpw    $0,rnd_history                  // signal_u_error?
        !           642:        je      decrement_exponent
        !           643:        orb     underflow_mask+inexact_mask,%gs:sr_errors
        !           644: decrement_exponent:
        !           645:        testb   $0x80,msb_frac1                         // test msb of fraction
        !           646:        jnz     do_store_valid          // dont decrement if 800..0h
        !           647:        decw    expon1(%ebp)                            // else, decrement expon
        !           648: do_store_valid:
        !           649:        cmpw    $0,rnd_history                  // signal_p_error?
        !           650:        je      adjust_flags
        !           651:        orb     $inexact_mask,%gs:sr_errors     // signal_p_error.
        !           652:        cmpb    true,added_one          // was rounding done by adding one?
        !           653:        jne     adjust_flags            // if not, branch to adjust flags
        !           654:        orb     $a_mask,%gs:sr_flags            // else, set a_bit
        !           655: adjust_flags:
        !           656:        xor     %eax,%eax               // cf = 0, sf = 0, zf = 0 for
        !           657:        inc     %eax                    //  store valid exit
        !           658:        ret
        !           659: 
        !           660: //single_real_store    endp
        !           661: //
        !           662: // ************************************************************************
        !           663: //                     double_real_store:
        !           664: //                     ******************
        !           665: //     function:
        !           666: //             implements store to double-precision real format
        !           667: //
        !           668: //     inputs:
        !           669: //             operand1
        !           670: //
        !           671: //     outputs:
        !           672: //             double precision real in memory;
        !           673: //             stack popped if indicated.
        !           674: //
        !           675: //     data accessed:
        !           676: //             - mem_operand_pointer           offset_operand1
        !           677: //             - sign1                         tag1
        !           678: //             - expon1                        word_frac1
        !           679: //             - msb_frac1                     offset_operand1
        !           680: //
        !           681: //     data changed:
        !           682: //             - sign1                         word_frac1
        !           683: //
        !           684: //     procedures called:
        !           685: //             test_3w                         store_valid
        !           686: //             right_shift_frac1_cl            pop_free
        !           687: //             double_zero                     double_fill
        !           688: //             store_denormd                   double_frac_mem
        !           689: //
        !           690: // ***************************************************************************
        !           691:        ALIGN
        !           692: double_real_store:     //proc
        !           693:        push    $pop_free                               // return to pop_free
        !           694:        mov     low_extended_expon_for_double,%esi
        !           695:        movb    prec53,%dl                              // 53-bit precision
        !           696:        movb    tag1(%ebp),%al                  // separate special cases
        !           697:        cmpb    valid,%al
        !           698:        je      double_valid
        !           699:        cmpb    denormd,%al
        !           700:        je      double_denormd
        !           701:        cmpb    special,%al
        !           702:        jne     inv_or_inf
        !           703:        movw    $0x3c00,expon1(%ebp)
        !           704:        jmp     double_frac_mem
        !           705:        ALIGN
        !           706: inv_or_inf:
        !           707:        cmpb    inv,%al
        !           708:        jne     double_special
        !           709:        testb   $0x40,msb_frac1                 // check whether nan is quiet
        !           710:        jnz     double_special                          // branch if nan is quiet
        !           711:        orb     invalid_mask,%gs:sr_errors      // set i_error for snan
        !           712:        testb   invalid_mask,%gs:sr_masks       // if unmasked, just exit
        !           713:        jnz     make_dbl_qnan                           // else, change to qnan
        !           714: dbl_special_return:
        !           715:        ret
        !           716:        ALIGN
        !           717: make_dbl_qnan:
        !           718:        orb     $0x40,msb_frac1
        !           719: double_special:
        !           720:        movw    $0x3c00+0x07ff,expon1(%ebp)
        !           721:        jmp     double_frac_mem                 // store frac to memory
        !           722:        ALIGN
        !           723: double_denormd:
        !           724:        mov     $offset_operand1,%edi   // op1 is denormal or pseudo-denormal
        !           725:        call    norm_denorm             // dont set d_error; just normalize
        !           726: double_valid:
        !           727:        mov     high_extended_expon_for_double,%edi
        !           728:        call    store_valid
        !           729:        jz      double_infinity                 // zf = 1 ==> store infinity
        !           730:        js      double_max                              // sf = 1 ==> store max
        !           731:        jc      double_qnan                             // cf = 1 ==> store qnan
        !           732: double_store:
        !           733:        movb    3+lsb_frac1,%al // else store double
        !           734:        cbtw
        !           735:        mov     $dword_frac1+6,%edi
        !           736:        call    test_3w
        !           737:        jz      double_zero                             // store signed zero
        !           738: double_frac_mem:
        !           739:        movb    $3,%cl                                  // start by shifting
        !           740:        call    right_shift_frac1_cl            // fraction right 3 bits
        !           741:        les     mem_operand_pointer(%ebp),%edi  // es:edi points to memop
        !           742: //     push    %ds                             // save a?msr
        !           743: //     push    %ss
        !           744: //     pop     %ds                             // set up source pointer
        !           745:        lea     3+word_frac1,%esi               // move frac to memory
        !           746: 
        !           747:        /* FAST_MOVSL */
        !           748:        movl    %ss:0(%esi),%ecx
        !           749:        movl    %ecx,%es:0(%edi)
        !           750:        movw    %ss:4(%esi),%ecx
        !           751:        movw    %ecx,%es:4(%edi)
        !           752: //     addl    $6,%esi
        !           753: //     addl    $6,%edi
        !           754: //     movl    $0,%ecx
        !           755: 
        !           756: //     pop     %ds                                     // reload a?msr
        !           757:        movw    expon1(%ebp),%ax                // fetch high-order word,
        !           758:        subw    $0x3c00,%ax                             // with expon, sign, and
        !           759:        shlw    $4,%ax                          // top 4 bits of fraction
        !           760:        andb    $0x0f,msb_frac1
        !           761:        orb     msb_frac1,%al
        !           762:        andb    $0x80,sign1(%ebp)
        !           763:        orb     sign1(%ebp),%ah
        !           764:        movw    %ax,%es:6(%edi)                         // es:di points to expon
        !           765: //..
        !           766: //..           pushad
        !           767: //..           push    es
        !           768: //..           push    edi
        !           769: //..           push    ax
        !           770: //..           call    fpsushort
        !           771: //..           add     esp,12
        !           772: //..           popad
        !           773: //..           cld
        !           774: //..
        !           775: 
        !           776:        ret                                     // do pop or free
        !           777:        ALIGN
        !           778: 
        !           779: double_zero:
        !           780:        xor     %eax,%eax                       // store +/- 0 to memory
        !           781: double_fill:
        !           782:        les     mem_operand_pointer(%ebp),%edi  // es:edi points to memop
        !           783:        mov     %eax,%es:(%edi)
        !           784: //..
        !           785: //..           pushad
        !           786: //..           push    es
        !           787: //..           push    edi
        !           788: //..           push    eax
        !           789: //..           call    fpsulong
        !           790: //..           add     esp,12
        !           791: //..
        !           792: 
        !           793:        movw    %ax,%es:4(%edi)
        !           794: //..
        !           795: //..           push    es
        !           796: //..           push    edi+4
        !           797: //..           push    ax
        !           798: //..           call    fpsushort
        !           799: //..           add     esp,12
        !           800: //..           popad
        !           801: //..           cld
        !           802: //..
        !           803:        movb    sign1(%ebp),%ah
        !           804:        andb    $0x80,%ah
        !           805: double_expon:
        !           806:        movw    %ax,%es:6(%edi)                 // store the exponent
        !           807: //..
        !           808: //..           pushad
        !           809: //..           push    es
        !           810: //..           push    edi+12
        !           811: //..           push    ax
        !           812: //..           call    fpsushort
        !           813: //..           add     esp,12
        !           814: //..           popad
        !           815: //..           cld
        !           816: //..
        !           817:        ret
        !           818:        ALIGN
        !           819: 
        !           820: double_max:
        !           821:        mov     $0x0ffffffff,%eax                       // set fraction to ff..f
        !           822:        call    double_fill
        !           823:        movw    $0x7fef,%ax                             // set exponent to 7feh
        !           824:        orb     sign1(%ebp),%ah                 // or sign bit
        !           825:        jmp     double_expon
        !           826:        ALIGN
        !           827: double_infinity:
        !           828:        call    double_zero                     // first clear the memop
        !           829:        orw     $0x7ff0,%es:6(%edi)     // es:di -> memop
        !           830: //..
        !           831: //..           pushad
        !           832: //..           push    es
        !           833: //..           push    edi+6
        !           834: //..           call    fpfushort
        !           835: //..           or      ax,7ff0h
        !           836: //..           push    ax
        !           837: //..           call    fpsushort
        !           838: //..           add     esp,12
        !           839: //..           popad
        !           840: //..           cld
        !           841: //..
        !           842:        ret
        !           843:        ALIGN
        !           844: double_qnan:
        !           845:        mov     $0xffffffff,%eax                // set fraction to ff..f
        !           846:        call    double_fill
        !           847:        movw    $0xffff,%es:6(%edi)     // es:di -> memop (set exp to ff..f)
        !           848:        pop     %eax                            // skip pop or free
        !           849:        ret                                     //   since this happens on error
        !           850: //double_real_store    endp
        !           851: //
        !           852: // ***********************************************************************
        !           853: //             fix16:
        !           854: //
        !           855: //     function:
        !           856: //              fixes valid number to a 16-bit integer.
        !           857: //
        !           858: //     inputs:
        !           859: //              operand1
        !           860: //
        !           861: //     outputs:
        !           862: //             16-bit integer in word_frac1 + 8;
        !           863: //             overflow indication in zf (zf:1 => no overflow)
        !           864: //
        !           865: //     data accessed:
        !           866: //             - offset_operand1               sign1
        !           867: //             - expon1                        word_frac1
        !           868: //             - offset_operand1
        !           869: //
        !           870: //     data changed:
        !           871: //             - word_frac1                    extra_word_reg
        !           872: //
        !           873: //     procedures called:
        !           874: //             sticky_right_shift              round
        !           875: //             careful_round                   p_error?
        !           876: //
        !           877: // ***************************************************************************
        !           878:        ALIGN
        !           879: fix16: //proc
        !           880:        mov     high_int16_exponent,%ecx                // calc shift amount
        !           881:        sub     dword_expon1,%ecx                       // if expon1 > high expon
        !           882:        js      no_fix16_ovf                    // then overflow (zf=0)
        !           883:        cmp     max_int16_shift,%ecx                    // dont let shift amount
        !           884:        jbe     do_shift_16                     // exceed max_int16_shift
        !           885:        mov     max_int16_shift,%ecx
        !           886: do_shift_16:
        !           887:        mov     $offset_operand1,%edi           // shift frac1 by cl
        !           888:        xorb    %al,%al
        !           889:        call    sticky_right_shift
        !           890:        mov     $offset_operand1,%edi           // round to 16-bit prec
        !           891:        movb    prec16,%dl
        !           892:        movb    false,%al
        !           893:        call    round
        !           894:        cmpb    false,%al                               // overflow if al=true
        !           895:        jnz     no_fix16_ovf                            // round cy out (zf=1)
        !           896:        cmpw    $0x8000,8+word_frac1
        !           897:        jb      check_sign_16                           // no overflow if < 8000h
        !           898:        ja      no_fix16_ovf                            // else, overflow (zf=0)
        !           899:        cmpb    negative,sign1(%ebp)    // oflow if = 8000h and
        !           900:        jnz     no_fix16_ovf                            // sign1 = pos (zf=0)
        !           901: check_sign_16:
        !           902:        movb    positive,%al                    // al is overflow flag
        !           903:        cmpb    sign1(%ebp),%al                 // negate integer if
        !           904:        jz      no_fix16_ovf                            // sign is neg (zf=1)
        !           905:        negw    8+word_frac1
        !           906:        xorb    %al,%al                                 // no overflow (zf=1)
        !           907: no_fix16_ovf:
        !           908:        ret
        !           909: //fix16        endp
        !           910: //
        !           911: // ***********************************************************************
        !           912: //                     int16_store:
        !           913: //
        !           914: //     function:
        !           915: //             stores into 16-bit integer format
        !           916: //
        !           917: //     inputs:
        !           918: //             operand1
        !           919: //
        !           920: //     outputs:
        !           921: //             16-bit integer in memory operand location
        !           922: //
        !           923: //     data accessed:
        !           924: //             - mem_operand_pointer           tag1
        !           925: //             - word_frac1                    msb_frac1
        !           926: //             - offset_operand1               extra_word_reg
        !           927: //
        !           928: //     data changed:
        !           929: //
        !           930: //     procedures called:
        !           931: //             fix16                           pop_free
        !           932: //             invalid_or_special              get_rnd_control
        !           933: //             set_i_error                     i_masked?
        !           934: //             set_p_error                     clear_p_error
        !           935: //
        !           936: // ************************************************************************
        !           937:        ALIGN
        !           938: int16_store:   //proc
        !           939: //
        !           940:        cmpb    valid,tag1(%ebp)
        !           941:        je      valid_16
        !           942:        cmpb    denormd,tag1(%ebp)
        !           943:        jne     special_16
        !           944: valid_16:
        !           945:        call    fix16                           // make op1 a 16-bit int
        !           946:        jnz     special_16                      // if zf=0, oflow on fix
        !           947:        cmpw    $0,rnd_history
        !           948:        je      store_16
        !           949:        orb     $inexact_mask,%gs:sr_errors
        !           950:        cmpb    true,added_one
        !           951:        jne     store_16
        !           952:        orb     $a_mask,%gs:sr_flags
        !           953: store_16:
        !           954:        movw    8+word_frac1,%ax        // move integer to memory
        !           955: pointer_16:
        !           956:        les     mem_operand_pointer(%ebp),%edi  //set es:di to location
        !           957: finish_16:
        !           958:        movw    %ax,%es:(%edi)          // store integer to mem
        !           959: //..
        !           960: //..           pushad
        !           961: //..           push    es
        !           962: //..           push    edi
        !           963: //..           push    ax
        !           964: //..           call    fpsushort
        !           965: //..           add     esp,12
        !           966: //..           popad
        !           967: //..           cld
        !           968: //..
        !           969:        jmp     pop_free                        // pop stack and go home
        !           970:        ALIGN
        !           971: special_16:
        !           972:        xorw    %ax,%ax
        !           973:        cmpb    special,tag1(%ebp)              // is operand tagged special?
        !           974:        je      pointer_16                              // yes, load memop ptr and exit
        !           975:        orb     invalid_mask,%gs:sr_errors// no, set invalid error
        !           976:        movw    $0x8000,%ax                     // load inv constant into ax
        !           977:        testb   invalid_mask,%gs:sr_masks// is invalid error masked?
        !           978:        jnz     pointer_16                              // yes, store invalid constant
        !           979:        ret
        !           980: //int16_store  endp
        !           981: //
        !           982: // ***********************************************************************
        !           983: //             fix32:
        !           984: //
        !           985: //     function:
        !           986: //              fixes valid number to a 32-bit integer.
        !           987: //
        !           988: //     inputs:
        !           989: //              operand1
        !           990: //
        !           991: //     outputs:
        !           992: //             32-bit integer in word_frac1 + 6;
        !           993: //             overflow indication in zf (zf:1 => no overflow)
        !           994: //
        !           995: //     data accessed:
        !           996: //             - offset_operand1               sign1
        !           997: //             - dword_expon1                  word_frac1
        !           998: //             - offset_operand1
        !           999: //
        !          1000: //     data changed:
        !          1001: //             - word_frac1
        !          1002: //
        !          1003: //     procedures called:
        !          1004: //             sticky_right_shift              round
        !          1005: //
        !          1006: // ***************************************************************************
        !          1007:        ALIGN
        !          1008: fix32: //proc
        !          1009:        mov     high_int32_exponent,%ecx                // calc shift amount
        !          1010:        sub     dword_expon1,%ecx                       // if expon1 > high expon
        !          1011:        js      no_fix32_ovf                                    // then overflow (zf=0)
        !          1012:        cmp     max_int32_shift,%ecx                    // dont let shift amount
        !          1013:        jbe     do_shift_32                                             // exceed max_int32_shift
        !          1014:        mov     max_int32_shift,%ecx
        !          1015: do_shift_32:
        !          1016:        mov     $offset_operand1,%edi           // shift frac1 by cl
        !          1017:        xorb    %al,%al
        !          1018:        call    sticky_right_shift
        !          1019:        mov     $offset_operand1,%edi           // round to 16-bit prec
        !          1020:        movb    prec32,%dl
        !          1021:        movb    false,%al
        !          1022:        call    round
        !          1023:        cmpb    false,%al                               // overflow if al=true
        !          1024:        jnz     no_fix32_ovf                            // round cy out (zf=1)
        !          1025:        cmpl    $0x080000000,dword_frac1+frac32(%ebp)
        !          1026:        jb      check_sign_32                           // no overflow if < 80000000h
        !          1027:        ja      no_fix32_ovf                            // else, overflow (zf=0)
        !          1028:        cmpb    negative,sign1(%ebp)    // oflow if = 80000000h and
        !          1029:        jnz     no_fix32_ovf                            // sign1 = pos (zf=0)
        !          1030: check_sign_32:
        !          1031:        movb    positive,%al                    // al is overflow flag
        !          1032:        cmpb    sign1(%ebp),%al                 // negate integer if
        !          1033:        jz      no_fix32_ovf                            // sign is neg (zf=1)
        !          1034:        negl    dword_frac1+frac32(%ebp)
        !          1035:        xorb    %al,%al                                 // no overflow (zf=1)
        !          1036: no_fix32_ovf:
        !          1037:        ret
        !          1038: //fix32        endp
        !          1039: //
        !          1040: // **************************************************************************
        !          1041: //             int32_store:
        !          1042: //
        !          1043: //     function:
        !          1044: //             stores into 32-bit integer format
        !          1045: //
        !          1046: //     input:
        !          1047: //             operand1
        !          1048: //
        !          1049: //     output:
        !          1050: //             32-bit integer in location pointed to by es:di.
        !          1051: //
        !          1052: //     data accessed:
        !          1053: //             - mem_operand_pointer           offset_operand1
        !          1054: //             - sign1                         tag1
        !          1055: //             - expon1                        word_frac1
        !          1056: //             - msb_frac1                     offset_operand1
        !          1057: //
        !          1058: //     data changed:
        !          1059: //             - word_frac1
        !          1060: //
        !          1061: //     procedures called:
        !          1062: //             pop_free
        !          1063: //             fix32
        !          1064: //
        !          1065: // **************************************************************************
        !          1066:        ALIGN
        !          1067: int32_store:   //proc
        !          1068:        cmpb    valid,tag1(%ebp)
        !          1069:        je      valid_32
        !          1070:        cmpb    denormd,tag1(%ebp)
        !          1071:        jne     special_32
        !          1072: valid_32:
        !          1073:        call    fix32                           // make op1 a 32-bit int
        !          1074:        jnz     special_32                      // if zf=0, oflow on fix
        !          1075:        cmpw    $0,rnd_history
        !          1076:        je      store_32
        !          1077:        orb     $inexact_mask,%gs:sr_errors
        !          1078:        cmpb    true,added_one
        !          1079:        jne     store_32
        !          1080:        orb     $a_mask,%gs:sr_flags
        !          1081: store_32:
        !          1082:        mov     dword_frac1+frac32(%ebp),%eax   // move integer to eax
        !          1083: pointer_32:
        !          1084:        les     mem_operand_pointer(%ebp),%edi  //set es:di to location
        !          1085: finish_32:
        !          1086:        mov     %eax,%es:(%edi)         // store integer to mem
        !          1087: //..
        !          1088: //..           pushad
        !          1089: //..           push    es
        !          1090: //..           push    edi
        !          1091: //..           push    eax
        !          1092: //..           call    fpsulong
        !          1093: //..           add     esp,12
        !          1094: //..           popad
        !          1095: //..           cld
        !          1096: //..
        !          1097:        jmp     pop_free                        // pop stack and go home
        !          1098:        ALIGN
        !          1099: special_32:
        !          1100:        xor     %eax,%eax
        !          1101:        cmpb    special,tag1(%ebp)              // is operand tagged special?
        !          1102:        je      pointer_32                              // yes, load memop ptr and exit
        !          1103:        orb     invalid_mask,%gs:sr_errors// no, set invalid error
        !          1104:        mov     $0x080000000,%eax       // load inv constant into ax
        !          1105:        testb   invalid_mask,%gs:sr_masks// is invalid error masked?
        !          1106:        jnz     pointer_32                              // yes, store invalid constant
        !          1107:        ret
        !          1108: //int32_store  endp
        !          1109: //
        !          1110: // ***********************************************************************
        !          1111: //             fix64:
        !          1112: //
        !          1113: //     function:
        !          1114: //              fixes valid number to a 64-bit integer.
        !          1115: //
        !          1116: //     inputs:
        !          1117: //              operand1
        !          1118: //
        !          1119: //     outputs:
        !          1120: //             64-bit integer in word_frac1 + 2;
        !          1121: //             overflow indication in zf (zf:1 => no overflow)
        !          1122: //
        !          1123: //     data accessed:
        !          1124: //             - offset_operand1               sign1
        !          1125: //             - dword_expon1                  word_frac1
        !          1126: //             - offset_operand1
        !          1127: //
        !          1128: //     data changed:
        !          1129: //             - word_frac1
        !          1130: //
        !          1131: //     procedures called:
        !          1132: //             sticky_right_shift              round
        !          1133: //
        !          1134: // ***************************************************************************
        !          1135:        ALIGN
        !          1136: fix64: //proc
        !          1137:        mov     high_int64_exponent,%ecx                // calc shift amount
        !          1138:        sub     dword_expon1,%ecx                       // if expon1 > high expon
        !          1139:        js      no_fix64_ovf                            // then overflow (zf=0)
        !          1140:        cmp     max_int64_shift,%ecx                    // dont let shift amount
        !          1141:        jbe     do_shift_64                             // exceed max_int64_shift
        !          1142:        mov     max_int64_shift,%ecx
        !          1143: do_shift_64:
        !          1144:        mov     $offset_operand1,%edi           // shift frac1 by cl
        !          1145:        xorb    %al,%al
        !          1146:        call    sticky_right_shift
        !          1147:        mov     $offset_operand1,%edi           // round to 64-bit prec
        !          1148:        movb    prec64,%dl
        !          1149:        movb    false,%al
        !          1150:        call    round
        !          1151:        cmpb    false,%al                               // overflow if al=true
        !          1152:        jnz     no_fix64_ovf                            // round cy out (zf=1)
        !          1153:        cmpl    $0x080000000,dword_frac1+frac32(%ebp)
        !          1154:        jb      check_sign_64                   // no overflow if < 80000000h
        !          1155:        ja      no_fix64_ovf                            // else, overflow (zf=0)
        !          1156:        cmp     $0,dword_frac1+frac64(%ebp)
        !          1157:        jnz     no_fix64_ovf
        !          1158:        cmpb    negative,sign1(%ebp)    // oflow if = 800..0h and
        !          1159:        jnz     no_fix64_ovf                            // sign1 = pos (zf=0)
        !          1160: check_sign_64:
        !          1161:        movb    positive,%al                    // al is overflow flag
        !          1162:        cmpb    sign1(%ebp),%al                 // negate integer if
        !          1163:        jz      no_fix64_ovf                            // sign is neg (zf=1)
        !          1164:        xor     %eax,%eax
        !          1165:        negl    dword_frac1+frac64(%ebp)
        !          1166:        sbb     dword_frac1+frac32(%ebp),%eax
        !          1167:        mov     %eax,dword_frac1+frac32(%ebp)
        !          1168:        xorb    %al,%al                                 // no overflow (zf=1)
        !          1169: no_fix64_ovf:
        !          1170:        ret
        !          1171: //fix64        endp
        !          1172: //
        !          1173: // *****************************************************************************
        !          1174: //                     int64_store:
        !          1175: //                     ************
        !          1176: //     function:
        !          1177: //             stores into 64-bit integer format
        !          1178: //
        !          1179: //     input:
        !          1180: //             operand1
        !          1181: //
        !          1182: //     output:
        !          1183: //             64-bit integer in memory location pointed to by es:edi.
        !          1184: //
        !          1185: //     data accessed:
        !          1186: //             - mem_operand_pointer           offset_operand1
        !          1187: //             - sign1                         tag1
        !          1188: //             - expon1                        word_frac1
        !          1189: //             - msb_frac1                     offset_operand1
        !          1190: //
        !          1191: //     data changed:
        !          1192: //             - word_frac1
        !          1193: //
        !          1194: //     procedures called:
        !          1195: //             pop_free
        !          1196: //
        !          1197: // ***************************************************************************
        !          1198:        ALIGN
        !          1199: int64_store:   //proc
        !          1200:        cmpb    valid,tag1(%ebp)
        !          1201:        je      valid_64
        !          1202:        cmpb    denormd,tag1(%ebp)
        !          1203:        jne     special_64
        !          1204: valid_64:
        !          1205:        call    fix64                           // make op1 a 64-bit int
        !          1206:        jnz     special_64                      // if zf=0, oflow on fix
        !          1207:        cmpw    $0,rnd_history
        !          1208:        je      store_64
        !          1209:        orb     $inexact_mask,%gs:sr_errors
        !          1210:        cmpb    true,added_one
        !          1211:        jne     store_64
        !          1212:        orb     $a_mask,%gs:sr_flags
        !          1213: store_64:
        !          1214:        mov     dword_frac1+frac64(%ebp),%eax   // move integer to edx:eax
        !          1215:        mov     dword_frac1+frac32(%ebp),%edx   // move integer to edx:eax
        !          1216: pointer_64:
        !          1217:        les     mem_operand_pointer(%ebp),%edi  //set es:edi to location
        !          1218: finish_64:
        !          1219:        mov     %eax,%es:(%edi)         // store low integer to low mem
        !          1220: //..
        !          1221: //..           pushad
        !          1222: //..           push    es
        !          1223: //..           push    edi
        !          1224: //..           push    eax
        !          1225: //..           call    fpsulong
        !          1226: //..           add     esp,12
        !          1227: //..           popad
        !          1228: //..           cld
        !          1229: //..
        !          1230:        mov     %edx,%es:4(%edi)                // store high integer to high mem
        !          1231: //..
        !          1232: //..           pushad
        !          1233: //..           push    es
        !          1234: //..           push    edi
        !          1235: //..           push    edx
        !          1236: //..           call    fpsulong
        !          1237: //..           add     esp,12
        !          1238: //..           popad
        !          1239: //..           cld
        !          1240: //..
        !          1241:        jmp     pop_free                        // pop stack and go home
        !          1242:        ALIGN
        !          1243: special_64:
        !          1244:        xor     %eax,%eax
        !          1245:        cltd
        !          1246:        cmpb    special,tag1(%ebp)              // is operand tagged special?
        !          1247:        je      pointer_64                              // yes, load memop ptr and exit
        !          1248:        orb     invalid_mask,%gs:sr_errors// no, set invalid error
        !          1249:        mov     $0x080000000,%edx       // load inv constant into ax
        !          1250:        testb   invalid_mask,%gs:sr_masks// is invalid error masked?
        !          1251:        jnz     pointer_64              // yes, store invalid constant
        !          1252:        ret
        !          1253: 
        !          1254: //int64_store  endp
        !          1255: //
        !          1256: //a_med        ends
        !          1257: //
        !          1258: //     end

unix.superglobalmegacorp.com

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