Annotation of kernel/machdep/i386/fp_emul/fp_dcode.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   "dcode.s"
        !            26: 
        !            27:        .ident  "@(#)kern-fp:dcode.s    1.1"
        !            28: 
        !            29: // *************************************************************************
        !            30: //
        !            31: //                     d c o d e .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: //             converts the 80387 instruction into information
        !            44: //               about the first operand, information about the
        !            45: //               second operand, information about the result, 
        !            46: //               and the operation type.  defines mem_operand_ptr.
        !            47: //
        !            48: //     public procedures:
        !            49: //             e80387
        !            50: //
        !            51: // ****************************************************************************
        !            52: //
        !            53: //...March 3, 1987...
        !            54: //
        !            55: //        .file   *a_mdc*
        !            56: //$nolist
        !            57: #include       "fp_e80387.h"
        !            58: //$list
        !            59: //
        !            60: //...declare stack segment...
        !            61: //
        !            62: //stack        stackseg        200
        !            63: //
        !            64: //...declare status register segment...
        !            65: //
        !            66:        .data   //a_msr segment rw      public
        !            67: //     extrn   sr_masks,sr_errors,sr_instr_offset
        !            68: //     extrn   sr_instr_base,sr_mem_offset,sr_mem_base
        !            69: //a_msr        ends
        !            70: //
        !            71: //...declare status register selector segment...
        !            72: //
        !            73:        .data   //a_msrs        segment rw      public
        !            74: // a_msr_selector: .long   a_msr
        !            75: //a_msrs       ends
        !            76: //
        !            77:        .text   //a_med segment er      public
        !            78: //
        !            79: //     extrn   load,store,chsign,compar
        !            80: //     extrn   arith,ldcw,save,restore
        !            81: //     extrn   free_reg,abs_value,init,log
        !            82: //     extrn   fxtrac,splog,exp,tan
        !            83: //     extrn   arctan,sqrt,remr,intpt
        !            84: //     extrn   scale,exchange,restore_status
        !            85: //     extrn   stenv,stcw,stsw,load_con
        !            86: //     extrn   decr_top,incr_top,clex,exam
        !            87: //     extrn   fetch_an_op,sin,cos,sincos
        !            88: //     extrn   rem1
        !            89: //
        !            90:        .globl  _e80387
        !            91: 
        !            92: // --------------------------------------JKD-----------------------
        !            93: 
        !            94: // --------------------------------------JKD-----------------------
        !            95: 
        !            96: //        .globl  a_msr_selector
        !            97: //
        !            98: // *********************************************************************
        !            99: //
        !           100: //     address table for instruction group decoding handlers
        !           101: //
        !           102: // *********************************************************************
        !           103:                                                // 10-9-8  (mod = 3)::1
        !           104: group_handler:  
        !           105:        .long   arith_short_real        //  0 0 0  0
        !           106:        .long   arith_top_reg           //  0 0 0  1
        !           107:        .long   load_short_real         //  0 0 1  0
        !           108:        .long   transcendentals         //  0 0 1  1
        !           109:        .long   arith_short_int         //  0 1 0  0
        !           110:        .long   double_pop              //  0 1 0  1
        !           111:        .long   load_short_int          //  0 1 1  0
        !           112:        .long   administrative          //  0 1 1  1
        !           113:        .long   arith_long_real         //  1 0 0  0
        !           114:        .long   arith_reg_top           //  1 0 0  1
        !           115:        .long   load_long_real          //  1 0 1  0
        !           116:        .long   store_reg               //  1 0 1  1
        !           117:        .long   arith_word_int          //  1 1 0  0
        !           118:        .long   arith_reg_pop           //  1 1 0  1
        !           119:        .long   load_word_int           //  1 1 1  0
        !           120:        .long   transfer_status         //  1 1 1  1
        !           121: // *********************************************************************
        !           122: //
        !           123: //     address table for r/m decoding handlers
        !           124: //
        !           125: // *********************************************************************
        !           126: rm_handler:    
        !           127:        .long   rm_0                    // ea = (bx) + (si) + disp
        !           128:        .long   rm_1                    // ea = (bx) + (di) + disp
        !           129:        .long   rm_2                    // ea = (bp) + (si) + disp
        !           130:        .long   rm_3                    // ea = (bp) + (di) + disp
        !           131:        .long   rm_4                    // ea = (si) + disp
        !           132:        .long   rm_5                    // ea = (di) + disp
        !           133:        .long   rm_6                    // ea = (bp) + disp*
        !           134:        .long   rm_7                    // ea = (bx) + disp
        !           135: // *********************************************************************
        !           136: //
        !           137: //     address table for 32 bit base register decoding handlers
        !           138: //
        !           139: // *********************************************************************
        !           140: base32:        
        !           141:        .long   base_0                  // ea = (eax) + disp
        !           142:        .long   base_1                  // ea = (ecx) + disp
        !           143:        .long   base_2                  // ea = (edx) + disp
        !           144:        .long   base_3                  // ea = (ebx) + disp
        !           145:        .long   base_4                  // ea = (esp) + disp
        !           146:        .long   base_5                  // ea = (ebp) + disp*
        !           147:        .long   base_6                  // ea = (esi) + disp
        !           148:        .long   base_7                  // ea = (edi) + disp
        !           149: // *********************************************************************
        !           150: //
        !           151: //     address table for 32 bit index register decoding handlers
        !           152: //
        !           153: // *********************************************************************
        !           154: index32:       
        !           155:        .long   index_0                 // ea = (eax*ss) 
        !           156:        .long   index_1                 // ea = (ecx*ss) 
        !           157:        .long   index_2                 // ea = (edx*ss) 
        !           158:        .long   index_3                 // ea = (ebx*ss) 
        !           159:        .long   index_4                 // ea = (esp*ss) 
        !           160:        .long   index_5                 // ea = (ebp*ss) 
        !           161:        .long   index_6                 // ea = (esi*ss) 
        !           162:        .long   index_7                 // ea = (edi*ss) 
        !           163: // *********************************************************************
        !           164: //
        !           165: //     address table for instruction operations
        !           166: //
        !           167: // *********************************************************************
        !           168: op_table:      
        !           169:        .long   load,store,chsign,compar,free_reg,arith,arith,arith
        !           170:        .long   arith,ldcw,save,restore,free_reg,abs_value,init
        !           171:        .long   fxtrac,two_arg_trans,two_arg_trans,exp,tan
        !           172:        .long   two_arg_trans,sqrt,remr,intpt,scale
        !           173:        .long   exchange,free_reg,restore_status,stenv,stcw,stsw
        !           174:        .long   load_con,load_con,load_con,load_con,load_con,load_con
        !           175:        .long   load_con,decr_top,incr_top,clex,compar,exam,sin,cos,sincos
        !           176:        .long   remr,compar
        !           177: //
        !           178: // *********************************************************************
        !           179: //
        !           180: //     arithmetic operation type decode table
        !           181: //
        !           182: // *********************************************************************
        !           183:                                                //          5-4-3
        !           184:        ALIGN
        !           185: group_0a_0b_2a_4a_4b_6a_6b_op: 
        !           186:        .byte   add_op  // fadd     0 0 0
        !           187:        .byte   mul_op                  // fmul     0 0 1
        !           188:        .byte   compar_op               // fcom     0 1 0
        !           189:        .byte   compar_pop              // fcomp    0 1 1
        !           190:        .byte   sub_op                  // fsub     1 0 0
        !           191:        .byte   subr_op                 // fsubr    1 0 1
        !           192:        .byte   div_op                  // fdiv     1 1 0
        !           193:        .byte   divr_op                 // fdivr    1 1 1
        !           194: //
        !           195: // *********************************************************************
        !           196: //
        !           197: //     control word/environment operation type decode table
        !           198: //
        !           199: // *********************************************************************
        !           200:                                                //          5-4-3
        !           201:        ALIGN
        !           202: group_1a_op:   
        !           203:        .byte   load_op                 // fld      0 0 0
        !           204:        .byte   error_op                // reserved 0 0 1
        !           205:        .byte   store_op                // fst      0 1 0
        !           206:        .byte   store_pop               // fstp     0 1 1
        !           207:        .byte   ldenv_op                // fldenv   1 0 0
        !           208:        .byte   ldcw_op                 // fldcw    1 0 1
        !           209:        .byte   stenv_op                // fstenv   1 1 0
        !           210:        .byte   stcw_op                 // fstsw    1 1 1
        !           211: //
        !           212: // *********************************************************************
        !           213: //
        !           214: //     load/exchange/nop operation decode table
        !           215: //
        !           216: // *********************************************************************
        !           217:                                                //          5-4-3-2-1-0
        !           218:        ALIGN
        !           219: group_1ba_op:  
        !           220:        .byte   load_op                 // fld      0 0 0 r e g
        !           221:        .byte   exchange_op             // fxch     0 0 1 r e g
        !           222:        .byte   null_op                 // fnop     0 1 1 r e g
        !           223:        .byte   store_pop               // fstp *   0 1 1 r e g
        !           224: //
        !           225: // *********************************************************************
        !           226: //
        !           227: //     transcendental operation decode table
        !           228: //
        !           229: // *********************************************************************
        !           230:                                                //          5-4-3-2-1-0
        !           231:        ALIGN
        !           232: group_1bb_op:  
        !           233:        .byte   chsign_op               // fchs     1 0 0 0 0 0
        !           234:        .byte   abs_op                  // fabs     1 0 0 0 0 1
        !           235:        .byte   error_op                // reserved 1 0 0 0 1 0
        !           236:        .byte   error_op                // reserved 1 0 0 0 1 1
        !           237:        .byte   test_op                 // ftst     1 0 0 1 0 0
        !           238:        .byte   exam_op                 // fxam     1 0 0 1 0 1
        !           239:        .byte   error_op                // reserved 1 0 0 1 1 0
        !           240:        .byte   error_op                // reserved 1 0 0 1 1 1
        !           241:        .byte   load_1_op               // fld1     1 0 1 0 0 0
        !           242:        .byte   load_l2t_op             // fldl2t   1 0 1 0 0 1
        !           243:        .byte   load_l2e_op             // fldl2e   1 0 1 0 1 0
        !           244:        .byte   load_pi_op              // fldpi    1 0 1 0 1 1
        !           245:        .byte   load_lg2_op             // fldlg2   1 0 1 1 0 0
        !           246:        .byte   load_ln2_op             // fldln2   1 0 1 1 0 1
        !           247:        .byte   load_0_op               // fldz     1 0 1 1 1 0
        !           248:        .byte   error_op                // reserved 1 0 1 1 1 1
        !           249:        .byte   exp_op                  // f2xm1    1 1 0 0 0 0
        !           250:        .byte   log_op                  // fyl2x    1 1 0 0 0 1
        !           251:        .byte   tan_op                  // fptan    1 1 0 0 1 0
        !           252:        .byte   arctan_op               // fpatan   1 1 0 0 1 1
        !           253:        .byte   fxtrac_op               // fxtract  1 1 0 1 0 0
        !           254:        .byte   rem1_op                 // fprem1   1 1 0 1 0 1
        !           255:        .byte   decstp_op               // fdecstp  1 1 0 1 1 0
        !           256:        .byte   incstp_op               // fincstp  1 1 0 1 1 1
        !           257:        .byte   remr_op                 // fprem    1 1 1 0 0 0
        !           258:        .byte   splog_op                // fyl2xp1  1 1 1 0 0 1
        !           259:        .byte   sqrt_op                 // fsqrt    1 1 1 0 1 0
        !           260:        .byte   sincos_op               // fsincos  1 1 1 0 1 1
        !           261:        .byte   intpt_op                // frndint  1 1 1 1 0 0
        !           262:        .byte   scale_op                // fscale   1 1 1 1 0 1
        !           263:        .byte   sin_op                  // fsin     1 1 1 1 1 0
        !           264:        .byte   cos_op              // fcos     1 1 1 1 1 1
        !           265: //
        !           266: // *********************************************************************
        !           267: //
        !           268: //     tempreal/bcd/short integer/long integer operation decode table
        !           269: //
        !           270: // *********************************************************************
        !           271:                                                //          5-4-3
        !           272:        ALIGN
        !           273: group_3a_7a_op:        
        !           274:        .byte   load_op                 // fild     0 0 0
        !           275:        .byte   error_op                // reserved 0 0 1
        !           276:        .byte   store_op                // fist     0 1 0
        !           277:        .byte   store_pop               // fistp    0 1 1
        !           278:        .byte   load_op                 // (fbld)   1 0 0
        !           279:        .byte   load_op                 // f(i)ld   1 0 1
        !           280:        .byte   store_pop               // (fbstp)  1 1 0
        !           281:        .byte   store_pop               // f(i)stp  1 1 1
        !           282: //
        !           283: // *********************************************************************
        !           284: //
        !           285: //     clear exception/initialize operation decode table
        !           286: //
        !           287: // *********************************************************************
        !           288:                                                //          5-4-3-2-1-0
        !           289:        ALIGN
        !           290: group_3b_op:   
        !           291:        .byte   null_op                 // feni     1 0 0 0 0 0
        !           292:        .byte   null_op                 // fdisi    1 0 0 0 0 1
        !           293:        .byte   cler_op                 // fclex    1 0 0 0 1 0
        !           294:        .byte   init_op                 // finit    1 0 0 0 1 1
        !           295:        .byte   null_op                 // fsetpm   1 0 0 1 0 0
        !           296:        .byte   error_op                // reserved 1 0 0 1 0 1
        !           297:        .byte   error_op                // reserved 1 0 0 1 1 0
        !           298:        .byte   error_op                // reserved 1 0 0 1 1 1
        !           299: //
        !           300: // *********************************************************************
        !           301: //
        !           302: //     restore/save operation decode table
        !           303: //
        !           304: // *********************************************************************
        !           305:                                                //          5-4-3
        !           306:        ALIGN
        !           307: group_5a_op:   
        !           308:        .byte   load_op                 // fld      0 0 0
        !           309:        .byte   error_op                // reserved 0 0 1
        !           310:        .byte   store_op                // fst      0 1 0
        !           311:        .byte   store_pop               // fstp     0 1 1
        !           312:        .byte   restore_op              // frstor   1 0 0
        !           313:        .byte   error_op                // reserved 1 0 1
        !           314:        .byte   save_op                 // fsave    1 1 0
        !           315:        .byte   stsw_op                 // fstsw    1 1 1
        !           316: //
        !           317: // *********************************************************************
        !           318: //
        !           319: //     free register/store operation decode table
        !           320: //
        !           321: // *********************************************************************
        !           322:                                                //          5-4-3
        !           323:        ALIGN
        !           324: group_5b_op:   
        !           325:        .byte   free_op                 // ffree    0 0 0
        !           326:        .byte   exchange_op             // fxch *   0 0 1
        !           327:        .byte   store_op                // fst      0 1 0
        !           328:        .byte   store_pop               // fstp     0 1 1
        !           329:        .byte   ucom_op                 // fucom    1 0 0
        !           330:        .byte   ucom_pop                // fucomp   1 0 1
        !           331:        .byte   error_op                // reserved 1 1 0
        !           332:        .byte   error_op                // reserved 1 1 1
        !           333: //
        !           334: // *********************************************************************
        !           335: //
        !           336: //     transfer status operation decode table
        !           337: //
        !           338: // *********************************************************************
        !           339:                                                //          5-4-3
        !           340:        ALIGN
        !           341: group_7b_op:   
        !           342:        .byte   free_op                 // ffree *  0 0 0
        !           343:        .byte   exchange_op             // fxch *   0 0 1
        !           344:        .byte   store_pop               // fstp *   0 1 0
        !           345:        .byte   store_pop               // fstp *   0 1 1
        !           346:        .byte   stsw_op                 // fstsw    1 0 0
        !           347:        .byte   error_op                // reserved 1 0 1
        !           348:        .byte   error_op                // reserved 1 1 0
        !           349:        .byte   error_op                // reserved 1 1 1
        !           350: //
        !           351: // *********************************************************************
        !           352: //
        !           353: //     load/store environment/control word operand 1 loc/for table
        !           354: //
        !           355: // *********************************************************************
        !           356:                                                     //          5-4-3
        !           357:        ALIGN
        !           358: group_1a_op1_lf:       
        !           359:        .value  memory_opnd*0x100+single_real // fld      0 0 0
        !           360:        .value  null*0x100+null              // reserved 0 0 1
        !           361:        .value  stack_top*0x100+extended_fp   // fst      0 1 0
        !           362:        .value  stack_top*0x100+extended_fp   // fstp     0 1 1
        !           363:        .value  null*0x100+null               // fldenv   1 0 0
        !           364:        .value  null*0x100+null               // fldcw    1 0 1
        !           365:        .value  null*0x100+null              // fstenv   1 1 0
        !           366:        .value  null*0x100+null              // fstcw    1 1 1
        !           367: //
        !           368: // *********************************************************************
        !           369: //
        !           370: //       transcendental operand/result format codes
        !           371: //
        !           372: // *********************************************************************
        !           373: //
        !           374: #define        null_fmt        0
        !           375: #define        top_fmt         1       
        !           376: #define        topm1_fmt       2       
        !           377: #define        topp1_fmt       3
        !           378: #define        op1     0x40
        !           379: #define        op2     0x10
        !           380: #define        res1    4
        !           381: #define        res2    1
        !           382: //
        !           383: //     transcendental operand/result form at types
        !           384: //
        !           385: // #define     fprem_type      op1*top_fmt+op2*topm1_fmt+res1*top_fmt
        !           386: #define        fprem_type      0x64
        !           387: // #define     fyl2x_type      op1*top_fmt+op2*topm1_fmt+res1*topm1_fmt
        !           388: #define        fyl2x_type      0x68
        !           389: #define        fdecstp_type    null_fmt
        !           390: #define        fchs_type       op1*top_fmt+res1*top_fmt
        !           391: #define        fld1_type       res1*topp1_fmt
        !           392: #define        ftst_type       op1*top_fmt
        !           393: // #define     fptan_type      op1*top_fmt+res1*top_fmt+res2*topp1_fmt
        !           394: #define        fptan_type      0x47
        !           395: // #define     fpatan_type     op1*topm1_fmt+op2*top_fmt+res1*topm1_fmt
        !           396: #define        fpatan_type     0x98
        !           397: #define        fscale_type     op1*topm1_fmt+op2*top_fmt+res1*top_fmt
        !           398: //
        !           399: //fsin_type   equ op1*top_fmt + res1*top_fmt
        !           400: //fcos_type   equ op1*top_fmt + res1*top_fmt
        !           401: //
        !           402: //     operand/result format/location table
        !           403: //
        !           404:        ALIGN
        !           405: group_1bb_lf:  
        !           406:        .value  null                                    // null_fmt
        !           407:        .value  stack_top*0x100+extended_fp             // top_fmt
        !           408:        .value  stack_top_minus_1*0x100+extended_fp     // topm1_fmt
        !           409:        .value  stack_top_plus_1*0x100+extended_fp      // topp1_fmt
        !           410: //
        !           411: // *********************************************************************
        !           412: //
        !           413: //     transcendental operand/result format/location type table
        !           414: //
        !           415: // *********************************************************************
        !           416:                                                //          5-4-3-2-1-0
        !           417:        ALIGN
        !           418: group_1bb_type:        
        !           419:        .byte   fchs_type               // fchs     1 0 0 0 0 0
        !           420:        .byte   fchs_type               // fabs     1 0 0 0 0 1
        !           421:        .byte   fdecstp_type            // reserved 1 0 0 0 1 0
        !           422:        .byte   fdecstp_type            // reserved 1 0 0 0 1 1
        !           423:        .byte   ftst_type               // ftst     1 0 0 1 0 0
        !           424:        .byte   ftst_type               // fxam     1 0 0 1 0 1
        !           425:        .byte   fdecstp_type            // reserved 1 0 0 1 1 0
        !           426:        .byte   fdecstp_type            // reserved 1 0 0 1 1 1
        !           427:        .byte   fld1_type               // fld1     1 0 1 0 0 0
        !           428:        .byte   fld1_type               // fldl2t   1 0 1 0 0 1
        !           429:        .byte   fld1_type               // fldl2e   1 0 1 0 1 0
        !           430:        .byte   fld1_type               // fldpi    1 0 1 0 1 1
        !           431:        .byte   fld1_type               // fldlg2   1 0 1 1 0 0
        !           432:        .byte   fld1_type               // fldln2   1 0 1 1 0 1
        !           433:        .byte   fld1_type               // fldz     1 0 1 1 1 0
        !           434:        .byte   fdecstp_type            // reserved 1 0 1 1 1 1
        !           435:        .byte   fchs_type               // f2xm1    1 1 0 0 0 0
        !           436:        .byte   fyl2x_type              // fyl2x    1 1 0 0 0 1
        !           437:        .byte   fptan_type              // fptan    1 1 0 0 1 0
        !           438:        .byte   fpatan_type             // fpatan   1 1 0 0 1 1
        !           439:        .byte   fptan_type              // fxtract  1 1 0 1 0 0
        !           440:        .byte   fprem_type              // fprem1   1 1 0 1 0 1
        !           441:        .byte   fdecstp_type            // fdecstp  1 1 0 1 1 0
        !           442:        .byte   fdecstp_type            // fincstp  1 1 0 1 1 1
        !           443:        .byte   fprem_type              // fprem    1 1 1 0 0 0
        !           444:        .byte   fyl2x_type              // fyl2xp1  1 1 1 0 0 1
        !           445:        .byte   fchs_type               // fsqrt    1 1 1 0 1 0
        !           446:        .byte   fptan_type              // fsincos  1 1 1 0 1 1
        !           447:        .byte   fchs_type               // frndint  1 1 1 1 0 0
        !           448:        .byte   fscale_type             // fscale   1 1 1 1 0 1
        !           449:        .byte   fchs_type               // fsin     1 1 1 1 1 0
        !           450:        .byte   fchs_type               // fcos     1 1 1 1 1 1
        !           451: //
        !           452: // *********************************************************************
        !           453: //
        !           454: //     load/store short integer/tempreal operand 1 format table
        !           455: //
        !           456: // *********************************************************************
        !           457:                                                //          5-4-3
        !           458:        ALIGN
        !           459: group_3a_op1_fmt:      
        !           460:        .byte   int32                   // fild     0 0 0
        !           461:        .byte   null                    // reserved 0 0 1
        !           462:        .byte   extended_fp             // fist     0 1 0
        !           463:        .byte   extended_fp             // fistp    0 1 1
        !           464:        .byte   null                    // reserved 1 0 0
        !           465:        .byte   extended_fp             // fld      1 0 1
        !           466:        .byte   null                    // reserved 1 1 0
        !           467:        .byte   extended_fp             // fstp     1 1 1
        !           468: // *********************************************************************
        !           469: //
        !           470: //     load/store integer/tempreal/bcd operand 1 location table
        !           471: //
        !           472: // *********************************************************************
        !           473:                                                //          5-4-3
        !           474:        ALIGN
        !           475: group_3a_7a_op1_loc:   
        !           476:        .byte   memory_opnd             // fild     0 0 0
        !           477:        .byte   null                    // reserved 0 0 1
        !           478:        .byte   stack_top               // fist     0 1 0
        !           479:        .byte   stack_top               // fistp    0 1 1
        !           480:        .byte   memory_opnd             // (fbld)   1 0 0
        !           481:        .byte   memory_opnd             // f(i)ld   1 0 1
        !           482:        .byte   stack_top               // (fbstp)  1 1 0
        !           483:        .byte   stack_top               // f(i)stp  1 1 1
        !           484: //
        !           485: // *********************************************************************
        !           486: //
        !           487: //     load/store short integer/tempreal result format table
        !           488: //
        !           489: // *********************************************************************
        !           490:                                                //          5-4-3
        !           491:        ALIGN
        !           492: group_3a_res_fmt:      
        !           493:        .byte   extended_fp             // fild     0 0 0
        !           494:        .byte   null                    // reserved 0 0 1
        !           495:        .byte   int32                   // fist     0 1 0
        !           496:        .byte   int32                   // fistp    0 1 1
        !           497:        .byte   null                    // reserved 1 0 0
        !           498:        .byte   extended_fp             // fld      1 0 1
        !           499:        .byte   null                    // reserved 1 1 0
        !           500:        .byte   extended_fp             // fstp     1 1 1
        !           501: // *********************************************************************
        !           502: //
        !           503: //     load/store integer/tempreal/bcd result location table
        !           504: //
        !           505: // *********************************************************************
        !           506:                                                //          5-4-3
        !           507:        ALIGN
        !           508: group_3a_7a_res_loc:   
        !           509:        .byte   stack_top               // fild     0 0 0
        !           510:        .byte   null                    // reserved 0 0 1
        !           511:        .byte   memory_opnd             // fist     0 1 0
        !           512:        .byte   memory_opnd             // fistp    0 1 1
        !           513:        .byte   stack_top_plus_1        // (fbld)   1 0 0
        !           514:        .byte   stack_top_plus_1        // f(i)ld   1 0 1
        !           515:        .byte   memory_opnd             // (fbstp)  1 1 0
        !           516:        .byte   memory_opnd             // f(i)stp  1 1 1
        !           517: //
        !           518: // *********************************************************************
        !           519: //
        !           520: //     load/store state/status word operand 1 loc/for table
        !           521: //
        !           522: // *********************************************************************
        !           523:                                                     //          5-4-3
        !           524:        ALIGN
        !           525: group_5a_op1_lf:       
        !           526:        .value  memory_opnd*0x100+double_real // fld      0 0 0
        !           527:        .value  null*0x100+null              // reserved 0 0 1
        !           528:        .value  stack_top*0x100+extended_fp   // fst      0 1 0
        !           529:        .value  stack_top*0x100+extended_fp   // fstp     0 1 1
        !           530:        .value  null*0x100+null               // frstor   1 0 0
        !           531:        .value  null*0x100+null              // reserved 1 0 1
        !           532:        .value  null*0x100+null              // fsave    1 1 0
        !           533:        .value  null*0x100+null              // fstsw    1 1 1
        !           534: // *********************************************************************
        !           535: //
        !           536: //     bcd/long integer operand 1 format table
        !           537: //
        !           538: // *********************************************************************
        !           539:                                                //          5-4-3
        !           540:        ALIGN
        !           541: group_7a_op1_fmt:      
        !           542:        .byte   int16                   // fild     0 0 0
        !           543:        .byte   null                    // reserved 0 0 1
        !           544:        .byte   extended_fp             // fist     0 1 0
        !           545:        .byte   extended_fp             // fistp    0 1 1
        !           546:        .byte   bcd                     // fbld     1 0 0
        !           547:        .byte   int64                   // fild     1 0 1
        !           548:        .byte   extended_fp             // fbstp    1 1 0
        !           549:        .byte   extended_fp             // fistp    1 1 1
        !           550: //
        !           551: // *********************************************************************
        !           552: //
        !           553: //     bcd/long integer result format table
        !           554: //
        !           555: // *********************************************************************
        !           556:                                                //          5-4-3
        !           557:        ALIGN
        !           558: group_7a_res_fmt:      
        !           559:        .byte   extended_fp             // fild     0 0 0
        !           560:        .byte   null                    // reserved 0 0 1
        !           561:        .byte   int16                   // fist     0 1 0
        !           562:        .byte   int16                   // fistp    0 1 1
        !           563:        .byte   extended_fp             // fbld     1 0 0
        !           564:        .byte   extended_fp             // fild     1 0 1
        !           565:        .byte   bcd                     // fbstp    1 1 0
        !           566:        .byte   int64                   // fistp    1 1 1
        !           567: // for the return from e80387
        !           568:        .set    KFL, 0x3bfff            // clear NT bit in flags
        !           569:         .text
        !           570: // ***********************************************************************
        !           571: //                     e80387:
        !           572: //
        !           573: //     function:
        !           574: //             executive program for 80387 emulator.
        !           575: //             decode instruction, i.e. separate operation,operand
        !           576: //             and result info; get memory operand pointer.
        !           577: //
        !           578: //     inputs:
        !           579: //             instruction (in memory).
        !           580: //
        !           581: //     outputs:
        !           582: //             op1, op2, operation, result, result2, and memory operand
        !           583: //             pointer info
        !           584: //
        !           585: //     data accessed:
        !           586: //             - op1_format                    op1_location
        !           587: //             - op1_use_up                    op2_format
        !           588: //             - op2_location                  op2_use_up
        !           589: //             - operation_type                result_location
        !           590: //             - result_format                 result2_format
        !           591: //             - result2_location
        !           592: //
        !           593: //     data changed:
        !           594: //             - mem_operand_pointer           op1_location
        !           595: //             - op1_format                    op1_use_up
        !           596: //             - op2_format                    op2_location
        !           597: //             - op2_use_up                    result_location
        !           598: //             - result_format                 result2_format
        !           599: //             - result2_location
        !           600: //
        !           601: // ***************************************************************************
        !           602: //     assume  %ds:a_med
        !           603: //     ---------------------JKD
        !           604: //     .data
        !           605: //LJKD:
        !           606: //     .string         * ADDRESS is %x %x\n*
        !           607: //     .text
        !           608: //
        !           609: //     ---------------------JKD
        !           610:        ALIGN
        !           611: _e80387:       //proc
        !           612:        movl    %esp, %ebp
        !           613:        movl    0x4(%ebp),%esp          // pick up state pointer.
        !           614:        subl    $(WORK_AREA_SIZE),%esp // stack space
        !           615:        mov     %esp,%ebp               //set bp to global_reentrant_seg
        !           616:        
        !           617:        /* establish addressibility to the floating point state */
        !           618:        push    $FPSTATESEL             // set window to fp registers
        !           619:        pop     %gs                     // in u area
        !           620: 
        !           621:         /* clear the work area */
        !           622:         lea     work_area(%ebp),%edi
        !           623:         xorl    %eax,%eax
        !           624:         movl    $WORK_AREA_WORDS,%ecx    // number of longs to clear.
        !           625:        
        !           626:        FALLSTHRU
        !           627: 1:
        !           628:         movl    %eax,0(%edi)
        !           629:        addl    $4,%edi
        !           630:        decl    %ecx
        !           631:        testl   %ecx,%ecx
        !           632:        jg      1b
        !           633: 
        !           634: /* always 32 bits */
        !           635: //     movb    $0, is16bit(%ebp)       // record we are not 16 bit
        !           636: 
        !           637:        FALLSTHRU
        !           638: continu_init:
        !           639: 
        !           640: #ifdef FP_COUNTERS
        !           641:        /* this keeps track of how many floating point ops were emulated */
        !           642:        push    %ss
        !           643:        pop     %ds
        !           644:        movl    $_fp_total,%ecx
        !           645:        movl    0(%ecx),%eax
        !           646:        inc     %eax
        !           647:        movl    %eax,0(%ecx)
        !           648: #endif /* FP_COUNTERS */
        !           649: 
        !           650:        movb    $null,%dl                       // initialize op1 and op2
        !           651:        movb    %dl,%cl                 //  format registers to null
        !           652:        MOVL    $do_nothing*0x100+do_nothing,%bx // initialize useups
        !           653:        lds     saved_eip(%ebp),%esi // load instruction pointer
        !           654: 
        !           655:        movb    $1,oprnd_siz32(%ebp)    //set operand size=32
        !           656:        movb    $1,addrs_siz32(%ebp)    //set address size=32
        !           657: #ifdef MS_DOS
        !           658:        lar     saved_cs(%ebp),%eax     //load access right byte of cs
        !           659:        test    $0x00400000,%eax                //check 32 bit default ?
        !           660:        jnz     get_opcode              //if yes continue
        !           661:        decb    oprnd_siz32(%ebp)       //else default is 16bit
        !           662:        decb    addrs_siz32(%ebp)
        !           663: #endif /* MS_DOS */
        !           664:        FALLSTHRU
        !           665: get_opcode:    
        !           666:        MOVL    (%esi),%ax              //load two bytes
        !           667: 
        !           668:        inc     %esi                    //inc pointer
        !           669:        andb    $0x87,%al                       // is the first byte a prefix
        !           670:        jns     get_opcode              // yes skip for now
        !           671:        addb    $0x40,%ah                       // no, add 1 to mod
        !           672:        rclb    $1,%al                  // cf set if mod = 3
        !           673:        rolb    $1,%al                  // form handler table index
        !           674:        MOVL    $0x3800,%si             // form bits 5-4-3 index in si
        !           675:        andw    %ax,%si
        !           676:        shrw    $11,%si
        !           677:        MOVL    $0x001e,%di             // form group handler table
        !           678:        andw    %ax,%di                 //  index in di
        !           679:        shlw    $1,%di                  // take care of dd instead of dw
        !           680:        push    %cs                     // copy cs to ds for addressing
        !           681:        pop     %ds                     //  all the tables
        !           682:        movswl  %si,%esi
        !           683:        movswl  %di,%edi
        !           684:        call    *%cs:group_handler(%edi)     // call the proper group handler
        !           685:        andb    $0x07,%ah                       // store register number (r/m)
        !           686:        movw    %ax,operation_type(%ebp)        // and operation type
        !           687:        movw    %dx,op1_format(%ebp) // store operand and result
        !           688:        movw    %cx,op2_format(%ebp) // formats and locations
        !           689:        movw    %si,result_format(%ebp)
        !           690:        movw    %di,result2_format(%ebp)
        !           691:        movb    %bh,op1_use_up(%ebp)    // store op1 and op2 useups
        !           692:        movb    %bl,op2_use_up(%ebp)
        !           693:        lds     saved_eip(%ebp),%esi // load instruction pointer
        !           694:        mov     %esi,instruction_pointer(%ebp) // save old pointer
        !           695:        movw    %ds,instruction_pointer+4(%ebp)
        !           696:        XORL    %cx,%cx                 // extended addressing = false
        !           697:        xor     %ebx,%ebx
        !           698:        FALLSTHRU
        !           699: segment_ds:
        !           700:        movw    saved_ds(%ebp),%dx      // assume ds is pointer base
        !           701: get_mod_rm_byte:
        !           702:        MOVL    (%esi),%ax      // load first two bytes again
        !           703: 
        !           704:        inc     %esi                    // bump instruction pointer
        !           705:        andb    %al,%al                 // is there an override?
        !           706:        js      got_mod_rm              // no, ah contains mod r/m byte
        !           707:        cmpb    $0x67,%al                       // is there an address overide
        !           708:        jne     check_prefix66          // no is it 66
        !           709:        xorb    $1,addrs_siz32(%ebp)    //yes adjust address size
        !           710:        jmp     get_mod_rm_byte
        !           711:        ALIGN
        !           712: check_prefix66:
        !           713:        cmpb    $0x66,%al               //is it 66 overide
        !           714:        jne     other_prefix            //no some other prefix
        !           715:        xorb    $1,oprnd_siz32(%ebp)    //adjust operand size
        !           716:        jmp     get_mod_rm_byte
        !           717:        ALIGN
        !           718: other_prefix:
        !           719:        decw    %cx                     // yes, boolean = true
        !           720:        MOVL    saved_fs(%ebp),%dx      // load fs: override
        !           721:        cmpb    $0x64,%al                       // is it fs: ?
        !           722:        je      get_mod_rm_byte         // yes, scan past prefix byte
        !           723:        MOVL    saved_gs(%ebp),%dx      // load gs: override
        !           724:        cmpb    $0x65,%al                       // is it gs: ?
        !           725:        je      get_mod_rm_byte         // yes, scan past prefix byte
        !           726:        MOVL    saved_es(%ebp),%dx      // load es: override
        !           727:        cmpb    $0x26,%al                       // is it es: ?
        !           728:        je      get_mod_rm_byte         // yes, scan past prefix byte
        !           729:        MOVL    saved_cs(%ebp),%dx      // no, load cs: override
        !           730:        cmpb    $0x2e,%al                       // is it cs: ?
        !           731:        je      get_mod_rm_byte         // yes, scan past prefix byte
        !           732:        MOVL    old_ss(%ebp),%dx                        // no, load ss: override
        !           733:        cmpb    $0x36,%al                       // is it ss: ?
        !           734:        je      get_mod_rm_byte         // yes, scan past prefix byte
        !           735:        jmp     segment_ds              // no, assume ds: override
        !           736:        ALIGN
        !           737: got_mod_rm:
        !           738: 
        !           739:        inc     %esi                    // bump instruction pointer
        !           740:        movb    %ah,%bl                 // save mod r/m in bl
        !           741: 
        !           742:        testb   $1,addrs_siz32(%ebp)    //check if 32bit addressing
        !           743:        jnz     addrs_32_bit
        !           744: 
        !           745:        movzwl    (%esi),%eax      // load possible displacement
        !           746: 
        !           747:        push    %eax
        !           748:        MOVL    saved_ds(%ebp), %ax     // restore %ds register to its initial
        !           749:        movw    %ax, %ds                // value.
        !           750:        pop     %eax
        !           751: 
        !           752:        cmpb    $0x0c0,%bl                      // is mod = 3?
        !           753:        jnc     store_return            // yes, no memory operand
        !           754:        shlb    $1,%bl                  // no, is mod = 2?
        !           755:        jc      mod_2                   // yes, disp = disp-hi: disp-lo
        !           756:        js      mod_1                   // branch if mod = 1
        !           757:        andb    $0x0e,%bl                       // mod = 0
        !           758:        cmpb    $0x0c,%bl                       // does r/m = 6?
        !           759:        je      store_ea                // yes, ea = disp-hi: disp-lo
        !           760:        xorw    %ax,%ax                 // no, disp = 0
        !           761:        dec     %esi                    // subtract one for return
        !           762:        FALLSTHRU
        !           763: mod_1:
        !           764:        dec     %esi                    // subtract one for return
        !           765:        cbtw                             // extend disp to 16 bits
        !           766: mod_2:
        !           767:        and     $0x0000000e,%ebx                // ax now = real displacement
        !           768:        shl     $1,%ebx                 // take care of dd instead of dw
        !           769:        call    *%cs:rm_handler(%ebx)    // call r/m handler (cs <> ds)
        !           770:        FALLSTHRU
        !           771: store_ea:
        !           772:        inc     %esi                    // add two for return address
        !           773:        inc     %esi
        !           774: store_on:
        !           775:        movw    %dx,mem_operand_pointer+4(%ebp) // store base
        !           776:        mov     %eax,mem_operand_pointer(%ebp) // store offset
        !           777:        testb   $0x80,operation_type(%ebp)      // update sr_memop pointer?
        !           778:        jnz     store_return            // no, must be administrative
        !           779:        movw    %dx,%gs:sr_mem_base     // yes, store base in a?msr
        !           780:        mov     %eax,%gs:sr_mem_offset  // store offset in a?msr
        !           781:        FALLSTHRU
        !           782: store_return:
        !           783:        mov     %esi,saved_eip(%ebp)    // update return address
        !           784:        mov     offset_op1_rec,%esi     //set up for fetch_an_op
        !           785:        mov     $offset_operand1,%edi
        !           786:        movl    $0, before_error_signals(%ebp)
        !           787:        movl    $0, extra_dword_reg(%ebp)
        !           788:        movl    $0, extra_dword_reg+4(%ebp)
        !           789:        movl    $0, extra_dword_reg+8(%ebp)
        !           790:        call    fetch_an_op             // fetch op1
        !           791:        pushw   %ax                     //save stack error flag
        !           792:        mov     offset_op2_rec,%esi     //set up for fetch_an_op
        !           793:        mov     $offset_operand2,%edi
        !           794:        call    fetch_an_op             // fetch op2
        !           795:        popw    %bx                     // combine stack error flags
        !           796:        orw     %bx,%ax                 // set/reset zf, clear cf
        !           797:        movb    operation_type(%ebp),%bl        // load operation type
        !           798:        rclb    $1,%bl                  // shift save ptrs flag to cf
        !           799:        jnc     pending_unmasked_xcptns_// all non-administratives must check
        !           800:        movb    operation_type(%ebp),%cl// duo-form administratives are all
        !           801:        cmpb    $ldenv_op,%cl                   // treated as unwaited forms:
        !           802:        ja      do_operation            // fnstenv, fnstcw, fnstsw, and fnclex
        !           803:        cmpb    $init_op,%cl                                    // and fninit
        !           804:        je      do_operation                            // and
        !           805:        cmpb    $save_op,%cl            // fnsave all ignore pending unmasked
        !           806:        je      do_operation                    // exceptions and just execute.
        !           807:        FALLSTHRU
        !           808: pending_unmasked_xcptns_:
        !           809:        movb    %gs:sr_masks,%cl
        !           810:        notb    %cl
        !           811:        andb    $0x3f,%cl
        !           812:        andb    %gs:sr_errors,%cl
        !           813:        jz      no_pending_unmasked_xcptns
        !           814:        int     $16
        !           815:        jmp     pending_unmasked_xcptns_
        !           816:        ALIGN
        !           817: no_pending_unmasked_xcptns:
        !           818:        testb   $0x80,operation_type(%ebp)
        !           819:        jnz     do_operation
        !           820:        push    %eax
        !           821:        les     instruction_pointer(%ebp),%eax // load instruction ptr
        !           822:        mov     %eax,%gs:sr_instr_offset        // store offset in status reg
        !           823:        movw    %es,%gs:sr_instr_base   // store base in status reg
        !           824:        pop     %eax
        !           825:        FALLSTHRU
        !           826: do_operation:
        !           827:        movswl  %bx,%ebx
        !           828:        rol     $1,%ebx                 //take care of dd
        !           829:        orw     %ax,%ax         // give zf value expected by following call
        !           830: 
        !           831:        call    *%cs:op_table(%ebx)          // call instruction operator
        !           832:        movb    %gs:sr_masks,%al                //set zf to false if any
        !           833:        notb    %al                     // unmasked errors,
        !           834:        andb    $0x7f,%al       //get rid of es bit
        !           835:        andb    %gs:sr_errors,%al               //set al to 0 if none
        !           836:        jz      release_stack
        !           837:        movb    $0,%al
        !           838:        movb    operation_type(%ebp),%cl
        !           839:        testb   $0x80,%cl
        !           840:        jz      mark_errors
        !           841:        cmpb    $ldenv_op,%cl
        !           842:        ja      get_done
        !           843:        FALLSTHRU
        !           844: mark_errors:
        !           845:        orw     $0x8080, %gs:sr_errors  //taking care of es and B
        !           846:        movb    $0x02,%al                       // load nonzero ie mask
        !           847:        jmp     get_done
        !           848:        ALIGN
        !           849: release_stack:
        !           850:        andw    $0x7f7f, %gs:sr_errors
        !           851: get_done:
        !           852: 
        !           853:        /* 
        !           854:         * This code checks if the next instruction is a floating point op.
        !           855:         * If so, just process it and save the fault.
        !           856:         */
        !           857:        movl    saved_eip(%ebp), %esi
        !           858:        movl    %esi,%edi
        !           859: 
        !           860: #if    0
        !           861:        /* 
        !           862:         * This is to test that we are not within 11 bytes of the end
        !           863:         * of a page.  If we are, it is best to let the processor trap
        !           864:         * into the kernel for the next instruction because the code page 
        !           865:         * may not be in memory.  It is not good when the page is not in
        !           866:         * memory and the kernel attempts to reference that location.
        !           867:         */
        !           868:        andl    $0xff5,%edi             // isolate bits that will be all ones
        !           869:        xor     $0xff5,%edi             // are they all ones?
        !           870:        jz      all_done                // yes - let processor handle it.
        !           871:        andl    $0xfff,%edi             // start of a new page?
        !           872:        jz      all_done                // yes - do not take a chance
        !           873: #endif
        !           874: 
        !           875:        /*
        !           876:         * The last check is to make sure we are not going through a
        !           877:         * floating point loop which will not end.  After 5 instructions
        !           878:         * return to user space.
        !           879:         */
        !           880:        mov     inst_counter(%ebp),%ecx // get count
        !           881:        inc     %ecx
        !           882:        mov     %ecx,inst_counter(%ebp)
        !           883:        cmpb    $5,%cl                  // too many inst?
        !           884:        jz      all_done                // yes return to user space
        !           885: 
        !           886:        /*
        !           887:         * Now check if the next instruction is a floating point opcode.
        !           888:         */
        !           889:        movl    0(%esi),%ecx            
        !           890:        andl    $0xf8,%ecx
        !           891:        cmpl    $0xd8,%ecx              // escape sequence for fp instructions
        !           892:        je      continu_init            // it is an fp instruction
        !           893: 
        !           894:        FALLSTHRU
        !           895: all_done:
        !           896: 
        !           897:        andb    saved_flags+1(%ebp),%al         // interrupt enabled?
        !           898:        jz      no_exception            // branch if no exception
        !           899:        int     $16                     // 80387 exception interrupt
        !           900:        FALLSTHRU
        !           901: no_exception:
        !           902: 
        !           903:        addl    $(WORK_AREA_SIZE),%esp  // stack space
        !           904: 
        !           905:        popl    %gs
        !           906:        popl    %fs
        !           907:        popl    %es
        !           908:        popl    %ds
        !           909:        popa
        !           910:        addl    $8, %esp        // get TRAPNO and ERROR off the stack
        !           911: 
        !           912:        // User may have set NT bit before doing a system call.
        !           913:        // This would be bad, so we turn it off here.
        !           914:        // On a system call, the flags get pushed, then popped.  Since the
        !           915:        // VM bit always gets zeroed when pushed, we do not need to clear it.
        !           916:        andl    $KFL, 8(%esp)    // clear the NT bit in the flags
        !           917:        iret
        !           918: 
        !           919:        ALIGN
        !           920: rm_0:
        !           921:        addw    saved_ebx(%ebp),%ax     // ea = (bx) + (si) + disp
        !           922: rm_4:
        !           923:        addw    saved_esi(%ebp),%ax     // ea = (si) + disp
        !           924:        ret
        !           925:        ALIGN
        !           926: rm_5:
        !           927:        addw    saved_edi(%ebp),%ax     // ea = (di) + disp
        !           928:        ret
        !           929:        ALIGN
        !           930: rm_1:
        !           931:        addw    saved_edi(%ebp),%ax     // ea = (bx) + (di) + disp
        !           932: rm_7:
        !           933:        addw    saved_ebx(%ebp),%ax     // ea = (bx) + disp
        !           934:        ret
        !           935:        ALIGN
        !           936: rm_2:
        !           937:        addw    saved_esi(%ebp),%ax     // ea = (bp) + (si) + disp
        !           938: rm_6:
        !           939:        addw    saved_ebp(%ebp),%ax     // ea = (bp) + disp
        !           940:        jcxz    segment_ss              // branch if no override given
        !           941:        ret
        !           942:        ALIGN
        !           943: rm_3:
        !           944:        addw    saved_edi(%ebp),%ax     // ea = (bp) + (di) + disp
        !           945:        jmp     rm_6                    // merge with r/m = 6
        !           946:        ALIGN
        !           947: segment_ss:
        !           948:        MOVL    old_ss(%ebp),%dx        // for r/m = 2, 3, or 6, the
        !           949:        ret                             // standard base = ss
        !           950:        ALIGN
        !           951: //
        !           952: addrs_32_bit:  
        !           953:        xor     %edi,%edi                       //clear edi
        !           954:        cmpb    $0xc0, %ah      
        !           955:        jae     no_sib
        !           956:        andb    $0x07,%ah                       //check if sib present
        !           957:        cmpb    $0x04,%ah
        !           958:        jne     no_sib                  //
        !           959:        movb    (%esi),%bh              //yes get  sib byte
        !           960:        inc     %esi
        !           961:        FALLSTHRU
        !           962: no_sib:
        !           963:        mov     (%esi),%eax             //get displacement
        !           964: 
        !           965:        push    %ds
        !           966:        pop     %fs                     / save selector
        !           967: //
        !           968: //     assume  %ds:a_msrs
        !           969: //
        !           970: //        push    a_msrs                  / push the dynamic selector
        !           971: //        pop     %ds                     /  for the a?msr segment
        !           972: //        push    a_msr_selector          / and load it into ds
        !           973: //        pop     %ds
        !           974: //
        !           975: //     assume  %ds:a_msr               ; assume ds=a?msr from here on
        !           976: //
        !           977:        push    %eax
        !           978:        MOVL    saved_ds(%ebp), %ax     // restore %ds register to its initial
        !           979:        movw    %ax, %ds                //segment value.
        !           980:        pop     %eax
        !           981: 
        !           982:        cmpb    $0x0c0,%bl                      // is mod = 3?
        !           983:        jnc     store_return            // yes, no memory operand
        !           984:        add     $4,%esi
        !           985:        shlb    $1,%bl                  // no, is mod = 2?
        !           986:        jc      mod32_2                 // yes, disp = disp-hi: disp-lo
        !           987:        js      mod32_1                 // branch if mod = 1
        !           988:        andb    $0x0e,%bl                       // mod = 0
        !           989:        inc     %edi                    // set flag
        !           990:        cmpb    $0x0a,%bl                       // does r/m = 5?i
        !           991:        je      store_on                // yes, ea = disp-hi: disp-lo
        !           992:        xor     %eax,%eax                       // no, disp = 0
        !           993:        dec     %esi                    // subtract one for return
        !           994:        FALLSTHRU
        !           995: mod32_1:
        !           996:        sub     $3,%esi                 // adjust esi
        !           997:        movsbl  %al,%eax                // extend disp to 32 bits
        !           998: mod32_2:
        !           999:        andb    $0x0f,%bl                       //check if sib present
        !          1000:        cmpb    $0x8,%bl
        !          1001:        je      process_sib
        !          1002:        and     $0x0000000e,%ebx                //no sib get base register
        !          1003:        shl     $1,%ebx                 //form index in table
        !          1004:        call    *%cs:base32(%ebx)
        !          1005:        jmp     store_on                //store displacement
        !          1006:        ALIGN
        !          1007: 
        !          1008: process_sib:   
        !          1009:        movb    %bh,%bl                 //
        !          1010:        and     %edi,%edi                       //edi=1 if mod=0
        !          1011:        jz      get_base                //
        !          1012:        andb    $0x07,%bh                       //get last 3 bits
        !          1013:        cmpb    $0x05,%bh                       //if mod=0 and basereg=5,no base
        !          1014:        jne     get_base
        !          1015:        mov     %fs:(%esi),%eax         //get displacement
        !          1016:        add     $4,%esi                 // adjust esi
        !          1017:        jmp     get_sir                 //get sir
        !          1018:        ALIGN
        !          1019: 
        !          1020: get_base:      
        !          1021:        MOVL    %bx,%di                 //save bx
        !          1022:        and     $0x00000007,%ebx                //form index in the base table
        !          1023:        shl     $2,%ebx
        !          1024:        call    *%cs:base32(%ebx)
        !          1025:        MOVL    %di,%bx                 //restore bx
        !          1026: 
        !          1027:        FALLSTHRU
        !          1028: get_sir:       
        !          1029:        movb    %bl,%bh                 //load sib byte
        !          1030:        andb    $0x038,%bh                      //get midle 3 bits
        !          1031:        cmpb    $0x020,%bh                      //index=4 no index reg
        !          1032:        je      store_on                //if no index jmp out
        !          1033:        movb    %bl,%cl                 //save bl
        !          1034:        rolb    $2,%cl                  //get high order 2 bits
        !          1035:        andb    $0x03,%cl                       //in the low bits
        !          1036:        shrb    $1,%bl                  //form index into table
        !          1037:        and     $0x0000001c,%ebx
        !          1038:        call    *%cs:index32(%ebx)               //add sir to displacement
        !          1039:        jmp     store_on
        !          1040:        ALIGN
        !          1041: 
        !          1042: base_0:        
        !          1043:        add     saved_eax(%ebp),%eax
        !          1044:        ret
        !          1045:        ALIGN
        !          1046: base_1:
        !          1047:        add     saved_ecx(%ebp),%eax
        !          1048:        ret
        !          1049:        ALIGN
        !          1050: base_2:
        !          1051:        add     saved_edx(%ebp),%eax
        !          1052:        ret
        !          1053:        ALIGN
        !          1054: base_3:
        !          1055:        add     saved_ebx(%ebp),%eax
        !          1056:        ret
        !          1057:        ALIGN
        !          1058: base_4:
        !          1059:        add     old_esp(%ebp),%eax
        !          1060:        jcxz    segmentss
        !          1061:        ret
        !          1062:        ALIGN
        !          1063: base_5:
        !          1064:        add     saved_ebp(%ebp),%eax
        !          1065:        jcxz    segmentss
        !          1066:        ret
        !          1067:        ALIGN
        !          1068: segmentss:     
        !          1069:        MOVL    old_ss(%ebp),%dx                // for esp, ebp as base registers
        !          1070:        ret
        !          1071:        ALIGN
        !          1072: 
        !          1073: base_6:
        !          1074:        add     saved_esi(%ebp),%eax
        !          1075:        ret
        !          1076:        ALIGN
        !          1077: base_7:
        !          1078:        add     saved_edi(%ebp),%eax
        !          1079:        ret
        !          1080:        ALIGN
        !          1081: 
        !          1082: index_0:       
        !          1083:        mov     saved_eax(%ebp),%edi
        !          1084:        shll    %cl,%edi
        !          1085:        add     %edi,%eax
        !          1086:        ret
        !          1087:        ALIGN
        !          1088: index_1:       
        !          1089:        mov     saved_ecx(%ebp),%edi
        !          1090:        shll    %cl,%edi
        !          1091:        add     %edi,%eax
        !          1092:        ret
        !          1093:        ALIGN
        !          1094: index_2:       
        !          1095:        mov     saved_edx(%ebp),%edi
        !          1096:        shll    %cl,%edi
        !          1097:        add     %edi,%eax
        !          1098:        ret
        !          1099:        ALIGN
        !          1100: index_3:       
        !          1101:        mov     saved_ebx(%ebp),%edi
        !          1102:        shll    %cl,%edi
        !          1103:        add     %edi,%eax
        !          1104: index_4:
        !          1105:        ret
        !          1106:        ALIGN
        !          1107: index_5:       
        !          1108:        mov     saved_ebp(%ebp),%edi
        !          1109:        shll    %cl,%edi
        !          1110:        add     %edi,%eax
        !          1111:        ret
        !          1112:        ALIGN
        !          1113: index_6:       
        !          1114:        mov     saved_esi(%ebp),%edi
        !          1115:        shll    %cl,%edi
        !          1116:        add     %edi,%eax
        !          1117:        ret
        !          1118:        ALIGN
        !          1119: index_7:       
        !          1120:        mov     saved_edi(%ebp),%edi
        !          1121:        shll    %cl,%edi
        !          1122:        add     %edi,%eax
        !          1123:        ret
        !          1124:        ALIGN
        !          1125: 
        !          1126: //
        !          1127: //     assume  %ds:a_med
        !          1128: // ****************************************************************************
        !          1129: //
        !          1130: //     instruction group decoding handlers
        !          1131: //
        !          1132: // ****************************************************************************
        !          1133: //
        !          1134: //     these handlers load all necessary operation, operand, and result
        !          1135: //     information into the following registers for storage into the
        !          1136: //     global data records upon return:
        !          1137: //
        !          1138: //      dh => op1_location             dl => op1_format (null)
        !          1139: //      ch => op2_location             cl => op2_format (null)
        !          1140: //      si => result_location/result_format
        !          1141: //      di => result2_location/result2_format
        !          1142: //      bh => op1_use_up (do_nothing)  bl => op2_use_up (do_nothing)
        !          1143: //      ah => (mod r/m, reg byte)      al => operation_type
        !          1144: //
        !          1145: //     parentheses indicate initial values upon entry.
        !          1146: //
        !          1147: // ****************************************************************************
        !          1148: //
        !          1149: //     group 0a - standard arithmetic instructions with short-real operands
        !          1150: //
        !          1151: arith_short_real:
        !          1152:        movb    $single_real,%cl                // op2 format is short real
        !          1153: op1_top_op2_mem_0a:
        !          1154:        movb    $memory_opnd,%ch                // op2 loc is memory operand
        !          1155: op1_top_stand_arith_op_0a:
        !          1156:        movb    group_0a_0b_2a_4a_4b_6a_6b_op(%esi),%al // arithmetic op
        !          1157:        MOVL    %dx,%di                 // result2 format is null
        !          1158:        MOVL    $(stack_top*0x100+extended_fp),%dx // op1 top extended_fp
        !          1159:        MOVL    %dx,%si                 // result is same as op1
        !          1160:        FALLSTHRU
        !          1161: arith_op_0a:
        !          1162:        cmpb    $subr_op,%al            // is it fsubr ?
        !          1163:        je      fsubr_0a                // reverse operands
        !          1164:        cmpb    $divr_op,%al            // is it fdivr ?
        !          1165:        je      fdivr_0a                // reverse operands
        !          1166:        cmpb    $compar_pop,%al         // is it fcomp ?
        !          1167:        jne     exit_0a                 // no, return
        !          1168:        movb    $compar_op,%al          // yes, op type is compare
        !          1169:        movb    pop_stack,%bh           // op1 useup is pop stack
        !          1170:        FALLSTHRU
        !          1171: exit_0a:
        !          1172:        ret
        !          1173:        ALIGN
        !          1174: fsubr_0a:
        !          1175:        movb    $sub_op,%al             // operation type is subtract
        !          1176:        jmp     swap_0a         // switch operand locations
        !          1177:        ALIGN
        !          1178: fdivr_0a:
        !          1179:        movb    $div_op,%al             // operation type is division
        !          1180: swap_0a:
        !          1181:        xchgb   %bl,%bh                 // switch operand useups
        !          1182:        xchgw   %cx,%dx                 // switch operand fmt/loc
        !          1183:        ret
        !          1184:        ALIGN
        !          1185: //
        !          1186: //     group 2a - standard arithmetic instructions with short integer operands
        !          1187: //
        !          1188: arith_short_int:
        !          1189:        movb    $int32,%cl              // op2 format is short integer
        !          1190:        jmp     op1_top_op2_mem_0a      // finish loading information
        !          1191:        ALIGN
        !          1192: //
        !          1193: //     group 4a - standard arithmetic instructions with long-real operands
        !          1194: //
        !          1195: arith_long_real:
        !          1196:        movb    $double_real,%cl                // op2 format is long real
        !          1197:        jmp     op1_top_op2_mem_0a      // load rest of information
        !          1198:        ALIGN
        !          1199: //
        !          1200: //     group 6a - standard arithmetic instructions with word-integer operands
        !          1201: //
        !          1202: arith_word_int:
        !          1203:        movb    $int16,%cl              // op2 format is word integer
        !          1204:        jmp     op1_top_op2_mem_0a      // load rest of information
        !          1205:        ALIGN
        !          1206: //
        !          1207: //     group 0b - standard arithmetic instructions with inner-stack operands
        !          1208: //
        !          1209: arith_top_reg:
        !          1210:        MOVL    $(reg*0x100+extended_fp),%cx // op2 is reg extended_fp
        !          1211:        jmp     op1_top_stand_arith_op_0a // load rest of information
        !          1212:        ALIGN
        !          1213: //
        !          1214: //     group 6b - reversed arithmetic with register operand and pop useup
        !          1215: //
        !          1216: arith_reg_pop:
        !          1217:        movb    pop_stack,%bl           // op2 useup is pop stack
        !          1218: //
        !          1219: //     group 4b - reversed arithmetic instructions with inner-stack operands
        !          1220: //
        !          1221: arith_reg_top:
        !          1222:        movb    group_0a_0b_2a_4a_4b_6a_6b_op(%esi),%al // arithmetic ops
        !          1223:        MOVL    %dx,%di                 // result2 format is null
        !          1224:        MOVL    $(stack_top*0x100+extended_fp),%dx // op1 top extended_fp
        !          1225:        MOVL    $(reg*0x100+extended_fp),%cx // op2 is reg extended_fp
        !          1226:        MOVL    %cx,%si                 // result is same as op2
        !          1227:        jmp     arith_op_0a             // load rest of information
        !          1228:        ALIGN
        !          1229: //
        !          1230: //     group 1a - load/store instructions with short-real operand
        !          1231: //                load/store environment/control word with string operand
        !          1232: //
        !          1233: load_short_real:
        !          1234:        movb    group_1a_op(%esi),%al   // load operation type
        !          1235:        shlw    $1,%si                  // change byte index to word
        !          1236:        movswl  %si,%esi
        !          1237:        MOVL    group_1a_op1_lf(%esi),%dx       // load op1 loc/for
        !          1238:        MOVL    $(memory_opnd*0x100+single_real),%si // result format
        !          1239:        FALLSTHRU
        !          1240: load_store_1a:
        !          1241:        MOVL    %cx,%di                 // result2 format is null
        !          1242:        cmpb    $load_op,%al            // is it fld?
        !          1243:        je      fld_1a                  // result goes to stack top
        !          1244:        cmpb    $store_pop,%al          // is it fstp?
        !          1245:        je      fstp_1a                 // op1 useup is pop stack
        !          1246:        cmpb    $store_op,%al           // is it fst?
        !          1247:        je      fst_1a                  // result goes to memory
        !          1248:        MOVL    %di,%si                 // else, result format is null
        !          1249:        ret
        !          1250:        ALIGN
        !          1251: fld_1a:
        !          1252:        MOVL    $(stack_top_plus_1*0x100+extended_fp),%si // result is top
        !          1253:        ret
        !          1254:        ALIGN
        !          1255: fstp_1a:
        !          1256:        movb    pop_stack,%bh           // op1 useup is pop stack
        !          1257:        movb    $store_op,%al           // operation type is store
        !          1258: fst_1a:
        !          1259:        ret
        !          1260:        ALIGN
        !          1261: //
        !          1262: //     group 3a - short integer/tempreal load/store instructions
        !          1263: //
        !          1264: load_short_int:
        !          1265:        movb    group_3a_7a_op(%esi),%al        // load operation type
        !          1266:        movb    group_3a_res_fmt(%esi),%dl      // load result format
        !          1267:        movb    group_3a_7a_res_loc(%esi),%dh // load result location
        !          1268:        pushw   %dx                     // push result fmt/loc
        !          1269:        movb    group_3a_op1_fmt(%esi),%dl      // load op1 format
        !          1270:        movb    group_3a_7a_op1_loc(%esi),%dh // load op1 location
        !          1271:        popw    %si                     // pop result fmt/loc
        !          1272:        jmp     load_store_1a           // finish loading information
        !          1273:        ALIGN
        !          1274: //
        !          1275: //     group 5a - load/store instructions with long-real operand
        !          1276: //                  load/store state/status word instructions
        !          1277: //
        !          1278: load_long_real:
        !          1279:        movb    group_5a_op(%esi),%al   // load operation type
        !          1280:        shlw    $1,%si                  // change byte index to word
        !          1281:        movswl  %si,%esi
        !          1282:        MOVL    group_5a_op1_lf(%esi),%dx       // load op1 loc/for
        !          1283:        MOVL    $(memory_opnd*0x100+double_real),%si // result format
        !          1284:        jmp     load_store_1a           // load rest of information
        !          1285:        ALIGN
        !          1286: //
        !          1287: //     group 7a - load/store word-integer/bcd/long-integer instructions
        !          1288: //
        !          1289: load_word_int:
        !          1290:        movb    group_3a_7a_op(%esi),%al        // load operation type
        !          1291:        movb    group_7a_res_fmt(%esi),%dl      // load result format
        !          1292:        movb    group_3a_7a_res_loc(%esi),%dh // load result location
        !          1293:        pushw   %dx                     // push result fmt/loc
        !          1294:        movb    group_7a_op1_fmt(%esi),%dl      // load op1 format
        !          1295:        movb    group_3a_7a_op1_loc(%esi),%dh // load op1 location
        !          1296:        popw    %si                     // pop result fmt/loc
        !          1297:        jmp     load_store_1a           // finish loading information
        !          1298:        ALIGN
        !          1299: //
        !          1300: //     group 1b - load/store/transcendental instructions with inner
        !          1301: //                stack operands
        !          1302: transcendentals:
        !          1303:        testb   $0x20,%ah                       // does bit 5 = 0?
        !          1304:        jz      group_1ba               // yes, its a load/store op
        !          1305:        MOVL    $0x1f00,%si             // no, its a transcendental
        !          1306:        andw    %ax,%si                 // calculate new table index
        !          1307:        shrw    $8,%si                  // shift right one byte
        !          1308:        movswl  %si,%esi
        !          1309:        movb    group_1bb_type(%esi),%al        // load format/location type
        !          1310:        rolb    $1,%al                  // rotate one left
        !          1311:        movl    $4,%ecx                 // load loop count
        !          1312:        FALLSTHRU
        !          1313: load_lf_1bb:
        !          1314:        rolb    $2,%al                  // shift next field into di
        !          1315:        MOVL    $0x0006,%di             // form table index
        !          1316:        andw    %ax,%di
        !          1317:        movswl  %di,%edi
        !          1318:        pushw   group_1bb_lf(%edi)      // stack next format/location
        !          1319:        LOOP(load_lf_1bb)               // decode four fields
        !          1320:        movb    group_1bb_op(%esi),%al  // load operation type
        !          1321:        cmpb    $log_op,%al             // is it fyl2x?
        !          1322:        je      pop_op1_1bb             // yes, operand 1 gets popped
        !          1323:        cmpb    $splog_op,%al           // is it fyl2xp1?
        !          1324:        je      pop_op1_1bb             // yes, operand 1 gets popped
        !          1325:        cmpb    $arctan_op,%al          // is it fpatan?
        !          1326:        jne     return_1bb              // no, load return information
        !          1327:        FALLSTHRU
        !          1328: pop_op1_1bb:
        !          1329:        movb    pop_stack,%bh           // pop operand 1
        !          1330: return_1bb:
        !          1331:        popw    %di                     // load operand 1 information
        !          1332:        popw    %si                     // load operand 2 information
        !          1333:        popw    %cx                     // load result 1 information
        !          1334:        popw    %dx                     // load result 2 information
        !          1335:        ret
        !          1336:        ALIGN
        !          1337: group_1ba:
        !          1338:        MOVL    %cx,%di                 // assume result2 always null
        !          1339:        movb    group_1ba_op(%esi),%al  // load operation type
        !          1340: load_store_1ba:
        !          1341:        cmpb    $load_op,%al            // is it fld st(i) ?
        !          1342:        je      fld_1ba                 // op1 is a register
        !          1343:        cmpb    $exchange_op,%al                // is it fxch st(i) ?
        !          1344:        je      fxch_1ba                // op1 is stack top
        !          1345:        cmpb    $store_pop,%al          // is it fstp st(i)? *
        !          1346:        je      fstp_1ba                // pop op1
        !          1347:        cmpb    $store_op,%al           // is it fst st(i)?
        !          1348:        je      fst_1ba                 // dont pop op1
        !          1349:        MOVL    %di,%si                 // result format is null
        !          1350:        ret
        !          1351:        ALIGN
        !          1352: fld_1ba:
        !          1353:        MOVL    $(reg*0x100+extended_fp),%dx // op1 is a stack reg
        !          1354:        MOVL    $(stack_top_plus_1*0x100+extended_fp),%si // result pushed
        !          1355:        ret
        !          1356:        ALIGN
        !          1357: fxch_1ba:
        !          1358:        MOVL    $(stack_top*0x100+extended_fp),%dx // op1 is stack top
        !          1359:        MOVL    $(reg*0x100+extended_fp),%cx // op2 is a stack reg
        !          1360:        MOVL    %cx,%si                 // result is the stack reg
        !          1361:        MOVL    %dx,%di                 // result2 is the stack top
        !          1362:        ret
        !          1363:        ALIGN
        !          1364: fstp_1ba:
        !          1365:        movb    $store_op,%al           // operation type is store
        !          1366:        movb    pop_stack,%bh           // op1 useup is pop stack
        !          1367: fst_1ba:
        !          1368:        MOVL    $(stack_top*0x100+extended_fp),%dx // op1 is stack top
        !          1369:        MOVL    $(reg*0x100+extended_fp),%si // result is stack reg
        !          1370:        ret
        !          1371:        ALIGN
        !          1372: //
        !          1373: //     group 5b - free register/store to register instructions
        !          1374: //
        !          1375: store_reg:
        !          1376:        movb    group_5b_op(%esi),%al   // load operation type
        !          1377:        cmpb    $ucom_pop,%al
        !          1378:        jne     test_ucom_op
        !          1379:        movb    pop_stack,%bh
        !          1380:        movb    $ucom_op,%al
        !          1381:        FALLSTHRU
        !          1382: test_ucom_op:
        !          1383:        cmpb    $ucom_op,%al
        !          1384:        jne     test_ffree_5b
        !          1385:        MOVL    $(reg*0x100+extended_fp),%cx // op2 is reg extended_fp
        !          1386:        MOVL    %dx,%di                 // result2 format is null
        !          1387:        MOVL    %dx,%si                 // result format is null
        !          1388:        MOVL    $(stack_top*0x100+extended_fp),%dx // op1 top extended_fp
        !          1389:        ret
        !          1390:        ALIGN
        !          1391: test_ffree_5b:
        !          1392:        cmpb    $free_op,%al            // is it ffree st(i)?
        !          1393:        jne     load_store_1ba          // no, must be fst(p)/fxch
        !          1394:        movb    free,%bh                        // yes, op1 useup is free
        !          1395:        jmp     load_store_1ba          // load rest of information
        !          1396:        ALIGN
        !          1397: //
        !          1398: //     group 7b - transfer status instruction
        !          1399: //
        !          1400: transfer_status:
        !          1401:        movb    group_7b_op(%esi),%al   // load operation type
        !          1402:        cmpb    $free_op,%al            // is it ffreep st(i) ?
        !          1403:        jne     not_ffreep_7b           // no, useup is do nothing
        !          1404:        movb    pop_stack,%bl           // yes, op1 useup is pop
        !          1405:        FALLSTHRU
        !          1406: not_ffreep_7b:
        !          1407:        cmpb    $stsw_op,%al            // is it fstsw ax ?
        !          1408:        jne     test_ffree_5b           // no, handle like group 5b
        !          1409:        movb    $reg,%ch                // yes, op2 loc is reg
        !          1410:        jmp     test_ffree_5b           // finish loading information
        !          1411:        ALIGN
        !          1412: //
        !          1413: //     group 2b - fucompp
        !          1414: //
        !          1415: double_pop:    
        !          1416:        cmpb    $0x029,%ah                      // is it fucompp
        !          1417:        jne     reserved                // is a reserved instruction
        !          1418:        movb    pop_stack,%bl           // op2 useup is pop stack
        !          1419:        movb    pop_stack,%bh
        !          1420:        movb    $ucom_op,%al
        !          1421:        MOVL    $(reg*0x100+extended_fp),%cx // op2 is reg extended_fp
        !          1422:        MOVL    %dx,%di                 // result2 format is null
        !          1423:        MOVL    %dx,%si                 // result format is null
        !          1424:        MOVL    $(stack_top*0x100+extended_fp),%dx // op1 top extended_fp
        !          1425:        ret
        !          1426:        ALIGN
        !          1427: //
        !          1428: //     group 2b - reserved
        !          1429: //
        !          1430: reserved:
        !          1431:        movb    $error_op,%al           // illegal operation
        !          1432: null_results_2b:
        !          1433:        MOVL    %cx,%si                 // result is null
        !          1434:        MOVL    %cx,%di                 // result2 is null
        !          1435:        ret
        !          1436:        ALIGN
        !          1437: //
        !          1438: //     group 3b - administrative instructions
        !          1439: //
        !          1440: administrative:
        !          1441:        MOVL    $0x0700,%si             // calculate new table index
        !          1442:        andw    %ax,%si
        !          1443:        shrw    $8,%si                  // shift right one byte
        !          1444:        movswl  %si,%esi
        !          1445:        movb    group_3b_op(%esi),%al   // load operation type
        !          1446:        jmp     null_results_2b         // result and result2 are null
        !          1447: //
        !          1448: //e80387       endp

unix.superglobalmegacorp.com

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