|
|
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.