|
|
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
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.