Source to machdep/i386/fp_emul/fp_dcode.s


Enter a symbol's name here to quickly find it.

/*
 * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
 *
 * @[email protected]
 * 
 * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
 * Reserved.  This file contains Original Code and/or Modifications of
 * Original Code as defined in and that are subject to the Apple Public
 * Source License Version 1.0 (the 'License').  You may not use this file
 * except in compliance with the License.  Please obtain a copy of the
 * License at http://www.apple.com/publicsource and read it before using
 * this file.
 * 
 * The Original Code and all software distributed under the License are
 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
 * License for the specific language governing rights and limitations
 * under the License."
 * 
 * @[email protected]
 */

	.file	"dcode.s"

	.ident	"@(#)kern-fp:dcode.s	1.1"

// *************************************************************************
//
// 			d c o d e .m o d 
//			================
//
//	================================================================
//               intel corporation proprietary information
//    this software  is  supplied  under  the  terms  of  a  license
//    agreement  or non-disclosure agreement  with intel corporation
//    and  may not be copied nor disclosed except in accordance with
//    the terms of that agreement.                                  
//	================================================================
//
//	function:
//		converts the 80387 instruction into information
//               about the first operand, information about the
//               second operand, information about the result, 
//               and the operation type.  defines mem_operand_ptr.
//
//	public procedures:
//		e80387
//
// ****************************************************************************
//
//...March 3, 1987...
//
//        .file   *a_mdc*
//$nolist
#include	"fp_e80387.h"
//$list
//
//...declare stack segment...
//
//stack	stackseg	200
//
//...declare status register segment...
//
	.data	//a_msr	segment	rw	public
//	extrn	sr_masks,sr_errors,sr_instr_offset
//	extrn	sr_instr_base,sr_mem_offset,sr_mem_base
//a_msr	ends
//
//...declare status register selector segment...
//
	.data	//a_msrs	segment	rw	public
// a_msr_selector: .long   a_msr
//a_msrs	ends
//
	.text	//a_med	segment	er	public
//
//	extrn	load,store,chsign,compar
//	extrn	arith,ldcw,save,restore
//	extrn	free_reg,abs_value,init,log
//	extrn	fxtrac,splog,exp,tan
//	extrn	arctan,sqrt,remr,intpt
//	extrn	scale,exchange,restore_status
//	extrn	stenv,stcw,stsw,load_con
//	extrn	decr_top,incr_top,clex,exam
//	extrn	fetch_an_op,sin,cos,sincos
//	extrn	rem1
//
	.globl	_e80387

// --------------------------------------JKD-----------------------

// --------------------------------------JKD-----------------------

//        .globl  a_msr_selector
//
// *********************************************************************
//
//	address table for instruction group decoding handlers
//
// *********************************************************************
						// 10-9-8  (mod = 3)::1
group_handler:  
	.long   arith_short_real        //  0 0 0  0
	.long	arith_top_reg		//  0 0 0  1
	.long	load_short_real		//  0 0 1  0
	.long	transcendentals		//  0 0 1  1
	.long	arith_short_int		//  0 1 0  0
	.long	double_pop		//  0 1 0  1
	.long	load_short_int		//  0 1 1  0
	.long	administrative		//  0 1 1  1
	.long	arith_long_real		//  1 0 0  0
	.long	arith_reg_top		//  1 0 0  1
	.long	load_long_real		//  1 0 1  0
	.long	store_reg		//  1 0 1  1
	.long	arith_word_int		//  1 1 0  0
	.long	arith_reg_pop		//  1 1 0  1
	.long	load_word_int		//  1 1 1  0
	.long	transfer_status		//  1 1 1  1
// *********************************************************************
//
//	address table for r/m decoding handlers
//
// *********************************************************************
rm_handler:	
	.long	rm_0			// ea = (bx) + (si) + disp
	.long	rm_1			// ea = (bx) + (di) + disp
	.long	rm_2			// ea = (bp) + (si) + disp
	.long	rm_3			// ea = (bp) + (di) + disp
	.long	rm_4			// ea = (si) + disp
	.long	rm_5			// ea = (di) + disp
	.long	rm_6			// ea = (bp) + disp*
	.long	rm_7			// ea = (bx) + disp
// *********************************************************************
//
//	address table for 32 bit base register decoding handlers
//
// *********************************************************************
base32:	
	.long	base_0			// ea = (eax) + disp
	.long	base_1			// ea = (ecx) + disp
	.long	base_2			// ea = (edx) + disp
	.long	base_3			// ea = (ebx) + disp
	.long	base_4			// ea = (esp) + disp
	.long	base_5			// ea = (ebp) + disp*
	.long	base_6			// ea = (esi) + disp
	.long	base_7			// ea = (edi) + disp
// *********************************************************************
//
//	address table for 32 bit index register decoding handlers
//
// *********************************************************************
index32:	
	.long	index_0			// ea = (eax*ss) 
	.long	index_1			// ea = (ecx*ss) 
	.long	index_2			// ea = (edx*ss) 
	.long	index_3			// ea = (ebx*ss) 
	.long	index_4			// ea = (esp*ss) 
	.long	index_5			// ea = (ebp*ss) 
	.long	index_6			// ea = (esi*ss) 
	.long	index_7			// ea = (edi*ss) 
// *********************************************************************
//
//	address table for instruction operations
//
// *********************************************************************
op_table:	
	.long	load,store,chsign,compar,free_reg,arith,arith,arith
	.long	arith,ldcw,save,restore,free_reg,abs_value,init
	.long	fxtrac,two_arg_trans,two_arg_trans,exp,tan
	.long	two_arg_trans,sqrt,remr,intpt,scale
	.long	exchange,free_reg,restore_status,stenv,stcw,stsw
	.long	load_con,load_con,load_con,load_con,load_con,load_con
	.long	load_con,decr_top,incr_top,clex,compar,exam,sin,cos,sincos
	.long	remr,compar
//
// *********************************************************************
//
//	arithmetic operation type decode table
//
// *********************************************************************
						//          5-4-3
	ALIGN
group_0a_0b_2a_4a_4b_6a_6b_op:	
	.byte	add_op	// fadd     0 0 0
	.byte	mul_op			// fmul     0 0 1
	.byte	compar_op 		// fcom     0 1 0
	.byte	compar_pop		// fcomp    0 1 1
	.byte	sub_op			// fsub     1 0 0
	.byte	subr_op			// fsubr    1 0 1
	.byte	div_op			// fdiv     1 1 0
	.byte	divr_op			// fdivr    1 1 1
//
// *********************************************************************
//
//	control word/environment operation type decode table
//
// *********************************************************************
						//          5-4-3
	ALIGN
group_1a_op:	
	.byte	load_op			// fld      0 0 0
	.byte	error_op		// reserved 0 0 1
	.byte	store_op		// fst      0 1 0
	.byte	store_pop		// fstp     0 1 1
	.byte	ldenv_op		// fldenv   1 0 0
	.byte	ldcw_op			// fldcw    1 0 1
	.byte	stenv_op		// fstenv   1 1 0
	.byte	stcw_op			// fstsw    1 1 1
//
// *********************************************************************
//
//	load/exchange/nop operation decode table
//
// *********************************************************************
						//          5-4-3-2-1-0
	ALIGN
group_1ba_op:	
	.byte	load_op			// fld      0 0 0 r e g
	.byte	exchange_op		// fxch     0 0 1 r e g
	.byte	null_op			// fnop     0 1 1 r e g
	.byte	store_pop		// fstp *   0 1 1 r e g
//
// *********************************************************************
//
//	transcendental operation decode table
//
// *********************************************************************
						//          5-4-3-2-1-0
	ALIGN
group_1bb_op:	
	.byte	chsign_op		// fchs     1 0 0 0 0 0
	.byte	abs_op			// fabs     1 0 0 0 0 1
	.byte	error_op		// reserved 1 0 0 0 1 0
	.byte	error_op		// reserved 1 0 0 0 1 1
	.byte	test_op			// ftst     1 0 0 1 0 0
	.byte	exam_op			// fxam     1 0 0 1 0 1
	.byte	error_op		// reserved 1 0 0 1 1 0
	.byte	error_op		// reserved 1 0 0 1 1 1
	.byte	load_1_op		// fld1     1 0 1 0 0 0
	.byte	load_l2t_op		// fldl2t   1 0 1 0 0 1
	.byte	load_l2e_op		// fldl2e   1 0 1 0 1 0
	.byte	load_pi_op		// fldpi    1 0 1 0 1 1
	.byte	load_lg2_op		// fldlg2   1 0 1 1 0 0
	.byte	load_ln2_op		// fldln2   1 0 1 1 0 1
	.byte	load_0_op		// fldz     1 0 1 1 1 0
	.byte	error_op		// reserved 1 0 1 1 1 1
	.byte	exp_op			// f2xm1    1 1 0 0 0 0
	.byte	log_op			// fyl2x    1 1 0 0 0 1
	.byte	tan_op			// fptan    1 1 0 0 1 0
	.byte	arctan_op		// fpatan   1 1 0 0 1 1
	.byte	fxtrac_op		// fxtract  1 1 0 1 0 0
	.byte	rem1_op			// fprem1   1 1 0 1 0 1
	.byte	decstp_op		// fdecstp  1 1 0 1 1 0
	.byte	incstp_op		// fincstp  1 1 0 1 1 1
	.byte	remr_op			// fprem    1 1 1 0 0 0
	.byte	splog_op		// fyl2xp1  1 1 1 0 0 1
	.byte	sqrt_op			// fsqrt    1 1 1 0 1 0
	.byte	sincos_op		// fsincos  1 1 1 0 1 1
	.byte	intpt_op		// frndint  1 1 1 1 0 0
	.byte	scale_op		// fscale   1 1 1 1 0 1
	.byte	sin_op			// fsin     1 1 1 1 1 0
	.byte	cos_op		    // fcos     1 1 1 1 1 1
//
// *********************************************************************
//
//	tempreal/bcd/short integer/long integer operation decode table
//
// *********************************************************************
						//          5-4-3
	ALIGN
group_3a_7a_op:	
	.byte	load_op			// fild     0 0 0
	.byte	error_op		// reserved 0 0 1
	.byte	store_op		// fist     0 1 0
	.byte	store_pop		// fistp    0 1 1
	.byte	load_op			// (fbld)   1 0 0
	.byte	load_op			// f(i)ld   1 0 1
	.byte	store_pop		// (fbstp)  1 1 0
	.byte	store_pop		// f(i)stp  1 1 1
//
// *********************************************************************
//
//	clear exception/initialize operation decode table
//
// *********************************************************************
						//          5-4-3-2-1-0
	ALIGN
group_3b_op:	
	.byte	null_op			// feni     1 0 0 0 0 0
	.byte	null_op			// fdisi    1 0 0 0 0 1
	.byte	cler_op			// fclex    1 0 0 0 1 0
	.byte	init_op			// finit    1 0 0 0 1 1
	.byte	null_op			// fsetpm   1 0 0 1 0 0
	.byte	error_op		// reserved 1 0 0 1 0 1
	.byte	error_op		// reserved 1 0 0 1 1 0
	.byte	error_op		// reserved 1 0 0 1 1 1
//
// *********************************************************************
//
//	restore/save operation decode table
//
// *********************************************************************
						//          5-4-3
	ALIGN
group_5a_op:	
	.byte	load_op			// fld      0 0 0
	.byte	error_op		// reserved 0 0 1
	.byte	store_op		// fst      0 1 0
	.byte	store_pop		// fstp     0 1 1
	.byte	restore_op		// frstor   1 0 0
	.byte	error_op		// reserved 1 0 1
	.byte	save_op			// fsave    1 1 0
	.byte	stsw_op			// fstsw    1 1 1
//
// *********************************************************************
//
//	free register/store operation decode table
//
// *********************************************************************
						//          5-4-3
	ALIGN
group_5b_op:	
	.byte	free_op			// ffree    0 0 0
	.byte	exchange_op		// fxch *   0 0 1
	.byte	store_op		// fst      0 1 0
	.byte	store_pop		// fstp     0 1 1
	.byte	ucom_op			// fucom    1 0 0
	.byte	ucom_pop		// fucomp   1 0 1
	.byte	error_op		// reserved 1 1 0
	.byte	error_op		// reserved 1 1 1
//
// *********************************************************************
//
//	transfer status operation decode table
//
// *********************************************************************
						//          5-4-3
	ALIGN
group_7b_op:	
	.byte	free_op			// ffree *  0 0 0
	.byte	exchange_op		// fxch *   0 0 1
	.byte	store_pop		// fstp *   0 1 0
	.byte	store_pop		// fstp *   0 1 1
	.byte	stsw_op			// fstsw    1 0 0
	.byte	error_op		// reserved 1 0 1
	.byte	error_op		// reserved 1 1 0
	.byte	error_op		// reserved 1 1 1
//
// *********************************************************************
//
//	load/store environment/control word operand 1 loc/for table
//
// *********************************************************************
						     //          5-4-3
	ALIGN
group_1a_op1_lf:	
	.value  memory_opnd*0x100+single_real // fld      0 0 0
	.value  null*0x100+null              // reserved 0 0 1
	.value  stack_top*0x100+extended_fp   // fst      0 1 0
	.value  stack_top*0x100+extended_fp   // fstp     0 1 1
	.value  null*0x100+null               // fldenv   1 0 0
	.value  null*0x100+null               // fldcw    1 0 1
	.value  null*0x100+null              // fstenv   1 1 0
	.value  null*0x100+null              // fstcw    1 1 1
//
// *********************************************************************
//
//       transcendental operand/result format codes
//
// *********************************************************************
//
#define	null_fmt	0
#define	top_fmt		1	
#define	topm1_fmt	2	
#define	topp1_fmt	3
#define	op1	0x40
#define	op2	0x10
#define	res1	4
#define	res2	1
//
//	transcendental operand/result form at types
//
// #define	fprem_type	op1*top_fmt+op2*topm1_fmt+res1*top_fmt
#define	fprem_type	0x64
// #define	fyl2x_type	op1*top_fmt+op2*topm1_fmt+res1*topm1_fmt
#define	fyl2x_type	0x68
#define	fdecstp_type	null_fmt
#define	fchs_type	op1*top_fmt+res1*top_fmt
#define	fld1_type	res1*topp1_fmt
#define	ftst_type	op1*top_fmt
// #define	fptan_type	op1*top_fmt+res1*top_fmt+res2*topp1_fmt
#define	fptan_type	0x47
// #define	fpatan_type	op1*topm1_fmt+op2*top_fmt+res1*topm1_fmt
#define	fpatan_type	0x98
#define	fscale_type	op1*topm1_fmt+op2*top_fmt+res1*top_fmt
//
//fsin_type   equ op1*top_fmt + res1*top_fmt
//fcos_type   equ op1*top_fmt + res1*top_fmt
//
//	operand/result format/location table
//
	ALIGN
group_1bb_lf:	
	.value	null					// null_fmt
	.value  stack_top*0x100+extended_fp             // top_fmt
	.value  stack_top_minus_1*0x100+extended_fp     // topm1_fmt
	.value  stack_top_plus_1*0x100+extended_fp      // topp1_fmt
//
// *********************************************************************
//
//	transcendental operand/result format/location type table
//
// *********************************************************************
						//          5-4-3-2-1-0
	ALIGN
group_1bb_type:	
	.byte	fchs_type		// fchs     1 0 0 0 0 0
	.byte	fchs_type		// fabs     1 0 0 0 0 1
	.byte	fdecstp_type		// reserved 1 0 0 0 1 0
	.byte	fdecstp_type		// reserved 1 0 0 0 1 1
	.byte	ftst_type		// ftst     1 0 0 1 0 0
	.byte	ftst_type		// fxam     1 0 0 1 0 1
	.byte	fdecstp_type		// reserved 1 0 0 1 1 0
	.byte	fdecstp_type		// reserved 1 0 0 1 1 1
	.byte	fld1_type		// fld1     1 0 1 0 0 0
	.byte	fld1_type		// fldl2t   1 0 1 0 0 1
	.byte	fld1_type		// fldl2e   1 0 1 0 1 0
	.byte	fld1_type		// fldpi    1 0 1 0 1 1
	.byte	fld1_type		// fldlg2   1 0 1 1 0 0
	.byte	fld1_type		// fldln2   1 0 1 1 0 1
	.byte	fld1_type		// fldz     1 0 1 1 1 0
	.byte	fdecstp_type		// reserved 1 0 1 1 1 1
	.byte	fchs_type		// f2xm1    1 1 0 0 0 0
	.byte	fyl2x_type		// fyl2x    1 1 0 0 0 1
	.byte	fptan_type		// fptan    1 1 0 0 1 0
	.byte	fpatan_type		// fpatan   1 1 0 0 1 1
	.byte	fptan_type		// fxtract  1 1 0 1 0 0
	.byte	fprem_type		// fprem1   1 1 0 1 0 1
	.byte	fdecstp_type		// fdecstp  1 1 0 1 1 0
	.byte	fdecstp_type		// fincstp  1 1 0 1 1 1
	.byte	fprem_type		// fprem    1 1 1 0 0 0
	.byte	fyl2x_type		// fyl2xp1  1 1 1 0 0 1
	.byte	fchs_type		// fsqrt    1 1 1 0 1 0
	.byte	fptan_type		// fsincos  1 1 1 0 1 1
	.byte	fchs_type		// frndint  1 1 1 1 0 0
	.byte	fscale_type		// fscale   1 1 1 1 0 1
	.byte	fchs_type		// fsin     1 1 1 1 1 0
	.byte	fchs_type		// fcos     1 1 1 1 1 1
//
// *********************************************************************
//
//	load/store short integer/tempreal operand 1 format table
//
// *********************************************************************
						//          5-4-3
	ALIGN
group_3a_op1_fmt:	
	.byte	int32			// fild     0 0 0
	.byte	null			// reserved 0 0 1
	.byte	extended_fp		// fist     0 1 0
	.byte	extended_fp		// fistp    0 1 1
	.byte	null			// reserved 1 0 0
	.byte	extended_fp		// fld      1 0 1
	.byte	null			// reserved 1 1 0
	.byte	extended_fp		// fstp     1 1 1
// *********************************************************************
//
//	load/store integer/tempreal/bcd operand 1 location table
//
// *********************************************************************
						//          5-4-3
	ALIGN
group_3a_7a_op1_loc:	
	.byte	memory_opnd		// fild     0 0 0
	.byte	null			// reserved 0 0 1
	.byte	stack_top		// fist     0 1 0
	.byte	stack_top		// fistp    0 1 1
	.byte	memory_opnd		// (fbld)   1 0 0
	.byte	memory_opnd		// f(i)ld   1 0 1
	.byte	stack_top		// (fbstp)  1 1 0
	.byte	stack_top		// f(i)stp  1 1 1
//
// *********************************************************************
//
//	load/store short integer/tempreal result format table
//
// *********************************************************************
						//          5-4-3
	ALIGN
group_3a_res_fmt:	
	.byte	extended_fp		// fild     0 0 0
	.byte	null			// reserved 0 0 1
	.byte	int32			// fist     0 1 0
	.byte	int32			// fistp    0 1 1
	.byte	null			// reserved 1 0 0
	.byte	extended_fp		// fld      1 0 1
	.byte	null			// reserved 1 1 0
	.byte	extended_fp		// fstp     1 1 1
// *********************************************************************
//
//	load/store integer/tempreal/bcd result location table
//
// *********************************************************************
						//          5-4-3
	ALIGN
group_3a_7a_res_loc:	
	.byte	stack_top		// fild     0 0 0
	.byte	null			// reserved 0 0 1
	.byte	memory_opnd		// fist     0 1 0
	.byte	memory_opnd		// fistp    0 1 1
	.byte	stack_top_plus_1	// (fbld)   1 0 0
	.byte	stack_top_plus_1	// f(i)ld   1 0 1
	.byte	memory_opnd		// (fbstp)  1 1 0
	.byte	memory_opnd		// f(i)stp  1 1 1
//
// *********************************************************************
//
//	load/store state/status word operand 1 loc/for table
//
// *********************************************************************
						     //          5-4-3
	ALIGN
group_5a_op1_lf:	
	.value  memory_opnd*0x100+double_real // fld      0 0 0
	.value  null*0x100+null              // reserved 0 0 1
	.value  stack_top*0x100+extended_fp   // fst      0 1 0
	.value  stack_top*0x100+extended_fp   // fstp     0 1 1
	.value  null*0x100+null               // frstor   1 0 0
	.value  null*0x100+null              // reserved 1 0 1
	.value  null*0x100+null              // fsave    1 1 0
	.value  null*0x100+null              // fstsw    1 1 1
// *********************************************************************
//
//	bcd/long integer operand 1 format table
//
// *********************************************************************
						//          5-4-3
	ALIGN
group_7a_op1_fmt:	
	.byte	int16			// fild     0 0 0
	.byte	null			// reserved 0 0 1
	.byte	extended_fp		// fist     0 1 0
	.byte	extended_fp		// fistp    0 1 1
	.byte	bcd			// fbld     1 0 0
	.byte	int64			// fild     1 0 1
	.byte	extended_fp		// fbstp    1 1 0
	.byte	extended_fp		// fistp    1 1 1
//
// *********************************************************************
//
//	bcd/long integer result format table
//
// *********************************************************************
						//          5-4-3
	ALIGN
group_7a_res_fmt:	
	.byte	extended_fp		// fild     0 0 0
	.byte	null			// reserved 0 0 1
	.byte	int16			// fist     0 1 0
	.byte	int16			// fistp    0 1 1
	.byte	extended_fp		// fbld     1 0 0
	.byte	extended_fp		// fild     1 0 1
	.byte	bcd			// fbstp    1 1 0
	.byte	int64			// fistp    1 1 1
// for the return from e80387
	.set    KFL, 0x3bfff            // clear NT bit in flags
        .text
// ***********************************************************************
//			e80387:
//
//	function:
//		executive program for 80387 emulator.
//		decode instruction, i.e. separate operation,operand
//		and result info; get memory operand pointer.
//
//	inputs:
//		instruction (in memory).
//
//	outputs:
//		op1, op2, operation, result, result2, and memory operand
//		pointer info
//
//	data accessed:
//		- op1_format			op1_location
//		- op1_use_up			op2_format
//		- op2_location			op2_use_up
//		- operation_type		result_location
//		- result_format			result2_format
//		- result2_location
//
//	data changed:
//		- mem_operand_pointer		op1_location
//		- op1_format			op1_use_up
//		- op2_format			op2_location
//		- op2_use_up			result_location
//		- result_format			result2_format
//		- result2_location
//
// ***************************************************************************
//	assume	%ds:a_med
//	---------------------JKD
//	.data
//LJKD:
//	.string		* ADDRESS is %x %x\n*
//	.text
//
//	---------------------JKD
	ALIGN
_e80387:	//proc
	movl	%esp, %ebp
	movl	0x4(%ebp),%esp		// pick up state pointer.
	subl    $(WORK_AREA_SIZE),%esp // stack space
	mov	%esp,%ebp		//set bp to global_reentrant_seg
	
	/* establish addressibility to the floating point state */
	push	$FPSTATESEL		// set window to fp registers
	pop	%gs			// in u area

        /* clear the work area */
        lea     work_area(%ebp),%edi
        xorl    %eax,%eax
        movl    $WORK_AREA_WORDS,%ecx    // number of longs to clear.
	
	FALLSTHRU
1:
        movl    %eax,0(%edi)
	addl	$4,%edi
	decl	%ecx
	testl	%ecx,%ecx
	jg	1b

/* always 32 bits */
//	movb	$0, is16bit(%ebp)	// record we are not 16 bit

	FALLSTHRU
continu_init:

#ifdef FP_COUNTERS
	/* this keeps track of how many floating point ops were emulated */
	push	%ss
	pop	%ds
	movl	$_fp_total,%ecx
	movl	0(%ecx),%eax
	inc	%eax
	movl	%eax,0(%ecx)
#endif /* FP_COUNTERS */

	movb	$null,%dl			// initialize op1 and op2
	movb	%dl,%cl			//  format registers to null
	MOVL    $do_nothing*0x100+do_nothing,%bx // initialize useups
	lds	saved_eip(%ebp),%esi // load instruction pointer

	movb	$1,oprnd_siz32(%ebp)	//set operand size=32
	movb	$1,addrs_siz32(%ebp)	//set address size=32
#ifdef MS_DOS
	lar	saved_cs(%ebp),%eax	//load access right byte of cs
	test	$0x00400000,%eax		//check 32 bit default ?
	jnz	get_opcode		//if yes continue
	decb	oprnd_siz32(%ebp)	//else default is 16bit
	decb	addrs_siz32(%ebp)
#endif /* MS_DOS */
	FALLSTHRU
get_opcode:	
	MOVL	(%esi),%ax		//load two bytes

	inc	%esi			//inc pointer
	andb	$0x87,%al			// is the first byte a prefix
	jns	get_opcode		// yes skip for now
	addb	$0x40,%ah			// no, add 1 to mod
	rclb	$1,%al			// cf set if mod = 3
	rolb	$1,%al			// form handler table index
	MOVL	$0x3800,%si		// form bits 5-4-3 index in si
	andw	%ax,%si
	shrw	$11,%si
	MOVL	$0x001e,%di		// form group handler table
	andw	%ax,%di			//  index in di
	shlw	$1,%di			// take care of dd instead of dw
	push	%cs			// copy cs to ds for addressing
	pop	%ds			//  all the tables
	movswl  %si,%esi
	movswl  %di,%edi
	call    *%cs:group_handler(%edi)     // call the proper group handler
	andb	$0x07,%ah			// store register number (r/m)
	movw	%ax,operation_type(%ebp)	// and operation type
	movw	%dx,op1_format(%ebp) // store operand and result
	movw	%cx,op2_format(%ebp) // formats and locations
	movw	%si,result_format(%ebp)
	movw	%di,result2_format(%ebp)
	movb	%bh,op1_use_up(%ebp)	// store op1 and op2 useups
	movb	%bl,op2_use_up(%ebp)
	lds	saved_eip(%ebp),%esi // load instruction pointer
	mov	%esi,instruction_pointer(%ebp) // save old pointer
	movw	%ds,instruction_pointer+4(%ebp)
	XORL	%cx,%cx			// extended addressing = false
	xor	%ebx,%ebx
	FALLSTHRU
segment_ds:
	movw	saved_ds(%ebp),%dx	// assume ds is pointer base
get_mod_rm_byte:
	MOVL	(%esi),%ax	// load first two bytes again

	inc	%esi			// bump instruction pointer
	andb	%al,%al			// is there an override?
	js	got_mod_rm		// no, ah contains mod r/m byte
	cmpb	$0x67,%al			// is there an address overide
	jne	check_prefix66		// no is it 66
	xorb	$1,addrs_siz32(%ebp)	//yes adjust address size
	jmp	get_mod_rm_byte
	ALIGN
check_prefix66:
	cmpb	$0x66,%al		//is it 66 overide
	jne	other_prefix		//no some other prefix
	xorb	$1,oprnd_siz32(%ebp)	//adjust operand size
	jmp	get_mod_rm_byte
	ALIGN
other_prefix:
	decw	%cx			// yes, boolean = true
	MOVL	saved_fs(%ebp),%dx	// load fs: override
	cmpb	$0x64,%al			// is it fs: ?
	je	get_mod_rm_byte		// yes, scan past prefix byte
	MOVL	saved_gs(%ebp),%dx	// load gs: override
	cmpb	$0x65,%al			// is it gs: ?
	je	get_mod_rm_byte		// yes, scan past prefix byte
	MOVL	saved_es(%ebp),%dx	// load es: override
	cmpb	$0x26,%al			// is it es: ?
	je	get_mod_rm_byte		// yes, scan past prefix byte
	MOVL	saved_cs(%ebp),%dx	// no, load cs: override
	cmpb	$0x2e,%al			// is it cs: ?
	je	get_mod_rm_byte		// yes, scan past prefix byte
	MOVL	old_ss(%ebp),%dx			// no, load ss: override
	cmpb	$0x36,%al			// is it ss: ?
	je	get_mod_rm_byte		// yes, scan past prefix byte
	jmp	segment_ds		// no, assume ds: override
	ALIGN
got_mod_rm:

	inc	%esi			// bump instruction pointer
	movb	%ah,%bl			// save mod r/m in bl

	testb	$1,addrs_siz32(%ebp)	//check if 32bit addressing
	jnz	addrs_32_bit

	movzwl    (%esi),%eax      // load possible displacement

	push	%eax
	MOVL	saved_ds(%ebp), %ax	// restore %ds register to its initial
	movw	%ax, %ds		// value.
	pop	%eax

	cmpb	$0x0c0,%bl			// is mod = 3?
	jnc	store_return		// yes, no memory operand
	shlb    $1,%bl                  // no, is mod = 2?
	jc	mod_2			// yes, disp = disp-hi: disp-lo
	js	mod_1			// branch if mod = 1
	andb	$0x0e,%bl			// mod = 0
	cmpb	$0x0c,%bl			// does r/m = 6?
	je	store_ea		// yes, ea = disp-hi: disp-lo
	xorw	%ax,%ax			// no, disp = 0
	dec	%esi			// subtract one for return
	FALLSTHRU
mod_1:
	dec	%esi			// subtract one for return
	cbtw                             // extend disp to 16 bits
mod_2:
	and	$0x0000000e,%ebx		// ax now = real displacement
	shl	$1,%ebx			// take care of dd instead of dw
	call    *%cs:rm_handler(%ebx)    // call r/m handler (cs <> ds)
	FALLSTHRU
store_ea:
	inc	%esi			// add two for return address
	inc	%esi
store_on:
	movw	%dx,mem_operand_pointer+4(%ebp) // store base
	mov	%eax,mem_operand_pointer(%ebp) // store offset
	testb	$0x80,operation_type(%ebp)	// update sr_memop pointer?
	jnz	store_return		// no, must be administrative
	movw	%dx,%gs:sr_mem_base	// yes, store base in a?msr
	mov	%eax,%gs:sr_mem_offset	// store offset in a?msr
	FALLSTHRU
store_return:
	mov	%esi,saved_eip(%ebp)	// update return address
	mov	offset_op1_rec,%esi	//set up for fetch_an_op
	mov	$offset_operand1,%edi
	movl	$0, before_error_signals(%ebp)
	movl	$0, extra_dword_reg(%ebp)
	movl	$0, extra_dword_reg+4(%ebp)
	movl	$0, extra_dword_reg+8(%ebp)
	call	fetch_an_op		// fetch op1
	pushw	%ax			//save stack error flag
	mov	offset_op2_rec,%esi	//set up for fetch_an_op
	mov	$offset_operand2,%edi
	call	fetch_an_op		// fetch op2
	popw	%bx			// combine stack error flags
	orw	%bx,%ax			// set/reset zf, clear cf
	movb	operation_type(%ebp),%bl	// load operation type
	rclb	$1,%bl			// shift save ptrs flag to cf
	jnc	pending_unmasked_xcptns_// all non-administratives must check
	movb	operation_type(%ebp),%cl// duo-form administratives are all
	cmpb	$ldenv_op,%cl			// treated as unwaited forms:
	ja	do_operation		// fnstenv, fnstcw, fnstsw, and fnclex
	cmpb	$init_op,%cl					// and fninit
	je	do_operation				// and
	cmpb	$save_op,%cl		// fnsave all ignore pending unmasked
	je	do_operation			// exceptions and just execute.
	FALLSTHRU
pending_unmasked_xcptns_:
	movb	%gs:sr_masks,%cl
	notb	%cl
	andb	$0x3f,%cl
	andb	%gs:sr_errors,%cl
	jz	no_pending_unmasked_xcptns
	int	$16
	jmp	pending_unmasked_xcptns_
	ALIGN
no_pending_unmasked_xcptns:
	testb	$0x80,operation_type(%ebp)
	jnz	do_operation
	push	%eax
	les	instruction_pointer(%ebp),%eax // load instruction ptr
	mov	%eax,%gs:sr_instr_offset	// store offset in status reg
	movw	%es,%gs:sr_instr_base	// store base in status reg
	pop	%eax
	FALLSTHRU
do_operation:
	movswl  %bx,%ebx
	rol	$1,%ebx			//take care of dd
	orw	%ax,%ax		// give zf value expected by following call

	call    *%cs:op_table(%ebx)          // call instruction operator
	movb	%gs:sr_masks,%al		//set zf to false if any
	notb	%al			// unmasked errors,
	andb	$0x7f,%al	//get rid of es bit
	andb	%gs:sr_errors,%al		//set al to 0 if none
	jz	release_stack
	movb	$0,%al
	movb	operation_type(%ebp),%cl
	testb	$0x80,%cl
	jz	mark_errors
	cmpb	$ldenv_op,%cl
	ja	get_done
	FALLSTHRU
mark_errors:
	orw	$0x8080, %gs:sr_errors	//taking care of es and B
	movb	$0x02,%al			// load nonzero ie mask
	jmp	get_done
	ALIGN
release_stack:
	andw	$0x7f7f, %gs:sr_errors
get_done:

	/* 
	 * This code checks if the next instruction is a floating point op.
	 * If so, just process it and save the fault.
	 */
	movl	saved_eip(%ebp), %esi
	movl	%esi,%edi

#if	0
	/* 
	 * This is to test that we are not within 11 bytes of the end
	 * of a page.  If we are, it is best to let the processor trap
	 * into the kernel for the next instruction because the code page 
	 * may not be in memory.  It is not good when the page is not in
	 * memory and the kernel attempts to reference that location.
	 */
	andl	$0xff5,%edi		// isolate bits that will be all ones
	xor	$0xff5,%edi		// are they all ones?
	jz	all_done		// yes - let processor handle it.
	andl	$0xfff,%edi		// start of a new page?
	jz	all_done		// yes - do not take a chance
#endif

	/*
	 * The last check is to make sure we are not going through a
	 * floating point loop which will not end.  After 5 instructions
	 * return to user space.
	 */
	mov	inst_counter(%ebp),%ecx // get count
	inc	%ecx
	mov	%ecx,inst_counter(%ebp)
	cmpb	$5,%cl			// too many inst?
	jz	all_done		// yes return to user space

	/*
	 * Now check if the next instruction is a floating point opcode.
	 */
	movl	0(%esi),%ecx		
	andl	$0xf8,%ecx
	cmpl	$0xd8,%ecx		// escape sequence for fp instructions
	je	continu_init		// it is an fp instruction

	FALLSTHRU
all_done:

	andb	saved_flags+1(%ebp),%al		// interrupt enabled?
	jz	no_exception		// branch if no exception
	int	$16			// 80387 exception interrupt
	FALLSTHRU
no_exception:

	addl    $(WORK_AREA_SIZE),%esp	// stack space

	popl	%gs
	popl	%fs
	popl	%es
	popl	%ds
	popa
	addl    $8, %esp        // get TRAPNO and ERROR off the stack

	// User may have set NT bit before doing a system call.
	// This would be bad, so we turn it off here.
	// On a system call, the flags get pushed, then popped.  Since the
	// VM bit always gets zeroed when pushed, we do not need to clear it.
	andl    $KFL, 8(%esp)    // clear the NT bit in the flags
	iret

	ALIGN
rm_0:
	addw	saved_ebx(%ebp),%ax	// ea = (bx) + (si) + disp
rm_4:
	addw	saved_esi(%ebp),%ax	// ea = (si) + disp
	ret
	ALIGN
rm_5:
	addw	saved_edi(%ebp),%ax	// ea = (di) + disp
	ret
	ALIGN
rm_1:
	addw	saved_edi(%ebp),%ax	// ea = (bx) + (di) + disp
rm_7:
	addw	saved_ebx(%ebp),%ax	// ea = (bx) + disp
	ret
	ALIGN
rm_2:
	addw	saved_esi(%ebp),%ax	// ea = (bp) + (si) + disp
rm_6:
	addw	saved_ebp(%ebp),%ax	// ea = (bp) + disp
	jcxz	segment_ss		// branch if no override given
	ret
	ALIGN
rm_3:
	addw	saved_edi(%ebp),%ax	// ea = (bp) + (di) + disp
	jmp	rm_6			// merge with r/m = 6
	ALIGN
segment_ss:
	MOVL	old_ss(%ebp),%dx	// for r/m = 2, 3, or 6, the
	ret				// standard base = ss
	ALIGN
//
addrs_32_bit:	
	xor	%edi,%edi			//clear edi
	cmpb	$0xc0, %ah	
	jae	no_sib
	andb	$0x07,%ah			//check if sib present
	cmpb	$0x04,%ah
	jne	no_sib			//
	movb	(%esi),%bh		//yes get  sib byte
	inc	%esi
	FALLSTHRU
no_sib:
	mov	(%esi),%eax		//get displacement

	push	%ds
	pop	%fs			/ save selector
//
//	assume	%ds:a_msrs
//
//        push    a_msrs                  / push the dynamic selector
//        pop     %ds                     /  for the a?msr segment
//        push    a_msr_selector          / and load it into ds
//        pop     %ds
//
//	assume	%ds:a_msr		; assume ds=a?msr from here on
//
	push	%eax
	MOVL	saved_ds(%ebp), %ax	// restore %ds register to its initial
	movw 	%ax, %ds		//segment value.
	pop	%eax

	cmpb	$0x0c0,%bl			// is mod = 3?
	jnc	store_return		// yes, no memory operand
	add	$4,%esi
	shlb	$1,%bl			// no, is mod = 2?
	jc	mod32_2			// yes, disp = disp-hi: disp-lo
	js	mod32_1			// branch if mod = 1
	andb	$0x0e,%bl			// mod = 0
	inc	%edi			// set flag
	cmpb	$0x0a,%bl			// does r/m = 5?i
	je	store_on		// yes, ea = disp-hi: disp-lo
	xor	%eax,%eax			// no, disp = 0
	dec	%esi			// subtract one for return
	FALLSTHRU
mod32_1:
	sub	$3,%esi			// adjust esi
	movsbl  %al,%eax                // extend disp to 32 bits
mod32_2:
	andb	$0x0f,%bl			//check if sib present
	cmpb	$0x8,%bl
	je	process_sib
	and	$0x0000000e,%ebx		//no sib get base register
	shl	$1,%ebx			//form index in table
	call    *%cs:base32(%ebx)
	jmp	store_on		//store displacement
	ALIGN

process_sib:	
	movb	%bh,%bl			//
	and	%edi,%edi			//edi=1 if mod=0
	jz	get_base		//
	andb	$0x07,%bh			//get last 3 bits
	cmpb	$0x05,%bh			//if mod=0 and basereg=5,no base
	jne	get_base
	mov	%fs:(%esi),%eax		//get displacement
	add	$4,%esi			// adjust esi
	jmp	get_sir			//get sir
	ALIGN

get_base:	
	MOVL	%bx,%di			//save bx
	and	$0x00000007,%ebx		//form index in the base table
	shl	$2,%ebx
	call    *%cs:base32(%ebx)
	MOVL	%di,%bx			//restore bx

	FALLSTHRU
get_sir:	
	movb	%bl,%bh			//load sib byte
	andb	$0x038,%bh			//get midle 3 bits
	cmpb	$0x020,%bh			//index=4 no index reg
	je	store_on		//if no index jmp out
	movb	%bl,%cl			//save bl
	rolb	$2,%cl			//get high order 2 bits
	andb	$0x03,%cl			//in the low bits
	shrb	$1,%bl			//form index into table
	and	$0x0000001c,%ebx
	call    *%cs:index32(%ebx)               //add sir to displacement
	jmp	store_on
	ALIGN

base_0:	
	add	saved_eax(%ebp),%eax
	ret
	ALIGN
base_1:
	add	saved_ecx(%ebp),%eax
	ret
	ALIGN
base_2:
	add	saved_edx(%ebp),%eax
	ret
	ALIGN
base_3:
	add	saved_ebx(%ebp),%eax
	ret
	ALIGN
base_4:
	add	old_esp(%ebp),%eax
	jcxz	segmentss
	ret
	ALIGN
base_5:
	add	saved_ebp(%ebp),%eax
	jcxz	segmentss
	ret
	ALIGN
segmentss:	
	MOVL	old_ss(%ebp),%dx		// for esp, ebp as base registers
	ret
	ALIGN

base_6:
	add	saved_esi(%ebp),%eax
	ret
	ALIGN
base_7:
	add	saved_edi(%ebp),%eax
	ret
	ALIGN

index_0:	
	mov	saved_eax(%ebp),%edi
	shll    %cl,%edi
	add	%edi,%eax
	ret
	ALIGN
index_1:	
	mov	saved_ecx(%ebp),%edi
	shll    %cl,%edi
	add	%edi,%eax
	ret
	ALIGN
index_2:	
	mov	saved_edx(%ebp),%edi
	shll    %cl,%edi
	add	%edi,%eax
	ret
	ALIGN
index_3:	
	mov	saved_ebx(%ebp),%edi
	shll    %cl,%edi
	add	%edi,%eax
index_4:
	ret
	ALIGN
index_5:	
	mov	saved_ebp(%ebp),%edi
	shll    %cl,%edi
	add	%edi,%eax
	ret
	ALIGN
index_6:	
	mov	saved_esi(%ebp),%edi
	shll    %cl,%edi
	add	%edi,%eax
	ret
	ALIGN
index_7:	
	mov	saved_edi(%ebp),%edi
	shll    %cl,%edi
	add	%edi,%eax
	ret
	ALIGN

//
//	assume	%ds:a_med
// ****************************************************************************
//
//	instruction group decoding handlers
//
// ****************************************************************************
//
//	these handlers load all necessary operation, operand, and result
//	information into the following registers for storage into the
//	global data records upon return:
//
//	 dh => op1_location		dl => op1_format (null)
//	 ch => op2_location		cl => op2_format (null)
//	 si => result_location/result_format
//	 di => result2_location/result2_format
//	 bh => op1_use_up (do_nothing)	bl => op2_use_up (do_nothing)
//	 ah => (mod r/m, reg byte)	al => operation_type
//
//	parentheses indicate initial values upon entry.
//
// ****************************************************************************
//
//	group 0a - standard arithmetic instructions with short-real operands
//
arith_short_real:
	movb	$single_real,%cl		// op2 format is short real
op1_top_op2_mem_0a:
	movb	$memory_opnd,%ch		// op2 loc is memory operand
op1_top_stand_arith_op_0a:
	movb	group_0a_0b_2a_4a_4b_6a_6b_op(%esi),%al // arithmetic op
	MOVL	%dx,%di			// result2 format is null
	MOVL    $(stack_top*0x100+extended_fp),%dx // op1 top extended_fp
	MOVL	%dx,%si			// result is same as op1
	FALLSTHRU
arith_op_0a:
	cmpb	$subr_op,%al		// is it fsubr ?
	je	fsubr_0a		// reverse operands
	cmpb	$divr_op,%al		// is it fdivr ?
	je	fdivr_0a		// reverse operands
	cmpb	$compar_pop,%al		// is it fcomp ?
	jne	exit_0a			// no, return
	movb	$compar_op,%al		// yes, op type is compare
	movb	pop_stack,%bh		// op1 useup is pop stack
	FALLSTHRU
exit_0a:
	ret
	ALIGN
fsubr_0a:
	movb	$sub_op,%al		// operation type is subtract
	jmp	swap_0a		// switch operand locations
	ALIGN
fdivr_0a:
	movb	$div_op,%al		// operation type is division
swap_0a:
	xchgb	%bl,%bh			// switch operand useups
	xchgw	%cx,%dx			// switch operand fmt/loc
	ret
	ALIGN
//
//	group 2a - standard arithmetic instructions with short integer operands
//
arith_short_int:
	movb	$int32,%cl		// op2 format is short integer
	jmp	op1_top_op2_mem_0a	// finish loading information
	ALIGN
//
//	group 4a - standard arithmetic instructions with long-real operands
//
arith_long_real:
	movb	$double_real,%cl		// op2 format is long real
	jmp	op1_top_op2_mem_0a	// load rest of information
	ALIGN
//
//	group 6a - standard arithmetic instructions with word-integer operands
//
arith_word_int:
	movb	$int16,%cl		// op2 format is word integer
	jmp	op1_top_op2_mem_0a	// load rest of information
	ALIGN
//
//	group 0b - standard arithmetic instructions with inner-stack operands
//
arith_top_reg:
	MOVL    $(reg*0x100+extended_fp),%cx // op2 is reg extended_fp
	jmp	op1_top_stand_arith_op_0a // load rest of information
	ALIGN
//
//	group 6b - reversed arithmetic with register operand and pop useup
//
arith_reg_pop:
	movb	pop_stack,%bl		// op2 useup is pop stack
//
//	group 4b - reversed arithmetic instructions with inner-stack operands
//
arith_reg_top:
	movb	group_0a_0b_2a_4a_4b_6a_6b_op(%esi),%al // arithmetic ops
	MOVL	%dx,%di			// result2 format is null
	MOVL    $(stack_top*0x100+extended_fp),%dx // op1 top extended_fp
	MOVL    $(reg*0x100+extended_fp),%cx // op2 is reg extended_fp
	MOVL	%cx,%si			// result is same as op2
	jmp	arith_op_0a		// load rest of information
	ALIGN
//
//	group 1a - load/store instructions with short-real operand
//		   load/store environment/control word with string operand
//
load_short_real:
	movb	group_1a_op(%esi),%al	// load operation type
	shlw	$1,%si			// change byte index to word
	movswl  %si,%esi
	MOVL	group_1a_op1_lf(%esi),%dx	// load op1 loc/for
	MOVL    $(memory_opnd*0x100+single_real),%si // result format
	FALLSTHRU
load_store_1a:
	MOVL	%cx,%di			// result2 format is null
	cmpb	$load_op,%al		// is it fld?
	je	fld_1a			// result goes to stack top
	cmpb	$store_pop,%al		// is it fstp?
	je	fstp_1a			// op1 useup is pop stack
	cmpb	$store_op,%al		// is it fst?
	je	fst_1a			// result goes to memory
	MOVL	%di,%si			// else, result format is null
	ret
	ALIGN
fld_1a:
	MOVL    $(stack_top_plus_1*0x100+extended_fp),%si // result is top
	ret
	ALIGN
fstp_1a:
	movb	pop_stack,%bh		// op1 useup is pop stack
	movb	$store_op,%al		// operation type is store
fst_1a:
	ret
	ALIGN
//
//	group 3a - short integer/tempreal load/store instructions
//
load_short_int:
	movb	group_3a_7a_op(%esi),%al	// load operation type
	movb	group_3a_res_fmt(%esi),%dl	// load result format
	movb	group_3a_7a_res_loc(%esi),%dh // load result location
	pushw	%dx			// push result fmt/loc
	movb	group_3a_op1_fmt(%esi),%dl	// load op1 format
	movb	group_3a_7a_op1_loc(%esi),%dh // load op1 location
	popw	%si			// pop result fmt/loc
	jmp	load_store_1a		// finish loading information
	ALIGN
//
//	group 5a - load/store instructions with long-real operand
//                  load/store state/status word instructions
//
load_long_real:
	movb	group_5a_op(%esi),%al	// load operation type
	shlw	$1,%si			// change byte index to word
	movswl  %si,%esi
	MOVL	group_5a_op1_lf(%esi),%dx	// load op1 loc/for
	MOVL    $(memory_opnd*0x100+double_real),%si // result format
	jmp	load_store_1a		// load rest of information
	ALIGN
//
//	group 7a - load/store word-integer/bcd/long-integer instructions
//
load_word_int:
	movb	group_3a_7a_op(%esi),%al	// load operation type
	movb	group_7a_res_fmt(%esi),%dl	// load result format
	movb	group_3a_7a_res_loc(%esi),%dh // load result location
	pushw	%dx			// push result fmt/loc
	movb	group_7a_op1_fmt(%esi),%dl	// load op1 format
	movb	group_3a_7a_op1_loc(%esi),%dh // load op1 location
	popw	%si			// pop result fmt/loc
	jmp	load_store_1a		// finish loading information
	ALIGN
//
//	group 1b - load/store/transcendental instructions with inner
//		   stack operands
transcendentals:
	testb	$0x20,%ah			// does bit 5 = 0?
	jz	group_1ba		// yes, its a load/store op
	MOVL	$0x1f00,%si		// no, its a transcendental
	andw	%ax,%si			// calculate new table index
	shrw	$8,%si			// shift right one byte
	movswl  %si,%esi
	movb	group_1bb_type(%esi),%al	// load format/location type
	rolb	$1,%al			// rotate one left
	movl	$4,%ecx			// load loop count
	FALLSTHRU
load_lf_1bb:
	rolb	$2,%al			// shift next field into di
	MOVL	$0x0006,%di		// form table index
	andw	%ax,%di
	movswl  %di,%edi
	pushw	group_1bb_lf(%edi)	// stack next format/location
	LOOP(load_lf_1bb)		// decode four fields
	movb	group_1bb_op(%esi),%al	// load operation type
	cmpb	$log_op,%al		// is it fyl2x?
	je	pop_op1_1bb		// yes, operand 1 gets popped
	cmpb	$splog_op,%al		// is it fyl2xp1?
	je	pop_op1_1bb		// yes, operand 1 gets popped
	cmpb	$arctan_op,%al		// is it fpatan?
	jne	return_1bb		// no, load return information
	FALLSTHRU
pop_op1_1bb:
	movb	pop_stack,%bh		// pop operand 1
return_1bb:
	popw	%di			// load operand 1 information
	popw	%si			// load operand 2 information
	popw	%cx			// load result 1 information
	popw	%dx			// load result 2 information
	ret
	ALIGN
group_1ba:
	MOVL	%cx,%di			// assume result2 always null
	movb	group_1ba_op(%esi),%al	// load operation type
load_store_1ba:
	cmpb	$load_op,%al		// is it fld st(i) ?
	je	fld_1ba			// op1 is a register
	cmpb	$exchange_op,%al		// is it fxch st(i) ?
	je	fxch_1ba		// op1 is stack top
	cmpb	$store_pop,%al		// is it fstp st(i)? *
	je	fstp_1ba		// pop op1
	cmpb	$store_op,%al		// is it fst st(i)?
	je	fst_1ba			// dont pop op1
	MOVL	%di,%si			// result format is null
	ret
	ALIGN
fld_1ba:
	MOVL    $(reg*0x100+extended_fp),%dx // op1 is a stack reg
	MOVL    $(stack_top_plus_1*0x100+extended_fp),%si // result pushed
	ret
	ALIGN
fxch_1ba:
	MOVL    $(stack_top*0x100+extended_fp),%dx // op1 is stack top
	MOVL    $(reg*0x100+extended_fp),%cx // op2 is a stack reg
	MOVL	%cx,%si			// result is the stack reg
	MOVL	%dx,%di			// result2 is the stack top
	ret
	ALIGN
fstp_1ba:
	movb	$store_op,%al		// operation type is store
	movb	pop_stack,%bh		// op1 useup is pop stack
fst_1ba:
	MOVL    $(stack_top*0x100+extended_fp),%dx // op1 is stack top
	MOVL    $(reg*0x100+extended_fp),%si // result is stack reg
	ret
	ALIGN
//
//	group 5b - free register/store to register instructions
//
store_reg:
	movb	group_5b_op(%esi),%al	// load operation type
	cmpb	$ucom_pop,%al
	jne	test_ucom_op
	movb	pop_stack,%bh
	movb	$ucom_op,%al
	FALLSTHRU
test_ucom_op:
	cmpb	$ucom_op,%al
	jne	test_ffree_5b
	MOVL    $(reg*0x100+extended_fp),%cx // op2 is reg extended_fp
	MOVL	%dx,%di			// result2 format is null
	MOVL	%dx,%si			// result format is null
	MOVL    $(stack_top*0x100+extended_fp),%dx // op1 top extended_fp
	ret
	ALIGN
test_ffree_5b:
	cmpb	$free_op,%al		// is it ffree st(i)?
	jne	load_store_1ba		// no, must be fst(p)/fxch
	movb	free,%bh			// yes, op1 useup is free
	jmp	load_store_1ba		// load rest of information
	ALIGN
//
//	group 7b - transfer status instruction
//
transfer_status:
	movb	group_7b_op(%esi),%al	// load operation type
	cmpb	$free_op,%al		// is it ffreep st(i) ?
	jne	not_ffreep_7b		// no, useup is do nothing
	movb	pop_stack,%bl		// yes, op1 useup is pop
	FALLSTHRU
not_ffreep_7b:
	cmpb	$stsw_op,%al		// is it fstsw ax ?
	jne	test_ffree_5b		// no, handle like group 5b
	movb	$reg,%ch		// yes, op2 loc is reg
	jmp	test_ffree_5b		// finish loading information
	ALIGN
//
//	group 2b - fucompp
//
double_pop:	
	cmpb	$0x029,%ah			// is it fucompp
	jne	reserved		// is a reserved instruction
	movb	pop_stack,%bl		// op2 useup is pop stack
	movb	pop_stack,%bh
	movb	$ucom_op,%al
	MOVL    $(reg*0x100+extended_fp),%cx // op2 is reg extended_fp
	MOVL	%dx,%di			// result2 format is null
	MOVL	%dx,%si			// result format is null
	MOVL    $(stack_top*0x100+extended_fp),%dx // op1 top extended_fp
	ret
	ALIGN
//
//	group 2b - reserved
//
reserved:
	movb	$error_op,%al		// illegal operation
null_results_2b:
	MOVL	%cx,%si			// result is null
	MOVL	%cx,%di			// result2 is null
	ret
	ALIGN
//
//	group 3b - administrative instructions
//
administrative:
	MOVL	$0x0700,%si		// calculate new table index
	andw	%ax,%si
	shrw	$8,%si			// shift right one byte
	movswl  %si,%esi
	movb	group_3b_op(%esi),%al	// load operation type
	jmp	null_results_2b		// result and result2 are null
//
//e80387	endp