|
|
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: /* ! 26: * Copyright (c) 1993 NeXT Computer, Inc. ! 27: * ! 28: * PC support Real mode emulation. ! 29: * ! 30: * HISTORY ! 31: * ! 32: * 23 Mar 1993 ? at NeXT ! 33: * Created. ! 34: */ ! 35: ! 36: #import <mach/mach_types.h> ! 37: ! 38: #import <architecture/i386/sel.h> ! 39: #import <machdep/i386/trap.h> ! 40: #import <machdep/i386/err_inline.h> ! 41: ! 42: #import "PCprivate.h" ! 43: #import "PCmiscInline.h" ! 44: #import "PCtaskInline.h" ! 45: ! 46: struct inst_prefix { ! 47: unsigned int opnd :1, ! 48: addr :1; ! 49: }; ! 50: ! 51: static __inline__ ! 52: vm_offset_t ! 53: segment_base( ! 54: sel_t sel ! 55: ) ! 56: { ! 57: return ((*(unsigned short *)&sel) << 4); ! 58: } ! 59: ! 60: static __inline__ ! 61: fetch_segment_byte( ! 62: thread_t thread, ! 63: sel_t sel, ! 64: unsigned short offset, ! 65: unsigned char *data ! 66: ) ! 67: { ! 68: vm_offset_t base = segment_base(sel); ! 69: ! 70: return (fetchByte(thread, base + offset, data)); ! 71: } ! 72: ! 73: static __inline__ ! 74: fetch_segment_2byte( ! 75: thread_t thread, ! 76: sel_t sel, ! 77: unsigned short offset, ! 78: unsigned short *data ! 79: ) ! 80: { ! 81: vm_offset_t base = segment_base(sel); ! 82: ! 83: return (fetch2Byte(thread, base + offset, data)); ! 84: } ! 85: ! 86: static __inline__ ! 87: store_segment_2byte( ! 88: thread_t thread, ! 89: sel_t sel, ! 90: unsigned short offset, ! 91: unsigned short data ! 92: ) ! 93: { ! 94: vm_offset_t base = segment_base(sel); ! 95: ! 96: return (store2Byte(thread, base + offset, data)); ! 97: } ! 98: ! 99: static __inline__ ! 100: fetch_segment_4byte( ! 101: thread_t thread, ! 102: sel_t sel, ! 103: unsigned short offset, ! 104: unsigned int *data ! 105: ) ! 106: { ! 107: vm_offset_t base = segment_base(sel); ! 108: ! 109: return (fetch4Byte(thread, base + offset, data)); ! 110: } ! 111: ! 112: static __inline__ ! 113: store_segment_4byte( ! 114: thread_t thread, ! 115: sel_t sel, ! 116: unsigned short offset, ! 117: unsigned int data ! 118: ) ! 119: { ! 120: vm_offset_t base = segment_base(sel); ! 121: ! 122: return (store4Byte(thread, base + offset, data)); ! 123: } ! 124: ! 125: static __inline__ ! 126: boolean_t ! 127: fetch_segment( ! 128: thread_t thread, ! 129: sel_t sel, ! 130: unsigned short offset, ! 131: void *data, ! 132: unsigned int length ! 133: ) ! 134: { ! 135: #define sdata ((unsigned short *)data) ! 136: vm_offset_t base = segment_base(sel); ! 137: ! 138: thread->recover = (vm_offset_t)&&fault; ! 139: ! 140: while (length > 0) { ! 141: asm volatile( ! 142: "movw %%fs:%1,%0" ! 143: : "=q" (*sdata) ! 144: : "m" (*(unsigned short *)(base + offset))); ! 145: ! 146: sdata++; offset += sizeof (*sdata); length -= sizeof (*sdata); ! 147: } ! 148: ! 149: thread->recover = 0; ! 150: return (TRUE); ! 151: ! 152: fault: ! 153: thread->recover = 0; ! 154: return (FALSE); ! 155: #undef sdata ! 156: } ! 157: ! 158: static __inline__ ! 159: boolean_t ! 160: store_segment( ! 161: thread_t thread, ! 162: sel_t sel, ! 163: unsigned short offset, ! 164: void *data, ! 165: unsigned int length ! 166: ) ! 167: { ! 168: #define sdata ((unsigned short *)data) ! 169: vm_offset_t base = segment_base(sel); ! 170: ! 171: thread->recover = (vm_offset_t)&&fault; ! 172: ! 173: while (length > 0) { ! 174: asm volatile( ! 175: "movw %0,%%fs:%1" ! 176: : ! 177: : "r" (*sdata), "m" (*(unsigned short *)(base + offset))); ! 178: ! 179: sdata++; offset += sizeof (*sdata); length -= sizeof (*sdata); ! 180: } ! 181: ! 182: thread->recover = 0; ! 183: return (TRUE); ! 184: ! 185: fault: ! 186: thread->recover = 0; ! 187: return (FALSE); ! 188: #undef sdata ! 189: } ! 190: ! 191: static ! 192: boolean_t ! 193: handle_bop( ! 194: thread_t thread, ! 195: thread_saved_state_t *state ! 196: ) ! 197: { ! 198: PCcontext_t context = threadPCContext(thread); ! 199: unsigned int inst; ! 200: unsigned char bbyte; ! 201: ! 202: if (!fetch_segment_4byte( ! 203: thread, ! 204: state->frame.cs, state->frame.eip, ! 205: &inst)) ! 206: return (FALSE); ! 207: ! 208: if (*(unsigned short *)&inst != 0xC4C4) ! 209: return (FALSE); ! 210: ! 211: bbyte = *((unsigned char *)&inst + 2); ! 212: ! 213: if (bbyte == 0xFE) { ! 214: PCcancelTimers(context); ! 215: ! 216: context->callHandler = PC_HANDLE_EXIT; ! 217: ! 218: PCcallMonitor(thread, state); ! 219: /* NOTREACHED */ ! 220: } ! 221: else if (bbyte == 0xFA) { ! 222: PCbopFA_t args; ! 223: ! 224: if (!fetch_segment( ! 225: thread, ! 226: state->frame.ss, state->frame.esp, ! 227: &args, sizeof (args))) ! 228: return (FALSE); ! 229: ! 230: return (PCbopFA(thread, state, &args)); ! 231: /* NOTREACHED */ ! 232: } ! 233: else if (bbyte == 0xFC) { ! 234: PCbopFC_t args; ! 235: ! 236: if (!fetch_segment( ! 237: thread, ! 238: state->frame.ss, state->frame.esp, ! 239: &args, sizeof (args))) ! 240: return (FALSE); ! 241: ! 242: return (PCbopFC(thread, state, &args)); ! 243: /* NOTREACHED */ ! 244: } ! 245: else if (bbyte == 0xFD) { ! 246: PCbopFD_t args; ! 247: ! 248: if (!fetch_segment( ! 249: thread, ! 250: state->frame.ss, state->frame.esp, ! 251: &args, sizeof (args))) ! 252: return (FALSE); ! 253: ! 254: PCbopFD(thread, state, &args); ! 255: /* NOTREACHED */ ! 256: } ! 257: else { ! 258: context->trapNum = bbyte; ! 259: context->callHandler = PC_HANDLE_BOP; ! 260: ! 261: PCcallMonitor(thread, state); ! 262: /* NOTREACHED */ ! 263: } ! 264: } ! 265: ! 266: static __inline__ ! 267: boolean_t ! 268: fetch_inst( ! 269: thread_t thread, ! 270: thread_saved_state_t *state, ! 271: int *offset, ! 272: unsigned char *inst, ! 273: struct inst_prefix *prefix ! 274: ) ! 275: { ! 276: sel_t cs; ! 277: unsigned short ip; ! 278: unsigned char ibyte; ! 279: int n; ! 280: ! 281: cs = state->frame.cs; ! 282: ip = state->frame.eip; ! 283: ! 284: for (n = 0; n < 15; n++) { // a reasonable limit ! 285: if (!fetch_segment_byte(thread, cs, ip + n, &ibyte)) ! 286: break; ! 287: ! 288: switch (ibyte) { ! 289: ! 290: case 0x66: // Operand-size prefix ! 291: prefix->opnd = TRUE; ! 292: break; ! 293: ! 294: case 0xf0: // LOCK prefix ! 295: break; ! 296: ! 297: default: ! 298: *offset = (ip + n) - ip; ! 299: *inst = ibyte - 0x90; ! 300: ! 301: return (TRUE); ! 302: } ! 303: } ! 304: ! 305: return (FALSE); ! 306: } ! 307: ! 308: static ! 309: boolean_t ! 310: emulate_CLI( ! 311: thread_t thread, ! 312: thread_saved_state_t *state, ! 313: int offset, ! 314: struct inst_prefix prefix ! 315: ) ! 316: { ! 317: PCcontext_t context = threadPCContext(thread); ! 318: ! 319: (unsigned short)state->frame.eip += (offset + 1); ! 320: ! 321: context->IF_flag = FALSE; ! 322: ! 323: return (TRUE); ! 324: } ! 325: ! 326: static ! 327: boolean_t ! 328: emulate_STI( ! 329: thread_t thread, ! 330: thread_saved_state_t *state, ! 331: int offset, ! 332: struct inst_prefix prefix ! 333: ) ! 334: { ! 335: PCcontext_t context = threadPCContext(thread); ! 336: ! 337: (unsigned short)state->frame.eip += (offset + 1); ! 338: ! 339: if (!context->IF_flag) { ! 340: context->IF_flag = TRUE; ! 341: ! 342: context->pendingCallbacks |= (context->runOptions & PC_RUN_IF_SET); ! 343: } ! 344: ! 345: return (TRUE); ! 346: } ! 347: ! 348: static boolean_t emulate_PUSHFD( ! 349: thread_t thread, ! 350: thread_saved_state_t *state, ! 351: int offset, ! 352: struct inst_prefix prefix); ! 353: ! 354: static ! 355: boolean_t ! 356: emulate_PUSHF( ! 357: thread_t thread, ! 358: thread_saved_state_t *state, ! 359: int offset, ! 360: struct inst_prefix prefix ! 361: ) ! 362: { ! 363: PCcontext_t context; ! 364: struct { ! 365: unsigned short flags; ! 366: } frame; ! 367: ! 368: if (prefix.opnd) ! 369: return (emulate_PUSHFD(thread, state, offset, prefix)); ! 370: ! 371: context = threadPCContext(thread); ! 372: ! 373: frame.flags = state->frame.eflags; ! 374: if (context->IF_flag) ! 375: frame.flags |= EFL_IF; ! 376: else ! 377: frame.flags &= ~EFL_IF; ! 378: ! 379: frame.flags |= (context->X_flags & (EFL_NT | EFL_IOPL)); ! 380: ! 381: if (!store_segment_2byte( ! 382: thread, ! 383: state->frame.ss, state->frame.esp - sizeof (frame), ! 384: frame.flags)) ! 385: return (FALSE); ! 386: ! 387: (unsigned short)state->frame.eip += (offset + 1); ! 388: ! 389: (unsigned short)state->frame.esp -= sizeof (frame); ! 390: ! 391: return (TRUE); ! 392: } ! 393: ! 394: static ! 395: boolean_t ! 396: emulate_PUSHFD( ! 397: thread_t thread, ! 398: thread_saved_state_t *state, ! 399: int offset, ! 400: struct inst_prefix prefix ! 401: ) ! 402: { ! 403: PCcontext_t context; ! 404: struct { ! 405: unsigned int eflags; ! 406: } frame; ! 407: ! 408: context = threadPCContext(thread); ! 409: ! 410: frame.eflags = state->frame.eflags; ! 411: if (context->IF_flag) ! 412: frame.eflags |= EFL_IF; ! 413: else ! 414: frame.eflags &= ~EFL_IF; ! 415: ! 416: frame.eflags |= (context->X_flags & (EFL_NT | EFL_IOPL)); ! 417: ! 418: if (!store_segment_4byte( ! 419: thread, ! 420: state->frame.ss, state->frame.esp - sizeof (frame), ! 421: frame.eflags)) ! 422: return (FALSE); ! 423: ! 424: (unsigned short)state->frame.eip += (offset + 1); ! 425: ! 426: (unsigned short)state->frame.esp -= sizeof (frame); ! 427: ! 428: return (TRUE); ! 429: } ! 430: ! 431: static boolean_t emulate_POPFD( ! 432: thread_t thread, ! 433: thread_saved_state_t *state, ! 434: int offset, ! 435: struct inst_prefix prefix); ! 436: ! 437: static ! 438: boolean_t ! 439: emulate_POPF( ! 440: thread_t thread, ! 441: thread_saved_state_t *state, ! 442: int offset, ! 443: struct inst_prefix prefix ! 444: ) ! 445: { ! 446: PCcontext_t context; ! 447: struct { ! 448: unsigned short flags; ! 449: } frame; ! 450: ! 451: if (prefix.opnd) ! 452: return (emulate_POPFD(thread, state, offset, prefix)); ! 453: ! 454: context = threadPCContext(thread); ! 455: ! 456: if (!fetch_segment_2byte( ! 457: thread, ! 458: state->frame.ss, state->frame.esp, ! 459: &frame.flags)) ! 460: return (FALSE); ! 461: ! 462: if ((context->debugOptions & PC_DEBUG_PRESERVE_TRACE) != 0) ! 463: frame.flags |= (state->frame.eflags & EFL_TF); ! 464: (unsigned short)state->frame.eflags = frame.flags; ! 465: state->frame.eflags &= ~( EFL_NT | EFL_IOPL | EFL_CLR ); ! 466: state->frame.eflags |= ( EFL_VM | EFL_IF | EFL_SET ); ! 467: ! 468: (unsigned short)state->frame.eip += (offset + 1); ! 469: (unsigned short)state->frame.esp += sizeof (frame); ! 470: ! 471: context->X_flags = (frame.flags & (EFL_NT | EFL_IOPL)); ! 472: ! 473: if (frame.flags & EFL_IF) { ! 474: if (!context->IF_flag) ! 475: context->pendingCallbacks |= (context->runOptions & PC_RUN_IF_SET); ! 476: ! 477: context->IF_flag = TRUE; ! 478: } ! 479: else ! 480: context->IF_flag = FALSE; ! 481: ! 482: return (TRUE); ! 483: } ! 484: ! 485: static ! 486: boolean_t ! 487: emulate_POPFD( ! 488: thread_t thread, ! 489: thread_saved_state_t *state, ! 490: int offset, ! 491: struct inst_prefix prefix ! 492: ) ! 493: { ! 494: PCcontext_t context; ! 495: struct { ! 496: unsigned long eflags; ! 497: } frame; ! 498: ! 499: context = threadPCContext(thread); ! 500: ! 501: if (!fetch_segment_4byte( ! 502: thread, ! 503: state->frame.ss, state->frame.esp, ! 504: &frame.eflags)) ! 505: return (FALSE); ! 506: ! 507: if ((context->debugOptions & PC_DEBUG_PRESERVE_TRACE) != 0) ! 508: frame.eflags |= (state->frame.eflags & EFL_TF); ! 509: state->frame.eflags = frame.eflags; ! 510: state->frame.eflags &= ~( EFL_NT | EFL_IOPL | EFL_CLR ); ! 511: state->frame.eflags |= ( EFL_VM | EFL_IF | EFL_SET ); ! 512: ! 513: (unsigned short)state->frame.eip += (offset + 1); ! 514: (unsigned short)state->frame.esp += sizeof (frame); ! 515: ! 516: context->X_flags = (frame.eflags & (EFL_NT | EFL_IOPL)); ! 517: ! 518: if (frame.eflags & EFL_IF) { ! 519: if (!context->IF_flag) ! 520: context->pendingCallbacks |= (context->runOptions & PC_RUN_IF_SET); ! 521: ! 522: context->IF_flag = TRUE; ! 523: } ! 524: else ! 525: context->IF_flag = FALSE; ! 526: ! 527: return (TRUE); ! 528: } ! 529: ! 530: static boolean_t emulate_IRETD( ! 531: thread_t thread, ! 532: thread_saved_state_t *state, ! 533: int offset, ! 534: struct inst_prefix prefix); ! 535: ! 536: static ! 537: boolean_t ! 538: emulate_IRET( ! 539: thread_t thread, ! 540: thread_saved_state_t *state, ! 541: int offset, ! 542: struct inst_prefix prefix ! 543: ) ! 544: { ! 545: PCcontext_t context; ! 546: struct { ! 547: unsigned short ip; ! 548: sel_t cs; ! 549: unsigned short flags; ! 550: } frame; ! 551: ! 552: if (prefix.opnd) ! 553: return (emulate_IRETD(thread, state, offset, prefix)); ! 554: ! 555: context = threadPCContext(thread); ! 556: ! 557: if (!fetch_segment( ! 558: thread, ! 559: state->frame.ss, state->frame.esp, ! 560: &frame, sizeof (frame))) ! 561: return (FALSE); ! 562: ! 563: (unsigned short)state->frame.eip = frame.ip; ! 564: state->frame.cs = frame.cs; ! 565: ! 566: if ((context->debugOptions & PC_DEBUG_PRESERVE_TRACE) != 0) ! 567: frame.flags |= (state->frame.eflags & EFL_TF); ! 568: (unsigned short)state->frame.eflags = frame.flags; ! 569: state->frame.eflags &= ~( EFL_NT | EFL_IOPL | EFL_CLR ); ! 570: state->frame.eflags |= ( EFL_VM | EFL_IF | EFL_SET ); ! 571: ! 572: (unsigned short)state->frame.esp += sizeof (frame); ! 573: ! 574: context->X_flags = (frame.flags & (EFL_NT | EFL_IOPL)); ! 575: ! 576: if (frame.flags & EFL_IF) { ! 577: if (!context->IF_flag) ! 578: context->pendingCallbacks |= (context->runOptions & PC_RUN_IF_SET); ! 579: ! 580: context->IF_flag = TRUE; ! 581: } ! 582: else ! 583: context->IF_flag = FALSE; ! 584: ! 585: return (TRUE); ! 586: } ! 587: ! 588: static ! 589: boolean_t ! 590: emulate_IRETD( ! 591: thread_t thread, ! 592: thread_saved_state_t *state, ! 593: int offset, ! 594: struct inst_prefix prefix ! 595: ) ! 596: { ! 597: PCcontext_t context; ! 598: struct { ! 599: unsigned long eip; ! 600: sel_t cs; ! 601: unsigned long eflags; ! 602: } frame; ! 603: ! 604: context = threadPCContext(thread); ! 605: ! 606: if (!fetch_segment( ! 607: thread, ! 608: state->frame.ss, state->frame.esp, ! 609: &frame, sizeof (frame))) ! 610: return (FALSE); ! 611: ! 612: state->frame.eip = frame.eip; ! 613: state->frame.cs = frame.cs; ! 614: ! 615: if ((context->debugOptions & PC_DEBUG_PRESERVE_TRACE) != 0) ! 616: frame.eflags |= (state->frame.eflags & EFL_TF); ! 617: state->frame.eflags = frame.eflags; ! 618: state->frame.eflags &= ~( EFL_NT | EFL_IOPL | EFL_CLR ); ! 619: state->frame.eflags |= ( EFL_VM | EFL_IF | EFL_SET ); ! 620: ! 621: (unsigned short)state->frame.esp += sizeof (frame); ! 622: ! 623: context->X_flags = (frame.eflags & (EFL_NT | EFL_IOPL)); ! 624: ! 625: if (frame.eflags & EFL_IF) { ! 626: if (!context->IF_flag) ! 627: context->pendingCallbacks |= (context->runOptions & PC_RUN_IF_SET); ! 628: ! 629: context->IF_flag = TRUE; ! 630: } ! 631: else ! 632: context->IF_flag = FALSE; ! 633: ! 634: return (TRUE); ! 635: } ! 636: ! 637: static ! 638: boolean_t ! 639: emulate_exception( ! 640: thread_t thread, ! 641: thread_saved_state_t *state, ! 642: int trapno ! 643: ) ! 644: { ! 645: PCcontext_t context; ! 646: struct { ! 647: unsigned short ip; ! 648: sel_t cs; ! 649: unsigned short flags; ! 650: } frame; ! 651: struct { ! 652: unsigned short ip; ! 653: sel_t cs; ! 654: } vector; ! 655: ! 656: context = threadPCContext(thread); ! 657: ! 658: frame.ip = state->frame.eip; ! 659: frame.cs = state->frame.cs; ! 660: ! 661: frame.flags = state->frame.eflags; ! 662: if (context->IF_flag) ! 663: frame.flags |= EFL_IF; ! 664: else ! 665: frame.flags &= ~EFL_IF; ! 666: ! 667: frame.flags |= (context->X_flags & (EFL_NT | EFL_IOPL)); ! 668: ! 669: if (!store_segment( ! 670: thread, ! 671: state->frame.ss, state->frame.esp - sizeof (frame), ! 672: &frame, sizeof (frame))) ! 673: return (FALSE); ! 674: ! 675: if (!fetch4Byte(thread, (trapno << 2), (unsigned long *)&vector)) ! 676: return (FALSE); ! 677: ! 678: (unsigned short)state->frame.esp -= sizeof (frame); ! 679: ! 680: state->frame.eip = vector.ip; ! 681: state->frame.cs = vector.cs; ! 682: ! 683: context->IF_flag = FALSE; ! 684: ! 685: if ((context->debugOptions & PC_DEBUG_PRESERVE_TRACE) == 0) ! 686: state->frame.eflags &= ~EFL_TF; ! 687: ! 688: return (TRUE); ! 689: } ! 690: ! 691: static ! 692: boolean_t ! 693: emulate_INTn( ! 694: thread_t thread, ! 695: thread_saved_state_t *state, ! 696: int offset, ! 697: struct inst_prefix prefix ! 698: ) ! 699: { ! 700: PCshared_t shared; ! 701: PCcontext_t context; ! 702: unsigned char trapno; ! 703: ! 704: shared = threadPCShared(thread); ! 705: context = currentContext(shared); ! 706: ! 707: if (!fetch_segment_byte( ! 708: thread, ! 709: state->frame.cs, state->frame.eip + offset + 1, ! 710: &trapno)) ! 711: return (FALSE); ! 712: ! 713: if (maskIsSet(&shared->intNMask, trapno)) { ! 714: context->trapNum = trapno; ! 715: context->errCode = 0; ! 716: if (trapno <= 7) ! 717: context->callHandler = PC_HANDLE_FAULT; ! 718: else ! 719: context->callHandler = PC_HANDLE_INTN; ! 720: ! 721: PCcallMonitor(thread, state); ! 722: /* NOTREACHED */ ! 723: } ! 724: ! 725: (unsigned short)state->frame.eip += (offset + 2); ! 726: ! 727: if (!emulate_exception(thread, state, trapno)) { ! 728: (unsigned short)state->frame.eip -= (offset + 2); ! 729: return (FALSE); ! 730: } ! 731: ! 732: return (TRUE); ! 733: } ! 734: ! 735: static ! 736: boolean_t ! 737: handle_exception( ! 738: thread_t thread, ! 739: thread_saved_state_t *state ! 740: ) ! 741: { ! 742: PCshared_t shared; ! 743: PCcontext_t context; ! 744: ! 745: shared = threadPCShared(thread); ! 746: context = currentContext(shared); ! 747: ! 748: if (maskIsSet(&shared->faultMask, state->trapno)) { ! 749: context->trapNum = state->trapno; ! 750: context->errCode = err_to_error_code(state->frame.err); ! 751: context->callHandler = PC_HANDLE_FAULT; ! 752: ! 753: PCcallMonitor(thread, state); ! 754: /* NOTREACHED */ ! 755: } ! 756: ! 757: if (!emulate_exception(thread, state, state->trapno)) ! 758: return (FALSE); ! 759: ! 760: return (TRUE); ! 761: } ! 762: ! 763: #define none 0 ! 764: #define STI emulate_STI ! 765: #define CLI emulate_CLI ! 766: #define PUSHF emulate_PUSHF ! 767: #define POPF emulate_POPF ! 768: #define IRET emulate_IRET ! 769: #define INTn emulate_INTn ! 770: ! 771: static ! 772: boolean_t (*inst_table[256])() = ! 773: { ! 774: /* 90 */ none, /* 91 */ none, /* 92 */ none, /* 93 */ none, ! 775: /* 94 */ none, /* 95 */ none, /* 96 */ none, /* 97 */ none, ! 776: /* 98 */ none, /* 99 */ none, /* 9A */ none, /* 9B */ none, ! 777: /* 9C */PUSHF, /* 9D */ POPF, /* 9E */ none, /* 9F */ none, ! 778: /* A0 */ none, /* A1 */ none, /* A2 */ none, /* A3 */ none, ! 779: /* A4 */ none, /* A5 */ none, /* A6 */ none, /* A7 */ none, ! 780: /* A8 */ none, /* A9 */ none, /* AA */ none, /* AB */ none, ! 781: /* AC */ none, /* AD */ none, /* AE */ none, /* AF */ none, ! 782: /* B0 */ none, /* B1 */ none, /* B2 */ none, /* B3 */ none, ! 783: /* B4 */ none, /* B5 */ none, /* B6 */ none, /* B7 */ none, ! 784: /* B8 */ none, /* B9 */ none, /* BA */ none, /* BB */ none, ! 785: /* BC */ none, /* BD */ none, /* BE */ none, /* BF */ none, ! 786: /* C0 */ none, /* C1 */ none, /* C2 */ none, /* C3 */ none, ! 787: /* C4 */ none, /* C5 */ none, /* C6 */ none, /* C7 */ none, ! 788: /* C8 */ none, /* C9 */ none, /* CA */ none, /* CB */ none, ! 789: /* CC */ none, /* CD */ INTn, /* CE */ none, /* CF */ IRET, ! 790: /* D0 */ none, /* D1 */ none, /* D2 */ none, /* D3 */ none, ! 791: /* D4 */ none, /* D5 */ none, /* D6 */ none, /* D7 */ none, ! 792: /* D8 */ none, /* D9 */ none, /* DA */ none, /* DB */ none, ! 793: /* DC */ none, /* DD */ none, /* DE */ none, /* DF */ none, ! 794: /* E0 */ none, /* E1 */ none, /* E2 */ none, /* E3 */ none, ! 795: /* E4 */ none, /* E5 */ none, /* E6 */ none, /* E7 */ none, ! 796: /* E8 */ none, /* E9 */ none, /* EA */ none, /* EB */ none, ! 797: /* EC */ none, /* ED */ none, /* EE */ none, /* EF */ none, ! 798: /* F0 */ none, /* F1 */ none, /* F2 */ none, /* F3 */ none, ! 799: /* F4 */ none, /* F5 */ none, /* F6 */ none, /* F7 */ none, ! 800: /* F8 */ none, /* F9 */ none, /* FA */ CLI, /* FB */ STI, ! 801: /* FC */ none, /* FD */ none, /* FE */ none, /* FF */ none, ! 802: }; ! 803: ! 804: static ! 805: boolean_t ! 806: emulate_instruction( ! 807: thread_t thread, ! 808: thread_saved_state_t *state ! 809: ) ! 810: { ! 811: int offset; ! 812: unsigned char inst; ! 813: struct inst_prefix prefix = { 0 }; ! 814: boolean_t (*emul)(); ! 815: ! 816: return ( ! 817: fetch_inst(thread, state, &offset, &inst, &prefix) && ! 818: (emul = inst_table[inst]) != 0 && ! 819: (*emul)(thread, state, offset, prefix)); ! 820: } ! 821: ! 822: boolean_t ! 823: PCemulateREAL( ! 824: thread_t thread, ! 825: thread_saved_state_t *state ! 826: ) ! 827: { ! 828: if (state->trapno == T_GENERAL_PROTECTION) { ! 829: if (!emulate_instruction(thread,state)) ! 830: return handle_exception(thread, state); ! 831: else ! 832: return TRUE; ! 833: } ! 834: else ! 835: if (state->trapno == T_INVALID_OPCODE) { ! 836: if (!handle_bop(thread, state)) ! 837: return handle_exception(thread, state); ! 838: else ! 839: return TRUE; ! 840: } ! 841: else ! 842: return handle_exception(thread, state); ! 843: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.