Annotation of kernel/machdep/i386/fp_emul/fp_reg.s, revision 1.1.1.1

1.1       root        1: /*
                      2:  * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
                      3:  *
                      4:  * @APPLE_LICENSE_HEADER_START@
                      5:  * 
                      6:  * Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
                      7:  * Reserved.  This file contains Original Code and/or Modifications of
                      8:  * Original Code as defined in and that are subject to the Apple Public
                      9:  * Source License Version 1.1 (the "License").  You may not use this file
                     10:  * except in compliance with the License.  Please obtain a copy of the
                     11:  * License at http://www.apple.com/publicsource and read it before using
                     12:  * this file.
                     13:  * 
                     14:  * The Original Code and all software distributed under the License are
                     15:  * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
                     16:  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
                     17:  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
                     18:  * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
                     19:  * License for the specific language governing rights and limitations
                     20:  * under the License.
                     21:  * 
                     22:  * @APPLE_LICENSE_HEADER_END@
                     23:  */
                     24: 
                     25:        .file   "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.