Annotation of kernel/machdep/i386/fp_emul/fp_status.s, revision 1.1

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