Annotation of kernel/machdep/i386/fp_emul/fp_reg.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   "reg.s"
        !            26: 
        !            27:        .ident  "@(#)kern-fp:reg.s      1.1"
        !            28: 
        !            29: // ****************************************************************************
        !            30: //
        !            31: //                     r e g . m o d
        !            32: //                     =============
        !            33: //
        !            34: //     ===============================================================
        !            35: //               intel corporation proprietary information
        !            36: //    this software  is  supplied  under  the  terms  of  a  license
        !            37: //    agreement  or non-disclosure agreement  with intel corporation
        !            38: //    and  may not be copied nor disclosed except in accordance with
        !            39: //    the terms of that agreement.                                  
        !            40: //     ===============================================================
        !            41: //
        !            42: //     function:
        !            43: //             operation cluster for the 80387 register stack.
        !            44: //
        !            45: //     public procedures:
        !            46: //             put_result      stack_full?     float_int16
        !            47: //             save_regs       restore_regs    set_up_indefinite
        !            48: //             getx            fetch_an_op     exchange        exam
        !            49: //             fxtrac          abs_value       chsign          put_op1_result
        !            50: //             put_si_result   do_exchange
        !            51: //
        !            52: //     internal procedures:
        !            53: //             extend_single   extend_double   get_bcd         fetch_an_op
        !            54: //             float16         float32         float64
        !            55: //
        !            56: // *****************************************************************************
        !            57: //
        !            58: //...March 3, 1987...
        !            59: //
        !            60: //$nolist
        !            61: #include       "fp_e80387.h"
        !            62: //$list
        !            63: //...declare status register segment...
        !            64: //
        !            65:        .data   //a_msr segment rw      public
        !            66: //     extrn   %gs:sr_masks,%gs:sr_errors,%gs:sr_flags,%gs:sr_regstack
        !            67: //a_msr        ends
        !            68: //
        !            69: //     assume  %ds:a_msr
        !            70: //
        !            71:        .text   //a_med segment er      public
        !            72: //
        !            73: //     extrn   store_reg_tag,decr_top,left_shift
        !            74: //     extrn   subtraction_normalize,clear_6w,test_3w
        !            75: //     extrn   move_op_to_result,save_status,set_z_bit
        !            76: //     extrn   restore_status,init,test_4w,test_6w
        !            77: //     extrn   left_shift_frac2_cl,left_shift_frac1_1
        !            78: //     extrn   left_shift_result_cl,get_top,set_i_error
        !            79: //     extrn   get_reg_tag,set_s_bit,set_d_error
        !            80: //     extrn   i_masked_,clear_c_bit,clear_cond_bits
        !            81: //     extrn   set_c_bit,set_a_bit,set_i_masked_
        !            82: //     extrn   move_op_to_op,set_stk_u_error,set_stk_o_error
        !            83: //     extrn   norm_denorm,correct_tag_word
        !            84: //     --------to be added for unix
        !            85: //..           extrn   fpfulong:far,fpfushort:far,fpsulong:far,fpsushort:far
        !            86: //
        !            87:        .globl  getx
        !            88:        .globl  fetch_an_op
        !            89:        .globl  put_result
        !            90:        .globl  stack_full_
        !            91:        .globl  fxtrac
        !            92:        .globl  float_int16
        !            93:        .globl  save
        !            94:        .globl  save_regs
        !            95:        .globl  restore_regs
        !            96:        .globl  restore
        !            97:        .globl  set_up_indefinite
        !            98:        .globl  exchange
        !            99:        .globl  exam
        !           100:        .globl  decompose
        !           101:        .globl  load
        !           102:        .globl  abs_value
        !           103:        .globl  chsign
        !           104:        .globl  put_op1_result
        !           105:        .globl  do_exchange
        !           106:        .globl  put_si_result
        !           107:        .globl  do_exchange_leave_a_bit
        !           108: //
        !           109: // *****************************************************************************
        !           110: //                     extend_single:
        !           111: //                     **************
        !           112: //     function:
        !           113: //             retrieves a single real operand from memory,
        !           114: //             extends its parts, and puts them in the operand
        !           115: //
        !           116: //     inputs:
        !           117: //             assumes mem_operand_pointer set up
        !           118: //             edi points to operand1 or operand2
        !           119: //
        !           120: //     outputs:
        !           121: //             extended operand in operand
        !           122: //
        !           123: //     data accessed:
        !           124: //             - mem_operand_pointer
        !           125: //
        !           126: //     data changed:
        !           127: //             - operands
        !           128: //
        !           129: //     procedures called:
        !           130: //             set_d_error
        !           131: //
        !           132: // ***************************************************************************
        !           133:        ALIGN
        !           134: extend_single: //proc
        !           135:        les     mem_operand_pointer(%ebp),%ebx
        !           136:        xor     %eax,%eax
        !           137:        mov     %eax,frac64(%ebp,%edi)          //clear low 5 bytes of
        !           138:        movb    %al,frac32(%ebp,%edi)   //fraction to 0
        !           139: //     ---- replace following line for unix
        !           140:        mov     %es:(%ebx),%eax                         // move 3 fraction
        !           141: 
        !           142: //..           
        !           143: //..           pushad
        !           144: //..           push    es
        !           145: //..           push    ebx
        !           146: //..           call    fpfulong
        !           147: //..           add     esp,8
        !           148: //..           popad
        !           149: //..           cld
        !           150: //..
        !           151:        mov     %eax,frac32+1(%ebp,%edi)        // bytes from memory
        !           152:        sar     $23,%eax                // get short real exponent in al
        !           153:        movb    %ah,sign(%ebp,%edi)     // transfer sign to operand
        !           154:        and     $0x000000ff,%eax        // strip sign bits (here, b8-b31)
        !           155:        movl    $0,before_error_signals(%ebp)   // initialize all to false
        !           156:        jnz     single_invalid_
        !           157:        movb    frac64+7(%ebp,%edi),%al // zero or denormalized?
        !           158:        orw     frac64+5(%ebp,%edi),%ax
        !           159:        jnz     single_denormalized
        !           160: zero_return:
        !           161:        movb    special,tag(%ebp,%edi)  // set tag to special,
        !           162:        mov     %eax,expon(%ebp,%edi)                   // expon to 0
        !           163:        ret
        !           164:        ALIGN
        !           165: single_denormalized:
        !           166:        movb    denormd,tag(%ebp,%edi)  // set tag to denormd
        !           167:        movb    true,signal_d_error_
        !           168:        testb   denorm_mask,%gs:sr_masks                // short cut for unmasked d-error
        !           169:        jnz     sngl_d_error_masked
        !           170:        ret
        !           171:        ALIGN
        !           172: sngl_d_error_masked:
        !           173:        movl    single_exp_offset+1,expon(%ebp,%edi)
        !           174:        bsrl    frac32(%ebp,%edi),%ecx
        !           175:        sub     $31,%ecx
        !           176:        neg     %ecx
        !           177:        shll    %cl,frac32(%ebp,%edi)
        !           178:        sub     %ecx,expon(%ebp,%edi)   // adjust exponent
        !           179:        ret
        !           180:        ALIGN
        !           181: single_invalid_:
        !           182:        cmpb    true,%al
        !           183:        jne     single_operand_is_valid
        !           184:        movl    $0x7fff,expon(%ebp,%edi)        //operand is inv/inf
        !           185:        testl   $0x7fffffff,frac32(%ebp,%edi)
        !           186:        movb    infinty,tag(%ebp,%edi)
        !           187:        jz      sngl_exit
        !           188:        movb    inv,tag(%ebp,%edi)              //invalid operand
        !           189:        testb   $0x40,msb(%ebp,%edi)
        !           190:        jnz     sngl_qnan
        !           191:        movb    true,signal_i_error_
        !           192: sngl_qnan:
        !           193: sngl_exit:
        !           194:        ret                                                                                                     //set tag to invalid
        !           195:        ALIGN
        !           196: single_operand_is_valid:
        !           197:        movb    valid,tag(%ebp,%edi)            //set tag to valid
        !           198:        add     single_exp_offset,%eax          //single_exp_offset,
        !           199:        mov     %eax,expon(%ebp,%edi)           //implicit bit to 1
        !           200:        orb     $0x80,frac64+7(%ebp,%edi)
        !           201:        ret
        !           202:        ALIGN
        !           203: //extend_single        endp
        !           204: //
        !           205: // ***********************************************************************
        !           206: //                     extend_double:
        !           207: //                     **************
        !           208: //     function:
        !           209: //             retrieves a double real operand from memory,
        !           210: //             extends its parts, and puts them in the operand
        !           211: //
        !           212: //     inputs:
        !           213: //             assumes mem_operand_pointer is set up
        !           214: //             edi points to operand1 or operand2
        !           215: //
        !           216: //     outputs:
        !           217: //             expanded operand in operand
        !           218: //
        !           219: //     data accessed:
        !           220: //             - mem_operand_pointer
        !           221: //
        !           222: //     data changed:
        !           223: //             - operand
        !           224: //
        !           225: //     procedures called:
        !           226: //
        !           227: //
        !           228: // *********************************************************************
        !           229:        ALIGN
        !           230: extend_double: //proc
        !           231: //     push    %ds                                                                                     // save a?msr
        !           232:        les     mem_operand_pointer(%ebp),%ebx
        !           233:        movb    $0,frac64(%ebp,%edi)                    //clear low byte of
        !           234:        mov     %es:(%ebx),%eax         //fraction to 0
        !           235: 
        !           236: //..
        !           237: //..           pushad
        !           238: //..           push    ds
        !           239: //..           push    ebx
        !           240: //..           call    fpfulong
        !           241: //..           pop             ebx
        !           242: //..
        !           243:        mov     %eax,frac64+1(%ebp,%edi)                //move 7 fraction bytes
        !           244:        mov     %es:4(%ebx),%eax                // from memory
        !           245: //..
        !           246: //..           push    ebx+4
        !           247: //..           call    fpfulong
        !           248: //..           add             esp,    8
        !           249: //..           popad
        !           250: //..           cld
        !           251: 
        !           252: //     pop     %ds                                                                     // reload a?msr
        !           253:        mov     %eax,frac32+1(%ebp,%edi)
        !           254:        sar     $20,%eax
        !           255:        cwtd
        !           256:        movb    %dl,sign(%ebp,%edi)     // transfer sign to operand
        !           257:        and     $0x000007ff,%eax        // strip sign bits (here,
        !           258:                                        // b11 - b31)
        !           259:        movl    $0,before_error_signals(%ebp)   // initialize both to false
        !           260:        jnz     double_invalid_
        !           261:        mov     frac64(%ebp,%edi),%eax          // exp=0 : is fraction 0?
        !           262:        or      frac32(%ebp,%edi),%eax
        !           263:        jnz     double_denormalized
        !           264:        jmp     zero_return
        !           265:        ALIGN
        !           266: double_denormalized:
        !           267:        movb    denormd,tag(%ebp,%edi)  // set tag to denormd
        !           268:        movb    true,signal_d_error_
        !           269:        testb   denorm_mask,%gs:sr_masks                // short cut for unmasked d-error
        !           270:        jnz     dubl_d_error_masked
        !           271:        ret
        !           272:        ALIGN
        !           273: dubl_d_error_masked:
        !           274:        movl    double_exp_offset+1+3,expon(%ebp,%edi)
        !           275:        bsrl    frac32(%ebp,%edi),%ecx
        !           276:        jz      top_28_zero
        !           277:        mov     frac64(%ebp,%edi),%eax
        !           278:        sub     $31,%ecx
        !           279:        neg     %ecx
        !           280:        shldl   %cl,%eax,frac32(%ebp,%edi)
        !           281:        shll    %cl,frac64(%ebp,%edi)
        !           282: dubl_denorm_expon:
        !           283:        sub     %ecx,expon(%ebp,%edi)   // adjust exponent
        !           284:        ret
        !           285:        ALIGN
        !           286: top_28_zero:
        !           287:        mov     frac64(%ebp,%edi),%eax
        !           288:        bsrl    %eax,%ecx
        !           289:        sub     $31,%ecx
        !           290:        neg     %ecx
        !           291:        shll    %cl,%eax
        !           292:        mov     %eax,frac32(%ebp,%edi)
        !           293:        movl    $0,frac64(%ebp,%edi)
        !           294:        add     $32,%ecx
        !           295:        jmp     dubl_denorm_expon
        !           296:        ALIGN
        !           297: double_invalid_:
        !           298:        cmpw    $0x07ff,%ax
        !           299:        jne     double_operand_is_valid
        !           300:        movl    $0x7fff,expon(%ebp,%edi)          // operand is nan or
        !           301:        andl    $0x0fffffff,frac32(%ebp,%edi) // inf. set exponent.
        !           302:        mov     frac32(%ebp,%edi),%eax    // mask expon bits
        !           303:        or      frac64(%ebp,%edi),%eax
        !           304:        movb    infinty,tag(%ebp,%edi)
        !           305:        jz      dubl_msb_set
        !           306:        movb    inv,tag(%ebp,%edi)              // invalid operand
        !           307:        testb   $0x08,msb(%ebp,%edi)
        !           308:        jnz     dubl_qnan
        !           309:        movb    true,signal_i_error_
        !           310:        testb   invalid_mask,%gs:sr_masks
        !           311:        jz      dubl_exit
        !           312: dubl_qnan:
        !           313:        jmp     norm_dubl_sgnfcnd
        !           314:        ALIGN
        !           315: double_operand_is_valid:
        !           316:        add     double_exp_offset,%eax          // double_exp_offset
        !           317:        mov     %eax,expon(%ebp,%edi)
        !           318:        movb    valid,tag(%ebp,%edi)            // set operand tag
        !           319: norm_dubl_sgnfcnd:
        !           320:        mov     frac64(%ebp,%edi),%eax
        !           321:        .byte   0x0f,0xa4,0x44,0x3d,0x08,0x03  //implements following inst.
        !           322: //     shldl   $3,%eax,frac32(%ebp,%edi)
        !           323:        shll    $3,frac64(%ebp,%edi)
        !           324: dubl_msb_set:
        !           325:        orb     $0x80,frac64+7(%ebp,%edi)       //set leading bit
        !           326: dubl_exit:
        !           327:        ret
        !           328: //extend_double        endp
        !           329: //
        !           330: // ****************************************************************************
        !           331: //                     getx:
        !           332: //                     *****
        !           333: //     function:
        !           334: //             fetches extended-format fp number from memory, unpacks it,
        !           335: //             and sets its tag
        !           336: //
        !           337: //     inputs:
        !           338: //             assumes mem_operand_pointer is set up
        !           339: //             edi points to operand1 or operand2
        !           340: //
        !           341: //     outputs:
        !           342: //             if number is valid, then exponent and msb set to all ones
        !           343: //
        !           344: //     data accessed:
        !           345: //             - mem_operand_pointer           extra_word_reg
        !           346: //
        !           347: //     data changed:
        !           348: //             - operand                       extra_word_reg
        !           349: //
        !           350: //     procedures called:
        !           351: //             test_4w                         test_3w
        !           352: //             set_d_error
        !           353: //
        !           354: // ****************************************************************************
        !           355:        ALIGN
        !           356: getx:  //proc
        !           357: //     push    %ds                                                                     // save a?msr
        !           358:        les     mem_operand_pointer(%ebp),%esi  // ds:esi ==> memop
        !           359: //
        !           360: getx_stackreg:
        !           361: //     push    %ss
        !           362: //     pop     %es                     // es:edi ==> operand
        !           363: 
        !           364:        add     $frac64,%edi            // bump di to frac64
        !           365:        push    %edi                    // save operand offset
        !           366:        lea     (%ebp,%edi),%edi
        !           367: //     mov     $0x0002,%ecx            // move first four words
        !           368:        /* FAST_MOVSL */
        !           369:        
        !           370:        movl    %es:0(%esi),%ecx
        !           371:        movl    %ecx,%ss:0(%edi)
        !           372:        movl    %es:4(%esi),%ecx
        !           373:        movl    %ecx,%ss:4(%edi)
        !           374: //     addl    $8,%esi
        !           375: //     movl    $0,%ecx
        !           376: 
        !           377:        movw    %es:8(%esi),%ax                 // get sign/expon word
        !           378: //..           pushad
        !           379: //..           push    ds
        !           380: //..rep_loop:  
        !           381: //..           push    esi
        !           382: //..           call    fpfulong
        !           383: //..           pop     esi
        !           384: //..           stosd
        !           385: //..           add     esi,4
        !           386: //..           loop    rep_loop
        !           387: //..           push    esi
        !           388: //..           call    fpfushort
        !           389: //..           add     esp,8
        !           390: //..           popad
        !           391: //..           cld
        !           392: //..
        !           393:        pop     %edi            // reload operand offset
        !           394: //     pop     %ds             // reload a?msr
        !           395:        cwtd                    // transmit sign to dx
        !           396:        movb    %dl,sign-frac64(%ebp,%edi)// and to operand
        !           397:        and     $0x7fff,%eax            // strip off sign bit
        !           398:        mov     %eax,expon-frac64(%ebp,%edi)            // store to operand
        !           399:        movl    $0,before_error_signals(%ebp)   // initialize both to false
        !           400:        jz      expon_zero                      // branch if exponent 0
        !           401:        testb   $0x80,msb-frac64(%ebp,%edi)
        !           402:        jnz     max_expon_
        !           403:        movb    unsupp,%dl                              // we have an
        !           404:        jmp     getx_set_tag                    // unsupported format
        !           405:        ALIGN
        !           406: max_expon_:
        !           407:        cmpw    $0x7fff,%ax                     // check for invalid
        !           408:        je      not_validx                      // or infinity
        !           409:        movb    valid,%dl                       // operand is valid
        !           410: getx_set_tag:
        !           411:        movb    %dl,tag-frac64(%ebp,%edi) // set operand tag
        !           412:        xor     %eax,%eax                       // (for stackreg return)
        !           413:        ret
        !           414:        ALIGN
        !           415: not_validx:
        !           416:        movb    infinty,%dl
        !           417:        mov     frac32-frac64(%ebp,%edi),%eax
        !           418:        and     $0x07fffffff,%eax
        !           419:        or      (%ebp,%edi),%eax
        !           420:        jz      getx_set_tag
        !           421:        movb    inv,%dl                         // set tag to invalid
        !           422:        jmp     getx_set_tag
        !           423:        ALIGN
        !           424: expon_zero:
        !           425:        mov     frac32-frac64(%ebp,%edi),%eax
        !           426:        or      (%ebp,%edi),%eax
        !           427:        movb    special,%dl                     // set tag to special
        !           428:        jz      getx_set_tag                    // if number is +/- 0
        !           429:        movb    denormd,%dl                     // set tag to denormd
        !           430:        jmp     getx_set_tag
        !           431:        ALIGN
        !           432: //getx endp
        !           433: //
        !           434: // ****************************************************************************
        !           435: //                     fetch_an_op:
        !           436: //                     ***********
        !           437: //     function:
        !           438: //             fetches one operand(op1 or op2) and puts its parts
        !           439: //             in operand1 or operand2
        !           440: //
        !           441: //     inputs:
        !           442: //             location of     op info in esi
        !           443: //             location of the operand in edi
        !           444: //
        !           445: //     outputs:
        !           446: //             operand parts in operand1 or operand2
        !           447: //
        !           448: //     procedures called:
        !           449: //             mem_fetch_routine               set_up_indefinite
        !           450: //             get_top
        !           451: //             getx_stackreg
        !           452: //
        !           453: // ***************************************************************************
        !           454: fetch_location:        
        !           455:        .long   from_memory,from_stack_top,from_stack_minus_1
        !           456:        .long   from_stack_plus_1,from_reg
        !           457: mem_fetch_routine:     
        !           458:        .long   extend_single,extend_double,float16,float32
        !           459:        .long   float64,getx,float16,float16,get_bcd
        !           460:        ALIGN
        !           461: fetch_an_op:   //proc
        !           462:        cmpb    $null,format(%ebp,%esi)// if format = null,
        !           463:        je      no_stack_error_on_fetch         // then no operand to get
        !           464:        xor     %ebx,%ebx
        !           465:        mov     %ebx,(%ebp,%edi)                // set low order dword of
        !           466:        movb    location(%ebp,%esi),%bl // fraction to zero
        !           467:        shl     $2,%ebx                         // handle each operand
        !           468:        jmp     *%cs:fetch_location(%ebx)               // location case separate
        !           469:        ALIGN
        !           470: from_memory:
        !           471:        movb    format(%ebp,%esi),%bl   // form table offset
        !           472:        shl     $2,%ebx
        !           473:        call    *%cs:mem_fetch_routine(%ebx)    // call routine to fetch
        !           474: no_stack_error_on_fetch:
        !           475:        xor     %eax,%eax                       // eax = 00000000h
        !           476:        ret
        !           477:        ALIGN
        !           478: from_stack_top:
        !           479:        call    get_top                 // get reg num in al
        !           480: unpack_reg:
        !           481:        call    reg_full_               // zf=1 (empty) cx=top
        !           482:        jz      from_stack_plus_1       // error if reg empty
        !           483:        mov     %ebx,%esi               // reg_full returns ebx as pointer
        !           484:                                        // to stackoffset =
        !           485:                                        //  (10*regnum) + offset regstack
        !           486:                                        // thus, ds:esi ==> regstack
        !           487: //
        !           488: //     push    %ds                     // stack a copy of a?msr
        !           489:        push    %gs                     // set ds to address register stack
        !           490:        pop     %es
        !           491:        jmp     getx_stackreg           // unpack register
        !           492:        ALIGN
        !           493: from_stack_minus_1:
        !           494:        call    get_top
        !           495:        incw    %ax
        !           496:        jmp     unpack_reg
        !           497:        ALIGN
        !           498: from_reg:
        !           499:        call    get_top
        !           500:        addb    reg_num(%ebp),%al
        !           501:        jmp     unpack_reg
        !           502:        ALIGN
        !           503: from_stack_plus_1:
        !           504:        call    set_up_indefinite               // store indefinite opr
        !           505:        incw    %ax                             // indicate stack error on return
        !           506:        ret
        !           507: 
        !           508: //fetch_an_op  endp
        !           509: //
        !           510: // *************************************************************************
        !           511: //                     get_bcd:
        !           512: //                     ********
        !           513: //     function:
        !           514: //             fetches a bcd number and converts it to an unpacked 
        !           515: //             tempreal in operand1.
        !           516: //     inputs:
        !           517: //             assumes mem_operand_pointer is set up.
        !           518: //             ignores di and uses operand2 and result fields.
        !           519: //
        !           520: //     outputs:
        !           521: //             unpacked operand in operand1
        !           522: //
        !           523: //     data accessed:
        !           524: //             - mem_operand_pointer           expon1
        !           525: //             - offset_operand1               sign1
        !           526: //             - tag1                          word_frac1
        !           527: //             - offset_operand1                       word_frac2
        !           528: //             - lsb__frac2                    offset_operand2
        !           529: //             - result_word_frac              offset_result
        !           530: //
        !           531: //     data changed:
        !           532: //             - sign1                         tag1
        !           533: //             - expon1                        word_frac1
        !           534: //             - word_frac2                    result_word_frac
        !           535: //
        !           536: //     procedures called:
        !           537: //             left_shift                      move_op_to_result
        !           538: //             subtraction_normalize           test_6w
        !           539: //
        !           540: // ******************************************************************************
        !           541:        ALIGN
        !           542: get_bcd:       //proc
        !           543: //     push    %ds                     // save a?msr
        !           544:        les     mem_operand_pointer(%ebp),%esi
        !           545: //     push    %ss                     // set up destination pointer
        !           546: //     pop     %es
        !           547:        lea     word_frac2,%edi         // es:di ==> word_frac2
        !           548: //     mov     $0x0005,%ecx
        !           549:        
        !           550:        /* FAST_MOVSW */
        !           551:        movl    %es:0(%esi),%ecx
        !           552:        movl    %ecx,%ss:0(%edi)
        !           553:        movl    %es:4(%esi),%ecx
        !           554:        movl    %ecx,%ss:4(%edi)
        !           555:        movw    %es:8(%esi),%cx
        !           556:        movw    %cx,%ss:8(%edi)
        !           557: //     addl    $10,%esi
        !           558: //     movl    $0,%ecx
        !           559: 
        !           560: //..
        !           561: //..           pushad
        !           562: //..           push    ds
        !           563: //..getbcd_loop:
        !           564: //..           push    esi
        !           565: //..           call    fpfushort
        !           566: //..           pop     esi
        !           567: //..           stosw
        !           568: //..           add     esi,2
        !           569: //..           loop    getbcd_loop
        !           570: //..           pop     ds
        !           571: //..           popad
        !           572: //..           cld
        !           573: //..
        !           574: //     pop     %ds                     // reload a?msr
        !           575:        cmpw    $0x0ffff,dword_frac1+10(%ebp)
        !           576:        jne     accept_bcd
        !           577:        mov     $offset_operand1,%edi
        !           578:        call    set_up_indefinite
        !           579:        ret
        !           580:        ALIGN
        !           581: accept_bcd:
        !           582:        movb    msb_frac2,%al   // get most significant byte
        !           583:        cbtw                            //  and transmit sign to ah
        !           584:        movb    %ah,sign1(%ebp)         // store sign into operand
        !           585:        mov     $offset_operand1,%edi   // set frac1 to 0
        !           586:        call    clear_6w
        !           587:        movb    $18,%cl                 //set loop count to 18 digits
        !           588:        FALLSTHRU
        !           589: convert_loop:
        !           590:        push    %ecx
        !           591:        movb    $4,%cl                  //shift frac2 left 4 bits to
        !           592:        call    left_shift_frac2_cl     // the next digit
        !           593:        and     $0x0f,msb_frac2 //clear previous digit
        !           594:        call    left_shift_frac1_1      // frac1 <= 10*frac1 + frac2(9):
        !           595:        mov     $offset_operand1,%esi   // 1) frac1 <= frac1 * 2
        !           596:        call    move_op_to_result       // 2) result_frac <= frac1 * 4
        !           597:        movb    $2,%cl
        !           598:        call    left_shift_result_cl
        !           599: //             mov     ax,(ebp).result_word_frac ; 3) frac1 <-- frac1 +
        !           600: //             add     word_frac1,ax           ;       result_frac
        !           601: //             mov     ax,(ebp).result_word_frac + 2
        !           602: //             adc     (ebp).word_frac1 + 2,ax
        !           603: //             mov     ax,(ebp).result_word_frac + 4
        !           604: //             adc     (ebp).word_frac1 + 4,ax
        !           605: //             mov     ax,(ebp).result_word_frac + 6
        !           606: //             adc     (ebp).word_frac1 + 6,ax
        !           607: //             mov     ax,(ebp).result_word_frac + 8
        !           608: //             adc     (ebp).word_frac1 + 8,ax
        !           609: //
        !           610:        mov     result_dword_frac(%ebp),%eax // 3) frac1 <-- frac1 +
        !           611:        xorw    %ax,%ax
        !           612:        add     %eax,dword_frac1(%ebp)          //      result_frac
        !           613:        mov     result_dword_frac+4(%ebp),%eax
        !           614:        adc     %eax,dword_frac1+4(%ebp)
        !           615:        mov     result_dword_frac+8(%ebp),%eax
        !           616:        adc     %eax,dword_frac1+8(%ebp)
        !           617:        xor     %eax,%eax                       // 4) frac1 <-- frac1 + frac(9)
        !           618:        movb    msb_frac2,%al
        !           619:        addw    %ax,word_frac1
        !           620:        movb    $0,%al
        !           621:        adc     %eax,dword_frac1+4(%ebp)
        !           622:        adc     %eax,dword_frac1+8(%ebp)
        !           623:        pop     %ecx                    //and loop
        !           624:        LOOP(convert_loop)
        !           625:        mov     $dword_frac1,%edi
        !           626:        call    test_6w                 //frac1 = 0?
        !           627:        jnz     make_floating_point
        !           628:        mov     %eax,dword_expon1               //set expon and tag for zero
        !           629:        movb    special,tag1(%ebp)
        !           630:        ret
        !           631:        ALIGN
        !           632: make_floating_point:
        !           633:        movl    $0x404e,dword_expon1    //set expon1 and normalize
        !           634:        mov     $offset_operand1,%edi
        !           635:        call    subtraction_normalize
        !           636:        movb    valid,tag1(%ebp)                //set tag to valid
        !           637:        ret
        !           638: //get_bcd      endp
        !           639: //
        !           640: // ******************************************************************************
        !           641: //                     put_result:
        !           642: //
        !           643: //     function:
        !           644: //             puts result on 80387 stack or in 80387 register.
        !           645: //             implements 80387 load instruction.
        !           646: //
        !           647: //     inputs:
        !           648: //             address of data parts  (in edi register)
        !           649: //             address of result info (in esi).
        !           650: //             (ebp).before_error_signals
        !           651: //     outputs:
        !           652: //             stack error indication (in al register).
        !           653: //
        !           654: //     data accessed:
        !           655: //
        !           656: //     data changed:
        !           657: //
        !           658: //     procedures called:
        !           659: //             decr_top                        stack_full?
        !           660: //             set_up_indefinite       store_reg_tag
        !           661: //             get_top
        !           662: //
        !           663: // ***************************************************************************
        !           664: location_case: 
        !           665:        .long   push_onto_stack
        !           666:        .long   put_in_stack_top
        !           667:        .long   put_in_stack_top_minus_1
        !           668:        .long   push_onto_stack
        !           669:        .long   put_in_reg
        !           670: //
        !           671:        ALIGN
        !           672: load:  //proc
        !           673:        jz      put_zf_in_ah                    // if zf set, no stack error
        !           674:        call    set_stk_u_error
        !           675:        testb   invalid_mask,%gs:sr_masks       // else, stack underflow error
        !           676:        jnz     put_zf_in_ah                    // if i_error masked, continue
        !           677:        ret                                     // else, return
        !           678:        ALIGN
        !           679: put_zf_in_ah:                          // if zf is set here, no stack
        !           680:        lahf                            // underflow occurred.  however,
        !           681:                                        // if zf is clear, stack underflow
        !           682:                                        // occurred and invalid is masked.
        !           683:        jnz     put_op1_result
        !           684: common_clear_a_bit:
        !           685:        andb    $~a_mask,%gs:sr_flags
        !           686: put_op1_result:
        !           687:        mov     $offset_operand1,%edi           // edi points to result record
        !           688: put_si_result:
        !           689:        mov     offset_result_rec,%esi  // merge with put_result
        !           690: put_result:
        !           691:        movzbl  location(%ebp,%esi),%ebx        //handle cases separately
        !           692:        shl     $2,%ebx
        !           693:        jmp     *%cs:location_case(%ebx)
        !           694:        ALIGN
        !           695: put_in_stack_top_minus_1:
        !           696:        call    get_top                         // put reg num of top-1 in al
        !           697:        incw    %ax
        !           698:        jmp     mask_top
        !           699:        ALIGN
        !           700: push_onto_stack:
        !           701:        sahf                    // zf clear iff stack underflow occurred with
        !           702:        jnz     push_value      //   invalid exception masked 
        !           703:        call    stack_full_                     // is top - 1 full?
        !           704:        jz      other_before_error_     // no, so detect other before errors.
        !           705:        call    set_stk_o_error         // set invalid error, stack bit, and
        !           706:                                        // c1 (a) bit
        !           707:        testb   invalid_mask,%gs:sr_masks
        !           708:        jz      exit_load                       // unmasked, so done with load
        !           709:        call    set_up_indefinite       // push indefinite as the result
        !           710:        jmp     push_value
        !           711:        ALIGN
        !           712: other_before_error_:
        !           713:        mov     before_error_signals(%ebp),%eax
        !           714:        or      %eax,%eax
        !           715:        jz      push_value
        !           716:        orb     %al,%al
        !           717:        jz      check_z_error
        !           718:        orb     invalid_mask,%gs:sr_errors
        !           719:        testb   invalid_mask,%gs:sr_masks
        !           720:        jz      exit_load                       // unmasked, so done with load
        !           721:        orb     $0x40,msb(%ebp,%edi)
        !           722:        jmp     push_value
        !           723:        ALIGN
        !           724: check_z_error:
        !           725:        orb     %ah,%ah
        !           726:        jz      signal_d_error
        !           727:        orb     zero_divide_mask,%gs:sr_errors
        !           728:        testb   zero_divide_mask,%gs:sr_masks
        !           729:        jz      exit_load                       // unmasked, so done with load
        !           730:        jmp     push_value
        !           731:        ALIGN
        !           732: signal_d_error:
        !           733:        orb     denorm_mask,%gs:sr_errors
        !           734:        testb   denorm_mask,%gs:sr_masks
        !           735:        jz      exit_load                       // unmasked, so done with load
        !           736: //     the following seven instructions were added to cope with a load from
        !           737: //     memory to (new) 87 stack top of a short_real or long_real operand.
        !           738: //     otherwise, such loads of a denormal source operand while the denormal
        !           739: //     exception is masked would incorrectly tag the loaded, normalized
        !           740: //     temporary_real operand as invalid, instead of valid.  the first four
        !           741: //     of these seven instructions have been commented out, because the
        !           742: //     executive procedure e80387 in the module *dcode* always initializes
        !           743: //     the op1_format field, even when its contents are deducible from the
        !           744: //     operation_type and op1_location fields, so it is enough to check
        !           745: //     whether the format field is single_real or double_real.
        !           746: //             cmp             (ebp).operation_type,   load_op
        !           747: //             jne             push value
        !           748: //             cmp             (ebp).op1_location,     memory_opnd
        !           749: //             jne             push_value
        !           750:        cmpb    $double_real,op1_format(%ebp)
        !           751:        ja      push_value
        !           752:        movb    valid,tag(%ebp,%edi)
        !           753: push_value:
        !           754:        call    decr_top                        // decrement top for push
        !           755: put_in_stack_top:
        !           756:        call    get_top                         // put reg num of stack top in al
        !           757:        jmp     mask_top
        !           758:        ALIGN
        !           759: put_in_reg:
        !           760:        call    get_top                         // put reg num specified in
        !           761:        addb    reg_num(%ebp),%al       // instruction in al
        !           762: mask_top:
        !           763:        and     $0x0007,%eax
        !           764:        mov     %eax,%ecx               // save reg num word in cx
        !           765:        movb    tag(%ebp,%edi),%al      // put new tag in al
        !           766:        call    store_reg_tag
        !           767:        lea     frac64(%ebp,%edi),%esi// ds:esi ==> operand frac64
        !           768:        mov     $sr_regstack,%edi       // form offset within %gs:sr_regstack
        !           769:        add     %ecx,%edi               // for result (10 * reg num)
        !           770:        shl     $2,%ecx
        !           771:        add     %ecx,%edi               // es:edi ==>  treal st(reg num)
        !           772: //     mov     $0x02,%ecx                      // count = 2 dwords
        !           773: //     push    %gs                             // set segment registers
        !           774: //     pop     %es
        !           775: //     push    %ds
        !           776: //     push    %ss
        !           777: //     pop     %ds
        !           778: 
        !           779:        /* FAST_MOVSL */
        !           780:        movl    %ss:0(%esi),%ecx
        !           781:        movl    %ecx,%gs:0(%edi)
        !           782:        movl    %ss:4(%esi),%ecx
        !           783:        movl    %ecx,%gs:4(%edi)
        !           784: //     addl    $8,%esi
        !           785: //     addl    $8,%edi
        !           786: //     movl    $0,%ecx
        !           787:        
        !           788:        movb    %ss:8(%esi),%ah                 // ah = sign of operand
        !           789:        andw    $0x8000,%ax             // form tempreal exponent
        !           790:        orw     %ss:12(%esi),%ax
        !           791: //     pop     %ds                     // reload a?msr into ds
        !           792:        movw    %ax,%gs:8(%edi)         // exponent => %gs:sr_regstack
        !           793: exit_load:
        !           794:        ret
        !           795: //load endp
        !           796: //
        !           797: // *****************************************************************************
        !           798: //                     stack_full?:
        !           799: //
        !           800: //     function:
        !           801: //             checks stack to see if an attempted push will
        !           802: //             generate a stack error.
        !           803: //
        !           804: //     inputs:
        !           805: //             tag for register on top of stack
        !           806: //
        !           807: //     outputs:
        !           808: //             zf = true if stack is empty; zf = false if stack is full.
        !           809: //
        !           810: //     procedures called:
        !           811: //             get_top                 get_reg_tag
        !           812: //
        !           813: // *****************************************************************************
        !           814:        ALIGN
        !           815: stack_full_:   //proc
        !           816:        call    get_top                 // determine reg no. of (top-1)
        !           817:        decw    %ax
        !           818: reg_full_:
        !           819:        andb    $0x07,%al
        !           820:        call    get_reg_tag
        !           821:        cmpb    $empty,%al      // if (top-1) is not empty,
        !           822: return:
        !           823:        ret                                     // then stack is full
        !           824: //stack_full_  endp
        !           825: //
        !           826: // ************************************************************************
        !           827: //                     decompose:
        !           828: //
        !           829: //     function:
        !           830: //             decomposes op1 into two parts
        !           831: //
        !           832: //     inputs:
        !           833: //             assumes op1 is set up, with tag1 /= unsupp and tag1 /= inv
        !           834: //
        !           835: //     outputs:
        !           836: //             puts the exponent, floated in op1; the fraction in op2
        !           837: //
        !           838: //     data accessed:
        !           839: //             - offset_operand                sign1
        !           840: //             - tag1                          expon1
        !           841: //             - offset_operand2               sign2
        !           842: //             - tag2                          expon2
        !           843: //
        !           844: //     data changed:
        !           845: //             - sign2                         expon2
        !           846: //
        !           847: //     procedures called:
        !           848: //             float_int32                     move_op_to_op
        !           849: //
        !           850: // ****************************************************************************
        !           851:        ALIGN
        !           852: decompose:     //proc
        !           853:        lea     dword_frac1(%ebp),%esi  // move op1 to op2
        !           854:        lea     dword_frac2(%ebp),%edi
        !           855:        call    move_op_to_op
        !           856:        cmpb    valid,tag1(%ebp)
        !           857:        jne     is_op1_denorm_
        !           858: put_sig_in_op2:
        !           859:        movl    $exponent_bias,dword_expon2     // set op2 exponent=bias
        !           860: put_exp_in_op1:
        !           861:        mov     dword_expon1,%eax       // float exp into op1
        !           862: unbias_expon:
        !           863:        sub     $exponent_bias,%eax     // first unbias it
        !           864:        mov     $offset_operand1,%edi
        !           865:        jmp     float_int32
        !           866:        ALIGN
        !           867: is_op1_denorm_:
        !           868:        cmpb    denormd,tag1(%ebp)
        !           869:        jne     op1_zero_or_inf
        !           870:        movb    true,signal_d_error_
        !           871:        testb   denorm_mask,%gs:sr_masks                // short cut if unmasked d-error
        !           872:        jz      interim_exit
        !           873:        mov     $offset_operand2,%edi
        !           874:        call    norm_denorm
        !           875:        mov     dword_expon2,%eax
        !           876:        movl    $exponent_bias,dword_expon2     // set op2 exponent=bias
        !           877:        jmp     unbias_expon
        !           878:        ALIGN
        !           879: op1_zero_or_inf:
        !           880:        cmpb    special,tag1(%ebp)
        !           881:        je      op1_zero                        // op1 and op2 are infinite
        !           882:        movb    positive,sign1(%ebp)
        !           883: interim_exit:
        !           884:        ret
        !           885:        ALIGN
        !           886: op1_zero:
        !           887:        movb    true,signal_z_error_            // if number=0, signal z-error
        !           888:        testb   zero_divide_mask,%gs:sr_masks   // if z_error is unmasked
        !           889:        jz      interim_exit                    // then just return
        !           890: make_op1_negative_inf:
        !           891:        movl    $0x07fff,dword_expon1           // else, make op1 -infinity
        !           892:        movb    $0x80,msb_frac1
        !           893:        movl    infinty*0x10000+NEGATIVE,sign1(%ebp)
        !           894:        ret
        !           895: //decompose    endp
        !           896: //
        !           897: // **************************************************************************
        !           898: //                     float16:
        !           899: //
        !           900: //     function:
        !           901: //             retrieves a 16-bit, 2s complement integer from memory,
        !           902: //             and fills in the operand
        !           903: //
        !           904: //     inputs:
        !           905: //             assumes mem_operand_pointer is set up
        !           906: //             edi points to operand1 or operand2
        !           907: //
        !           908: //     outputs:
        !           909: //             operand
        !           910: //
        !           911: //     data accessed:
        !           912: //             - mem_operand_pointer
        !           913: //
        !           914: //     data changed:
        !           915: //             - operand
        !           916: //
        !           917: //     procedures called:
        !           918: //             float_int32
        !           919: //
        !           920: // ***************************************************************************
        !           921:        ALIGN
        !           922: float16:       //proc
        !           923:        les     mem_operand_pointer(%ebp),%ebx  // fetch the
        !           924:                                                // 16-bit integer
        !           925:        movw    %es:(%ebx),%ax
        !           926: //..
        !           927: //..           pushad
        !           928: //..           push    es
        !           929: //..           push    ebx
        !           930: //..           call    fpfushort
        !           931: //..           add     esp,8
        !           932: //..           popad
        !           933: //..           cld
        !           934: //..
        !           935: float_int16:
        !           936:        movswl  %ax,%eax
        !           937:        jmp     float_int32
        !           938:        ALIGN
        !           939: //
        !           940: //
        !           941: //
        !           942: // *****************************************************************************
        !           943: //                     float32:
        !           944: //
        !           945: //     function:
        !           946: //             retrieves a 32-bit, 2s complement integer from memory
        !           947: //             and fills in the operand
        !           948: //
        !           949: //     inputs:
        !           950: //             assumes mem_operand_pointer is set up
        !           951: //             edi points to operand1 or operand2
        !           952: //
        !           953: //     outputs:
        !           954: //             operand
        !           955: //
        !           956: //     data accessed:
        !           957: //             - mem_operand_pointer
        !           958: //
        !           959: //     data changed:
        !           960: //             - operand
        !           961: //
        !           962: //     procedures called:
        !           963: //
        !           964: //
        !           965: // *****************************************************************************
        !           966: float32:
        !           967:        les     mem_operand_pointer(%ebp),%ebx
        !           968: 
        !           969:        mov     %es:(%ebx),%eax                 // move from memory to eax
        !           970: 
        !           971: //..
        !           972: //..           pushad
        !           973: //..           push    es
        !           974: //..           push    ebx
        !           975: //..           call    fpfulong
        !           976: //..           add     esp,8
        !           977: //..           popad
        !           978: //..           cld
        !           979: 
        !           980: float_int32:
        !           981:        mov     %eax,%edx                       // save integer in edx
        !           982:        xor     %eax,%eax                       // clear low 8 bytes
        !           983:        mov     %eax,(%ebp,%edi)
        !           984:        mov     %eax,frac64(%ebp,%edi)
        !           985:        or      %edx,%eax                       // if integer is zero,
        !           986:        jnz     get_sign_and_mag_32             // then load +0
        !           987:        mov     %eax,frac32(%ebp,%edi)
        !           988:        movb    %al,sign(%ebp,%edi)
        !           989:        movb    special,tag(%ebp,%edi)
        !           990:        mov     %eax,expon(%ebp,%edi)
        !           991:        ret
        !           992:        ALIGN
        !           993: get_sign_and_mag_32:
        !           994:        cltd                                    // transmit sign to edx
        !           995:        movb    %dl,sign(%ebp,%edi)             // and store to operand
        !           996:        jns     positive_int                            // branch if positive
        !           997:        neg     %eax                                    // negate if negative
        !           998: positive_int:
        !           999:        bsrl    %eax,%ecx
        !          1000:        sub     $31,%ecx
        !          1001:        neg     %ecx
        !          1002:        shl     %cl,%eax
        !          1003:        mov     %eax,frac32(%ebp,%edi)  // store normalized{abs(int)}
        !          1004:        mov     $0x401e,%eax                            // load valid exponent
        !          1005:        sub     %ecx,%eax
        !          1006:        mov     %eax,expon(%ebp,%edi)
        !          1007:        movb    valid,tag(%ebp,%edi)
        !          1008:        ret
        !          1009:        ALIGN
        !          1010: //float16      endp
        !          1011: //
        !          1012: // ******************************************************************************
        !          1013: //                     float64:
        !          1014: //
        !          1015: //     function:
        !          1016: //             retrieves a 64-bit, 2s complement integer from memory
        !          1017: //             and fills in the operand
        !          1018: //
        !          1019: //     inputs:
        !          1020: //             assumes mem_operand_pointer is set up
        !          1021: //             edi points to operand1 or operand2
        !          1022: //
        !          1023: //     outputs:
        !          1024: //             operand
        !          1025: //
        !          1026: //     data accessed:
        !          1027: //             - mem_operand_pointer
        !          1028: //
        !          1029: //     data changed:
        !          1030: //             - operand
        !          1031: //
        !          1032: //     procedures called:
        !          1033: //
        !          1034: //
        !          1035: // ****************************************************************************
        !          1036:        ALIGN
        !          1037: float64:       //proc
        !          1038: //     push    %ds                                     // save a?msr
        !          1039:        les     mem_operand_pointer(%ebp),%esi
        !          1040: //     push    %ss
        !          1041: //     pop     %es                             // es:edi ==> operand
        !          1042:        push    %edi                            // save op? offset
        !          1043:        lea     frac64(%ebp,%edi),%edi  // set operand offset
        !          1044: //     mov     $0x0002,%ecx            // move fraction from
        !          1045: 
        !          1046:        /* FAST_MOVSL */
        !          1047:        movl    %es:0(%esi),%ecx
        !          1048:        movl    %ecx,%ss:0(%edi)
        !          1049:        movl    %es:4(%esi),%ecx
        !          1050:        movl    %ecx,%ss:4(%edi)
        !          1051: //     addl    $8,%esi
        !          1052: //     addl    $8,%edi
        !          1053: //     movl    $0,%ecx
        !          1054: 
        !          1055: //..
        !          1056: //..           pushad
        !          1057: //..           push    ds
        !          1058: //..float64_loop:
        !          1059: //..           push    esi
        !          1060: //..           call    fpfulong
        !          1061: //..           pop     esi
        !          1062: //..           add     esi,4
        !          1063: //..           stosd
        !          1064: //..           loop    float64_loop
        !          1065: //..           pop     ds
        !          1066: //..           popad
        !          1067: //..           cld
        !          1068: //..
        !          1069:        pop     %edi                    // reload operand offset
        !          1070: //     pop     %ds                                     // reload a?msr
        !          1071:        mov     frac32(%ebp,%edi),%eax          // get long integer sign
        !          1072:        cltd                    // transmit sign to edx
        !          1073:        movb    %dl,sign(%ebp,%edi)     // and store to operand
        !          1074:        inc     %edx                    // test for '-' fract
        !          1075:        jnz     detect_zero_64
        !          1076:        notl    frac64(%ebp,%edi)               // '-', so form 2s
        !          1077:        add     $1,frac64(%ebp,%edi)    // complement
        !          1078:        notl    frac32(%ebp,%edi)
        !          1079:        adc     $0,frac32(%ebp,%edi)
        !          1080:        jmp     set_expon_64
        !          1081:        ALIGN
        !          1082: detect_zero_64:
        !          1083:        or      frac64(%ebp,%edi),%eax
        !          1084:        jnz     set_expon_64
        !          1085:        mov     %eax,expon(%ebp,%edi)                   // set expon = zero
        !          1086:        movb    special,tag(%ebp,%edi)
        !          1087:        ret
        !          1088:        ALIGN
        !          1089: set_expon_64:
        !          1090:        movl    $0x403e,expon(%ebp,%edi)        //set expon = 63
        !          1091:        bsrl    frac32(%ebp,%edi),%ecx
        !          1092:        jz      top_32_zero
        !          1093:        mov     frac64(%ebp,%edi),%eax
        !          1094:        sub     $31,%ecx
        !          1095:        neg     %ecx
        !          1096:        shldl   %cl,%eax,frac32(%ebp,%edi)
        !          1097:        shl     %cl,frac64(%ebp,%edi)
        !          1098: adjust_norm_expon:
        !          1099:        sub     %ecx,expon(%ebp,%edi)   // adjust exponent
        !          1100:        ret
        !          1101:        ALIGN
        !          1102: top_32_zero:
        !          1103:        mov     frac64(%ebp,%edi),%eax
        !          1104:        bsrl    %eax,%ecx
        !          1105:        sub     $31,%ecx
        !          1106:        neg     %ecx
        !          1107:        shl     %cl,%eax
        !          1108:        mov     %eax,frac32(%ebp,%edi)
        !          1109:        movl    $0,frac64(%ebp,%edi)
        !          1110:        add     $32,%ecx
        !          1111:        jmp     adjust_norm_expon
        !          1112:        ALIGN
        !          1113: //float64      endp
        !          1114: //
        !          1115: // ***************************************************************************
        !          1116: //                     save:
        !          1117: //
        !          1118: //     function:
        !          1119: //             implements 80387 save instruction
        !          1120: //
        !          1121: //     inputs:
        !          1122: //
        !          1123: //     outputs:
        !          1124: //
        !          1125: //     data accessed:
        !          1126: //             - mem_operand_pointer           result_rec_offset
        !          1127: //
        !          1128: //     data changed:
        !          1129: //
        !          1130: //     procedures called:
        !          1131: //             save_status             save_regs       init
        !          1132: //
        !          1133: // **************************************************************************
        !          1134:        ALIGN
        !          1135: save:  //proc
        !          1136:        call    save_status
        !          1137:        call    save_regs
        !          1138:        jmp     init                    // initialize environment
        !          1139: //save endp
        !          1140: //
        !          1141: // *************************************************************************
        !          1142: //                     save_regs:
        !          1143: //
        !          1144: //     function:
        !          1145: //             saves all registers in contiguous memory locations.
        !          1146: //
        !          1147: //     inputs:
        !          1148: //             memory operand pointer (in es:(di))
        !          1149: //
        !          1150: //     outputs:
        !          1151: //
        !          1152: //     data accessed:
        !          1153: //
        !          1154: //     data changed:
        !          1155: //
        !          1156: //     procedures called:
        !          1157: //             get_top
        !          1158: //
        !          1159: // ***************************************************************************
        !          1160:        ALIGN
        !          1161: save_regs:     //proc
        !          1162:        movb    $5,%cl                          // 5 words per register
        !          1163:        call    get_top                         // ax = top * 5
        !          1164:        push    %ds                             // set source seg register
        !          1165:        push    %gs
        !          1166:        pop     %ds
        !          1167:        mulb    %cl
        !          1168:        movw    $40,%cx                         // number words to move
        !          1169:        subw    %ax,%cx                         // from top of stack =
        !          1170:        mov     $sr_regstack,%esi               //  40 - top*5
        !          1171:        push    %esi                            // starting address =
        !          1172:        cwtl
        !          1173:        add     %eax,%esi                       //  %gs:sr_regstack + top*5
        !          1174:        add     %eax,%esi                       //  *2 bytes/word
        !          1175:        movzwl  %cx,%ecx
        !          1176:        FAST_MOVSW
        !          1177:        movw    %ax,%cx                         // move (top * 5) words
        !          1178:        pop     %esi                            // load starting address
        !          1179:        FAST_MOVSW
        !          1180:        pop     %ds                             // restore %ds
        !          1181:        ret
        !          1182: //save_regs    endp
        !          1183: //
        !          1184: // *****************************************************************************
        !          1185: //                     restore_regs:
        !          1186: //
        !          1187: //     function:
        !          1188: //             loads all registers from contiguous memory locations
        !          1189: //             implements 80387 restore instruction
        !          1190: //
        !          1191: //     inputs:
        !          1192: //             mem_operand_pointer
        !          1193: //
        !          1194: //     outputs:
        !          1195: //             loads the %gs:sr_regstack area of a?msr from memory
        !          1196: //
        !          1197: //     data accessed:
        !          1198: //
        !          1199: //     data changed:
        !          1200: //             - operand
        !          1201: //
        !          1202: //     procedures called:
        !          1203: //             restore_status                  get_top
        !          1204: //
        !          1205: // *************************************************************************
        !          1206:        ALIGN
        !          1207: restore:       //proc
        !          1208:        call    restore_status                  // this call defines es
        !          1209: restore_regs:
        !          1210:        movb    $5,%cl                          // 5 words per register
        !          1211:        call    get_top
        !          1212:        push    %ds                             // save a?msr
        !          1213: //     pop     %es
        !          1214: //     push    %ds
        !          1215:        mulb    %cl                             // ax = top*5
        !          1216:        mov     $40,%ecx                                // number words to move
        !          1217:        subw    %ax,%cx                         // from top of stack =
        !          1218:        mov     $sr_regstack,%edi               //  40 - top*5
        !          1219:        push    %edi                            // starting address =
        !          1220:        cwtl
        !          1221:        add     %eax,%edi                               //  %gs:sr_regstack + top*5
        !          1222:        add     %eax,%edi                               //  *2 bytes/word
        !          1223:        lds     mem_operand_pointer(%ebp),%esi  // source is in memory
        !          1224:        add     $14,%esi
        !          1225:        cmpb    $1,oprnd_siz32(%ebp)    //is it a 32 bit operand
        !          1226:        jne     status16                //no restore 16 bit status
        !          1227:        add     $14,%esi                                // skip the environment
        !          1228: //     --------replace following line for unix
        !          1229: status16:
        !          1230:        FAST_MOVSW
        !          1231: 
        !          1232: //..
        !          1233: //..           pushad
        !          1234: //..           push    ds
        !          1235: //..restor_loop:
        !          1236: //..           push    esi
        !          1237: //..           call    fpfushort
        !          1238: //..           pop     esi
        !          1239: //..           stosw
        !          1240: //..           add     esi,2
        !          1241: //..           loop    restor_loop
        !          1242: //..           pop     ds
        !          1243: //..           popad
        !          1244: //..           cld
        !          1245: //..
        !          1246:        movw    %ax,%cx
        !          1247:        pop     %edi                            // load starting address
        !          1248:        FAST_MOVSW
        !          1249:        pop     %ds                             // reload a?msr
        !          1250:        jmp     correct_tag_word
        !          1251: 
        !          1252: //     ret
        !          1253: //restore      endp
        !          1254: //
        !          1255: // *****************************************************************************
        !          1256: //                     set_up_indefinite:
        !          1257: //
        !          1258: //     function:
        !          1259: //             puts indefinite in the operand pointed to by edi
        !          1260: //
        !          1261: //     input:
        !          1262: //             edi points to operand
        !          1263: //
        !          1264: //     output:
        !          1265: //             indefinite in operand,  eax = 0, zf set (zf = 1)
        !          1266: //
        !          1267: //     data accessed:
        !          1268: //             - operand
        !          1269: //
        !          1270: //     data changed:
        !          1271: //             - operand
        !          1272: //
        !          1273: // ****************************************************************************
        !          1274:        ALIGN
        !          1275: set_up_indefinite:     //proc
        !          1276:        xor     %eax,%eax
        !          1277:        mov     %eax,frac64(%ebp,%edi)  //set up indef fraction
        !          1278:        movl    $0x0c0000000,frac32(%ebp,%edi)
        !          1279:        movb    negative,sign(%ebp,%edi) //set sign negative
        !          1280:        movl    $0x7fff,expon(%ebp,%edi)         //set exponent to 7fffh
        !          1281:        movb    inv,tag(%ebp,%edi)                       //set tag to invalid
        !          1282: common_return:
        !          1283:        ret
        !          1284:        ALIGN
        !          1285: //set_up_indefinite    endp
        !          1286: //
        !          1287: // ***********************************************************************
        !          1288: //                     exchange
        !          1289: //
        !          1290: //
        !          1291: //     function:
        !          1292: //             implements 80387 exchange instruction
        !          1293: //
        !          1294: //     inputs:
        !          1295: //             operand(s) in operands
        !          1296: //
        !          1297: //     outputs:
        !          1298: //             result(s) on stack
        !          1299: //
        !          1300: //     data accessed:
        !          1301: //             - result_rec_offset             offset_operand1
        !          1302: //
        !          1303: //     data changed:
        !          1304: //
        !          1305: //     procedures called:
        !          1306: //             put_result                      set_stk_u_error
        !          1307: //
        !          1308: // *************************************************************************
        !          1309:        ALIGN
        !          1310: exchange:      //proc
        !          1311:        jz      do_exchange             // if zf clear, then stack error
        !          1312:        call    set_stk_u_error
        !          1313:        testb   invalid_mask,%gs:sr_masks
        !          1314:        jz      common_return                   // if unmasked error, do nothing
        !          1315: do_exchange:
        !          1316: //     call    common_clear_a_bit              / put op1(top) in result(reg)
        !          1317:        and     $~a_mask,%gs:sr_flags
        !          1318: do_exchange_leave_a_bit:
        !          1319:        call    put_op1_result
        !          1320: set_zf_put_second_result:
        !          1321:        xor     %eax,%eax                               // set 86 zf
        !          1322:        lahf                                    // save set zf in ah
        !          1323: put_second_result:
        !          1324:        mov     $offset_operand2,%edi   // put op2(reg) in res2(top)
        !          1325:        mov     offset_result2_rec,%esi
        !          1326:        jmp     put_result
        !          1327: //exchange     endp
        !          1328: //
        !          1329: // ***********************************************************************
        !          1330: //                     exam:
        !          1331: //
        !          1332: //     function:
        !          1333: //             implements 80387 fxam instruction
        !          1334: //
        !          1335: //     inputs:
        !          1336: //             operand1
        !          1337: //
        !          1338: //     outputs:
        !          1339: //             operand type indicators set
        !          1340: //
        !          1341: //     data accessed:
        !          1342: //             - tag1                          sign1
        !          1343: //             - msb_frac1
        !          1344: //
        !          1345: //     data changed:
        !          1346: //
        !          1347: //     procedures called:
        !          1348: //
        !          1349: // ***********************************************************************
        !          1350:        ALIGN
        !          1351: exam:  //proc
        !          1352:        jz      something_on_stack      // branch on no stack error
        !          1353:        orb     $(zero_mask+sign_mask),%gs:sr_flags     // set s and z bits
        !          1354:        andb    $~(a_mask+c_mask),%gs:sr_flags  // clear a and c bits
        !          1355:        jmp     check_a_bit
        !          1356:        ALIGN
        !          1357: something_on_stack:
        !          1358:        andb    $~(zero_mask+c_mask+a_mask+sign_mask),%gs:sr_flags
        !          1359:                                        // clear condition code bits
        !          1360:        movb    tag1(%ebp),%al
        !          1361:        cmpb    unsupp,%al
        !          1362:        je      check_a_bit
        !          1363:        cmpb    inv,%al                         // remove special cases
        !          1364:        je      check_z_s_a_bits
        !          1365:        cmpb    infinty,%al
        !          1366:        je      set_c_to_one
        !          1367:        cmpb    denormd,%al
        !          1368:        jne     valid_or_zero
        !          1369:        orb     $(zero_mask+c_mask),%gs:sr_flags        // set s, z, c to 0, 1, 1
        !          1370:                                        // for denormalized op
        !          1371:        jmp     check_a_bit
        !          1372:        ALIGN
        !          1373: valid_or_zero:
        !          1374:        testb   $0x80,msb_frac1         // for valid or zero,
        !          1375:        jz      check_z_s_a_bits        // set c to msb of frac
        !          1376: set_c_to_one:
        !          1377:        orb     $c_mask,%gs:sr_flags
        !          1378: check_z_s_a_bits:
        !          1379:        rorb    $1,%al                          // set z-bit to lsb of tag1
        !          1380:        jnc     check_s_a_bits
        !          1381:        orb     $zero_mask,%gs:sr_flags
        !          1382: check_s_a_bits:
        !          1383:        rorb    $1,%al                          // set s-bit to lsb-1 of tag1
        !          1384:        jnc     check_a_bit
        !          1385:        orb     $sign_mask,%gs:sr_flags
        !          1386: check_a_bit:
        !          1387:        testb   $0x01,sign1(%ebp)       // set a-bit to sign bit
        !          1388:        jz      exchange_return
        !          1389:        orb     $a_mask,%gs:sr_flags    // set_a_bit
        !          1390: exchange_return:
        !          1391:        ret
        !          1392: //exam endp
        !          1393: //
        !          1394: // ***********************************************************************
        !          1395: //                     fxtrac:
        !          1396: //
        !          1397: //     function:
        !          1398: //             implements the 80387 fxtrac instruction
        !          1399: //
        !          1400: //     inputs:
        !          1401: //
        !          1402: //     outputs:
        !          1403: //             decomposed results in results
        !          1404: //
        !          1405: //     data accessed:
        !          1406: //             - result_rec_offset             result2_rec_offset
        !          1407: //             - offset_operand1               tag1
        !          1408: //             - offset_operand2
        !          1409: //
        !          1410: //     data changed:
        !          1411: //
        !          1412: //     procedures called:
        !          1413: //             set_up_indefinite               decompose
        !          1414: //             do_exchange     
        !          1415: //
        !          1416: // ***********************************************************************
        !          1417:        ALIGN
        !          1418: fxtrac:        //proc
        !          1419:        jz      detect_i_error  // branch if no stack error
        !          1420:        call    set_stk_u_error // set invalid error and stack bit, but
        !          1421:                                                // clear c1 (a) bit
        !          1422:        testb   invalid_mask,%gs:sr_masks
        !          1423:        jz      quick_out                       // branch if error unmasked
        !          1424:        mov     $offset_operand2,%edi           // for masked invalid error,
        !          1425:        call    set_up_indefinite                       // set op2 to indefinite
        !          1426:        orb     true,%al                        // clear zf to indicate that
        !          1427:        lahf                                    // stack underflow occurred.
        !          1428:        jmp     put_second_result
        !          1429:        ALIGN
        !          1430: detect_i_error:
        !          1431:        call    stack_full_
        !          1432:        jz      other_i_error_
        !          1433:        jmp     set_zf_put_second_result
        !          1434:        ALIGN
        !          1435: other_i_error_:
        !          1436:        andb    $~a_mask,%gs:sr_flags   // clear a-bit
        !          1437:        movl    $0,before_error_signals(%ebp)   // initialize all to zero
        !          1438:        movb    tag1(%ebp),%al                          // load operand tag
        !          1439:        cmpb    unsupp,%al
        !          1440:        jne     is_op1_nan_
        !          1441:        testb   invalid_mask,%gs:sr_masks       // short cut if unmasked i-error
        !          1442:        jnz     put_indef_in_op1
        !          1443: unmasked_i_error:
        !          1444:        orb     invalid_mask, %gs:sr_errors
        !          1445: quick_out:
        !          1446:        ret                     // return if unmasked error
        !          1447:        ALIGN
        !          1448: put_indef_in_op1:
        !          1449:        mov     $offset_operand1, %edi
        !          1450:        call    set_up_indefinite
        !          1451:        jmp     masked_i_error
        !          1452:        ALIGN
        !          1453: is_op1_nan_:
        !          1454:        cmpb    inv,%al
        !          1455:        jne     do_decompose
        !          1456:        testb   $0x40,msb_frac1                 // is op1 a signaling nan?
        !          1457:        jnz     op1_is_qnan
        !          1458:        testb   invalid_mask,%gs:sr_masks
        !          1459:        jz      unmasked_i_error
        !          1460:        orb     $0x40,msb_frac1                         // make op1 a quiet nan
        !          1461: masked_i_error:
        !          1462:        movb    true, signal_i_error_
        !          1463: op1_is_qnan:
        !          1464:        lea     dword_frac1(%ebp),%esi  // move op1 to op2
        !          1465:        lea     dword_frac2(%ebp),%edi
        !          1466:        call    move_op_to_op
        !          1467:        call    put_op1_result                          // no push occurs here
        !          1468:        jmp     set_zf_put_second_result                // put both results
        !          1469:        ALIGN
        !          1470: do_decompose:
        !          1471:        call    decompose
        !          1472:        jmp     do_exchange             // put both results
        !          1473:        ALIGN
        !          1474: //fxtrac       endp
        !          1475: //
        !          1476: // ***********************************************************************
        !          1477: //                     abs_value:
        !          1478: //
        !          1479: //     function:
        !          1480: //             implements the 80387 absolute value instruction
        !          1481: //
        !          1482: //     inputs:
        !          1483: //             assumes operand is set up
        !          1484: //
        !          1485: //     outputs:
        !          1486: //             absolute value of operand in result
        !          1487: //
        !          1488: //     procedures called:
        !          1489: //             set_stk_u_error
        !          1490: //
        !          1491: // ***************************************************************************
        !          1492:        ALIGN
        !          1493: abs_value:     //proc
        !          1494:        jz      do_abs_value                    // branch if no stack error
        !          1495:        call    set_stk_u_error         // set invalid error and stack bit,
        !          1496:                                        // but clear c1 (a) bit
        !          1497:        testb   invalid_mask,%gs:sr_masks
        !          1498:        jnz     abs_value_result        // masked error, so give indef already
        !          1499: common_exit:                           // set up in operand1 by fetch_an_op.
        !          1500:        ret                             // unmasked error
        !          1501:        ALIGN
        !          1502: do_abs_value:
        !          1503:        movb    positive,sign1(%ebp)// set sign to positive
        !          1504: abs_value_result:
        !          1505:        jmp     common_clear_a_bit              // put result on stack
        !          1506: //abs_value    endp
        !          1507: //
        !          1508: // ***********************************************************************
        !          1509: //                     chsign:
        !          1510: //
        !          1511: //     function:
        !          1512: //             implement the 80387 chsign instruction
        !          1513: //
        !          1514: //     inputs:
        !          1515: //             operand1
        !          1516: //
        !          1517: //     outputs:
        !          1518: //             result <==  -(operand1)
        !          1519: //
        !          1520: //     procedures called:
        !          1521: //             set_stk_u_error
        !          1522: //
        !          1523: // ************************************************************************
        !          1524:        ALIGN
        !          1525: chsign:        //proc
        !          1526:        jz      do_chsign                       // branch if no stack error
        !          1527:        call    set_stk_u_error // set invalid error and stack bit, but
        !          1528:                                                // clear c1 (a) bit
        !          1529:        testb   invalid_mask,%gs:sr_masks
        !          1530:        jnz     chsign_result           // put op1, set up as qnan indefinite
        !          1531:        ret                             // by fetch_an_op, into result
        !          1532:        ALIGN
        !          1533: do_chsign:
        !          1534:        notb    sign1(%ebp)                     // complement sign
        !          1535: chsign_result:
        !          1536:        jmp     common_clear_a_bit              // put op1 into result
        !          1537:        ALIGN
        !          1538: //chsign       endp
        !          1539: //
        !          1540: //a_med        ends
        !          1541: //
        !          1542: //     end

unix.superglobalmegacorp.com

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