Annotation of kernel/machdep/i386/fp_emul/fp_status.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   "status.s"
                     26: 
                     27:        .ident  "@(#)kern-fp:status.s   1.1"
                     28: //$tt(*80387   emulator        + + + s t a t u s + + + *)
                     29: // ************************************************************************
                     30: //
                     31: //                        s t a t u s . 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 80387 status register
                     44: //
                     45: //     public procedures:
                     46: //             stcw                    stenv                   pop_free
                     47: //             incr_top                decr_top                save_status
                     48: //             restore_status          clear_p_error           init
                     49: //             clex                    stsw                    ldcw
                     50: //             get_precision           store_precision         get_rnd_control
                     51: //             store_rnd_control       u_masked?               z_masked?
                     52: //             d_masked?               i_masked?               o_masked?
                     53: //             get_reg_tag             affine_infinity?        get_top
                     54: //             set_p_error             p_error?                set_u_error
                     55: //             set_o_error             set_z_error             set_i_error
                     56: //             i_error?                d_error?                set_d_error
                     57: //             set_z_bit               clear_z_bit             set_s_bit
                     58: //             clear_s_bit             set_a_bit               clear_a_bits
                     59: //             set_c_bit               clear_c_bit             store_reg_tag
                     60: //             set_i_masked?           set_d_masked?           set_z_masked?
                     61: //             clear_cond_bits
                     62: //
                     63: // ************************************************************************
                     64: //
                     65: //...March 3, 1987...
                     66: //
                     67:        .data   //a_msr segment rw      public
                     68: //
                     69: //...define the 80387 status register...
                     70: //
                     71: //%gs:sr_masks:        .byte   0x07f   / bit 6 on for d-step 8087  05/21/81
                     72: //%gs:sr_controls:     .byte   0x13
                     73: //%gs:sr_reserved1:    .value  0       / reserveds take care of 386 env
                     74: //%gs:sr_errors:       .byte   0
                     75: //%gs:sr_flags:        .byte   0       / bit 2 off for sim286  09/14/83
                     76: //%gs:sr_reserved2:    .value  0
                     77: //%gs:sr_tags: .value  0x0ffff
                     78: //%gs:sr_reserved3:    .value  0
                     79: //%gs:sr_instr_offset: .long   0
                     80: //%gs:sr_instr_base:   .value  0
                     81: //%gs:sr_reserved4:    .value  0
                     82: //%gs:sr_mem_offset:   .long   0
                     83: //%gs:sr_mem_base:     .value  0
                     84: //%gs:sr_reserved5:    .value  0
                     85: //%gs:sr_regstack:     .value  40      dup(0)
                     86: //#define      a_m%gs:sr_data  %gs:sr_masks
                     87: //a_msr        ends
                     88: //     assume  %ds:a_msr
                     89: //$nolist
                     90: #include       "fp_e80387.h"
                     91: //$list
                     92: //
                     93: //     .globl  %gs:sr_mem_offset
                     94: //     .globl  %gs:sr_controls
                     95: //     .globl  %gs:sr_mem_base
                     96: //     .globl  a_m%gs:sr_data
                     97: //     .globl  %gs:sr_regstack
                     98: //     .globl  %gs:sr_flags
                     99: //     .globl  %gs:sr_masks
                    100: //     .globl  %gs:sr_errors
                    101: //     .globl  %gs:sr_instr_offset
                    102: //     .globl  %gs:sr_instr_base
                    103:        .globl  incr_top
                    104:        .globl  decr_top
                    105:        .globl  save_status
                    106:        .globl  pop_free
                    107:        .globl  ldcw
                    108:        .globl  stenv
                    109:        .globl  clex
                    110:        .globl  stsw
                    111:        .globl  stcw
                    112:        .globl  get_precision
                    113:        .globl  store_precision
                    114:        .globl  get_rnd_control
                    115:        .globl  store_rnd_control
                    116:        .globl  u_masked_
                    117:        .globl  d_masked_
                    118:        .globl  get_top
                    119:        .globl  i_masked_
                    120:        .globl  o_masked_
                    121:        .globl  get_reg_tag
                    122:        .globl  affine_infinity_
                    123:        .globl  set_p_error
                    124:        .globl  set_u_error
                    125:        .globl  set_o_error
                    126:        .globl  init
                    127:        .globl  clear_p_error
                    128:        .globl  set_i_error
                    129:        .globl  set_d_error
                    130:        .globl  i_error_
                    131:        .globl  d_error_
                    132:        .globl  p_error_
                    133:        .globl  set_z_bit
                    134:        .globl  clear_z_bit
                    135:        .globl  set_s_bit
                    136:        .globl  clear_s_bit
                    137:        .globl  set_a_bit
                    138:        .globl  clear_cond_bits
                    139:        .globl  set_c_bit
                    140:        .globl  clear_c_bit
                    141:        .globl  store_reg_tag
                    142:        .globl  set_i_masked_
                    143:        .globl  set_d_masked_
                    144:        .globl  set_z_masked_
                    145:        .globl  clear_a_bit
                    146:        .globl  restore_status
                    147:        .globl  set_stk_u_error
                    148:        .globl  set_stk_o_error
                    149:        .globl  correct_tag_word
                    150:        .globl  free_reg
                    151: //
                    152:        .text   //a_med segment er      public
                    153: //     --------to be added for unix
                    154: //..           extrn   fpfulong:far,fpfushort:far,fpsulong:far,fpsushort:far
                    155: //
                    156: // *************************************************************************
                    157: //
                    158: //     the routines in this section manipulate the status and control
                    159: //     information stored in the 80387 status data segment, a?msr.
                    160: //
                    161: // ************************************************************************
                    162: //     transfer field group:   get_precision, store_precision, get_rnd_control
                    163: //      store_rnd_control, get_top, get_reg_tag, store_reg_tag
                    164: //
                    165: //     inputs: the *get* routines require no input parameters, except for the
                    166: //             procedures get_reg_tag and store_reg_tag which expect the
                    167: //             register number to be in al and cl, respectively
                    168: //             the *store* routines input the value to be stored in al.
                    169: //
                    170: //     outputs:  get_precison returns the 2-bit precision field in dl.
                    171: //               all other routines return justified values in al.
                    172: // ************************************************************************
                    173: 
                    174:        ALIGN
                    175: get_precision: //proc
                    176:        movb    $precision_mask,%dl     // load precision field mask
                    177:        andb    %gs:sr_controls,%dl             // mask in precision control
                    178:        ret
                    179: //get_precision        endp
                    180: //
                    181:        ALIGN
                    182: store_precision:       //proc
                    183:        andb    $~precision_mask,%gs:sr_controls // clear precision
                    184:        orb     %al,%gs:sr_controls             // store new precision control
                    185:        ret
                    186: //store_precision      endp
                    187: //
                    188:        ALIGN
                    189: get_rnd_control:       //proc
                    190:        movb    %gs:sr_controls,%al             // load control byte
                    191:        andb    $rnd_control_mask,%al   // mask in rounding control
                    192:        ret
                    193: //get_rnd_control      endp
                    194: //
                    195:        ALIGN
                    196: store_rnd_control:     //proc
                    197:        andb    $~rnd_control_mask,%gs:sr_controls // clear old field
                    198:        orb     %al,%gs:sr_controls             // store new rounding control
                    199:        ret
                    200: //store_rnd_control    endp
                    201: //
                    202:        ALIGN
                    203: get_top:       //proc
                    204:        movb    %gs:sr_flags,%al                // load status flag byte
                    205:        andb    $top_mask,%al           // mask in top field
                    206:        shrb    $3,%al                  // right justify top field
                    207:        ret
                    208: //get_top      endp
                    209: //
                    210:        ALIGN
                    211: get_reg_tag:   //proc
                    212:        movzbl  %al,%eax        // form word bit count
                    213:        mov     %eax,%ecx       // store in cx
                    214:        shl     $1,%ecx         // bit count = 2 * reg num
                    215:        mov     %ecx,%ebx       // else, must examine register
                    216:        shl     $2,%ebx         // form index to %gs:sr_regstack
                    217:        add     %ecx,%ebx       // index = 10 * register num
                    218:        add     $sr_regstack,%ebx       // + start of %gs:sr_regstack
                    219:        movw    %gs:sr_tags,%ax         // load tag word
                    220:        shrw    %cl,%ax                 // shift to tag of interest
                    221:        andb    $empty,%al              // mask out other tags
                    222:        cmpb    inv,%al                 // if tag not = 2,
                    223:        jne     got_tag                 // no further decoding needed
                    224:        movw    %gs:8(%ebx),%ax // load register exponent
                    225:        andw    $0x7fff,%ax     // mask off sign bit
                    226:        jnz     check_unsupp    // if expon /= 0, check unsupported format
                    227:        movb    denormd,%al             // if exponent zero, denormal
                    228:        ret
                    229:        ALIGN
                    230: check_unsupp:
                    231:        mov     %gs:4(%ebx),%eax        // get top 32 bits of significand
                    232:        test    $0x080000000,%eax       // is highest bit set.
                    233:        jnz     check_nan                       // if so, check for nan
                    234:        movb    unsupp,%al              // if not, its an unsupported format.
                    235:        ret
                    236:        ALIGN
                    237: check_nan:
                    238:        and     $0x07fffffff,%eax       // zero out most significant bit
                    239:        or      %gs:(%ebx),%eax         // or bottom 32 bits into top 32 bits.
                    240:        movb    infinty,%al             // tentatively set tag to infinitys
                    241:        jz      got_tag                 // if fraction is 0, its infinity
                    242:        movb    inv,%al                 // fraction is non zero, so tag as nan.
                    243: got_tag:
                    244:        ret
                    245: //get_reg_tag  endp
                    246: // ************************************************************************
                    247: //     test status bit group:  u_masked?, z_masked?, d_masked?, i_masked?,
                    248: //      o_masked?, affine_infinity?, p_error?, i_error?, d_error?,
                    249: //      set_i_masked?, set_d_masked?
                    250: //
                    251: //     inputs:  no input values are required.
                    252: //
                    253: //     outputs:  all boolean function return the complemented bit value
                    254: //      in the zf.  (test with jz on bit = 0.)
                    255: // ************************************************************************
                    256:        ALIGN
                    257: u_masked_:     //proc
                    258:        testb   underflow_mask,%gs:sr_masks     // test the u mask
                    259:        ret
                    260: //u_masked_    endp
                    261: //
                    262:        ALIGN
                    263: set_d_masked_: //proc
                    264:        call    set_d_error             // set the d error
                    265: d_masked_:
                    266:        testb   denorm_mask,%gs:sr_masks        // test the d mask
                    267:        ret
                    268: //set_d_masked_        endp
                    269: //
                    270:        ALIGN
                    271: set_i_masked_: //proc
                    272:        call    set_i_error             // set the i error
                    273: i_masked_:
                    274:        testb   invalid_mask,%gs:sr_masks       // test the i mask
                    275:        ret
                    276: //set_i_masked_        endp
                    277: //
                    278:        ALIGN
                    279: o_masked_:     //proc
                    280:        testb   overflow_mask,%gs:sr_masks      // test the o mask
                    281:        ret
                    282: //o_masked_    endp
                    283: //
                    284:        ALIGN
                    285: affine_infinity_:      //proc
                    286:        testb   infinity_control_mask,%gs:sr_controls // test ic
                    287:        ret
                    288: //affine_infinity_     endp
                    289: //
                    290:        ALIGN
                    291: p_error_:      //proc
                    292:        testb   $inexact_mask,%gs:sr_errors     // test the p error
                    293:        ret
                    294: //p_error_     endp
                    295: //
                    296:        ALIGN
                    297: i_error_:      //proc
                    298:        testb   invalid_mask,%gs:sr_errors      // test the i error
                    299:        ret
                    300: //i_error_     endp
                    301: //
                    302:        ALIGN
                    303: d_error_:      //proc
                    304:        testb   denorm_mask,%gs:sr_errors       // test the d error
                    305:        ret
                    306: //d_error_     endp
                    307: // ************************************************************************
                    308: //     set and reset bit group:  set_p_error, set_u_error, set_o_error
                    309: //      set_z_masked?, set_i_error, set_d_error, clear_s_bit, clear_z_bit
                    310: //      set_s_bit, set_z_bit, set_a_bit, clear_a_bit, set_c_bit, clear_c_bit
                    311: //      clear_cond_bits, clear_p_error, set_stk_u_error, set_stk_o_error
                    312: //
                    313: //     inputs:  no input values are required.
                    314: //
                    315: //     outputs:  all procedures set or reset the indicated status bit
                    316: // ************************************************************************
                    317:        ALIGN
                    318: set_stk_u_error:       //proc
                    319:        orb     invalid_mask+zero_mask,%gs:sr_errors
                    320:        andb    $~a_mask,%gs:sr_flags   // clear the a-bit
                    321:        ret
                    322: //set_stk_u_error      endp
                    323: //
                    324:        ALIGN
                    325: set_stk_o_error:       //proc
                    326:        orb     invalid_mask+zero_mask,%gs:sr_errors
                    327:        orb     $a_mask,%gs:sr_flags            // set the a-bit
                    328:        ret
                    329: //set_stk_o_error      endp
                    330: //
                    331:        ALIGN
                    332: set_p_error:   //proc
                    333:        orb     $inexact_mask,%gs:sr_errors     // set the p-error
                    334:        ret
                    335: //set_p_error  endp
                    336: //
                    337:        ALIGN
                    338: set_u_error:   //proc
                    339:        orb     underflow_mask,%gs:sr_errors // set the u-error
                    340:        ret
                    341: //set_u_error  endp
                    342: //
                    343:        ALIGN
                    344: set_o_error:   //proc
                    345:        orb     overflow_mask,%gs:sr_errors     // set the o-error
                    346:        ret
                    347: //set_o_error  endp
                    348: //
                    349:        ALIGN
                    350: set_i_error:   //proc
                    351:        orb     invalid_mask,%gs:sr_errors      // set the i-error
                    352:        ret
                    353: //set_i_error  endp
                    354: //
                    355:        ALIGN
                    356: set_d_error:   //proc
                    357:        orb     denorm_mask,%gs:sr_errors       // set the d-error
                    358:        ret
                    359: //set_d_error  endp
                    360: //
                    361:        ALIGN
                    362: set_z_masked_: //proc
                    363:        orb     zero_divide_mask,%gs:sr_errors // set the z-error
                    364:        testb   zero_divide_mask,%gs:sr_masks // test the z mask
                    365:        ret
                    366: //set_z_masked_        endp
                    367: //
                    368:        ALIGN
                    369: set_s_bit:     //proc
                    370:        orb     $sign_mask,%gs:sr_flags // set the s-bit
                    371:        ret
                    372: //set_s_bit    endp
                    373: //
                    374:        ALIGN
                    375: set_z_bit:     //proc
                    376:        orb     $zero_mask,%gs:sr_flags // set the z-bit
                    377:        ret
                    378: //set_z_bit    endp
                    379: //
                    380:        ALIGN
                    381: set_a_bit:     //proc
                    382:        orb     $a_mask,%gs:sr_flags            // set the a-bit
                    383:        ret
                    384: //set_a_bit    endp
                    385: //
                    386:        ALIGN
                    387: set_c_bit:     //proc
                    388:        orb     $c_mask,%gs:sr_flags            // set the c-bit
                    389:        ret
                    390: //set_c_bit    endp
                    391: //
                    392:        ALIGN
                    393: clear_s_bit:   //proc
                    394:        andb    $~sign_mask,%gs:sr_flags        // clear the s-bit
                    395:        ret
                    396: //clear_s_bit  endp
                    397: //
                    398:        ALIGN
                    399: clear_z_bit:   //proc
                    400:        andb    $~zero_mask,%gs:sr_flags        // clear the z-bit
                    401:        ret
                    402: //clear_z_bit  endp
                    403: //
                    404:        ALIGN
                    405: clear_a_bit:   //proc
                    406:        andb    $~a_mask,%gs:sr_flags   // clear the a-bit
                    407:        ret
                    408: //clear_a_bit  endp
                    409: //
                    410:        ALIGN
                    411: clear_cond_bits:       //proc
                    412:        andb    $~(c_mask+zero_mask+sign_mask+a_mask),%gs:sr_flags
                    413:        ret                             // clear all condition bits
                    414: //clear_cond_bits      endp
                    415: //
                    416:        ALIGN
                    417: clear_c_bit:   //proc
                    418:        andb    $~c_mask,%gs:sr_flags   // clear the c-bit
                    419:        ret
                    420: //clear_c_bit  endp
                    421: //
                    422:        ALIGN
                    423: clear_p_error: //proc
                    424:        andb    $~inexact_mask ,%gs:sr_errors   // clear the p-error
                    425:        ret
                    426: //clear_p_error        endp
                    427: //
                    428: // ************************************************************************
                    429: //                     pop_free:
                    430: //     function:
                    431: //             pops the stack and/or frees the register(s) as required
                    432: //
                    433: // ************************************************************************
                    434:        ALIGN
                    435: pop_free:      //proc
                    436:        call    i_masked_               // is invalid masked?
                    437:        jnz     check_op1               // if so, forget error
                    438:        call    i_error_                // check for i-error
                    439:        jnz     common_return           // if error, dont pop
                    440: 
                    441: free_reg:
                    442: check_op1:
                    443:        movb    op1_use_up(%ebp),%al    // pop or free op1
                    444:        call    process_use_up
                    445:        movb    op2_use_up(%ebp),%al    // pop or free op2
                    446: process_use_up:
                    447:        cmpb    pop_stack,%al           // is it a pop_stack?
                    448:        je      pop_it                  // yes, process it
                    449:        xorb    free,%al                        // no, is it free reg?
                    450:        jnz     exit_process            // no, done with use_up
                    451:        call    get_top                 // yes, get top pointer
                    452:        addb    reg_num(%ebp),%al       // convert relative num
                    453:        andb    $0x07,%al                       //  to absolute reg num
                    454: empty_reg_tag:
                    455:        movb    %al,%cl                 // cl = reg number
                    456:        movb    $empty,%al              // al = new tag value
                    457: store_reg_tag:
                    458:        shlb    $1,%cl                  // bit count = 2 * reg num
                    459:        rorw    %cl,%gs:sr_tags         // rotate tag to low bits
                    460:        andb    $~empty,%gs:sr_tags     // clear old reg num tag
                    461:        andb    $empty,%al              // clear bits 2-7 of new tag
                    462:        orb     %al,%gs:sr_tags // store new reg num tag and
                    463:        rolw    %cl,%gs:sr_tags         //  rotate the tag word back
                    464: exit_process:
                    465:        ret
                    466: pop_it:
                    467:        call    get_top                 // pop the stack once
                    468: //     the following six instructions have been commented out to prevent
                    469: //   an invalid operation from being signaled when the 87 tos is subject
                    470: //     to a freep st(i) (*6 in the 80387 t-spec).  in other words, it will
                    471: //     be o.k. to free st(0) and decrement stackpointer, so it will also be
                    472: //   o.k. to free an already empty st(0).
                    473: //             call    get_reg_tag             ; get register tag
                    474: //             cmp     al,empty                ; is the top empty?
                    475: //             jne     pop_ok                  ; no, stack may be popped
                    476: //             call    set_i_masked?           ; yes, stack error
                    477: //             jz      exit_process            ; abort if unmasked
                    478: //pop_ok:
                    479: //             call    get_top
                    480:        call    empty_reg_tag           //set tag of top empty
                    481: //pop_free     endp                            ; enter incr_top
                    482: //
                    483: // **************************************************************************
                    484: //                     incr_top:
                    485: //     function:
                    486: //             increments stack pointer
                    487: //
                    488: // **************************************************************************
                    489:        FALLSTHRU
                    490: incr_top:      //proc
                    491:        movb    $0x08,%cl                       // load increment top constant
                    492:        jmp     adjust_top      // merge with decr_top
                    493:        ALIGN
                    494: //incr_top     endp
                    495: // **************************************************************************
                    496: //                     decr_top:
                    497: //     function:
                    498: //             decrements stack pointer
                    499: //
                    500: // **************************************************************************
                    501:        ALIGN
                    502: decr_top:      //proc
                    503:        movb    $0x38,%cl                       // load decrement top constant
                    504: adjust_top:
                    505:        movb    %gs:sr_flags,%al                // get old top
                    506:        andb    $top_mask,%al
                    507:        xorb    %al,%gs:sr_flags                // clear old top field
                    508:        addb    %cl,%al                 // increment/decrement top
                    509:        andb    $top_mask,%al           // mask off bits 6-7
                    510:        orb     %al,%gs:sr_flags                // store new top field
                    511: common_return:
                    512:        ret
                    513: //decr_top     endp
                    514: //
                    515: // ******************************************************************************
                    516: //                     restore_status:
                    517: //     function:
                    518: //             implements the 80387 ldenv instruction.
                    519: //             restores status register from memory.
                    520: //
                    521: // **********************************************************************
                    522:        ALIGN
                    523: restore_status:        //proc
                    524:        push    %ds                     // save %ds
                    525:        push    %gs
                    526:        pop     %es                     // load destination base
                    527:        lds     mem_operand_pointer(%ebp),%esi // load environment pointer
                    528:        mov     $sr_masks,%edi // load dest offset
                    529:        mov     $0x0007,%ecx            // load environment from memory
                    530:        cmpb    $1,oprnd_siz32(%ebp)    //is it a 32 bit operand
                    531:        jne     restore_status16        //no restore 16 bit status
                    532:        FAST_MOVSL_ES
                    533:        pop     %ds
                    534:        orb     $0x40,%gs:sr_masks              // set stack mask
                    535:        jmp     correct_tag_word
                    536:        ALIGN
                    537: restore_status16:                                      //16 bit protected mode
                    538:        movsw                           // mov words
                    539:        inc     %edi
                    540:        inc     %edi
                    541:        loop    restore_status16
                    542: //     ---------
                    543: 
                    544: 
                    545: //------------------------------------------------------------------------
                    546: //..           pushad
                    547: //..           push    ds
                    548: //..restore_status32:
                    549: //..           push    esi
                    550: //..           call    fpfulong
                    551: //..           pop     esi
                    552: //..           stosd
                    553: //..           add     esi,4
                    554: //..           loop    restore_status32
                    555: //..           pop     ds
                    556: //..           popad
                    557: //..           cld
                    558: //..           ret
                    559: //..restore_status16:
                    560: //..           pushad
                    561: //..           push    ds
                    562: //..restor_loop:
                    563: //..           push    esi
                    564: //..           call    fpfushort
                    565: //..           pop     esi
                    566: //..           stosw
                    567: //..           add     esi,2
                    568: //..           add     edi,2
                    569: //..           loop    restor_loop
                    570: //..           pop     ds
                    571: //..           popad
                    572: //..           cld
                    573: //---------------------------------------------------------------------
                    574:        pop     %ds
                    575:        orb     $0x40,%gs:sr_masks              // set stack mask
                    576: correct_tag_word:
                    577:        mov     $8,%ecx
                    578:        xor     %ebx,%ebx
                    579: set_tags_loop:         //looping through physical locations of 0-7 regs
                    580:        mov     $10,%eax
                    581:        mul     %ebx
                    582:        mov     $sr_regstack,%esi
                    583:        add     %eax,%esi
                    584:        mov     $0x00000003,%eax
                    585:        and     %gs:sr_tags,%eax
                    586:        cmp     $3,%eax
                    587:        je      loop_back
                    588:        movw    %gs:8(%esi),%ax
                    589:        andw    $0x7fff,%ax                     // strip off sign bit
                    590:        jz      expon_zero                              // branch if exponent 0
                    591:        testb   $0x80,%gs:7(%esi)
                    592:        jnz     max_expon_
                    593:        movb    $2,%dl                          // we have an
                    594:        jmp     set_tag                         // unsupported format
                    595:        ALIGN
                    596: max_expon_:
                    597:        cmpw    $0x7fff,%ax                     // check for invalid
                    598:        je      not_validx                      // or infinity
                    599:        movb    $0,%dl                          // operand is valid
                    600:        jmp     set_tag
                    601:        ALIGN
                    602: not_validx:
                    603:        movb    $2,%dl
                    604:        jmp     set_tag
                    605:        ALIGN
                    606: expon_zero:
                    607:        mov     %gs:4(%esi),%eax
                    608:        or      %gs:(%esi),%eax
                    609:        movb    $1,%dl                          // set tag to special
                    610:        jz      set_tag                         // if number is +/- 0
                    611:        movb    $2,%dl                          // set tag to denormd
                    612: set_tag:
                    613:        andb    $~empty,%gs:sr_tags     // clear old reg num tag
                    614:        orb     %dl,%gs:sr_tags // store new reg num tag and
                    615: loop_back:
                    616:        rorw    $2,%gs:sr_tags          //  get next two bits
                    617:        inc     %ebx
                    618:        loop    set_tags_loop
                    619:        ret
                    620: //restore_status       endp
                    621: // **************************************************************************
                    622: //                     init:
                    623: //     function:
                    624: //             implements 80387 init instruction.  intializes
                    625: //             status register including mode word and error mask.
                    626: //
                    627: // ***********************************************************************
                    628:        ALIGN
                    629: init:  //proc
                    630:        movl    $0x137f,%eax            // initialize mode word
                    631:        movw    %ax,%gs:sr_masks
                    632:        movl    $0xffffffff,%ax         // ax = 0ffffh
                    633:        movw    %ax,%gs:sr_tags         // register tags = empty
                    634:        xor     %eax,%eax               // clear a reg
                    635:        movw    %ax,%gs:sr_errors               // clear the error flags
                    636: //             and     %gs:sr_flags,not top_mask       ; top of stack = 0, cbit=0
                    637:        ret
                    638: //init endp
                    639: // ***********************************************************************
                    640: //                     ldcw:
                    641: //     function:
                    642: //             implements 80387 ldcw instruction.  80387 control word
                    643: //             loaded (from memory location specified in instruction).
                    644: //
                    645: // ***********************************************************************
                    646:        ALIGN
                    647: ldcw:  //proc
                    648:        les     mem_operand_pointer(%ebp),%ebx //get new mode word
                    649:        movw    %es:(%ebx),%ax
                    650: //..
                    651: //..           pushad
                    652: //..           push    es
                    653: //..           push    ebx
                    654: //..           call    fpfushort
                    655: //..           pop     ebx
                    656: //..           pop     es
                    657: //..           popad
                    658: //..           cld
                    659: //..
                    660:        orw     $0x40,%ax                       // set stack mask
                    661:        movw    %ax,%gs:sr_masks        // store in status reg
                    662:        ret
                    663: //ldcw endp
                    664: // **********************************************************************
                    665: //                     stenv:
                    666: //     function:
                    667: //             implements 80387 fstenv instruction.  80387 environmemt
                    668: //             stored (in memory location specified in the instruction).
                    669: //
                    670: // **********************************************************************
                    671:        ALIGN
                    672: stenv: //proc
                    673:        call    save_status             // store status to memory
                    674:        orb     $0x07f,%gs:sr_masks             // set all individual masks
                    675:        ret
                    676: //stenv        endp
                    677: // **********************************************************************
                    678: //                     clex:
                    679: //     function:
                    680: //              clears all 80387 errors set in status register
                    681: //
                    682: // **********************************************************************
                    683:        ALIGN
                    684: clex:  //proc
                    685:        movb    $0,%gs:sr_errors                // clear error byte
                    686:        ret
                    687: //clex endp
                    688: // **********************************************************************
                    689: //                        stsw
                    690: //       function:
                    691: //                stores status word in memory location.  (i.e., implements
                    692: //                fstsw instruction.)  also implements 'fstsw ax'.
                    693: //
                    694: // **********************************************************************
                    695:        ALIGN
                    696: stsw:  //proc
                    697:        movb    op2_location(%ebp),%al  // load op2 location
                    698:        cmpb    $reg,%al                        // is this fstsw ax?
                    699:        movw    %gs:sr_errors,%ax       // get status word
                    700:        je      stsw_ax                 // branch on fstsw ax
                    701: store_word:
                    702:        les     mem_operand_pointer(%ebp),%ebx
                    703:        movw    %ax,%es:(%ebx)                  // store status to memory
                    704: 
                    705: //..           pushad
                    706: //..           push    es
                    707: //..           push    ebx
                    708: //..           push    ax
                    709: //..           call    fpsushort
                    710: //..           add     esp,12
                    711: //..           popad
                    712: //..           cld
                    713: //..
                    714:        ret
                    715: stsw_ax:
                    716:        movw    %ax,saved_eax(%ebp)     // store into register ax
                    717: //                     above instruction left for completeness but the ax 
                    718: //                     really has to be restored to the EAX above the global
                    719: //                     re-entrant segment
                    720: //     movl    %eax, (offset_eax)(%ebp)
                    721:        ret
                    722: //stsw endp
                    723: // *********************************************************************
                    724: //                     stcw:
                    725: //     function:
                    726: //             stores control word in memory location. (i.e., implements
                    727: //             fstcw instruction.)
                    728: //
                    729: // *********************************************************************
                    730:        ALIGN
                    731: stcw:  //proc
                    732:        movw    %gs:sr_masks,%ax        //get control word
                    733:        andw    $0x1f7f,%ax
                    734:        orw     $0x1040,%ax             //set/reset reserved bits
                    735:        jmp     store_word              //store it
                    736:        ALIGN
                    737: //stcw endp
                    738: // *********************************************************************
                    739: //                     save_status:
                    740: //     function:
                    741: //             saves status register to location specified by
                    742: //             memory operand pointer(in es:di)
                    743: //
                    744: // *********************************************************************
                    745:        ALIGN
                    746: save_status:   //proc
                    747:        push    %ds                     // save %ds
                    748:        push    %gs
                    749:        pop     %ds                     // and set it to address sr_masks
                    750:        andw    $0x1f7f,%gs:sr_masks
                    751:        orw     $0x1040,%gs:sr_masks    //set/reset reserved bits
                    752:        mov     $sr_masks,%esi // load source offset
                    753:        les     mem_operand_pointer(%ebp),%edi // load destination pointer
                    754:        mov     $0x0007,%ecx
                    755:        cmpb    $1,oprnd_siz32(%ebp)
                    756:        jne     save_status16
                    757:        FAST_MOVSL_ES
                    758:        pop     %ds                     // restore %ds
                    759:        ret
                    760:        ALIGN
                    761: save_status16:                                 //16 bit protected mode
                    762:        movsw                           // mov words
                    763:        inc     %esi
                    764:        inc     %esi
                    765:        loop    save_status16
                    766: //------------------------------------------------------------------------
                    767: //..           pushad
                    768: //..           push    es
                    769: //..save_status32:
                    770: //..           push    edi
                    771: //..           push    dword ptr (esi)
                    772: //..           call    fpsulong
                    773: //..           add     esp,8
                    774: //..           add     esi,4
                    775: //..           add     edi,4
                    776: //..           loop    save_status32
                    777: //..           pop     es
                    778: //..           popad
                    779: //..           cld
                    780: //..           ret
                    781: //..save_status16:
                    782: //..           pushad
                    783: //..           push    es
                    784: //..save_loop:
                    785: //..           push    edi
                    786: //..           push    word ptr (esi)
                    787: //..           call    fpsushort
                    788: //..           add     esp,8
                    789: //..           add     edi,2
                    790: //..           add     esi,4
                    791: //..           loop    save_loop
                    792: //..           pop     es
                    793: //..           popad
                    794: //..           cld
                    795:        pop     %ds                     // restore %ds
                    796:        ret
                    797: //save_status  endp
                    798: //
                    799: //a_med        ends
                    800: //
                    801: //     end

unix.superglobalmegacorp.com

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