Windows NT 4.0 source code leak
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

5881 lines
171 KiB

4 years ago
  1. /*++
  2. Copyright (c) 1994 DeskStation Technology, Inc.
  3. Module Name:
  4. xxbios.c
  5. Abstract:
  6. This module is an implementation of an 80286 emulator for performing
  7. video adapter initialization and INT 10 video BIOS calls.
  8. The main component of the emulator makes use of two lookup tables
  9. for address and instruction decoding, and two variables of type
  10. OPERAND that contain the decoded left and right operands. The
  11. emulator looks at the first byte of the instruction. This 8 bit
  12. value is used to lookup two functions in the DecodeOperandTable[].
  13. The first function is called to decode the left operand, and the
  14. second function is called to decode the right operand. The OPERAND
  15. data type can contain a register, an immediate value, or a memory
  16. location. The functions GetOperand() and PutOperand() allow the
  17. values of the left and right operand to be retrieved and stored.
  18. The DecodeInstructionTable[] is used to lookup the function to call
  19. to execute the instruction once the left and right operands have been
  20. decoded. The instruction type can be determined from the 8 bits in
  21. the first byte of the instruction and bits 3-5 of the second byte
  22. of the instruction. These 11 bits are used to lookup the appropriate
  23. function in DecodeInstructionTable[]. This function is called. The
  24. function associated with each instruction modifies the state of the
  25. 80286's internal registers, and the state of the memory system. The
  26. address decode functions will have already moved the instruction
  27. pointer to the beginning of the next instruction, so the main loop
  28. of the emulator calls the address decode functions and the
  29. instruction functions until the exit condition is met.
  30. The emulator is invoked in two different ways. The first is when
  31. the emulator is initialized. This initializes the state of all the
  32. internal registers, and the state of the memory system. Then, a
  33. check is made to see if a valid video BIOS is present in ISA memory.
  34. If one is found, the emulator is invoked on the BIOS's initialization
  35. code. The other way is to perform an INT 10 call. When an INT 10
  36. call is made, it passes in a data structure containing the inital
  37. values for AX,BX,CX,DX,SI,DI, and BP. The internal state of the
  38. processor is initialized to these values, and the INT 10 vector
  39. is looked up in memory. The CS and IP registers and initialized
  40. to start executing the INT 10 call, and the exit condition is
  41. initialized to stop the emulator when the INT 10 call returns.
  42. When the INT 10 call returns, the values of the internal registers
  43. are returned to the calling function. The calling function can
  44. examine these registers to get at the INT 10's return value.
  45. If the emulator encounters an error condition, the variable ErrorCode
  46. will contain the reason for the error.
  47. References:
  48. Borland International, "Turbo Assembler Quick Reference Guide", 1990.
  49. Choisser, John P., "The XT-AT Handbook", Annabooks, 1993.
  50. Duncan, Ray, "IBM ROM BIOS", Microsoft Press, 1988.
  51. Intel Corporation, "The 8086 Family Users's Manual", October 1979.
  52. Intel Corporation, "Microprocessors Volume I", 1994.
  53. "Macro Assembler by Microsoft" IBM Corporation, 1981.
  54. Norton, Peter, "The New Peter Norton Programmer's Guide to the IBM
  55. PC & PS/2", Microsoft Press, 1988.
  56. Wilton, Richard, "Programmer's Guide to PC & PS/2 Video Systems",
  57. Microsft Press, 1987.
  58. Author:
  59. Michael D. Kinney 19-Jun-1994
  60. Environment:
  61. Kernel mode only.
  62. Revision History:
  63. --*/
  64. /***************************************************************************/
  65. /* Include Files */
  66. /***************************************************************************/
  67. #include "nthal.h"
  68. #include "hal.h"
  69. #include "x86bios.h"
  70. //#define X86DEBUG
  71. //#define X86DEBUG1
  72. /***************************************************************************/
  73. /* Type Declarations */
  74. /***************************************************************************/
  75. typedef union REGISTER32
  76. {
  77. struct
  78. {
  79. UCHAR L;
  80. UCHAR H;
  81. };
  82. USHORT X;
  83. ULONG EX;
  84. } REGISTER32;
  85. typedef union REGISTERFLAG
  86. {
  87. struct
  88. {
  89. USHORT _cf:1;
  90. USHORT _x1:1;
  91. USHORT _pf:1;
  92. USHORT _x3:1;
  93. USHORT _af:1;
  94. USHORT _x5:1;
  95. USHORT _zf:1;
  96. USHORT _sf:1;
  97. USHORT _tf:1;
  98. USHORT _if:1;
  99. USHORT _df:1;
  100. USHORT _of:1;
  101. USHORT _x12:1;
  102. USHORT _x13:1;
  103. USHORT _x14:1;
  104. USHORT _x15:1;
  105. };
  106. struct
  107. {
  108. UCHAR L;
  109. UCHAR H;
  110. };
  111. USHORT X;
  112. ULONG EX;
  113. } REGISTERFLAG;
  114. typedef enum { NullOperand,
  115. Register8Operand, // 8 bit register operand
  116. Register16Operand, // 16 bit register operand
  117. Memory8Operand, // 8 bit memory reference (BYTE PTR)
  118. Memory16Operand, // 16 bit memory reference (WORD PTR)
  119. Immediate8Operand, // 8 bit immediate value
  120. Immediate16Operand, // 16 bit immediate value
  121. ShortLabelOperand, // 8 bit signed immediate value
  122. Immediate32Operand // 32 bit immediate value forming a segment:offset memory reference.
  123. } OPERANDTYPE;
  124. typedef struct OPERAND
  125. {
  126. OPERANDTYPE OperandType;
  127. UCHAR *Register8; // Pointer to 8 bit register variable
  128. USHORT *Register16; // Pointer to 16 bit register variable
  129. USHORT *MemorySegment; // Pointer to 16 bit segment register variable for memory address
  130. REGISTER32 MemoryOffset; // 16 bit value for memory address
  131. REGISTER32 Immediate8; // 8 bit value
  132. REGISTER32 Immediate16; // 16 bit value
  133. REGISTER32 ShortLabel; // 8 bit signed value
  134. REGISTER32 Immediate32Segment; // 16 bit value for immediate address
  135. REGISTER32 Immediate32Offset; // 16 bit value for immediate address
  136. } OPERAND;
  137. /***************************************************************************/
  138. /* Register Access Macros */
  139. /***************************************************************************/
  140. //
  141. // 16 Bit Instruction Pointer Register
  142. //
  143. #define IP (ip.X)
  144. //
  145. // 8 Bit General Purpose Registers
  146. //
  147. #define AL (a.L)
  148. #define AH (a.H)
  149. #define BL (b.L)
  150. #define BH (b.H)
  151. #define CL (c.L)
  152. #define CH (c.H)
  153. #define DL (d.L)
  154. #define DH (d.H)
  155. //
  156. // 16 Bit General Purpose, Base and Index Registers
  157. //
  158. #define AX (a.X)
  159. #define BX (b.X)
  160. #define CX (c.X)
  161. #define DX (d.X)
  162. #define SP (sp.X)
  163. #define BP (bp.X)
  164. #define SI (si.X)
  165. #define DI (di.X)
  166. //
  167. // 32 Bit General Purpose, Base and Index Registers
  168. //
  169. #define EAX (a.EX)
  170. #define EBX (b.EX)
  171. #define ECX (c.EX)
  172. #define EDX (d.EX)
  173. #define ESP (sp.EX)
  174. #define EBP (bp.EX)
  175. #define ESI (si.EX)
  176. #define EDI (di.EX)
  177. //
  178. // 16 Bit Segment Registers
  179. //
  180. #define CS (cs.X)
  181. #define DS (ds.X)
  182. #define SS (ss.X)
  183. #define ES (es.X)
  184. //
  185. // Flag Registers
  186. //
  187. #define CF (Flags._cf)
  188. #define PF (Flags._pf)
  189. #define AF (Flags._af)
  190. #define ZF (Flags._zf)
  191. #define SF (Flags._sf)
  192. #define TF (Flags._tf)
  193. #define IF (Flags._if)
  194. #define DF (Flags._df)
  195. #define OF (Flags._of)
  196. //
  197. // Debugging Macros
  198. //
  199. #ifdef X86DEBUG
  200. static ULONG DebugOutFile;
  201. static ULONG DebugInFile;
  202. static ULONG DebugCount;
  203. static UCHAR DebugGetChar;
  204. static UCHAR PrintMessage[512];
  205. static VOID CloseDebugPort()
  206. {
  207. Close(DebugOutFile);
  208. }
  209. static void SetBaudRate(ULONG Port,ULONG Rate)
  210. {
  211. ULONG Divisor;
  212. Divisor = (24000000/13)/(Rate*16);
  213. outp(Port+3,0x80);
  214. outp(Port+0,Divisor & 0xff);
  215. outp(Port+1,(Divisor>>8) & 0xff);
  216. outp(Port+3,0x03);
  217. }
  218. static VOID OpenDebugPort()
  219. {
  220. ULONG Port = 0x3f8;
  221. SetBaudRate(Port,9600);
  222. outp(Port + 1,0x00);
  223. outp(Port + 4,0x03);
  224. }
  225. static LONG SERRead(ULONG FileID,void *Buffer,ULONG N,ULONG *Count)
  226. {
  227. ULONG Port = 0x03f8;
  228. for(*Count=0;*Count<N;(*Count)++)
  229. {
  230. while (!(inp(Port+5) & 0x0001));
  231. *((CHAR *)(Buffer) + (*Count)) = inp(Port+0);
  232. }
  233. return(ESUCCESS);
  234. }
  235. static LONG SERWrite(ULONG FileID,void *Buffer,ULONG N,ULONG *Count)
  236. {
  237. ULONG Port = 0x3f8;
  238. for(*Count=0;*Count<N;(*Count)++)
  239. {
  240. while (!(inp(Port+5) & 0x0020));
  241. outp(Port,*((CHAR *)(Buffer)+(*Count)));
  242. }
  243. return(ESUCCESS);
  244. }
  245. #define DISPLAY(X) { OpenDebugPort(); SERWrite(DebugOutFile,X,strlen(X),&DebugCount); CloseDebugPort(); }
  246. #define ERROR(X) DISPLAY(X)
  247. #define PRINT1(X) sprintf(PrintMessage,X)
  248. #define PRINT2(X,Y) sprintf(PrintMessage,X,Y)
  249. #define PRINT3(X,Y,Z) sprintf(PrintMessage,X,Y,Z)
  250. #define PRINT4(X,Y,Z,A) sprintf(PrintMessage,X,Y,Z,A)
  251. #define STRCPY(X,Y) strcpy(X,Y)
  252. #define STRCAT(X,Y) strcat(X,Y)
  253. #define PAUSE { OpenDebugPort(); SERRead(DebugInFile,&DebugGetChar,1,&DebugCount); CloseDebugPort(); }
  254. #define GETCHAR(X) { OpenDebugPort(); SERRead(DebugInFile,&X,1,&DebugCount); CloseDebugPort(); }
  255. #define PUTCHAR(X) { OpenDebugPort(); SERWrite(DebugOutFile,&X,1,&DebugCount); CloseDebugPort(); }
  256. #else
  257. #define DISPLAY(X)
  258. #define ERROR(X)
  259. #define PRINT1(X)
  260. #define PRINT2(X,Y)
  261. #define PRINT3(X,Y,Z)
  262. #define PRINT4(X,Y,Z,A)
  263. #define STRCPY(X,Y)
  264. #define STRCAT(X,Y)
  265. #define PAUSE
  266. #endif
  267. #ifdef X86DEBUG1
  268. #define ADDRESSTRACESIZE 80
  269. static ULONG AddressTrace[ADDRESSTRACESIZE];
  270. static ULONG AddressTracePosition;
  271. #endif
  272. /***************************************************************************/
  273. /* Constants */
  274. /***************************************************************************/
  275. #define SUBOPERATION 0
  276. #define ADDOPERATION 1
  277. //
  278. // Define table for computing parity.
  279. //
  280. static const UCHAR ParityTable[16] = { 0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4 };
  281. /***************************************************************************/
  282. /* Global Variables */
  283. /***************************************************************************/
  284. static REGISTER32 ip; // x86 Processor Register IP.
  285. static REGISTER32 a; // x86 Processor Register EAX,AX,AL,AH.
  286. static REGISTER32 b; // x86 Processor Register EBX,BX,BL,BH.
  287. static REGISTER32 c; // x86 Processor Register ECX,CX,CL,CH.
  288. static REGISTER32 d; // x86 Processor Register EDX,DX,DL,DH.
  289. static REGISTER32 sp; // x86 Processor Register ESP,SP.
  290. static REGISTER32 bp; // x86 Processor Register EBP,BP.
  291. static REGISTER32 si; // x86 Processor Register ESI,SI.
  292. static REGISTER32 di; // x86 Processor Register ESI,DI.
  293. static REGISTER32 es; // x86 Processor Register ES.
  294. static REGISTER32 cs; // x86 Processor Register CS.
  295. static REGISTER32 ss; // x86 Processor Register SS.
  296. static REGISTER32 ds; // x86 Processor Register DS.
  297. static REGISTERFLAG Flags; // x86 Processor Register CF,PF,AF,ZF,SF,TF,IF,DF,OF.
  298. static USHORT msw; // 80286 Protected Mode Processor Register.
  299. static USHORT gdtLimit; // 80286 Protected Mode Processor Register.
  300. static ULONG gdtBase; // 80286 Protected Mode Processor Register.
  301. static USHORT idtLimit; // 80286 Protected Mode Processor Register.
  302. static ULONG idtBase; // 80286 Protected Mode Processor Register.
  303. static ULONG CSCacheRegister=0xffffffff; // 80286 Protected Mode Processor Register.
  304. static ULONG DSCacheRegister=0xffffffff; // 80286 Protected Mode Processor Register.
  305. static ULONG ESCacheRegister=0xffffffff; // 80286 Protected Mode Processor Register.
  306. static ULONG SSCacheRegister=0xffffffff; // 80286 Protected Mode Processor Register.
  307. static ULONG BiosIsaIoBaseAddress; // Base virtual address of 64K ISA I/O space used by emulator.
  308. static ULONG VDMBaseAddress; // Base virtual address of the 1MB area used by emulator.
  309. static ULONG ISABaseAddress; // Base virtual address of ISA Memory.
  310. static OPERAND LeftSource; // Storage area for left operand.
  311. static OPERAND RightSource; // Storage area for right operand.
  312. static OPERAND *LSRC = &LeftSource; // Pointer to left operand.
  313. static OPERAND *RSRC = &RightSource; // Pointer to right operand.
  314. static UCHAR OperationCodeByte; // 1st byte of instruction.
  315. static UCHAR ExtendedOperationCodeByte; // 2nd byte of special 286 instructions.
  316. static UCHAR InstructionSubIndex; // Value from 0-7 that is either 0 or the reg field from AddressModeByte.
  317. static UCHAR AddressModeByte; // 2nd byte of instruction if instruction uses an address mode.
  318. static UCHAR mod; // Address mode field.
  319. static UCHAR reg; // Address mode field.
  320. static UCHAR r_m; // Address mode field.
  321. static ULONG SegmentOveridePrefix; // TRUE if a segment overide exists (CS:,DS:,ES:,SS:).
  322. static USHORT *OverideSegmentRegister; // Pointer to 16 bit overide segment register.
  323. static ULONG RepeatPrefix; // TRUE if a REP prefix exists.
  324. static ULONG RepeatZeroFlag; // Flag for REPNZ and REPZ instructions.
  325. static ULONG LockPrefix; // TRUE if a LOCK prefix exists.
  326. static REGISTER32 CurrentIP; // IP value for the beginning of current instruction.
  327. static ULONG SSRegisterTouched = FALSE; // TRUE if previous instruction changed the value of the SS register.
  328. static USHORT Delta; // Increment value for string operations.
  329. static ULONG ExitFlag; // If TRUE, the interpreter will exit
  330. static ULONG GoFlag = FALSE; // TRUE if emulator is running. Set to FALSE on breakpoints.
  331. static USHORT ExitSegment; // Segment of break point that causes the emulator to exit.
  332. static USHORT ExitOffset; // Offset of break point that causes the emulator to exit.
  333. static USHORT StopSegment; // Segment of break point.
  334. static USHORT StopOffset; // Offset of break point.
  335. static UCHAR MemoryArray[0x0800]; // 2K memory for INT vectors, BIOS data, temp code, and stack.
  336. static X86BIOS_STATUS ErrorCode; // Reason for exiting emulator
  337. /*++
  338. Memory Access Functions:
  339. The following functions are used to read and write values to and from
  340. memory. Only part of the x86's 1MB address space is actually visible
  341. to the emulator. The address range from 0000:0000 to 0000:03FF exists
  342. to store INT vectors. The address range from 0000:0400 to 0000:04FF
  343. exists for the BIOS data area in case the video bios wants to store
  344. and retrieve value from here. The address range from 0000:0500 to
  345. 0000:0510 is an area where temporary code segements are build by the
  346. emulator for entry and exit points. The address range from
  347. 0000:0510 to 0000:07FF is the video BIOS's stack area. The stack
  348. pointer is initialized to the top of this area. The address range
  349. from A000:0000 to D000:FFFF is visible to the emulator. Memory
  350. accesses in this range perform memory read and write cycles to
  351. ISA Memory. Memory read to unavailable regions always return 0,
  352. and memory writes to unavailable regions perform no actions.
  353. |----------------------------------------|
  354. | |
  355. | E000:0000 - F000:FFFF : Unavailable |
  356. | |
  357. |----------------------------------------|
  358. | |
  359. | A000:0000 - D000:FFFF : ISA Memory |
  360. | |
  361. |----------------------------------------|
  362. | |
  363. | 0000:0800 - 9000:FFFF : Unavailable |
  364. | |
  365. |----------------------------------------|
  366. | |
  367. | 0000:0510 - 0000:07FF : Stack |
  368. | |
  369. |----------------------------------------|
  370. | |
  371. | 0000:0500 - 0000:050F : Reserved |
  372. | |
  373. |----------------------------------------|
  374. | |
  375. | 0000:0400 - 0000:04FF : BIOS Data Area |
  376. | |
  377. |----------------------------------------|
  378. | |
  379. | 0000:0000 - 0000:03FF : INT Vectors |
  380. | |
  381. |----------------------------------------|
  382. --*/
  383. static UCHAR GetAbsoluteMem(
  384. ULONG Offset
  385. )
  386. /*++
  387. Routine Description:
  388. This is the lowest level function for reading a byte from memory.
  389. Arguments:
  390. Offset - 20 bit value used to address a byte.
  391. Return Value:
  392. The byte stored at the address if that address is mapped.
  393. Otherwise, return 0.
  394. --*/
  395. {
  396. if (Offset>=0x0a0000 && Offset<0xe0000)
  397. return(*(UCHAR *)(ISABaseAddress + Offset));
  398. if (Offset<0x800)
  399. return(*(UCHAR *)(VDMBaseAddress + Offset));
  400. return(0);
  401. }
  402. static VOID PutAbsoluteMem(
  403. ULONG Offset,
  404. UCHAR Value
  405. )
  406. /*++
  407. Routine Description:
  408. This is the lowest level function for writing a byte to memory.
  409. The byte is written to the address if that address is mapped.
  410. Otherwise, no action is taken.
  411. Arguments:
  412. Offset - 20 bit value used to address a byte.
  413. Value - The 8 bit data value that is to be written.
  414. Return Value:
  415. None
  416. --*/
  417. {
  418. if (Offset>=0x0a0000 && Offset<0xe0000)
  419. *(UCHAR *)(ISABaseAddress + Offset) = Value;
  420. if (Offset<0x800)
  421. *(UCHAR *)(VDMBaseAddress + Offset) = Value;
  422. }
  423. static UCHAR GetMem(
  424. OPERAND *Operand,
  425. ULONG Offset
  426. )
  427. /*++
  428. Routine Description:
  429. This function reads a byte from memory. Operand contains the
  430. segment part and offset part of the address. If the processor is
  431. in protected mode, the segment cache registers are used to compute
  432. the address. If the processor is in real mode, the segment register
  433. is shifted left four bits, and added to the offset.
  434. Arguments:
  435. Operand - Contains a memory reference in the MemorySegment and
  436. MemoryOffset fields.
  437. Offset - Additional offset from the memory location described in
  438. Operand.
  439. Return Value:
  440. The byte read from the computed address.
  441. --*/
  442. {
  443. if (msw & 1)
  444. {
  445. if (Operand->MemorySegment == (PVOID)(&CS))
  446. return(GetAbsoluteMem(CSCacheRegister + Operand->MemoryOffset.X + Offset));
  447. else if (Operand->MemorySegment == (PVOID)(&ES))
  448. return(GetAbsoluteMem(ESCacheRegister + Operand->MemoryOffset.X + Offset));
  449. else if (Operand->MemorySegment == (PVOID)(&SS))
  450. return(GetAbsoluteMem(SSCacheRegister + Operand->MemoryOffset.X + Offset));
  451. else if (Operand->MemorySegment == (PVOID)(&DS))
  452. return(GetAbsoluteMem(DSCacheRegister + Operand->MemoryOffset.X + Offset));
  453. else
  454. DISPLAY("Protected mode GetMem() ERROR\n\r");
  455. }
  456. else
  457. return(GetAbsoluteMem( (((*Operand->MemorySegment)<<4) + Operand->MemoryOffset.X + Offset)&0xfffff ));
  458. }
  459. static VOID PutMem(
  460. OPERAND *Operand,
  461. ULONG Offset,
  462. UCHAR Value
  463. )
  464. /*++
  465. Routine Description:
  466. This function writes a byte to memory. Operand contains the
  467. segment part and offset part of the address. If the processor is
  468. in protected mode, the segment cache registers are used to compute
  469. the address. If the processor is in real mode, the segment register
  470. is shifted left four bits, and added to the offset.
  471. Arguments:
  472. Operand - Contains a memory reference in the MemorySegment and
  473. MemoryOffset fields.
  474. Offset - Additional offset from the memory location described in
  475. Operand.
  476. Value - 8 bit data value to be written to the computed address.
  477. Return Value:
  478. None.
  479. --*/
  480. {
  481. if (msw & 1)
  482. {
  483. if (Operand->MemorySegment == (PVOID)(&CS))
  484. PutAbsoluteMem(CSCacheRegister + Operand->MemoryOffset.X + Offset,Value);
  485. else if (Operand->MemorySegment == (PVOID)(&ES))
  486. PutAbsoluteMem(ESCacheRegister + Operand->MemoryOffset.X + Offset,Value);
  487. else if (Operand->MemorySegment == (PVOID)(&SS))
  488. PutAbsoluteMem(SSCacheRegister + Operand->MemoryOffset.X + Offset,Value);
  489. else if (Operand->MemorySegment == (PVOID)(&DS))
  490. PutAbsoluteMem(DSCacheRegister + Operand->MemoryOffset.X + Offset,Value);
  491. else
  492. DISPLAY("Protected mode PutMem() ERROR\n\r");
  493. }
  494. else
  495. PutAbsoluteMem( (((*Operand->MemorySegment)<<4) + Operand->MemoryOffset.X + Offset)&0xfffff , Value);
  496. }
  497. static ULONG GetSegmentCacheRegister(
  498. USHORT SegmentValue
  499. )
  500. /*++
  501. Routine Description:
  502. This function gets the 24 bit base address for a memory reference. The value
  503. of the segment register is passed in. If the processor is in protected mode,
  504. this value is used to lookup a 24 bit base address in the global descriptor
  505. table. If the processor is in real mode, the segement register value is shifted
  506. left 4 position and the 20 bit value is returned.
  507. Arguments:
  508. SegmentValue - 16 bit segment register value.
  509. Return Value:
  510. A 24 bit base address for a memory reference.
  511. --*/
  512. {
  513. if (msw&1)
  514. return(GetAbsoluteMem(gdtBase + SegmentValue + 2) | (GetAbsoluteMem(gdtBase + SegmentValue + 3) << 8) | (GetAbsoluteMem(gdtBase + SegmentValue + 4) << 16));
  515. else
  516. return((SegmentValue<<4)&0xfffff);
  517. }
  518. static UCHAR GetMemImmediate(
  519. USHORT Segment,
  520. USHORT Offset
  521. )
  522. /*++
  523. Routine Description:
  524. This function reads an 8 bit value from the memory location Segment:Offset.
  525. Arguments:
  526. Segment - 16 bit segment register value.
  527. Offset - 16 bit offset within the segment defined by Segment.
  528. Return Value:
  529. The 8 bit value read from the memory location Segemnt:Offset.
  530. --*/
  531. {
  532. if (msw&1)
  533. return(GetAbsoluteMem( GetSegmentCacheRegister(Segment)+Offset ));
  534. else
  535. return(GetAbsoluteMem((GetSegmentCacheRegister(Segment)+Offset)&0xfffff));
  536. }
  537. static VOID PutMemImmediate(
  538. USHORT Segment,
  539. USHORT Offset,
  540. UCHAR Value
  541. )
  542. /*++
  543. Routine Description:
  544. This function writes an 8 bit value to the memory location Segment:Offset.
  545. Arguments:
  546. Segment - 16 bit segment register value.
  547. Offset - 16 bit offset within the segment defined by Segment.
  548. Value - 8 bit value to write to the memory location Segment:Offset.
  549. Return Value:
  550. None.
  551. --*/
  552. {
  553. if (msw&1)
  554. PutAbsoluteMem(GetSegmentCacheRegister(Segment)+Offset,Value);
  555. else
  556. PutAbsoluteMem((GetSegmentCacheRegister(Segment)+Offset)&0xfffff,Value);
  557. }
  558. static UCHAR CodeMem(
  559. USHORT Offset
  560. )
  561. /*++
  562. Routine Description:
  563. This function reads an 8 bit value from the code area. The location
  564. read is CS:Offset.
  565. Arguments:
  566. Offset - 16 bit offset within the current code segment.
  567. Return Value:
  568. The 8 bit value read from the code area.
  569. --*/
  570. {
  571. return(GetAbsoluteMem((CSCacheRegister + Offset)&0xfffff));
  572. }
  573. static UCHAR GetStackMem(
  574. USHORT Offset
  575. )
  576. /*++
  577. Routine Description:
  578. This function reads an 8 bit value from the stack. The location
  579. read is SS:Offset.
  580. Arguments:
  581. Offset - 16 bit offset within the current stack segment.
  582. Return Value:
  583. The 8 bit value read from the stack.
  584. --*/
  585. {
  586. return(GetAbsoluteMem((SSCacheRegister + Offset)&0xfffff));
  587. }
  588. static VOID PutStackMem(
  589. USHORT Offset,
  590. UCHAR Value
  591. )
  592. /*++
  593. Routine Description:
  594. This function stores a byte onto the stack. The location written is
  595. SS:Offset.
  596. Arguments:
  597. Offset - 16 bit offset within the current stack segment.
  598. Value - 8 bit value to be stored onto the stack.
  599. Return Value:
  600. None.
  601. --*/
  602. {
  603. PutAbsoluteMem((SSCacheRegister + Offset)&0xfffff,Value);
  604. }
  605. //
  606. // Debugging functions
  607. //
  608. #ifdef X86DEBUG
  609. static VOID PrintProcessorState(UCHAR *S)
  610. {
  611. UCHAR T[256];
  612. ULONG CR;
  613. ULONG SR;
  614. sprintf(S,"AX=%04X BX=%04X CX=%04X DX=%04X SP=%04X BP=%04X SI=%04X DI=%04X\n\rDS=%04X ES=%04X SS=%04X CS=%04X IP=%04X ",
  615. AX,BX,CX,DX,SP,BP,SI,DI,DS,ES,SS,CS,CurrentIP.X);
  616. if (OF) strcat(S,"OV "); else strcat(S,"NV ");
  617. if (DF) strcat(S,"DN "); else strcat(S,"UP ");
  618. if (IF) strcat(S,"EI "); else strcat(S,"DI ");
  619. if (SF) strcat(S,"NG "); else strcat(S,"PL ");
  620. if (ZF) strcat(S,"ZR "); else strcat(S,"NZ ");
  621. if (AF) strcat(S,"AC "); else strcat(S,"NA ");
  622. if (PF) strcat(S,"PE "); else strcat(S,"PO ");
  623. if (CF) strcat(S,"CY\n\r"); else strcat(S,"NC\n\r");
  624. sprintf(T,"EAX=%08X EBX=%08X ECX=%08X EDX=%08X\n\rESP=%08X EBP=%08X ESI=%08X EDI=%08X\n\r",
  625. EAX,EBX,ECX,EDX,ESP,EBP,ESI,EDI);
  626. strcat(S,T);
  627. sprintf(T,"MSW=%04X GDTBase=%06X GDTLimit=%04X IDTBase=%06X IDTLimit=%04X\n\r",
  628. msw,gdtBase,gdtLimit,idtBase,idtLimit);
  629. strcat(S,T);
  630. sprintf(T,"DSCache=%04X ESCache=%04X SSCache=%04X CSCache=%04X\n\r",
  631. DSCacheRegister,ESCacheRegister,SSCacheRegister,CSCacheRegister);
  632. strcat(S,T);
  633. CR = GetCauseRegister();
  634. SR = GetStatusRegister();
  635. sprintf(T,"CR = %08X SR = %08X\n\r",CR,SR);
  636. strcat(S,T);
  637. }
  638. /***************************************************************************/
  639. static VOID PrintMemorySegmentName(OPERAND *Operand,UCHAR *S)
  640. {
  641. strcpy(S,"");
  642. switch (Operand->OperandType)
  643. {
  644. case Memory8Operand :
  645. case Memory16Operand : if (Operand->MemorySegment == (PVOID)(&CS))
  646. sprintf(S,"CS");
  647. else if (Operand->MemorySegment == (PVOID)(&ES))
  648. sprintf(S,"ES");
  649. else if (Operand->MemorySegment == (PVOID)(&SS))
  650. sprintf(S,"SS");
  651. else if (Operand->MemorySegment == (PVOID)(&DS))
  652. sprintf(S,"DS");
  653. break;
  654. default : ERROR("PrintMemorySegmentName()\n\r");
  655. break;
  656. }
  657. }
  658. /***************************************************************************/
  659. static VOID PrintMemoryAccessSize(OPERAND *Operand,UCHAR *S)
  660. {
  661. strcpy(S,"");
  662. switch (Operand->OperandType)
  663. {
  664. case Memory8Operand : sprintf(S,"BYTE PTR");
  665. break;
  666. case Memory16Operand : sprintf(S,"WORD PTR");
  667. break;
  668. default : ERROR("PrintMemoryAccessSize()\n\r");
  669. break;
  670. }
  671. }
  672. /***************************************************************************/
  673. static VOID PrintOperandName(OPERAND *Operand,UCHAR *S)
  674. {
  675. strcpy(S,"");
  676. switch (Operand->OperandType)
  677. {
  678. case Register8Operand : if (Operand->Register8 == (PVOID)(&AL))
  679. sprintf(S,"AL");
  680. else if (Operand->Register8 == (PVOID)(&AH))
  681. sprintf(S,"AH");
  682. else if (Operand->Register8 == (PVOID)(&BL))
  683. sprintf(S,"BL");
  684. else if (Operand->Register8 == (PVOID)(&BH))
  685. sprintf(S,"BH");
  686. else if (Operand->Register8 == (PVOID)(&CL))
  687. sprintf(S,"CL");
  688. else if (Operand->Register8 == (PVOID)(&CH))
  689. sprintf(S,"CH");
  690. else if (Operand->Register8 == (PVOID)(&DL))
  691. sprintf(S,"DL");
  692. else if (Operand->Register8 == (PVOID)(&DH))
  693. sprintf(S,"DH");
  694. break;
  695. case Register16Operand : if (Operand->Register16 == (PVOID)(&AX))
  696. sprintf(S,"AX");
  697. else if (Operand->Register16 == (PVOID)(&BX))
  698. sprintf(S,"BX");
  699. else if (Operand->Register16 == (PVOID)(&CX))
  700. sprintf(S,"CX");
  701. else if (Operand->Register16 == (PVOID)(&DX))
  702. sprintf(S,"DX");
  703. else if (Operand->Register16 == (PVOID)(&BP))
  704. sprintf(S,"BP");
  705. else if (Operand->Register16 == (PVOID)(&SP))
  706. sprintf(S,"SP");
  707. else if (Operand->Register16 == (PVOID)(&SI))
  708. sprintf(S,"SI");
  709. else if (Operand->Register16 == (PVOID)(&DI))
  710. sprintf(S,"DI");
  711. else if (Operand->Register16 == (PVOID)(&CS))
  712. sprintf(S,"CS");
  713. else if (Operand->Register16 == (PVOID)(&ES))
  714. sprintf(S,"ES");
  715. else if (Operand->Register16 == (PVOID)(&SS))
  716. sprintf(S,"SS");
  717. else if (Operand->Register16 == (PVOID)(&DS))
  718. sprintf(S,"DS");
  719. else if (Operand->Register16 == (PVOID)(&IP))
  720. sprintf(S,"IP");
  721. break;
  722. case Memory8Operand : sprintf(S,"[%04X]",Operand->MemoryOffset.X);
  723. break;
  724. case Memory16Operand : sprintf(S,"[%04X]",Operand->MemoryOffset.X);
  725. break;
  726. case Immediate8Operand : sprintf(S,"%02X",Operand->Immediate8.L);
  727. break;
  728. case Immediate16Operand : sprintf(S,"%04X",Operand->Immediate16.X);
  729. break;
  730. case ShortLabelOperand : sprintf(S,"%02X",Operand->ShortLabel.L);
  731. break;
  732. case Immediate32Operand : sprintf(S,"%04X:%04X",Operand->Immediate32Segment.X,Operand->Immediate32Offset.X);
  733. break;
  734. }
  735. }
  736. /***************************************************************************/
  737. static VOID PrintOperandValue(OPERAND *Operand,UCHAR *S)
  738. {
  739. strcpy(S,"");
  740. switch (Operand->OperandType)
  741. {
  742. case Register8Operand : if (Operand->Register8 == (PVOID)(&AL))
  743. sprintf(S,"%02X",AL);
  744. else if (Operand->Register8 == (PVOID)(&AH))
  745. sprintf(S,"%02X",AH);
  746. else if (Operand->Register8 == (PVOID)(&BL))
  747. sprintf(S,"%02X",BL);
  748. else if (Operand->Register8 == (PVOID)(&BH))
  749. sprintf(S,"%02X",BH);
  750. else if (Operand->Register8 == (PVOID)(&CL))
  751. sprintf(S,"%02X",CL);
  752. else if (Operand->Register8 == (PVOID)(&CH))
  753. sprintf(S,"%02X",CH);
  754. else if (Operand->Register8 == (PVOID)(&DL))
  755. sprintf(S,"%02X",DL);
  756. else if (Operand->Register8 == (PVOID)(&DH))
  757. sprintf(S,"%02X",DH);
  758. break;
  759. case Register16Operand : if (Operand->Register16 == (PVOID)(&AX))
  760. sprintf(S,"%04X",AX);
  761. else if (Operand->Register16 == (PVOID)(&BX))
  762. sprintf(S,"%04X",BX);
  763. else if (Operand->Register16 == (PVOID)(&CX))
  764. sprintf(S,"%04X",CX);
  765. else if (Operand->Register16 == (PVOID)(&DX))
  766. sprintf(S,"%04X",DX);
  767. else if (Operand->Register16 == (PVOID)(&BP))
  768. sprintf(S,"%04X",BP);
  769. else if (Operand->Register16 == (PVOID)(&SP))
  770. sprintf(S,"%04X",SP);
  771. else if (Operand->Register16 == (PVOID)(&SI))
  772. sprintf(S,"%04X",SI);
  773. else if (Operand->Register16 == (PVOID)(&DI))
  774. sprintf(S,"%04X",DI);
  775. else if (Operand->Register16 == (PVOID)(&CS))
  776. sprintf(S,"%04X",CS);
  777. else if (Operand->Register16 == (PVOID)(&ES))
  778. sprintf(S,"%04X",ES);
  779. else if (Operand->Register16 == (PVOID)(&SS))
  780. sprintf(S,"%04X",SS);
  781. else if (Operand->Register16 == (PVOID)(&DS))
  782. sprintf(S,"%04X",DS);
  783. else if (Operand->Register16 == (PVOID)(&IP))
  784. sprintf(S,"%04X",IP);
  785. break;
  786. case Memory8Operand : sprintf(S,"%02X",(ULONG)(GetMem(Operand,0)));
  787. break;
  788. case Memory16Operand : sprintf(S,"%04X",(ULONG)(GetMem(Operand,0)) | (ULONG)(GetMem(Operand,1)<<8));
  789. break;
  790. case Immediate8Operand : sprintf(S,"%02X",Operand->Immediate8.L);
  791. break;
  792. case Immediate16Operand : sprintf(S,"%04X",Operand->Immediate16.X);
  793. break;
  794. case ShortLabelOperand : sprintf(S,"%02X",Operand->ShortLabel.L);
  795. break;
  796. case Immediate32Operand : sprintf(S,"%04X:%04X",Operand->Immediate32Segment.X,Operand->Immediate32Offset.X);
  797. break;
  798. }
  799. }
  800. #endif
  801. static ULONG GetOperand(
  802. OPERAND *Operand,
  803. ULONG Offset
  804. )
  805. /*++
  806. Routine Description:
  807. This function is used to retrieve a value from either a register, a memory
  808. location, or an immediate value. The OperandType field of Operand contains
  809. the operand's type.
  810. Arguments:
  811. *Operand - Operand where Value is to be retrieved.
  812. Offset - For memory operands, Offset is the number of bytes forward of
  813. the effective address that Value is to be retrieved.
  814. Return Value:
  815. The 8 or 16 bit value retrieved from Operand.
  816. --*/
  817. {
  818. if (Offset!=0)
  819. if (Operand->OperandType!=Memory8Operand && Operand->OperandType!=Memory16Operand)
  820. {
  821. ERROR("GetOperand()\n\r");
  822. return(0);
  823. }
  824. switch (Operand->OperandType)
  825. {
  826. case Register8Operand : return((ULONG)(*(UCHAR *)(Operand->Register8)));
  827. break;
  828. case Register16Operand : return((ULONG)(*(USHORT *)(Operand->Register16)));
  829. break;
  830. case Memory8Operand : return((ULONG)(GetMem(Operand,Offset)));
  831. break;
  832. case Memory16Operand : return((ULONG)(GetMem(Operand,Offset) | (GetMem(Operand,Offset+1) << 8)));
  833. break;
  834. case Immediate8Operand : return((ULONG)(Operand->Immediate8.L));
  835. break;
  836. case Immediate16Operand : return((ULONG)(Operand->Immediate16.X));
  837. break;
  838. case ShortLabelOperand : return((ULONG)(Operand->ShortLabel.X));
  839. break;
  840. case Immediate32Operand : return((ULONG)(Operand->Immediate32Segment.X<<16 | Operand->Immediate32Offset.X));
  841. break;
  842. default : ERROR("GetOperand()\n\r");
  843. return(0);
  844. break;
  845. }
  846. }
  847. static VOID PutOperand(
  848. OPERAND *Operand,
  849. ULONG Offset,
  850. ULONG Value
  851. )
  852. /*++
  853. Routine Description:
  854. This function is used to store a value to either a register, or a memory
  855. location. The OperandType field of Operand contains the operand's type.
  856. Arguments:
  857. *Operand - Operand where Value is to be written.
  858. Offset - For memory operands, Offset is the number of bytes forward of
  859. the effective address that Value is to be written.
  860. Value - 8 or 16 bit immediate value that is to be written to Operand.
  861. Return Value:
  862. None.
  863. --*/
  864. {
  865. if (Offset!=0)
  866. if (Operand->OperandType!=Memory8Operand && Operand->OperandType!=Memory16Operand)
  867. {
  868. ERROR("PutOperand()\n\r");
  869. return;
  870. }
  871. switch (Operand->OperandType)
  872. {
  873. case Register8Operand : *(Operand->Register8) = Value;
  874. break;
  875. case Register16Operand : *(Operand->Register16) = Value;
  876. if (Operand->Register16 == (PVOID)(&CS))
  877. CSCacheRegister = GetSegmentCacheRegister(CS);
  878. else if (Operand->Register16 == (PVOID)(&ES))
  879. ESCacheRegister = GetSegmentCacheRegister(ES);
  880. else if (Operand->Register16 == (PVOID)(&SS))
  881. {
  882. SSCacheRegister = GetSegmentCacheRegister(SS);
  883. SSRegisterTouched = TRUE;
  884. }
  885. else if (Operand->Register16 == (PVOID)(&DS))
  886. DSCacheRegister = GetSegmentCacheRegister(DS);
  887. break;
  888. case Memory8Operand : PutMem(Operand,Offset,Value);
  889. break;
  890. case Memory16Operand : PutMem(Operand,Offset+0,Value);
  891. PutMem(Operand,Offset+1,Value>>8);
  892. break;
  893. case Immediate8Operand : Operand->Immediate8.L = Value;
  894. break;
  895. case Immediate16Operand : Operand->Immediate16.X = Value;
  896. break;
  897. case ShortLabelOperand : Operand->ShortLabel.L = Value;
  898. if (Operand->ShortLabel.L & 0x80)
  899. Operand->ShortLabel.H = 0xff;
  900. else
  901. Operand->ShortLabel.L = 0x00;
  902. break;
  903. case Immediate32Operand : Operand->Immediate32Segment.X = Value >> 16;
  904. Operand->Immediate32Offset.X = Value;
  905. break;
  906. default : ERROR("PutOperand()\n\r");
  907. break;
  908. }
  909. }
  910. /*++
  911. Address Decoding Support Functions:
  912. The following functions are used by the address decoding functions
  913. to decode operands.
  914. --*/
  915. static VOID GetAddressModeByte()
  916. /*++
  917. Routine Description:
  918. This function parses the address mode byte from the instruction currently
  919. being decoded. The mod, reg, and r/m bit fields are also extracted from
  920. the address mode byte, so they can be used by the address decoding
  921. functions.
  922. Arguments:
  923. None.
  924. Return Value:
  925. None.
  926. --*/
  927. {
  928. AddressModeByte = CodeMem(IP); IP++;
  929. mod = (AddressModeByte >> 6) & 0x03;
  930. reg = (AddressModeByte >> 3) & 0x07;
  931. r_m = (AddressModeByte >> 0) & 0x07;
  932. }
  933. USHORT *pGetCurrentSegment(
  934. USHORT *DefaultSegmentRegister
  935. )
  936. /*++
  937. Routine Description:
  938. This function returns the segment register that is active for
  939. the instruction that us currently being decoded. The default
  940. segement register for the address mode being parse is passed
  941. into this function. If there are no segement overide prefix
  942. instructions affecting this instruction, then the default
  943. segement register will be returned. Otherwise, the segement
  944. regeister referenced in the segment overide prefix instruction
  945. will be returned.
  946. Arguments:
  947. DefaultSegmentRegister - The default segment register for the
  948. address mode being decoded.
  949. Return Value:
  950. The segement register that is valid for the instruction that
  951. is currently being decoded.
  952. --*/
  953. {
  954. if (SegmentOveridePrefix)
  955. return(OverideSegmentRegister);
  956. else
  957. return(DefaultSegmentRegister);
  958. }
  959. static VOID pGetRegister8Operand(
  960. OPERAND *Operand,UCHAR reg
  961. )
  962. /*++
  963. Routine Description:
  964. This function builds an 8 bit general purpose register operand.
  965. Arguments:
  966. *Operand - Used to return the 8 bit genral purpose register operand.
  967. reg - 3 bit value used to determine which general purpose register
  968. is being referenced.
  969. Return Value:
  970. None.
  971. --*/
  972. {
  973. Operand->OperandType = Register8Operand;
  974. switch (reg)
  975. {
  976. case 0 : Operand->Register8 = &AL;
  977. break;
  978. case 1 : Operand->Register8 = &CL;
  979. break;
  980. case 2 : Operand->Register8 = &DL;
  981. break;
  982. case 3 : Operand->Register8 = &BL;
  983. break;
  984. case 4 : Operand->Register8 = &AH;
  985. break;
  986. case 5 : Operand->Register8 = &CH;
  987. break;
  988. case 6 : Operand->Register8 = &DH;
  989. break;
  990. case 7 : Operand->Register8 = &BH;
  991. break;
  992. }
  993. }
  994. static VOID pGetRegister16Operand(
  995. OPERAND *Operand,
  996. UCHAR reg
  997. )
  998. /*++
  999. Routine Description:
  1000. This function builds a 16 bit general purpose register operand.
  1001. Arguments:
  1002. *Operand - Used to return the 16 bit genral purpose register operand.
  1003. reg - 3 bit value used to determine which general purpose register
  1004. is being referenced.
  1005. Return Value:
  1006. None.
  1007. --*/
  1008. {
  1009. Operand->OperandType = Register16Operand;
  1010. switch (reg)
  1011. {
  1012. case 0 : Operand->Register16 = &AX;
  1013. break;
  1014. case 1 : Operand->Register16 = &CX;
  1015. break;
  1016. case 2 : Operand->Register16 = &DX;
  1017. break;
  1018. case 3 : Operand->Register16 = &BX;
  1019. break;
  1020. case 4 : Operand->Register16 = &SP;
  1021. break;
  1022. case 5 : Operand->Register16 = &BP;
  1023. break;
  1024. case 6 : Operand->Register16 = &SI;
  1025. break;
  1026. case 7 : Operand->Register16 = &DI;
  1027. break;
  1028. }
  1029. }
  1030. static VOID pGetSegmentRegisterOperand(
  1031. OPERAND *Operand,
  1032. UCHAR reg
  1033. )
  1034. /*++
  1035. Routine Description:
  1036. This function builds a segment register operand.
  1037. Arguments:
  1038. *Operand - Used to return the segment register operand.
  1039. reg - A 2 bit value used to determine which segment register is
  1040. being referenced.
  1041. Return Value:
  1042. None.
  1043. --*/
  1044. {
  1045. if (reg>=4)
  1046. {
  1047. ERROR("GetSegmentRegisterOperand()\n\r");
  1048. return;
  1049. }
  1050. Operand->OperandType = Register16Operand;
  1051. switch(reg)
  1052. {
  1053. case 0 : Operand->Register16 = &ES;
  1054. break;
  1055. case 1 : Operand->Register16 = &CS;
  1056. break;
  1057. case 2 : Operand->Register16 = &SS;
  1058. break;
  1059. case 3 : Operand->Register16 = &DS;
  1060. break;
  1061. }
  1062. }
  1063. static VOID pGetMemoryOperand(
  1064. OPERAND *Operand
  1065. )
  1066. /*++
  1067. Routine Description:
  1068. This function examines the bit fields from the address mode byte
  1069. and computes the effective address of a memory reference. The
  1070. mod field is used to parse the size and type of displacement from
  1071. the instruction, and the r_m field is used to determine which
  1072. registers are combined with the displacement to form the effective
  1073. address of the memory reference.
  1074. Arguments:
  1075. *Operand - The effective address of the memory is returned in this
  1076. parameter.
  1077. Return Value:
  1078. None.
  1079. --*/
  1080. {
  1081. REGISTER32 disp;
  1082. switch (mod)
  1083. {
  1084. case 0 : if (r_m==6)
  1085. {
  1086. disp.L = CodeMem(IP); IP++;
  1087. disp.H = CodeMem(IP); IP++;
  1088. }
  1089. else
  1090. disp.X = 0;
  1091. break;
  1092. case 1 : disp.L = CodeMem(IP); IP++;
  1093. if (disp.L & 0x80)
  1094. disp.H = 0xff;
  1095. else
  1096. disp.H = 0x00;
  1097. break;
  1098. case 2 : disp.L = CodeMem(IP); IP++;
  1099. disp.H = CodeMem(IP); IP++;
  1100. break;
  1101. }
  1102. switch (r_m)
  1103. {
  1104. case 0 : Operand->MemorySegment = pGetCurrentSegment(&DS);
  1105. Operand->MemoryOffset.X = BX + SI + disp.X;
  1106. break;
  1107. case 1 : Operand->MemorySegment = pGetCurrentSegment(&DS);
  1108. Operand->MemoryOffset.X = BX + DI + disp.X;
  1109. break;
  1110. case 2 : Operand->MemorySegment = pGetCurrentSegment(&SS);
  1111. Operand->MemoryOffset.X = BP + SI + disp.X;
  1112. break;
  1113. case 3 : Operand->MemorySegment = pGetCurrentSegment(&SS);
  1114. Operand->MemoryOffset.X = BP + DI + disp.X;
  1115. break;
  1116. case 4 : Operand->MemorySegment = pGetCurrentSegment(&DS);
  1117. Operand->MemoryOffset.X = SI + disp.X;
  1118. break;
  1119. case 5 : Operand->MemorySegment = pGetCurrentSegment(&DS);
  1120. Operand->MemoryOffset.X = DI + disp.X;
  1121. break;
  1122. case 6 : if (mod==0)
  1123. {
  1124. Operand->MemorySegment = pGetCurrentSegment(&DS);
  1125. Operand->MemoryOffset.X = disp.X;
  1126. }
  1127. else
  1128. {
  1129. Operand->MemorySegment = pGetCurrentSegment(&SS);
  1130. Operand->MemoryOffset.X = BP + disp.X;
  1131. }
  1132. break;
  1133. case 7 : Operand->MemorySegment = pGetCurrentSegment(&DS);
  1134. Operand->MemoryOffset.X = BX + disp.X;
  1135. break;
  1136. }
  1137. }
  1138. /*++
  1139. Address Decoding Functions:
  1140. The following functions are used to decode the operands from an
  1141. instruction. They all have an OPERAND variable as a parameter.
  1142. The decoded operand is returned in the OPERAND variable.
  1143. static VOID GetMemory8OrRegister8Operand(OPERAND *Operand)
  1144. Decodes an 8 bit general purpose register or a BYTE PTR memory operand
  1145. from an instruction.
  1146. static VOID GetMemory16OrRegister16Operand(OPERAND *Operand)
  1147. Decodes a 16 bit general purpose register or a WORD PTR memory operand
  1148. from an instruction.
  1149. static VOID GetRegister8Operand(OPERAND *Operand)
  1150. Decodes an 8 bit general purpose register from an instruction.
  1151. static VOID GetRegister16Operand(OPERAND *Operand)
  1152. Decodes a 16 bit general purpose register from an instruction.
  1153. static VOID GetSegmentRegisterOperand(OPERAND *Operand)
  1154. Decodes a 16 bit segment register from an instruction.
  1155. static VOID GetEmbeddedRegister8Operand(OPERAND *Operand)
  1156. Decodes an 8 bit general purpose register from an instruction. The
  1157. register number is embedded in 3 bits of the first byte of the
  1158. instruction.
  1159. static VOID GetEmbeddedRegister16Operand(OPERAND *Operand)
  1160. Decodes a 16 bit general purpose register from an instruction. The
  1161. register number is embedded in 3 bits of the first byte of the
  1162. instruction.
  1163. static VOID GetAccumulator8Operand(OPERAND *Operand)
  1164. Decodes the 8 bit general purpose register AL.
  1165. static VOID GetAccumulator16Operand(OPERAND *Operand)
  1166. Decodes the 16 bit general purpose register AX.
  1167. static VOID GetImmediate8Operand(OPERAND *Operand)
  1168. Decodes an 8 bit immediate value from an instruction.
  1169. static VOID GetImmediateSignExtend8Operand(OPERAND *Operand)
  1170. Decodes a 16 bit immediate value from an instruction. Only an 8 bit
  1171. value is encoded in the instruction. The 8 bit value is sign extended
  1172. to form a 16 bit value.
  1173. static VOID GetImmediate16Operand(OPERAND *Operand)
  1174. Decodes a 16 bot immediate value from an instruction.
  1175. static VOID GetShortLabelOperand(OPERAND *Operand)
  1176. Decodes an 8 bit signed immediate value from an instruction. This
  1177. operand is type is only used by branching instructions.
  1178. static VOID GetImmediate32Operand(OPERAND *Operand)
  1179. Decodes a 32 bit immediate value from an instruction. This is used
  1180. as a 16 bit segment and a 16 bit offset to reference a memory location.
  1181. static VOID GetMemory8Operand(OPERAND *Operand)
  1182. Decodes an 8 bit BYTE PTR memory operand from an instruction.
  1183. static VOID GetMemory16Operand(OPERAND *Operand)
  1184. Decodes an 16 bit WORD PTR memory operand from an instruction.
  1185. static VOID GetConstantOneOperand(OPERAND *Operand)
  1186. Decodes a constant operand whose value is 1.
  1187. static VOID GetRegisterCLOperand(OPERAND *Operand)
  1188. Decodes the 8 bit general purpose register CL.
  1189. static VOID GetRegisterDXOperand(OPERAND *Operand)
  1190. Decodes the 16 bit general purpose register DX.
  1191. static VOID GetRegisterESOperand(OPERAND *Operand)
  1192. Decodes the 16 bit segment register ES.
  1193. static VOID GetRegisterCSOperand(OPERAND *Operand)
  1194. Decodes the 16 bit segment register CS.
  1195. static VOID GetRegisterSSOperand(OPERAND *Operand)
  1196. Decodes the 16 bit segment register SS.
  1197. static VOID GetRegisterDSOperand(OPERAND *Operand)
  1198. Decodes the 16 bit segment register DS.
  1199. static VOID GetString8DSSIOperand(OPERAND *Operand)
  1200. Decodes the memory location for a string instruction. The operand
  1201. will be an 8 bit BYTE PTR memory location whose address is DS:SI.
  1202. static VOID GetString16DSSIOperand(OPERAND *Operand)
  1203. Decodes the memory location for a string instruction. The operand
  1204. will be an 16 bit WORD PTR memory location whose address is DS:SI.
  1205. static VOID GetString8ESDIOperand(OPERAND *Operand)
  1206. Decodes the memory location for a string instruction. The operand
  1207. will be an 8 bit BYTE PTR memory location whose address is ES:DI.
  1208. static VOID GetString16ESDIOperand(OPERAND *Operand)
  1209. Decodes the memory location for a string instruction. The operand
  1210. will be an 16 bit WORD PTR memory location whose address is ES:DI.
  1211. static VOID NullFunction()
  1212. This function is called when an instruction contains less than two
  1213. operand. If and instruction has no operands, then this function
  1214. would be called twice. Once for the left operand, and once for the
  1215. right operand.
  1216. --*/
  1217. /***************************************************************************/
  1218. static VOID GetMemory8OrRegister8Operand(OPERAND *Operand)
  1219. {
  1220. if (mod==3)
  1221. pGetRegister8Operand(Operand,r_m);
  1222. else
  1223. {
  1224. Operand->OperandType = Memory8Operand;
  1225. pGetMemoryOperand(Operand);
  1226. }
  1227. }
  1228. /***************************************************************************/
  1229. static VOID GetMemory16OrRegister16Operand(OPERAND *Operand)
  1230. {
  1231. if (mod==3)
  1232. pGetRegister16Operand(Operand,r_m);
  1233. else
  1234. {
  1235. Operand->OperandType = Memory16Operand;
  1236. pGetMemoryOperand(Operand);
  1237. }
  1238. }
  1239. /***************************************************************************/
  1240. static VOID GetRegister8Operand(OPERAND *Operand)
  1241. {
  1242. pGetRegister8Operand(Operand,reg);
  1243. }
  1244. /***************************************************************************/
  1245. static VOID GetRegister16Operand(OPERAND *Operand)
  1246. {
  1247. pGetRegister16Operand(Operand,reg);
  1248. }
  1249. /***************************************************************************/
  1250. static VOID GetSegmentRegisterOperand(OPERAND *Operand)
  1251. {
  1252. pGetSegmentRegisterOperand(Operand,reg);
  1253. }
  1254. /***************************************************************************/
  1255. static VOID GetEmbeddedRegister8Operand(OPERAND *Operand)
  1256. {
  1257. pGetRegister8Operand(Operand,OperationCodeByte & 0x07);
  1258. }
  1259. /***************************************************************************/
  1260. static VOID GetEmbeddedRegister16Operand(OPERAND *Operand)
  1261. {
  1262. pGetRegister16Operand(Operand,OperationCodeByte & 0x07);
  1263. }
  1264. /***************************************************************************/
  1265. static VOID GetAccumulator8Operand(OPERAND *Operand)
  1266. {
  1267. pGetRegister8Operand(Operand,0);
  1268. }
  1269. /***************************************************************************/
  1270. static VOID GetAccumulator16Operand(OPERAND *Operand)
  1271. {
  1272. pGetRegister16Operand(Operand,0);
  1273. }
  1274. /***************************************************************************/
  1275. static VOID GetImmediate8Operand(OPERAND *Operand)
  1276. {
  1277. Operand->OperandType = Immediate8Operand;
  1278. Operand->Immediate8.L = CodeMem(IP); IP++;
  1279. }
  1280. /***************************************************************************/
  1281. static VOID GetImmediateSignExtend8Operand(OPERAND *Operand)
  1282. {
  1283. Operand->OperandType = Immediate16Operand;
  1284. Operand->Immediate16.L = CodeMem(IP); IP++;
  1285. if (Operand->Immediate16.L & 0x80)
  1286. Operand->Immediate16.H = 0xff;
  1287. else
  1288. Operand->Immediate16.H = 0x00;
  1289. }
  1290. /***************************************************************************/
  1291. static VOID GetImmediate16Operand(OPERAND *Operand)
  1292. {
  1293. Operand->OperandType = Immediate16Operand;
  1294. Operand->Immediate16.L = CodeMem(IP); IP++;
  1295. Operand->Immediate16.H = CodeMem(IP); IP++;
  1296. }
  1297. /***************************************************************************/
  1298. static VOID GetShortLabelOperand(OPERAND *Operand)
  1299. {
  1300. Operand->OperandType = ShortLabelOperand;
  1301. Operand->ShortLabel.L = CodeMem(IP); IP++;
  1302. if (Operand->ShortLabel.L & 0x80)
  1303. Operand->ShortLabel.H = 0xff;
  1304. else
  1305. Operand->ShortLabel.H = 0x00;
  1306. }
  1307. /***************************************************************************/
  1308. static VOID GetImmediate32Operand(OPERAND *Operand)
  1309. {
  1310. Operand->OperandType = Immediate32Operand;
  1311. Operand->Immediate32Offset.L = CodeMem(IP); IP++;
  1312. Operand->Immediate32Offset.H = CodeMem(IP); IP++;
  1313. Operand->Immediate32Segment.L = CodeMem(IP); IP++;
  1314. Operand->Immediate32Segment.H = CodeMem(IP); IP++;
  1315. }
  1316. /***************************************************************************/
  1317. static VOID GetMemory8Operand(OPERAND *Operand)
  1318. {
  1319. Operand->OperandType = Memory8Operand;
  1320. Operand->MemorySegment = pGetCurrentSegment(&DS);
  1321. Operand->MemoryOffset.L = CodeMem(IP); IP++;
  1322. Operand->MemoryOffset.H = CodeMem(IP); IP++;
  1323. }
  1324. /***************************************************************************/
  1325. static VOID GetMemory16Operand(OPERAND *Operand)
  1326. {
  1327. Operand->OperandType = Memory16Operand;
  1328. Operand->MemorySegment = pGetCurrentSegment(&DS);
  1329. Operand->MemoryOffset.L = CodeMem(IP); IP++;
  1330. Operand->MemoryOffset.H = CodeMem(IP); IP++;
  1331. }
  1332. /***************************************************************************/
  1333. static VOID GetConstantOneOperand(OPERAND *Operand)
  1334. {
  1335. Operand->OperandType = Immediate8Operand;
  1336. Operand->Immediate8.L = 1;
  1337. }
  1338. /***************************************************************************/
  1339. static VOID GetRegisterCLOperand(OPERAND *Operand)
  1340. {
  1341. pGetRegister8Operand(Operand,1);
  1342. }
  1343. /***************************************************************************/
  1344. static VOID GetRegisterDXOperand(OPERAND *Operand)
  1345. {
  1346. pGetRegister16Operand(Operand,2);
  1347. }
  1348. /***************************************************************************/
  1349. static VOID GetRegisterESOperand(OPERAND *Operand)
  1350. {
  1351. pGetSegmentRegisterOperand(Operand,0);
  1352. }
  1353. /***************************************************************************/
  1354. static VOID GetRegisterCSOperand(OPERAND *Operand)
  1355. {
  1356. pGetSegmentRegisterOperand(Operand,1);
  1357. }
  1358. /***************************************************************************/
  1359. static VOID GetRegisterSSOperand(OPERAND *Operand)
  1360. {
  1361. pGetSegmentRegisterOperand(Operand,2);
  1362. }
  1363. /***************************************************************************/
  1364. static VOID GetRegisterDSOperand(OPERAND *Operand)
  1365. {
  1366. pGetSegmentRegisterOperand(Operand,3);
  1367. }
  1368. /***************************************************************************/
  1369. static VOID GetString8DSSIOperand(OPERAND *Operand)
  1370. {
  1371. Operand->OperandType = Memory8Operand;
  1372. Operand->MemorySegment = pGetCurrentSegment(&DS);
  1373. Operand->MemoryOffset.X = SI;
  1374. if (DF)
  1375. Delta = 0xFFFF;
  1376. else
  1377. Delta = 1;
  1378. }
  1379. /***************************************************************************/
  1380. static VOID GetString16DSSIOperand(OPERAND *Operand)
  1381. {
  1382. Operand->OperandType = Memory16Operand;
  1383. Operand->MemorySegment = pGetCurrentSegment(&DS);
  1384. Operand->MemoryOffset.X = SI;
  1385. if (DF)
  1386. Delta = 0xFFFE;
  1387. else
  1388. Delta = 2;
  1389. }
  1390. /***************************************************************************/
  1391. static VOID GetString8ESDIOperand(OPERAND *Operand)
  1392. {
  1393. Operand->OperandType = Memory8Operand;
  1394. Operand->MemorySegment = &ES;
  1395. Operand->MemoryOffset.X = DI;
  1396. if (DF)
  1397. Delta = 0xFFFF;
  1398. else
  1399. Delta = 1;
  1400. }
  1401. /***************************************************************************/
  1402. static VOID GetString16ESDIOperand(OPERAND *Operand)
  1403. {
  1404. Operand->OperandType = Memory16Operand;
  1405. Operand->MemorySegment = &ES;
  1406. Operand->MemoryOffset.X = DI;
  1407. if (DF)
  1408. Delta = 0xFFFE;
  1409. else
  1410. Delta = 2;
  1411. }
  1412. /***************************************************************************/
  1413. static VOID NullFunction()
  1414. {
  1415. }
  1416. /***************************************************************************/
  1417. /*++
  1418. Flag Functions:
  1419. The following functions compute the new values for the FLAGS register
  1420. after an instruction has been executed. The Sign flag, Zero flag,
  1421. and Parity flag only depend on the value of the result. However,
  1422. the Overflow flag, Carry flag, and Auxillary carry flag depend on the
  1423. values of the left and right operand as well os the result and weather
  1424. the operation involved addition or subtraction.
  1425. --*/
  1426. static VOID ComputeFlags8(
  1427. ULONG Result
  1428. )
  1429. /*++
  1430. Routine Description:
  1431. This function computes the Sign flag, Zero flag, and Parity flag for the
  1432. 8 bit result operand Result. If bit 7 is set, the Sign flag is true,
  1433. otherwise it is false. If all the bits are zero, the Zero flag is true,
  1434. otherwise it is false. The Parity flag is true if there are an even
  1435. number of bits set in the 8 bit quantity. ParityTable is used to speed
  1436. up this computation. Each entry in ParityTable contains the number of
  1437. bits set for a value that is equivalent to the index. ParityTable is 16
  1438. entries long, so it can handle 4 bit values. Two look ups are made for
  1439. bits 0:3 of Result and for bit 4:7 of result. These values are added
  1440. to get to total number of bits sets in the 8 bit Result operand. If this
  1441. sum is an even number, the Parity flag is set to true, otherwise it is
  1442. false.
  1443. Arguments:
  1444. Result - 8 bit result operand used to generate flag values.
  1445. Return Value:
  1446. None.
  1447. --*/
  1448. {
  1449. SF = (Result>>7) & 1;
  1450. ZF = (Result & 0xff) == 0x00;
  1451. if (((ParityTable[Result&0x0f] + ParityTable[(Result>>4) & 0x0f]) & 0x01) == 0)
  1452. PF = 1;
  1453. else
  1454. PF = 0;
  1455. }
  1456. static VOID ComputeFlags16(
  1457. ULONG Result
  1458. )
  1459. /*++
  1460. Routine Description:
  1461. This function computes the Sign flag, Zero flag, and Parity flag for the
  1462. 16 bit result operand Result. If bit 15 is set, the Sign flag is true,
  1463. otherwise it is false. If all the bits are zero, the Zero flag is true,
  1464. otherwise it is false. The Parity flag is true if there are an even
  1465. number of bits set in the lower 8 bits of Result. ParityTable is used to
  1466. speed up this computation. Each entry in ParityTable contains the number
  1467. of bits set for a value that is equivalent to the index. ParityTable is
  1468. 16 entries long, so it can handle 4 bit values. Two look ups are made for
  1469. bits 0:3 of Result and for bit 4:7 of result. These values are added
  1470. to get to total number of bits sets in the lower 8 bits of Result. If this
  1471. sum is an even number, the Parity flag is set to true, otherwise it is
  1472. false.
  1473. Arguments:
  1474. Result - 16 bit result operand used to generate flag values.
  1475. Return Value:
  1476. None.
  1477. --*/
  1478. {
  1479. SF = (Result>>15) & 1;
  1480. ZF = (Result & 0xffff) == 0x0000;
  1481. if (((ParityTable[Result&0x0f] + ParityTable[(Result>>4) & 0x0f]) & 0x01) == 0)
  1482. PF = 1;
  1483. else
  1484. PF = 0;
  1485. }
  1486. static VOID ComputeSignZeroParityFlags(
  1487. ULONG Result
  1488. )
  1489. /*++
  1490. Routine Description:
  1491. This function computes the Sign flag, Zero flag, and Parity flag for
  1492. the result operand of an instruction. The result operand may be either
  1493. an 8 bit quntity or a 16 bit quantity. The OperationCodeByte is
  1494. evaluated to determine the size of the operation, and the approriate
  1495. flag computation function is called.
  1496. Arguments:
  1497. Result - 8 or 16 bit result operand used to compute flag values.
  1498. Return Value:
  1499. None.
  1500. --*/
  1501. {
  1502. if (OperationCodeByte & 0x01) // 16 Bit Operation
  1503. ComputeFlags16(Result);
  1504. else // 8 Bit Operation
  1505. ComputeFlags8(Result);
  1506. }
  1507. static VOID ComputeAllFlags(
  1508. ULONG Left,
  1509. ULONG Right,
  1510. ULONG *Result,
  1511. ULONG AddFlag,
  1512. ULONG CarryIn
  1513. )
  1514. /*++
  1515. Routine Description:
  1516. This function computes all the flags that can be affected by an ALU
  1517. instruction. All instructions that use either an addition or a
  1518. subtraction operation that affect the state of the processors
  1519. flags use this function to perform the addition or subtraction
  1520. operation as well as all the flag computations.
  1521. Arguments:
  1522. Left - The 8 or 16 bit value for the left operand of the instruction,
  1523. Right - The 8 or 16 bit value for the right operand of the instruction.
  1524. *Result - The 8 or 16 bit Result operand for the instruction
  1525. AddFlag - Flag that is either ADDOPERATION or SUBOPERATION
  1526. CarryIn - Value of Carry flag before the instruction is executed.
  1527. Return Value:
  1528. The result of the operation is resturned in *Result..
  1529. --*/
  1530. {
  1531. ULONG SmallResult; // Use to compute Auxillary Carry flag.
  1532. if (AddFlag==ADDOPERATION)
  1533. {
  1534. *Result = Left + Right + CarryIn;
  1535. SmallResult = (Left & 0x0f) + (Right & 0x0f) + CarryIn;
  1536. }
  1537. else
  1538. {
  1539. *Result = Left - Right - CarryIn;
  1540. SmallResult = (Left & 0x0f) - (Right & 0x0f) - CarryIn;
  1541. Right = (~Right) + 1; // Right = (-Right);
  1542. }
  1543. if (OperationCodeByte & 0x01) // 16 Bit Operation
  1544. {
  1545. if ( (Left&0x8000) == (Right&0x8000) && (Left&0x8000)!=(*Result&0x8000) )
  1546. OF = 1;
  1547. else
  1548. OF = 0;
  1549. if (*Result & 0x10000)
  1550. CF = 1;
  1551. else
  1552. CF = 0;
  1553. if (SmallResult & 0x10)
  1554. AF = 1;
  1555. else
  1556. AF = 0;
  1557. ComputeFlags16(*Result); // Compute Sign, Zero, and Parity flags.
  1558. }
  1559. else // 8 Bit Operation
  1560. {
  1561. if ( (Left&0x80) == (Right&0x80) && (Left&0x80)!=(*Result&0x80) )
  1562. OF = 1;
  1563. else
  1564. OF = 0;
  1565. if (*Result & 0x100)
  1566. CF = 1;
  1567. else
  1568. CF = 0;
  1569. if (SmallResult & 0x10)
  1570. AF = 1;
  1571. else
  1572. AF = 0;
  1573. ComputeFlags8(*Result); // Compute Sign, Zero, and Parity flags.
  1574. }
  1575. }
  1576. static VOID
  1577. GenerateINT(
  1578. UCHAR Type
  1579. )
  1580. /*++
  1581. Routine Description:
  1582. This function forces and INT vector call to be made. The flags are saved
  1583. onto the stack along with the current values of CS and IP. CS and IP are
  1584. then initialized to the vector for the INT Type being generated.
  1585. Arguments:
  1586. Type - 8 bit value for the type of software interrupt to generate.
  1587. Return Value:
  1588. None.
  1589. --*/
  1590. {
  1591. if (SegmentOveridePrefix==TRUE)
  1592. IP--;
  1593. if (RepeatPrefix==TRUE)
  1594. IP--;
  1595. if (LockPrefix==TRUE)
  1596. IP--;
  1597. #ifdef X86DEBUG1
  1598. AddressTrace[AddressTracePosition] = CS<<16 | IP;
  1599. AddressTracePosition = (AddressTracePosition + 1) % ADDRESSTRACESIZE;
  1600. #endif
  1601. SP = SP - 2;
  1602. PutStackMem(SP+0,Flags.L & 0xd7);
  1603. PutStackMem(SP+1,Flags.H & 0x0f);
  1604. IF = 0;
  1605. TF = 0;
  1606. SP = SP - 2;
  1607. PutStackMem(SP+0,cs.L);
  1608. PutStackMem(SP+1,cs.H);
  1609. SP = SP - 2;
  1610. PutStackMem(SP+0,ip.L);
  1611. PutStackMem(SP+1,ip.H);
  1612. cs.L = GetMemImmediate(0,Type*4+2);
  1613. cs.H = GetMemImmediate(0,Type*4+3);
  1614. CSCacheRegister = GetSegmentCacheRegister(CS);
  1615. ip.L = GetMemImmediate(0,Type*4+0);
  1616. ip.H = GetMemImmediate(0,Type*4+1);
  1617. #ifdef X86DEBUG1
  1618. AddressTrace[AddressTracePosition] = CS<<16 | IP;
  1619. AddressTracePosition = (AddressTracePosition + 1) % ADDRESSTRACESIZE;
  1620. #endif
  1621. }
  1622. /*++
  1623. Instruction Functions:
  1624. The following functions perform the actions for each of the instructions
  1625. in the 80286 instruction set. The register macros defined at the top
  1626. of this file make these functions very readable. See an 80286 assembly
  1627. language book for a description of each of these instructions.
  1628. --*/
  1629. /***************************************************************************/
  1630. static VOID InstInvalid()
  1631. {
  1632. PRINT4("Invalid Instruction %04X:%04X %02X\n\r",CS,IP,OperationCodeByte);
  1633. DISPLAY(PrintMessage);
  1634. ErrorCode = x86BiosInvalidInstruction;
  1635. ExitFlag = TRUE;
  1636. }
  1637. /***************************************************************************/
  1638. static VOID InstAAA()
  1639. {
  1640. if ( ((AL & 0x0F) > 9) || (AF==1) )
  1641. {
  1642. AL = AL + 6;
  1643. AH = AL + 1;
  1644. AF = 1;
  1645. CF = 1;
  1646. AL = AL & 0x0F;
  1647. }
  1648. }
  1649. /***************************************************************************/
  1650. static VOID InstAAD()
  1651. {
  1652. AL = (AH * 0x0A) + AL;
  1653. AH = 0;
  1654. ComputeFlags8(AL);
  1655. }
  1656. /***************************************************************************/
  1657. static VOID InstAAM()
  1658. {
  1659. AH = AL / 0x0A;
  1660. AL = AL % 0x0A;
  1661. ComputeFlags16(AX);
  1662. }
  1663. /***************************************************************************/
  1664. static VOID InstAAS()
  1665. {
  1666. if ( ((AL & 0x0F) > 9) || (AF == 1) )
  1667. {
  1668. AL = AL - 6;
  1669. AH = AH - 1;
  1670. AF = 1;
  1671. CF = 1;
  1672. AL = AL & 0x0F;
  1673. }
  1674. }
  1675. /***************************************************************************/
  1676. static VOID InstADC()
  1677. {
  1678. ULONG Left;
  1679. ULONG Right;
  1680. ULONG Result;
  1681. Left = GetOperand(LSRC,0);
  1682. Right = GetOperand(RSRC,0);
  1683. ComputeAllFlags(Left,Right,&Result,ADDOPERATION,CF);
  1684. PutOperand(LSRC,0,Result);
  1685. }
  1686. /***************************************************************************/
  1687. static VOID InstADD()
  1688. {
  1689. ULONG Left;
  1690. ULONG Right;
  1691. ULONG Result;
  1692. Left = GetOperand(LSRC,0);
  1693. Right = GetOperand(RSRC,0);
  1694. ComputeAllFlags(Left,Right,&Result,ADDOPERATION,0);
  1695. PutOperand(LSRC,0,Result);
  1696. }
  1697. /***************************************************************************/
  1698. static VOID InstAND()
  1699. {
  1700. ULONG Result;
  1701. Result = GetOperand(LSRC,0) & GetOperand(RSRC,0);
  1702. PutOperand(LSRC,0,Result);
  1703. CF = 0;
  1704. OF = 0;
  1705. ComputeSignZeroParityFlags(Result);
  1706. }
  1707. /***************************************************************************/
  1708. static VOID InstOR()
  1709. {
  1710. ULONG Result;
  1711. Result = GetOperand(LSRC,0) | GetOperand(RSRC,0);
  1712. PutOperand(LSRC,0,Result);
  1713. CF = 0;
  1714. OF = 0;
  1715. ComputeSignZeroParityFlags(Result);
  1716. }
  1717. /***************************************************************************/
  1718. static VOID InstCMP()
  1719. {
  1720. ULONG Left;
  1721. ULONG Right;
  1722. ULONG Result;
  1723. Left = GetOperand(LSRC,0);
  1724. Right = GetOperand(RSRC,0);
  1725. ComputeAllFlags(Left,Right,&Result,SUBOPERATION,0);
  1726. }
  1727. /***************************************************************************/
  1728. static VOID InstSBB()
  1729. {
  1730. ULONG Left;
  1731. ULONG Right;
  1732. ULONG Result;
  1733. Left = GetOperand(LSRC,0);
  1734. Right = GetOperand(RSRC,0);
  1735. ComputeAllFlags(Left,Right,&Result,SUBOPERATION,CF);
  1736. PutOperand(LSRC,0,Result);
  1737. }
  1738. /***************************************************************************/
  1739. static VOID InstSUB()
  1740. {
  1741. ULONG Left;
  1742. ULONG Right;
  1743. ULONG Result;
  1744. Left = GetOperand(LSRC,0);
  1745. Right = GetOperand(RSRC,0);
  1746. ComputeAllFlags(Left,Right,&Result,SUBOPERATION,0);
  1747. PutOperand(LSRC,0,Result);
  1748. }
  1749. /***************************************************************************/
  1750. static VOID InstXOR()
  1751. {
  1752. ULONG Result;
  1753. Result = GetOperand(LSRC,0) ^ GetOperand(RSRC,0);
  1754. PutOperand(LSRC,0,Result);
  1755. CF = 0;
  1756. OF = 0;
  1757. ComputeSignZeroParityFlags(Result);
  1758. }
  1759. /***************************************************************************/
  1760. static VOID InstCBW()
  1761. {
  1762. if (AL & 0x80)
  1763. AH = 0xff;
  1764. else
  1765. AH = 0x00;
  1766. }
  1767. /***************************************************************************/
  1768. static VOID InstCLC()
  1769. {
  1770. CF = 0;
  1771. }
  1772. /***************************************************************************/
  1773. static VOID InstCLD()
  1774. {
  1775. DF = 0;
  1776. }
  1777. /***************************************************************************/
  1778. static VOID InstCLI()
  1779. {
  1780. IF = 0;
  1781. }
  1782. /***************************************************************************/
  1783. static VOID InstCMC()
  1784. {
  1785. if (CF == 0)
  1786. CF = 1;
  1787. else
  1788. CF = 0;
  1789. }
  1790. /***************************************************************************/
  1791. static VOID InstCWD()
  1792. {
  1793. if (AX & 0x8000)
  1794. DX = 0xffff;
  1795. else
  1796. DX = 0x0000;
  1797. }
  1798. /***************************************************************************/
  1799. static VOID InstDAA()
  1800. {
  1801. if ( ((AL & 0x0F) > 9) || (AF==1) )
  1802. {
  1803. AL = AL + 6;
  1804. AF = 1;
  1805. }
  1806. if ( (AL > 0x9f) || (CF==1) )
  1807. {
  1808. AL = AL + 0x60;
  1809. CF = 1;
  1810. }
  1811. ComputeFlags8(AL);
  1812. }
  1813. /***************************************************************************/
  1814. static VOID InstDAS()
  1815. {
  1816. if ( ((AL & 0x0F) > 9) || (AF==1) )
  1817. {
  1818. AL = AL - 6;
  1819. AF = 1;
  1820. }
  1821. if ( (AL > 0x9f) || (CF==1) )
  1822. {
  1823. AL = AL - 0x60;
  1824. CF = 1;
  1825. }
  1826. ComputeFlags8(AL);
  1827. }
  1828. /***************************************************************************/
  1829. static VOID InstDEC()
  1830. {
  1831. ULONG Left;
  1832. Left = GetOperand(LSRC,0);
  1833. Left = Left - 1;
  1834. PutOperand(LSRC,0,Left);
  1835. if (OperationCodeByte==0xfe) // 8 Bit Operation
  1836. {
  1837. if (Left==0x7f)
  1838. OF=1;
  1839. else
  1840. OF=0;
  1841. if ((Left & 0x0f)==0x0f)
  1842. AF = 1;
  1843. else
  1844. AF = 0;
  1845. ComputeFlags8(Left);
  1846. }
  1847. else
  1848. {
  1849. if (Left==0x7fff)
  1850. OF=1;
  1851. else
  1852. OF=0;
  1853. if ((Left & 0x0f)==0x0f)
  1854. AF = 1;
  1855. else
  1856. AF = 0;
  1857. ComputeFlags16(Left);
  1858. }
  1859. }
  1860. /***************************************************************************/
  1861. static VOID InstHLT()
  1862. {
  1863. ErrorCode = x86BiosHaltInstruction;
  1864. ExitFlag = TRUE;
  1865. }
  1866. /***************************************************************************/
  1867. static VOID InstINC()
  1868. {
  1869. ULONG Left;
  1870. Left = GetOperand(LSRC,0);
  1871. Left = Left + 1;
  1872. PutOperand(LSRC,0,Left);
  1873. if (OperationCodeByte == 0xfe) // 8 bit operation
  1874. {
  1875. if (Left==0x80)
  1876. OF=1;
  1877. else
  1878. OF=0;
  1879. if ((Left & 0x0f)==0x00)
  1880. AF = 1;
  1881. else
  1882. AF = 0;
  1883. ComputeFlags8(Left);
  1884. }
  1885. else
  1886. {
  1887. if (Left==0x8000)
  1888. OF=1;
  1889. else
  1890. OF=0;
  1891. if ((Left & 0x0f)==0x00)
  1892. AF = 1;
  1893. else
  1894. AF = 0;
  1895. ComputeFlags16(Left);
  1896. }
  1897. }
  1898. /***************************************************************************/
  1899. static VOID InstLAHF()
  1900. {
  1901. AH = Flags.L & 0xd7;
  1902. }
  1903. /***************************************************************************/
  1904. static VOID InstLDS()
  1905. {
  1906. PutOperand(LSRC,0,GetOperand(RSRC,0));
  1907. DS = GetOperand(RSRC,2);
  1908. DSCacheRegister = GetSegmentCacheRegister(DS);
  1909. }
  1910. /***************************************************************************/
  1911. static VOID InstSAHF()
  1912. {
  1913. Flags.L = AH & 0xd7;
  1914. }
  1915. /***************************************************************************/
  1916. static VOID InstSTC()
  1917. {
  1918. CF = 1;
  1919. }
  1920. /***************************************************************************/
  1921. static VOID InstSTD()
  1922. {
  1923. DF = 1;
  1924. }
  1925. /***************************************************************************/
  1926. static VOID InstSTI()
  1927. {
  1928. IF = 1;
  1929. SSRegisterTouched = TRUE;
  1930. }
  1931. /***************************************************************************/
  1932. static VOID InstWAIT()
  1933. {
  1934. ErrorCode = x86BiosWaitInstruction;
  1935. ExitFlag = TRUE;
  1936. }
  1937. /***************************************************************************/
  1938. static VOID InstPUSH()
  1939. {
  1940. ULONG Value;
  1941. Value = GetOperand(LSRC,0);
  1942. SP = SP - 2;
  1943. PutStackMem(SP+0,Value);
  1944. PutStackMem(SP+1,Value >> 8);
  1945. }
  1946. /***************************************************************************/
  1947. VOID InstPUSHA()
  1948. {
  1949. USHORT OriginalSP;
  1950. OriginalSP = SP;
  1951. SP = SP - 2;
  1952. PutStackMem(SP+0,AL);
  1953. PutStackMem(SP+1,AH);
  1954. SP = SP - 2;
  1955. PutStackMem(SP+0,BL);
  1956. PutStackMem(SP+1,BH);
  1957. SP = SP - 2;
  1958. PutStackMem(SP+0,CL);
  1959. PutStackMem(SP+1,CH);
  1960. SP = SP - 2;
  1961. PutStackMem(SP+0,DL);
  1962. PutStackMem(SP+1,DH);
  1963. SP = SP - 2;
  1964. PutStackMem(SP+0,OriginalSP);
  1965. PutStackMem(SP+1,OriginalSP >> 8);
  1966. SP = SP - 2;
  1967. PutStackMem(SP+0,BP);
  1968. PutStackMem(SP+1,BP >> 8);
  1969. SP = SP - 2;
  1970. PutStackMem(SP+0,SI);
  1971. PutStackMem(SP+1,SI >> 8);
  1972. SP = SP - 2;
  1973. PutStackMem(SP+0,DI);
  1974. PutStackMem(SP+1,DI >> 8);
  1975. }
  1976. /***************************************************************************/
  1977. static VOID InstPOP()
  1978. {
  1979. ULONG Value;
  1980. Value = GetStackMem(SP+0) | (GetStackMem(SP+1) << 8);
  1981. SP = SP + 2;
  1982. PutOperand(LSRC,0,Value);
  1983. }
  1984. /***************************************************************************/
  1985. VOID InstPOPA()
  1986. {
  1987. DI = GetStackMem(SP+0) | (GetStackMem(SP+1) << 8);
  1988. SP = SP + 2;
  1989. SI = GetStackMem(SP+0) | (GetStackMem(SP+1) << 8);
  1990. SP = SP + 2;
  1991. BP = GetStackMem(SP+0) | (GetStackMem(SP+1) << 8);
  1992. SP = SP + 2;
  1993. SP = SP + 2;
  1994. DX = GetStackMem(SP+0) | (GetStackMem(SP+1) << 8);
  1995. SP = SP + 2;
  1996. CX = GetStackMem(SP+0) | (GetStackMem(SP+1) << 8);
  1997. SP = SP + 2;
  1998. BX = GetStackMem(SP+0) | (GetStackMem(SP+1) << 8);
  1999. SP = SP + 2;
  2000. AX = GetStackMem(SP+0) | (GetStackMem(SP+1) << 8);
  2001. SP = SP + 2;
  2002. }
  2003. /***************************************************************************/
  2004. static VOID InstJO()
  2005. {
  2006. if (OF==1)
  2007. IP = IP + GetOperand(LSRC,0);
  2008. }
  2009. /***************************************************************************/
  2010. static VOID InstJNO()
  2011. {
  2012. if (OF==0)
  2013. IP = IP + GetOperand(LSRC,0);
  2014. }
  2015. /***************************************************************************/
  2016. static VOID InstJB()
  2017. {
  2018. if (CF==1)
  2019. IP = IP + GetOperand(LSRC,0);
  2020. }
  2021. /***************************************************************************/
  2022. static VOID InstJNB()
  2023. {
  2024. if (CF==0)
  2025. IP = IP + GetOperand(LSRC,0);
  2026. }
  2027. /***************************************************************************/
  2028. static VOID InstJE()
  2029. {
  2030. if (ZF==1)
  2031. IP = IP + GetOperand(LSRC,0);
  2032. }
  2033. /***************************************************************************/
  2034. static VOID InstJNE()
  2035. {
  2036. if (ZF==0)
  2037. IP = IP + GetOperand(LSRC,0);
  2038. }
  2039. /***************************************************************************/
  2040. static VOID InstJBE()
  2041. {
  2042. if (CF==1 || ZF==1)
  2043. IP = IP + GetOperand(LSRC,0);
  2044. }
  2045. /***************************************************************************/
  2046. static VOID InstJNBE()
  2047. {
  2048. if (CF==0 && ZF==0)
  2049. IP = IP + GetOperand(LSRC,0);
  2050. }
  2051. /***************************************************************************/
  2052. static VOID InstJS()
  2053. {
  2054. if (SF==1)
  2055. IP = IP + GetOperand(LSRC,0);
  2056. }
  2057. /***************************************************************************/
  2058. static VOID InstJNS()
  2059. {
  2060. if (SF==0)
  2061. IP = IP + GetOperand(LSRC,0);
  2062. }
  2063. /***************************************************************************/
  2064. static VOID InstJP()
  2065. {
  2066. if (PF==1)
  2067. IP = IP + GetOperand(LSRC,0);
  2068. }
  2069. /***************************************************************************/
  2070. static VOID InstJNP()
  2071. {
  2072. if (PF==0)
  2073. IP = IP + GetOperand(LSRC,0);
  2074. }
  2075. /***************************************************************************/
  2076. static VOID InstJL()
  2077. {
  2078. if (SF!=OF)
  2079. IP = IP + GetOperand(LSRC,0);
  2080. }
  2081. /***************************************************************************/
  2082. static VOID InstJNL()
  2083. {
  2084. if (SF==OF)
  2085. IP = IP + GetOperand(LSRC,0);
  2086. }
  2087. /***************************************************************************/
  2088. static VOID InstJLE()
  2089. {
  2090. if (ZF==1 || SF!=OF)
  2091. IP = IP + GetOperand(LSRC,0);
  2092. }
  2093. /***************************************************************************/
  2094. static VOID InstJNLE()
  2095. {
  2096. if (ZF==0 && SF==OF)
  2097. IP = IP + GetOperand(LSRC,0);
  2098. }
  2099. /***************************************************************************/
  2100. static VOID InstTEST()
  2101. {
  2102. ULONG Result;
  2103. if (OperationCodeByte == 0xf6)
  2104. GetImmediate8Operand(RSRC);
  2105. if (OperationCodeByte == 0xf7)
  2106. GetImmediate16Operand(RSRC);
  2107. Result = GetOperand(LSRC,0) & GetOperand(RSRC,0);
  2108. CF = 0;
  2109. OF = 0;
  2110. ComputeSignZeroParityFlags(Result);
  2111. }
  2112. /***************************************************************************/
  2113. static VOID InstXCHG()
  2114. {
  2115. ULONG Temp;
  2116. Temp = GetOperand(RSRC,0);
  2117. PutOperand(RSRC,0,GetOperand(LSRC,0));
  2118. PutOperand(LSRC,0,Temp);
  2119. }
  2120. /***************************************************************************/
  2121. static VOID InstMOV()
  2122. {
  2123. PutOperand(LSRC,0,GetOperand(RSRC,0));
  2124. }
  2125. /***************************************************************************/
  2126. static VOID InstLEA()
  2127. {
  2128. PutOperand(LSRC,0,RSRC->MemoryOffset.X);
  2129. }
  2130. /***************************************************************************/
  2131. static VOID InstCALL()
  2132. {
  2133. ULONG Value;
  2134. Value = GetOperand(LSRC,0);
  2135. switch (OperationCodeByte)
  2136. {
  2137. case 0xe8 : SP = SP - 2;
  2138. PutStackMem(SP+0,ip.L);
  2139. PutStackMem(SP+1,ip.H);
  2140. IP = IP + Value;
  2141. break;
  2142. case 0xff : if ( ((AddressModeByte >> 3) & 0x07) == 0x02)
  2143. {
  2144. SP = SP - 2;
  2145. PutStackMem(SP+0,ip.L);
  2146. PutStackMem(SP+1,ip.H);
  2147. IP = Value;
  2148. }
  2149. else if ( ((AddressModeByte >> 3) & 0x07) == 0x03)
  2150. {
  2151. SP = SP - 4;
  2152. PutStackMem(SP+0,ip.L);
  2153. PutStackMem(SP+1,ip.H);
  2154. PutStackMem(SP+2,cs.L);
  2155. PutStackMem(SP+3,cs.H);
  2156. IP = Value;
  2157. CS = GetOperand(LSRC,2);
  2158. CSCacheRegister = GetSegmentCacheRegister(CS);
  2159. }
  2160. break;
  2161. case 0x9a : SP = SP - 4;
  2162. PutStackMem(SP+0,ip.L);
  2163. PutStackMem(SP+1,ip.H);
  2164. PutStackMem(SP+2,cs.L);
  2165. PutStackMem(SP+3,cs.H);
  2166. IP = Value;
  2167. CS = Value >> 16;
  2168. CSCacheRegister = GetSegmentCacheRegister(CS);
  2169. break;
  2170. }
  2171. }
  2172. /***************************************************************************/
  2173. static VOID InstPUSHF()
  2174. {
  2175. SP = SP - 2;
  2176. PutStackMem(SP+0,Flags.L & 0xd7);
  2177. PutStackMem(SP+1,Flags.H & 0x0f);
  2178. }
  2179. /**********************************f*****************************************/
  2180. static VOID InstPOPF()
  2181. {
  2182. Flags.L = GetStackMem(SP+0) & 0xd7;
  2183. Flags.H = GetStackMem(SP+1) & 0x0f;
  2184. SP = SP + 2;
  2185. }
  2186. /***************************************************************************/
  2187. static VOID InstMOVS()
  2188. {
  2189. if (RepeatPrefix==TRUE)
  2190. {
  2191. while(CX!=0)
  2192. {
  2193. PutOperand(LSRC,0,GetOperand(RSRC,0));
  2194. CX = CX - 1;
  2195. SI += Delta;
  2196. DI += Delta;
  2197. LSRC->MemoryOffset.X += Delta;
  2198. RSRC->MemoryOffset.X += Delta;
  2199. }
  2200. }
  2201. else
  2202. {
  2203. PutOperand(LSRC,0,GetOperand(RSRC,0));
  2204. SI = SI + Delta;
  2205. DI = DI + Delta;
  2206. }
  2207. }
  2208. /***************************************************************************/
  2209. static VOID InstCMPS()
  2210. {
  2211. ULONG Left;
  2212. ULONG Right;
  2213. ULONG Result;
  2214. if (RepeatPrefix==TRUE)
  2215. {
  2216. while(CX!=0)
  2217. {
  2218. Left = GetOperand(LSRC,0);
  2219. Right = GetOperand(RSRC,0);
  2220. ComputeAllFlags(Left,Right,&Result,SUBOPERATION,0);
  2221. CX--;
  2222. SI += Delta;
  2223. DI += Delta;
  2224. LSRC->MemoryOffset.X += Delta;
  2225. RSRC->MemoryOffset.X += Delta;
  2226. if (ZF != RepeatZeroFlag)
  2227. return;
  2228. }
  2229. }
  2230. else
  2231. {
  2232. Left = GetOperand(LSRC,0);
  2233. Right = GetOperand(RSRC,0);
  2234. ComputeAllFlags(Left,Right,&Result,SUBOPERATION,0);
  2235. SI += Delta;
  2236. DI += Delta;
  2237. }
  2238. }
  2239. /***************************************************************************/
  2240. static VOID InstSTOS()
  2241. {
  2242. if (RepeatPrefix==TRUE)
  2243. {
  2244. while(CX!=0)
  2245. {
  2246. PutOperand(LSRC,0,GetOperand(RSRC,0));
  2247. CX--;
  2248. DI += Delta;
  2249. LSRC->MemoryOffset.X += Delta;
  2250. }
  2251. }
  2252. else
  2253. {
  2254. PutOperand(LSRC,0,GetOperand(RSRC,0));
  2255. DI += Delta;
  2256. }
  2257. }
  2258. /***************************************************************************/
  2259. static VOID InstLODS()
  2260. {
  2261. if (RepeatPrefix==TRUE)
  2262. {
  2263. while(CX!=0)
  2264. {
  2265. PutOperand(LSRC,0,GetOperand(RSRC,0));
  2266. CX--;
  2267. SI += Delta;
  2268. RSRC->MemoryOffset.X += Delta;
  2269. }
  2270. }
  2271. else
  2272. {
  2273. PutOperand(LSRC,0,GetOperand(RSRC,0));
  2274. SI += Delta;
  2275. }
  2276. }
  2277. /***************************************************************************/
  2278. static VOID InstSCAS()
  2279. {
  2280. ULONG Left;
  2281. ULONG Right;
  2282. ULONG Result;
  2283. if (RepeatPrefix==TRUE)
  2284. {
  2285. while(CX!=0)
  2286. {
  2287. Left = GetOperand(LSRC,0);
  2288. Right = GetOperand(RSRC,0);
  2289. ComputeAllFlags(Left,Right,&Result,SUBOPERATION,0);
  2290. CX--;
  2291. DI += Delta;
  2292. RSRC->MemoryOffset.X += Delta;
  2293. if (ZF != RepeatZeroFlag)
  2294. return;
  2295. }
  2296. }
  2297. else
  2298. {
  2299. Left = GetOperand(LSRC,0);
  2300. Right = GetOperand(RSRC,0);
  2301. ComputeAllFlags(Left,Right,&Result,SUBOPERATION,0);
  2302. DI += Delta;
  2303. }
  2304. }
  2305. /***************************************************************************/
  2306. static VOID InstRET()
  2307. {
  2308. ip.L = GetStackMem(SP+0);
  2309. ip.H = GetStackMem(SP+1);
  2310. SP = SP + 2;
  2311. switch(OperationCodeByte)
  2312. {
  2313. case 0xc2 : SP = SP + GetOperand(LSRC,0);
  2314. break;
  2315. case 0xca : cs.L = GetStackMem(SP + 0);
  2316. cs.H = GetStackMem(SP + 1);
  2317. CSCacheRegister = GetSegmentCacheRegister(CS);
  2318. SP = SP + 2;
  2319. SP = SP + GetOperand(LSRC,0);
  2320. break;
  2321. case 0xcb : cs.L = GetStackMem(SP + 0);
  2322. cs.H = GetStackMem(SP + 1);
  2323. CSCacheRegister = GetSegmentCacheRegister(CS);
  2324. SP = SP + 2;
  2325. break;
  2326. }
  2327. }
  2328. /***************************************************************************/
  2329. static VOID InstLES()
  2330. {
  2331. PutOperand(LSRC,0,GetOperand(RSRC,0));
  2332. ES = GetOperand(RSRC,2);
  2333. ESCacheRegister = GetSegmentCacheRegister(ES);
  2334. }
  2335. /***************************************************************************/
  2336. static VOID InstINT()
  2337. {
  2338. if (OperationCodeByte & 0x01)
  2339. GenerateINT(GetOperand(LSRC,0));
  2340. else
  2341. GenerateINT(3);
  2342. }
  2343. /***************************************************************************/
  2344. static VOID InstINTO()
  2345. {
  2346. if (OF == 1)
  2347. GenerateINT(4);
  2348. }
  2349. /***************************************************************************/
  2350. static VOID InstIRET()
  2351. {
  2352. #ifdef X86DEBUG1
  2353. AddressTrace[AddressTracePosition] = CS<<16 | IP;
  2354. AddressTracePosition = (AddressTracePosition + 1) % ADDRESSTRACESIZE;
  2355. #endif
  2356. ip.L = GetStackMem(SP+0);
  2357. ip.H = GetStackMem(SP+1);
  2358. SP = SP + 2;
  2359. cs.L = GetStackMem(SP+0);
  2360. cs.H = GetStackMem(SP+1);
  2361. CSCacheRegister = GetSegmentCacheRegister(CS);
  2362. SP = SP + 2;
  2363. Flags.L = GetStackMem(SP+0) & 0xd7;
  2364. Flags.H = GetStackMem(SP+1) & 0x0f;
  2365. SP = SP + 2;
  2366. #ifdef X86DEBUG1
  2367. AddressTrace[AddressTracePosition] = CS<<16 | IP;
  2368. AddressTracePosition = (AddressTracePosition + 1) % ADDRESSTRACESIZE;
  2369. #endif
  2370. }
  2371. /***************************************************************************/
  2372. static VOID InstROL()
  2373. {
  2374. ULONG Count;
  2375. ULONG Temp;
  2376. ULONG Value;
  2377. ULONG TempF;
  2378. Value = GetOperand(LSRC,0);
  2379. Count = GetOperand(RSRC,0);
  2380. Temp = Count;
  2381. while (Temp!=0)
  2382. {
  2383. if (OperationCodeByte & 0x01)
  2384. CF = (Value>>15) & 1;
  2385. else
  2386. CF = (Value>>7) & 1;
  2387. Value = (Value << 1) | CF;
  2388. Temp = Temp - 1;
  2389. }
  2390. if (Count==1)
  2391. {
  2392. if (OperationCodeByte & 0x01)
  2393. TempF = (Value>>15) & 1;
  2394. else
  2395. TempF = (Value>>7) & 1;
  2396. if (TempF != CF)
  2397. OF = 1;
  2398. else
  2399. OF = 0;
  2400. }
  2401. PutOperand(LSRC,0,Value);
  2402. }
  2403. /***************************************************************************/
  2404. static VOID InstROR()
  2405. {
  2406. ULONG Count;
  2407. ULONG Temp;
  2408. ULONG Value;
  2409. ULONG TempF;
  2410. Value = GetOperand(LSRC,0);
  2411. Count = GetOperand(RSRC,0);
  2412. Temp = Count;
  2413. while (Temp!=0)
  2414. {
  2415. CF = Value & 1;
  2416. if (OperationCodeByte & 0x01)
  2417. Value = ((Value >> 1) & 0x7fff) | (CF << 15);
  2418. else
  2419. Value = ((Value >> 1) & 0x7f) | (CF << 7);
  2420. Temp = Temp - 1;
  2421. }
  2422. if (Count==1)
  2423. {
  2424. if (OperationCodeByte & 0x01)
  2425. TempF = (Value>>14) & 3;
  2426. else
  2427. TempF = (Value>>6) & 3;
  2428. if (TempF==1 || TempF==2)
  2429. OF = 1;
  2430. else
  2431. OF = 0;
  2432. }
  2433. PutOperand(LSRC,0,Value);
  2434. }
  2435. /***************************************************************************/
  2436. static VOID InstRCL()
  2437. {
  2438. ULONG Count;
  2439. ULONG Temp;
  2440. ULONG Value;
  2441. ULONG TempF;
  2442. ULONG tmpcf;
  2443. Value = GetOperand(LSRC,0);
  2444. Count = GetOperand(RSRC,0);
  2445. Temp = Count;
  2446. while (Temp!=0)
  2447. {
  2448. tmpcf = CF;
  2449. if (OperationCodeByte & 0x01)
  2450. CF = (Value>>15) & 1;
  2451. else
  2452. CF = (Value>>7) & 1;
  2453. Value = (Value << 1) | tmpcf;
  2454. Temp = Temp - 1;
  2455. }
  2456. if (Count==1)
  2457. {
  2458. if (OperationCodeByte & 0x01)
  2459. TempF = (Value>>15) & 1;
  2460. else
  2461. TempF = (Value>>7) & 1;
  2462. if (TempF != CF)
  2463. OF = 1;
  2464. else
  2465. OF = 0;
  2466. }
  2467. PutOperand(LSRC,0,Value);
  2468. }
  2469. /***************************************************************************/
  2470. static VOID InstRCR()
  2471. {
  2472. ULONG Count;
  2473. ULONG Temp;
  2474. ULONG Value;
  2475. ULONG TempF;
  2476. ULONG tmpcf;
  2477. Value = GetOperand(LSRC,0);
  2478. Count = GetOperand(RSRC,0);
  2479. Temp = Count;
  2480. while (Temp!=0)
  2481. {
  2482. tmpcf = CF;
  2483. CF = Value & 1;
  2484. if (OperationCodeByte & 0x01)
  2485. Value = ((Value >> 1) & 0x7fff) | (tmpcf << 15);
  2486. else
  2487. Value = ((Value >> 1) & 0x7f) | (tmpcf << 7);
  2488. Temp = Temp - 1;
  2489. }
  2490. if (Count==1)
  2491. {
  2492. if (OperationCodeByte & 0x01)
  2493. TempF = (Value>>14) & 3;
  2494. else
  2495. TempF = (Value>>6) & 3;
  2496. if (TempF==1 || TempF==2)
  2497. OF = 1;
  2498. else
  2499. OF = 0;
  2500. }
  2501. PutOperand(LSRC,0,Value);
  2502. }
  2503. /***************************************************************************/
  2504. static VOID InstSAL()
  2505. {
  2506. ULONG Count;
  2507. ULONG Temp;
  2508. ULONG Value;
  2509. ULONG TempF;
  2510. Value = GetOperand(LSRC,0);
  2511. Count = GetOperand(RSRC,0);
  2512. Temp = Count;
  2513. while (Temp!=0)
  2514. {
  2515. if (OperationCodeByte & 0x01)
  2516. CF = (Value>>15) & 1;
  2517. else
  2518. CF = (Value>>7) & 1;
  2519. Value = (Value << 1);
  2520. Temp = Temp - 1;
  2521. }
  2522. if (Count==1)
  2523. {
  2524. if (OperationCodeByte & 0x01)
  2525. TempF = (Value>>15) & 1;
  2526. else
  2527. TempF = (Value>>7) & 1;
  2528. if (TempF != CF)
  2529. OF = 1;
  2530. else
  2531. OF = 0;
  2532. }
  2533. PutOperand(LSRC,0,Value);
  2534. ComputeSignZeroParityFlags(Value);
  2535. }
  2536. /***************************************************************************/
  2537. static VOID InstSHR()
  2538. {
  2539. ULONG Count;
  2540. ULONG Temp;
  2541. ULONG Value;
  2542. ULONG TempF;
  2543. Value = GetOperand(LSRC,0);
  2544. Count = GetOperand(RSRC,0);
  2545. Temp = Count;
  2546. while (Temp!=0)
  2547. {
  2548. CF = Value & 1;
  2549. if (OperationCodeByte & 0x01)
  2550. Value = ((Value >> 1) & 0x7fff);
  2551. else
  2552. Value = ((Value >> 1) & 0x7f);
  2553. Temp = Temp - 1;
  2554. }
  2555. if (Count==1)
  2556. {
  2557. if (OperationCodeByte & 0x01)
  2558. TempF = (Value>>14) & 3;
  2559. else
  2560. TempF = (Value>>6) & 3;
  2561. if (TempF==1 || TempF==2)
  2562. OF = 1;
  2563. else
  2564. OF = 0;
  2565. }
  2566. PutOperand(LSRC,0,Value);
  2567. ComputeSignZeroParityFlags(Value);
  2568. }
  2569. /***************************************************************************/
  2570. static VOID InstSAR()
  2571. {
  2572. ULONG Count;
  2573. ULONG Temp;
  2574. ULONG Value;
  2575. ULONG TempF;
  2576. Value = GetOperand(LSRC,0);
  2577. Count = GetOperand(RSRC,0);
  2578. Temp = Count;
  2579. while (Temp!=0)
  2580. {
  2581. CF = Value & 1;
  2582. if (OperationCodeByte & 0x01)
  2583. Value = ((Value >> 1) & 0x7fff) | (Value & 0x8000);
  2584. else
  2585. Value = ((Value >> 1) & 0x7f) | (Value & 0x80);
  2586. Temp = Temp - 1;
  2587. }
  2588. if (Count==1)
  2589. {
  2590. if (OperationCodeByte & 0x01)
  2591. TempF = (Value>>14) & 3;
  2592. else
  2593. TempF = (Value>>6) & 3;
  2594. if (TempF==1 || TempF==2)
  2595. OF = 1;
  2596. else
  2597. OF = 0;
  2598. }
  2599. PutOperand(LSRC,0,Value);
  2600. ComputeSignZeroParityFlags(Value);
  2601. }
  2602. /***************************************************************************/
  2603. static VOID InstXLAT()
  2604. {
  2605. USHORT Segment;
  2606. Segment = *pGetCurrentSegment(&DS);
  2607. AL = GetMemImmediate(Segment,BX + AL);
  2608. }
  2609. /***************************************************************************/
  2610. static VOID InstESC()
  2611. {
  2612. }
  2613. /***************************************************************************/
  2614. static VOID InstLOOPNE()
  2615. {
  2616. CX--;
  2617. if (ZF==0 && CX!=0)
  2618. IP = IP + GetOperand(LSRC,0);
  2619. }
  2620. /***************************************************************************/
  2621. static VOID InstLOOPE()
  2622. {
  2623. CX--;
  2624. if (ZF==1 && CX!=0)
  2625. IP = IP + GetOperand(LSRC,0);
  2626. }
  2627. /***************************************************************************/
  2628. static VOID InstLOOP()
  2629. {
  2630. CX--;
  2631. if (CX!=0)
  2632. IP = IP + GetOperand(LSRC,0);
  2633. }
  2634. /***************************************************************************/
  2635. static VOID InstJCXZ()
  2636. {
  2637. if (CX==0)
  2638. IP = IP + GetOperand(LSRC,0);
  2639. }
  2640. /***************************************************************************/
  2641. static VOID InstIN()
  2642. {
  2643. ULONG Port;
  2644. ULONG Value;
  2645. Port = GetOperand(RSRC,0);
  2646. if (LSRC->OperandType == Register16Operand)
  2647. if (Port & 0x01)
  2648. {
  2649. Value = READ_REGISTER_UCHAR(BiosIsaIoBaseAddress+Port) | (READ_REGISTER_UCHAR(BiosIsaIoBaseAddress+Port+1)<<8);
  2650. }
  2651. else
  2652. {
  2653. Value = READ_REGISTER_USHORT(BiosIsaIoBaseAddress+Port);
  2654. }
  2655. else
  2656. {
  2657. Value = READ_REGISTER_UCHAR(BiosIsaIoBaseAddress+Port);
  2658. }
  2659. PutOperand(LSRC,0,Value);
  2660. }
  2661. /***************************************************************************/
  2662. static VOID InstINS()
  2663. {
  2664. ULONG Port;
  2665. ULONG Value;
  2666. Port = GetOperand(RSRC,0);
  2667. if (RepeatPrefix)
  2668. {
  2669. while(CX!=0)
  2670. {
  2671. if (OperationCodeByte & 0x01)
  2672. if (Port & 0x01)
  2673. {
  2674. Value = READ_REGISTER_UCHAR(BiosIsaIoBaseAddress+Port) | (READ_REGISTER_UCHAR(BiosIsaIoBaseAddress+Port+1)<<8);
  2675. }
  2676. else
  2677. {
  2678. Value = READ_REGISTER_USHORT(BiosIsaIoBaseAddress+Port);
  2679. }
  2680. else
  2681. {
  2682. Value = READ_REGISTER_UCHAR(BiosIsaIoBaseAddress+Port);
  2683. }
  2684. PutOperand(LSRC,0,Value);
  2685. CX--;
  2686. DI += Delta;
  2687. LSRC->MemoryOffset.X += Delta;
  2688. }
  2689. }
  2690. else
  2691. {
  2692. if (OperationCodeByte & 0x01)
  2693. if (Port & 0x01)
  2694. {
  2695. Value = READ_REGISTER_UCHAR(BiosIsaIoBaseAddress+Port) | (READ_REGISTER_UCHAR(BiosIsaIoBaseAddress+Port+1)<<8);
  2696. }
  2697. else
  2698. {
  2699. Value = READ_REGISTER_USHORT(BiosIsaIoBaseAddress+Port);
  2700. }
  2701. else
  2702. {
  2703. Value = READ_REGISTER_UCHAR(BiosIsaIoBaseAddress+Port);
  2704. }
  2705. PutOperand(LSRC,0,Value);
  2706. DI += Delta;
  2707. }
  2708. }
  2709. /***************************************************************************/
  2710. static VOID InstOUT()
  2711. {
  2712. ULONG Port;
  2713. ULONG Value;
  2714. Port = GetOperand(RSRC,0);
  2715. Value = GetOperand(LSRC,0);
  2716. if (LSRC->OperandType == Register16Operand)
  2717. if (Port & 0x01)
  2718. {
  2719. WRITE_REGISTER_UCHAR(BiosIsaIoBaseAddress + Port,Value);
  2720. WRITE_REGISTER_UCHAR(BiosIsaIoBaseAddress + Port + 1,Value>>8);
  2721. }
  2722. else
  2723. {
  2724. WRITE_REGISTER_USHORT(BiosIsaIoBaseAddress + Port,Value);
  2725. }
  2726. else
  2727. {
  2728. WRITE_REGISTER_UCHAR(BiosIsaIoBaseAddress + Port,Value);
  2729. }
  2730. }
  2731. /***************************************************************************/
  2732. static VOID InstOUTS()
  2733. {
  2734. ULONG Port;
  2735. ULONG Value;
  2736. Port = GetOperand(RSRC,0);
  2737. if (RepeatPrefix)
  2738. {
  2739. while(CX!=0)
  2740. {
  2741. Value = GetOperand(LSRC,0);
  2742. if (OperationCodeByte & 0x01)
  2743. if (Port & 0x01)
  2744. {
  2745. WRITE_REGISTER_UCHAR(BiosIsaIoBaseAddress + Port,Value);
  2746. WRITE_REGISTER_UCHAR(BiosIsaIoBaseAddress + Port + 1,Value>>8);
  2747. }
  2748. else
  2749. {
  2750. WRITE_REGISTER_USHORT(BiosIsaIoBaseAddress + Port,Value);
  2751. }
  2752. else
  2753. {
  2754. WRITE_REGISTER_UCHAR(BiosIsaIoBaseAddress + Port,Value);
  2755. }
  2756. CX--;
  2757. SI += Delta;
  2758. LSRC->MemoryOffset.X += Delta;
  2759. }
  2760. }
  2761. else
  2762. {
  2763. Value = GetOperand(LSRC,0);
  2764. if (OperationCodeByte & 0x01)
  2765. if (Port & 0x01)
  2766. {
  2767. WRITE_REGISTER_UCHAR(BiosIsaIoBaseAddress + Port,Value);
  2768. WRITE_REGISTER_UCHAR(BiosIsaIoBaseAddress + Port + 1,Value>>8);
  2769. }
  2770. else
  2771. {
  2772. WRITE_REGISTER_USHORT(BiosIsaIoBaseAddress + Port,Value);
  2773. }
  2774. else
  2775. {
  2776. WRITE_REGISTER_UCHAR(BiosIsaIoBaseAddress + Port,Value);
  2777. }
  2778. SI += Delta;
  2779. }
  2780. }
  2781. /***************************************************************************/
  2782. static VOID InstJMP()
  2783. {
  2784. ULONG Value;
  2785. Value = GetOperand(LSRC,0);
  2786. switch(OperationCodeByte)
  2787. {
  2788. case 0xe9 : IP = IP + Value;
  2789. break;
  2790. case 0xea : IP = Value;
  2791. CS = Value >> 16;
  2792. CSCacheRegister = GetSegmentCacheRegister(CS);
  2793. break;
  2794. case 0xeb : IP = IP + Value;
  2795. break;
  2796. case 0xff : if (reg==4)
  2797. IP = Value;
  2798. if (reg==5)
  2799. {
  2800. IP = Value;
  2801. CS = GetOperand(LSRC,2);
  2802. CSCacheRegister = GetSegmentCacheRegister(CS);
  2803. }
  2804. break;
  2805. }
  2806. }
  2807. /***************************************************************************/
  2808. static VOID InstLOCK()
  2809. {
  2810. LockPrefix = TRUE;
  2811. }
  2812. /***************************************************************************/
  2813. static VOID InstREP()
  2814. {
  2815. RepeatPrefix = TRUE;
  2816. RepeatZeroFlag = OperationCodeByte & 0x01;
  2817. }
  2818. /***************************************************************************/
  2819. static VOID InstNOT()
  2820. {
  2821. PutOperand(LSRC,0,0xFFFF - GetOperand(LSRC,0));
  2822. }
  2823. /***************************************************************************/
  2824. static VOID InstNEG()
  2825. {
  2826. ULONG Left;
  2827. ULONG Result;
  2828. Left = GetOperand(LSRC,0);
  2829. Result = 0xFFFF - Left + 1;
  2830. PutOperand(LSRC,0,Result);
  2831. if (Result == 0)
  2832. CF = 0;
  2833. else
  2834. CF = 1;
  2835. }
  2836. /***************************************************************************/
  2837. static VOID InstMUL()
  2838. {
  2839. ULONG Temp;
  2840. if (OperationCodeByte & 0x01)
  2841. {
  2842. Temp = (ULONG)(AX) * (ULONG)(GetOperand(LSRC,0));
  2843. AX = Temp & 0xffff;
  2844. DX = (Temp >> 16) & 0xffff;
  2845. if (DX==0)
  2846. CF = 0;
  2847. else
  2848. CF = 1;
  2849. }
  2850. else
  2851. {
  2852. Temp = (ULONG)(AL) * (ULONG)(GetOperand(LSRC,0));
  2853. AX = Temp & 0xffff;
  2854. if (AH==0)
  2855. CF = 0;
  2856. else
  2857. CF = 1;
  2858. }
  2859. OF = CF;
  2860. }
  2861. /***************************************************************************/
  2862. static VOID InstIMUL()
  2863. {
  2864. LONG Temp;
  2865. if (OperationCodeByte & 0x01)
  2866. {
  2867. if (OperationCodeByte == 0xf7)
  2868. Temp = (ULONG)(AX) * (ULONG)(GetOperand(LSRC,0));
  2869. else
  2870. Temp = (ULONG)(GetOperand(LSRC,0)) * (ULONG)(GetOperand(RSRC,0));
  2871. AX = Temp & 0xffff;
  2872. DX = (Temp >> 16) & 0xffff;
  2873. if ( ((AX & 0x8000)==0 && DX==0) || ((AX & 0x8000)==0x8000 && DX==0xffff))
  2874. CF = 0;
  2875. else
  2876. CF = 1;
  2877. }
  2878. else
  2879. {
  2880. if (OperationCodeByte == 0xf6)
  2881. Temp = (ULONG)(AL) * (ULONG)(GetOperand(LSRC,0));
  2882. else
  2883. Temp = (ULONG)(GetOperand(LSRC,0)) * (ULONG)(GetOperand(RSRC,0));
  2884. AX = Temp & 0xffff;
  2885. if ( ((AL & 0x80)==0 && AH==0) || ((AL & 0x80)==0x80 && AH==0xff))
  2886. CF = 0;
  2887. else
  2888. CF = 1;
  2889. }
  2890. OF = CF;
  2891. }
  2892. /***************************************************************************/
  2893. static VOID InstDIV()
  2894. {
  2895. ULONG Numr;
  2896. ULONG Divr;
  2897. if (OperationCodeByte & 0x01)
  2898. {
  2899. Numr = ((ULONG)DX << 16) | AX;
  2900. Divr = (ULONG)GetOperand(LSRC,0);
  2901. if (Divr==0)
  2902. {
  2903. ErrorCode = x86BiosDivideByZero;
  2904. ExitFlag = TRUE;
  2905. return;
  2906. }
  2907. if ((Numr/Divr) > 0xffff)
  2908. {
  2909. ErrorCode = x86BiosDivideByZero;
  2910. ExitFlag = TRUE;
  2911. return;
  2912. }
  2913. AX = Numr/Divr;
  2914. DX = Numr%Divr;
  2915. }
  2916. else
  2917. {
  2918. Numr = AX;
  2919. Divr = (ULONG)GetOperand(LSRC,0);
  2920. if (Divr==0)
  2921. {
  2922. ErrorCode = x86BiosDivideByZero;
  2923. ExitFlag = TRUE;
  2924. return;
  2925. }
  2926. if ((Numr/Divr) > 0xff)
  2927. {
  2928. ErrorCode = x86BiosDivideByZero;
  2929. ExitFlag = TRUE;
  2930. return;
  2931. }
  2932. AL = Numr/Divr;
  2933. AH = Numr%Divr;
  2934. }
  2935. }
  2936. /***************************************************************************/
  2937. static VOID InstIDIV()
  2938. {
  2939. ULONG Numr;
  2940. ULONG Divr;
  2941. if (OperationCodeByte & 0x01)
  2942. {
  2943. Numr = ((ULONG)DX << 16) | AX;
  2944. Divr = (ULONG)GetOperand(LSRC,0);
  2945. if (Divr==0)
  2946. {
  2947. ErrorCode = x86BiosDivideByZero;
  2948. ExitFlag = TRUE;
  2949. return;
  2950. }
  2951. if ((Numr/Divr) > 0xffff)
  2952. {
  2953. ErrorCode = x86BiosDivideByZero;
  2954. ExitFlag = TRUE;
  2955. return;
  2956. }
  2957. AX = Numr/Divr;
  2958. DX = Numr%Divr;
  2959. }
  2960. else
  2961. {
  2962. Numr = AX;
  2963. Divr = (ULONG)GetOperand(LSRC,0);
  2964. if (Divr==0)
  2965. {
  2966. ErrorCode = x86BiosDivideByZero;
  2967. ExitFlag = TRUE;
  2968. return;
  2969. }
  2970. if ((Numr/Divr) > 0xff)
  2971. {
  2972. ErrorCode = x86BiosDivideByZero;
  2973. ExitFlag = TRUE;
  2974. return;
  2975. }
  2976. AL = Numr/Divr;
  2977. AH = Numr%Divr;
  2978. }
  2979. }
  2980. /***************************************************************************/
  2981. static VOID InstSegmentOveride()
  2982. {
  2983. SegmentOveridePrefix = TRUE;
  2984. OverideSegmentRegister = LSRC->Register16;
  2985. }
  2986. /***************************************************************************/
  2987. //
  2988. // Most of the 80286 Protected Mode Instructions are sent to this function.
  2989. // Most of these instructions are unimplemented because they are not
  2990. // normally used, and hence are difficult to test. So far, I have not seen
  2991. // any addin card BIOS's use these instructions.
  2992. //
  2993. static VOID InstDescriptorTable()
  2994. {
  2995. if (ExtendedOperationCodeByte==0x00)
  2996. {
  2997. switch(reg)
  2998. {
  2999. case 0 : DISPLAY("SLDT");
  3000. break;
  3001. case 1 : DISPLAY("STR");
  3002. break;
  3003. case 2 : DISPLAY("LLDT");
  3004. break;
  3005. case 3 : DISPLAY("LTR");
  3006. break;
  3007. case 4 : DISPLAY("VERR read");
  3008. break;
  3009. case 5 : DISPLAY("VERR write");
  3010. break;
  3011. default : DISPLAY("Unknown Instruction");
  3012. break;
  3013. }
  3014. }
  3015. else if (ExtendedOperationCodeByte==0x01)
  3016. {
  3017. switch(reg)
  3018. {
  3019. case 0 : PutOperand(LSRC,0,gdtLimit);
  3020. PutOperand(LSRC,2,(gdtBase & 0x00ffffff));
  3021. PutOperand(LSRC,4,((gdtBase & 0x00ffffff) | 0xff000000)>>16);
  3022. return;
  3023. case 1 : DISPLAY("SIDT");
  3024. PutOperand(LSRC,0,idtLimit);
  3025. PutOperand(LSRC,2,(idtBase & 0x00ffffff));
  3026. PutOperand(LSRC,4,((idtBase & 0x00ffffff) | 0xff000000)>>16);
  3027. break;
  3028. case 2 : gdtLimit = GetOperand(LSRC,0);
  3029. gdtBase = (GetOperand(LSRC,2) | (GetOperand(LSRC,4)<<16)) & 0x00ffffff;
  3030. return;
  3031. case 3 : idtLimit = GetOperand(LSRC,0);
  3032. idtBase = (GetOperand(LSRC,2) | (GetOperand(LSRC,4)<<16)) & 0x00ffffff;
  3033. return;
  3034. case 4 : PutOperand(LSRC,0,msw);
  3035. return;
  3036. case 6 : msw = GetOperand(LSRC,0);
  3037. return;
  3038. default : DISPLAY("Unknown Instruction");
  3039. break;
  3040. }
  3041. }
  3042. else if (ExtendedOperationCodeByte==0x02)
  3043. {
  3044. DISPLAY("LAR");
  3045. }
  3046. else if (ExtendedOperationCodeByte==0x03)
  3047. {
  3048. DISPLAY("LSL");
  3049. }
  3050. else if (ExtendedOperationCodeByte==0x06)
  3051. {
  3052. DISPLAY("CTS");
  3053. }
  3054. else if (ExtendedOperationCodeByte==0x63)
  3055. {
  3056. DISPLAY("ARPL");
  3057. }
  3058. else
  3059. {
  3060. DISPLAY("Unknown Instruction");
  3061. }
  3062. DISPLAY("\n\r");
  3063. InstInvalid();
  3064. }
  3065. /***************************************************************************/
  3066. VOID InstENTER()
  3067. {
  3068. ULONG Left;
  3069. ULONG Right;
  3070. Left = GetOperand(LSRC,0);
  3071. Right = GetOperand(RSRC,0);
  3072. if (Right==0)
  3073. {
  3074. SP = SP - 2;
  3075. PutStackMem(SP+0,BP);
  3076. PutStackMem(SP+1,BP>>8);
  3077. BP = SP;
  3078. SP = SP - Left;
  3079. }
  3080. else
  3081. {
  3082. DISPLAY("ENTER with L!=0\n\r");
  3083. ErrorCode = x86BiosInvalidInstruction;
  3084. ExitFlag = TRUE;
  3085. }
  3086. }
  3087. /***************************************************************************/
  3088. VOID InstLEAVE()
  3089. {
  3090. SP = BP;
  3091. BP = GetStackMem(SP+0) | (GetStackMem(SP+1)<<8);
  3092. SP = SP + 2;
  3093. }
  3094. /***************************************************************************/
  3095. /*++
  3096. Address Decoding Tables:
  3097. The size of the address decoding table was reduced by defining 8 bit
  3098. tokens for the different address decoding functions. These tokens
  3099. are stored in the address decoding table. When an instruction is
  3100. being decoded, a token will be retrieved for the left operand and for
  3101. the right operand. The DecodeOperandFunctionTable[] is used to
  3102. convert this 8 bit token to a function pointer which can be called.
  3103. The AddressModeByteRequired[] table is used to identify which address
  3104. modes require and address mode byte to be parsed from an instruction.
  3105. If either the left operand or the right operand use an address mode
  3106. for which AddressModeByteRequired[] is true, then the second byte of
  3107. the instruction is an address mode byte.
  3108. --*/
  3109. #define NULL_OPERAND 0
  3110. #define REG8_MEM8 1 // AddressModeByte required
  3111. #define REG16_MEM16 2 // AddressModeByte required
  3112. #define REG8 3 // AddressModeByte required
  3113. #define REG16 4 // AddressModeByte required
  3114. #define SEGREG 5 // AddressModeByte required
  3115. #define EMBEDDED_REG8 6
  3116. #define EMBEDDED_REG16 7
  3117. #define ACC8 8
  3118. #define ACC16 9
  3119. #define IMMED8 10
  3120. #define IMMED8_SX 11
  3121. #define IMMED16 12
  3122. #define SHORT_LABEL 13
  3123. #define IMMED32 14
  3124. #define MEM8 15
  3125. #define MEM16 16
  3126. #define CONST_1 17
  3127. #define REG_CL 18
  3128. #define REG_DX 19
  3129. #define STRING8_DSSI 20
  3130. #define STRING16_DSSI 21
  3131. #define STRING8_ESDI 22
  3132. #define STRING16_ESDI 23
  3133. #define REG_ES 24
  3134. #define REG_DS 25
  3135. #define REG_SS 26
  3136. #define REG_CS 27
  3137. static const UCHAR AddressModeByteRequired[28] = {0,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
  3138. static const VOID (*DecodeOperandFunctionTable[28])() =
  3139. {
  3140. NullFunction,
  3141. GetMemory8OrRegister8Operand,
  3142. GetMemory16OrRegister16Operand,
  3143. GetRegister8Operand,
  3144. GetRegister16Operand,
  3145. GetSegmentRegisterOperand,
  3146. GetEmbeddedRegister8Operand,
  3147. GetEmbeddedRegister16Operand,
  3148. GetAccumulator8Operand,
  3149. GetAccumulator16Operand,
  3150. GetImmediate8Operand,
  3151. GetImmediateSignExtend8Operand,
  3152. GetImmediate16Operand,
  3153. GetShortLabelOperand,
  3154. GetImmediate32Operand,
  3155. GetMemory8Operand,
  3156. GetMemory16Operand,
  3157. GetConstantOneOperand,
  3158. GetRegisterCLOperand,
  3159. GetRegisterDXOperand,
  3160. GetString8DSSIOperand,
  3161. GetString16DSSIOperand,
  3162. GetString8ESDIOperand,
  3163. GetString16ESDIOperand,
  3164. GetRegisterESOperand,
  3165. GetRegisterDSOperand,
  3166. GetRegisterSSOperand,
  3167. GetRegisterCSOperand
  3168. };
  3169. static const UCHAR DecodeOperandsTable[256][2] =
  3170. {
  3171. { REG8_MEM8 , REG8 }, // 00 ADD
  3172. { REG16_MEM16 , REG16 }, // 01 ADD
  3173. { REG8 , REG8_MEM8 }, // 02 ADD
  3174. { REG16 , REG16_MEM16 }, // 03 ADD
  3175. { ACC8 , IMMED8 }, // 04 ADD
  3176. { ACC16 , IMMED16 }, // 05 ADD
  3177. { REG_ES , NULL_OPERAND }, // 06 PUSH ES
  3178. { REG_ES , NULL_OPERAND }, // 07 POP ES
  3179. { REG8_MEM8 , REG8 }, // 08 OR
  3180. { REG16_MEM16 , REG16 }, // 09 OR
  3181. { REG8 , REG8_MEM8 }, // 0A OR
  3182. { REG16 , REG16_MEM16 }, // 0B OR
  3183. { ACC8 , IMMED8 }, // 0C OR
  3184. { ACC16 , IMMED16 }, // 0D OR
  3185. { REG_CS , NULL_OPERAND }, // 0E PUSH CS
  3186. { NULL_OPERAND , NULL_OPERAND }, // 0F 286 Extended Operation Codes
  3187. { REG8_MEM8 , REG8 }, // 10 ADC
  3188. { REG16_MEM16 , REG16 }, // 11 ADC
  3189. { REG8 , REG8_MEM8 }, // 12 ADC
  3190. { REG16 , REG16_MEM16 }, // 13 ADC
  3191. { ACC8 , IMMED8 }, // 14 ADC
  3192. { ACC16 , IMMED16 }, // 15 ADC
  3193. { REG_SS , NULL_OPERAND }, // 16 PUSH SS
  3194. { REG_SS , NULL_OPERAND }, // 17 POP SS
  3195. { REG8_MEM8 , REG8 }, // 18 SBB
  3196. { REG16_MEM16 , REG16 }, // 19 SBB
  3197. { REG8 , REG8_MEM8 }, // 1A SBB
  3198. { REG16 , REG16_MEM16 }, // 1B SBB
  3199. { ACC8 , IMMED8 }, // 1C SBB
  3200. { ACC16 , IMMED16 }, // 1D SBB
  3201. { REG_DS , NULL_OPERAND }, // 1E PUSH DS
  3202. { REG_DS , NULL_OPERAND }, // 1F POP DS
  3203. { REG8_MEM8 , REG8 }, // 20 AND
  3204. { REG16_MEM16 , REG16 }, // 21 AND
  3205. { REG8 , REG8_MEM8 }, // 22 ANC
  3206. { REG16 , REG16_MEM16 }, // 23 AND
  3207. { ACC8 , IMMED8 }, // 24 AND
  3208. { ACC16 , IMMED16 }, // 25 AND
  3209. { REG_ES , NULL_OPERAND }, // 26 ES: (segment overide)
  3210. { NULL_OPERAND , NULL_OPERAND }, // 27 DAA
  3211. { REG8_MEM8 , REG8 }, // 28 SUB
  3212. { REG16_MEM16 , REG16 }, // 29 SUB
  3213. { REG8 , REG8_MEM8 }, // 2A SUB
  3214. { REG16 , REG16_MEM16 }, // 2B SUB
  3215. { ACC8 , IMMED8 }, // 2C SUB
  3216. { ACC16 , IMMED16 }, // 2D SUB
  3217. { REG_CS , NULL_OPERAND }, // 2E CS: (segment overide)
  3218. { NULL_OPERAND , NULL_OPERAND }, // 2F DAS
  3219. { REG8_MEM8 , REG8 }, // 30 XOR
  3220. { REG16_MEM16 , REG16 }, // 31 XOR
  3221. { REG8 , REG8_MEM8 }, // 32 XOR
  3222. { REG16 , REG16_MEM16 }, // 33 XOR
  3223. { ACC8 , IMMED8 }, // 34 XOR
  3224. { ACC16 , IMMED16 }, // 35 XOR
  3225. { REG_SS , NULL_OPERAND }, // 36 SS: (segment overide)
  3226. { NULL_OPERAND , NULL_OPERAND }, // 37 AAA
  3227. { REG8_MEM8 , REG8 }, // 38 CMP
  3228. { REG16_MEM16 , REG16 }, // 39 CMP
  3229. { REG8 , REG8_MEM8 }, // 3A CMP
  3230. { REG16 , REG16_MEM16 }, // 3B CMP
  3231. { ACC8 , IMMED8 }, // 3C CMP
  3232. { ACC16 , IMMED16 }, // 3D CMP
  3233. { REG_DS , NULL_OPERAND }, // 3E DS: (segment overide)
  3234. { NULL_OPERAND , NULL_OPERAND }, // 3F AAS
  3235. { EMBEDDED_REG16 , NULL_OPERAND }, // 40 INC
  3236. { EMBEDDED_REG16 , NULL_OPERAND }, // 41 INC
  3237. { EMBEDDED_REG16 , NULL_OPERAND }, // 42 INC
  3238. { EMBEDDED_REG16 , NULL_OPERAND }, // 43 INC
  3239. { EMBEDDED_REG16 , NULL_OPERAND }, // 44 INC
  3240. { EMBEDDED_REG16 , NULL_OPERAND }, // 45 INC
  3241. { EMBEDDED_REG16 , NULL_OPERAND }, // 46 INC
  3242. { EMBEDDED_REG16 , NULL_OPERAND }, // 47 INC
  3243. { EMBEDDED_REG16 , NULL_OPERAND }, // 48 DEC
  3244. { EMBEDDED_REG16 , NULL_OPERAND }, // 49 DEC
  3245. { EMBEDDED_REG16 , NULL_OPERAND }, // 4A DEC
  3246. { EMBEDDED_REG16 , NULL_OPERAND }, // 4B DEC
  3247. { EMBEDDED_REG16 , NULL_OPERAND }, // 4C DEC
  3248. { EMBEDDED_REG16 , NULL_OPERAND }, // 4D DEC
  3249. { EMBEDDED_REG16 , NULL_OPERAND }, // 4E DEC
  3250. { EMBEDDED_REG16 , NULL_OPERAND }, // 4F DEC
  3251. { EMBEDDED_REG16 , NULL_OPERAND }, // 50 PUSH
  3252. { EMBEDDED_REG16 , NULL_OPERAND }, // 51 PUSH
  3253. { EMBEDDED_REG16 , NULL_OPERAND }, // 52 PUSH
  3254. { EMBEDDED_REG16 , NULL_OPERAND }, // 53 PUSH
  3255. { EMBEDDED_REG16 , NULL_OPERAND }, // 54 PUSH
  3256. { EMBEDDED_REG16 , NULL_OPERAND }, // 55 PUSH
  3257. { EMBEDDED_REG16 , NULL_OPERAND }, // 56 PUSH
  3258. { EMBEDDED_REG16 , NULL_OPERAND }, // 57 PUSH
  3259. { EMBEDDED_REG16 , NULL_OPERAND }, // 58 POP
  3260. { EMBEDDED_REG16 , NULL_OPERAND }, // 59 POP
  3261. { EMBEDDED_REG16 , NULL_OPERAND }, // 5A POP
  3262. { EMBEDDED_REG16 , NULL_OPERAND }, // 5B POP
  3263. { EMBEDDED_REG16 , NULL_OPERAND }, // 5C POP
  3264. { EMBEDDED_REG16 , NULL_OPERAND }, // 5D POP
  3265. { EMBEDDED_REG16 , NULL_OPERAND }, // 5E POP
  3266. { EMBEDDED_REG16 , NULL_OPERAND }, // 5F POP
  3267. { NULL_OPERAND , NULL_OPERAND }, // 60 PUSHA
  3268. { NULL_OPERAND , NULL_OPERAND }, // 61 POPA
  3269. { NULL_OPERAND , NULL_OPERAND }, // 62 (not used)
  3270. { NULL_OPERAND , NULL_OPERAND }, // 63 (not used)
  3271. { NULL_OPERAND , NULL_OPERAND }, // 64 (not used)
  3272. { NULL_OPERAND , NULL_OPERAND }, // 65 (not used)
  3273. { NULL_OPERAND , NULL_OPERAND }, // 66 (not used)
  3274. { NULL_OPERAND , NULL_OPERAND }, // 67 (not used)
  3275. { IMMED16 , NULL_OPERAND }, // 68 PUSH
  3276. { REG16_MEM16 , IMMED16 }, // 69 IMUL
  3277. { IMMED8_SX , NULL_OPERAND }, // 6A PUSH
  3278. { REG16_MEM16 , IMMED8_SX }, // 6B IMUL
  3279. { STRING8_ESDI , REG_DX }, // 6C INS
  3280. { STRING16_ESDI , REG_DX }, // 6D INS
  3281. { STRING8_DSSI , REG_DX }, // 6E OUTS
  3282. { STRING16_DSSI , REG_DX }, // 6F OUTS
  3283. { SHORT_LABEL , NULL_OPERAND }, // 70 JO
  3284. { SHORT_LABEL , NULL_OPERAND }, // 71 JNO
  3285. { SHORT_LABEL , NULL_OPERAND }, // 72 JB
  3286. { SHORT_LABEL , NULL_OPERAND }, // 73 JNB
  3287. { SHORT_LABEL , NULL_OPERAND }, // 74 JE
  3288. { SHORT_LABEL , NULL_OPERAND }, // 75 JNE
  3289. { SHORT_LABEL , NULL_OPERAND }, // 76 JBE
  3290. { SHORT_LABEL , NULL_OPERAND }, // 77 JNBE
  3291. { SHORT_LABEL , NULL_OPERAND }, // 78 JS
  3292. { SHORT_LABEL , NULL_OPERAND }, // 79 JNS
  3293. { SHORT_LABEL , NULL_OPERAND }, // 7A JP
  3294. { SHORT_LABEL , NULL_OPERAND }, // 7B JNP
  3295. { SHORT_LABEL , NULL_OPERAND }, // 7C JL
  3296. { SHORT_LABEL , NULL_OPERAND }, // 7D JNL
  3297. { SHORT_LABEL , NULL_OPERAND }, // 7E JLE
  3298. { SHORT_LABEL , NULL_OPERAND }, // 7F JNLE
  3299. { REG8_MEM8 , IMMED8 }, // 80 ADD/OR/ADC/SBB/AND/SUB/XOR/CMP
  3300. { REG16_MEM16 , IMMED16 }, // 81 ADD/OR/ADC/SBB/AND/SUB/XOR/CMP
  3301. { REG8_MEM8 , IMMED8 }, // 82 ADD/OR/ADC/SBB/AND/SUB/XOR/CMP
  3302. { REG16_MEM16 , IMMED8_SX }, // 83 ADD/OR/ADC/SBB/AND/SUB/XOR/CMP
  3303. { REG8_MEM8 , REG8 }, // 84 TEST
  3304. { REG16_MEM16 , REG16 }, // 85 TEST
  3305. { REG8_MEM8 , REG8 }, // 86 XCHG
  3306. { REG16_MEM16 , REG16 }, // 87 XCHG
  3307. { REG8_MEM8 , REG8 }, // 88 MOV
  3308. { REG16_MEM16 , REG16 }, // 89 MOV
  3309. { REG8 , REG8_MEM8 }, // 8A MOV
  3310. { REG16 , REG16_MEM16 }, // 8B MOV
  3311. { REG16_MEM16 , SEGREG }, // 8C MOV
  3312. { REG16 , REG16_MEM16 }, // 8D LEA
  3313. { SEGREG , REG16_MEM16 }, // 8E MOV
  3314. { REG16_MEM16 , NULL_OPERAND }, // 8F POP
  3315. { ACC16 , EMBEDDED_REG16 }, // 90 XCHG
  3316. { ACC16 , EMBEDDED_REG16 }, // 91 XCHG
  3317. { ACC16 , EMBEDDED_REG16 }, // 92 XCHG
  3318. { ACC16 , EMBEDDED_REG16 }, // 93 XCHG
  3319. { ACC16 , EMBEDDED_REG16 }, // 94 XCHG
  3320. { ACC16 , EMBEDDED_REG16 }, // 95 XCHG
  3321. { ACC16 , EMBEDDED_REG16 }, // 96 XCHG
  3322. { ACC16 , EMBEDDED_REG16 }, // 97 XCHG
  3323. { NULL_OPERAND , NULL_OPERAND }, // 98 CBW
  3324. { NULL_OPERAND , NULL_OPERAND }, // 99 CWD
  3325. { IMMED32 , NULL_OPERAND }, // 9A CALL
  3326. { NULL_OPERAND , NULL_OPERAND }, // 9B WAIT
  3327. { NULL_OPERAND , NULL_OPERAND }, // 9C PUSHF
  3328. { NULL_OPERAND , NULL_OPERAND }, // 9D POPF
  3329. { NULL_OPERAND , NULL_OPERAND }, // 9E SAHF
  3330. { NULL_OPERAND , NULL_OPERAND }, // 9F LAHF
  3331. { ACC8 , MEM8 }, // A0 MOV
  3332. { ACC16 , MEM16 }, // A1 MOV
  3333. { MEM8 , ACC8 }, // A2 MOV
  3334. { MEM16 , ACC16 }, // A3 MOV
  3335. { STRING8_ESDI , STRING8_DSSI }, // A4 MOVS
  3336. { STRING16_ESDI , STRING16_DSSI }, // A5 MOVS
  3337. { STRING8_ESDI , STRING8_DSSI }, // A6 CMPS
  3338. { STRING16_ESDI , STRING16_DSSI }, // A7 CMPS
  3339. { ACC8 , IMMED8 }, // A8 TEST
  3340. { ACC16 , IMMED16 }, // A9 TEST
  3341. { STRING8_ESDI , ACC8 }, // AA STOS
  3342. { STRING16_ESDI , ACC16 }, // AB STOS
  3343. { ACC8 , STRING8_DSSI }, // AC LODS
  3344. { ACC16 , STRING16_DSSI }, // AD LODS
  3345. { ACC8 , STRING8_ESDI }, // AE SCAS
  3346. { ACC16 , STRING16_ESDI }, // AF SCAS
  3347. { EMBEDDED_REG8 , IMMED8 }, // B0 MOV
  3348. { EMBEDDED_REG8 , IMMED8 }, // B1 MOV
  3349. { EMBEDDED_REG8 , IMMED8 }, // B2 MOV
  3350. { EMBEDDED_REG8 , IMMED8 }, // B3 MOV
  3351. { EMBEDDED_REG8 , IMMED8 }, // B4 MOV
  3352. { EMBEDDED_REG8 , IMMED8 }, // B5 MOV
  3353. { EMBEDDED_REG8 , IMMED8 }, // B6 MOV
  3354. { EMBEDDED_REG8 , IMMED8 }, // B7 MOV
  3355. { EMBEDDED_REG16 , IMMED16 }, // B8 MOV
  3356. { EMBEDDED_REG16 , IMMED16 }, // B9 MOV
  3357. { EMBEDDED_REG16 , IMMED16 }, // BA MOV
  3358. { EMBEDDED_REG16 , IMMED16 }, // BB MOV
  3359. { EMBEDDED_REG16 , IMMED16 }, // BC MOV
  3360. { EMBEDDED_REG16 , IMMED16 }, // BD MOV
  3361. { EMBEDDED_REG16 , IMMED16 }, // BE MOV
  3362. { EMBEDDED_REG16 , IMMED16 }, // BF MOV
  3363. { REG8_MEM8 , IMMED8 }, // C0 (286) ROL/ROR/RCL/RCR/SAL/SHR/SAR
  3364. { REG16_MEM16 , IMMED8 }, // C1 (286) ROL/ROR/RCL/RCR/SAL/SHR/SAR
  3365. { IMMED16 , NULL_OPERAND }, // C2 RET
  3366. { NULL_OPERAND , NULL_OPERAND }, // C3 RET
  3367. { REG16 , REG16_MEM16 }, // C4 LES
  3368. { REG16 , REG16_MEM16 }, // C5 LDS
  3369. { REG8_MEM8 , IMMED8 }, // C6 MOV
  3370. { REG16_MEM16 , IMMED16 }, // C7 MOV
  3371. { IMMED16 , IMMED8 }, // C8 ENTER
  3372. { NULL_OPERAND , NULL_OPERAND }, // C9 LEAVE
  3373. { IMMED16 , NULL_OPERAND }, // CA RET
  3374. { NULL_OPERAND , NULL_OPERAND }, // CB RET
  3375. { NULL_OPERAND , NULL_OPERAND }, // CC INT 3
  3376. { IMMED8 , NULL_OPERAND }, // CD INT
  3377. { NULL_OPERAND , NULL_OPERAND }, // CE INTO
  3378. { NULL_OPERAND , NULL_OPERAND }, // CF IRET
  3379. { REG8_MEM8 , CONST_1 }, // D0 ROL/ROR/RCL/RCR/SAL/SHR/SAR
  3380. { REG16_MEM16 , CONST_1 }, // D1 ROL/ROR/RCL/RCR/SAL/SHR/SAR
  3381. { REG8_MEM8 , REG_CL }, // D2 ROL/ROR/RCL/RCR/SAL/SHR/SAR
  3382. { REG16_MEM16 , REG_CL }, // D3 ROL/ROR/RCL/RCR/SAL/SHR/SAR
  3383. { IMMED8 , NULL_OPERAND }, // D4 AAM
  3384. { IMMED8 , NULL_OPERAND }, // D5 AAD
  3385. { NULL_OPERAND , NULL_OPERAND }, // D6 (not used)
  3386. { NULL_OPERAND , NULL_OPERAND }, // D7 XLAT
  3387. { IMMED8 , NULL_OPERAND }, // D8 ESC
  3388. { REG16_MEM16 , NULL_OPERAND }, // D9 ESC
  3389. { REG16_MEM16 , NULL_OPERAND }, // DA ESC
  3390. { REG16_MEM16 , NULL_OPERAND }, // DB ESC
  3391. { REG16_MEM16 , NULL_OPERAND }, // DC ESC
  3392. { REG16_MEM16 , NULL_OPERAND }, // DD ESC
  3393. { REG16_MEM16 , NULL_OPERAND }, // DE ESC
  3394. { IMMED8 , NULL_OPERAND }, // DF ESC
  3395. { SHORT_LABEL , NULL_OPERAND }, // E0 LOOPNE
  3396. { SHORT_LABEL , NULL_OPERAND }, // E1 LOOPE
  3397. { SHORT_LABEL , NULL_OPERAND }, // E2 LOOP
  3398. { SHORT_LABEL , NULL_OPERAND }, // E3 JCXZ
  3399. { ACC8 , IMMED8 }, // E4 IN
  3400. { ACC16 , IMMED8 }, // E5 IN
  3401. { ACC8 , IMMED8 }, // E6 OUT
  3402. { ACC16 , IMMED8 }, // E7 OUT
  3403. { IMMED16 , NULL_OPERAND }, // E8 CALL
  3404. { IMMED16 , NULL_OPERAND }, // E9 JMP
  3405. { IMMED32 , NULL_OPERAND }, // EA JMP
  3406. { SHORT_LABEL , NULL_OPERAND }, // EB JMP
  3407. { ACC8 , REG_DX }, // EC IN
  3408. { ACC16 , REG_DX }, // ED IN
  3409. { ACC8 , REG_DX }, // EE OUT
  3410. { ACC16 , REG_DX }, // EF OUT
  3411. { NULL_OPERAND , NULL_OPERAND }, // F0 LOCK
  3412. { NULL_OPERAND , NULL_OPERAND }, // F1 (not used)
  3413. { NULL_OPERAND , NULL_OPERAND }, // F2 REPNE
  3414. { NULL_OPERAND , NULL_OPERAND }, // F3 REPE
  3415. { NULL_OPERAND , NULL_OPERAND }, // F4 HLT
  3416. { NULL_OPERAND , NULL_OPERAND }, // F5 CMC
  3417. { REG8_MEM8 , NULL_OPERAND }, // F6 TEST/NOT/NEG/MUL/IMUL/DIV/IDIV/TEST
  3418. { REG16_MEM16 , NULL_OPERAND }, // F7 TEST/NOT/NEG/MUL/IMUL/DIV/IDIV/TEST
  3419. { NULL_OPERAND , NULL_OPERAND }, // F8 CLC
  3420. { NULL_OPERAND , NULL_OPERAND }, // F9 STC
  3421. { NULL_OPERAND , NULL_OPERAND }, // FA CLI
  3422. { NULL_OPERAND , NULL_OPERAND }, // FB STI
  3423. { NULL_OPERAND , NULL_OPERAND }, // FC CLD
  3424. { NULL_OPERAND , NULL_OPERAND }, // FD STD
  3425. { REG8_MEM8 , NULL_OPERAND }, // FE INC/DEC
  3426. { REG16_MEM16 , NULL_OPERAND } // FF INC/DEC/CALL/JMP/PUSH
  3427. };
  3428. /*++
  3429. Instruction Decoding Tables:
  3430. The size of the instruction decoding table was reduced by defining 8 bit
  3431. tokens for the different instruction functions. These tokens are stored
  3432. in the instruction decoding table. When an instruction is being decoded,
  3433. a token will be retrieved. For instructions without address mode bytes,
  3434. the first token for that instruction will be retrieved. For instructions
  3435. with address mode byes, bits 3-5 of the address mode byte will be used
  3436. as a sub index into the instruction decoding table. This table has 256
  3437. rows for each possible operation code value, and is 8 columns wide for
  3438. each of the 8 possible values for bits 3-5 of the address mode byte.
  3439. Once an instruction token has been retrieved, the
  3440. DecodeInstructionFunctionTable[] can be used to convert the token to a
  3441. function pointer. This function is called to execute the instruction.
  3442. --*/
  3443. #define NUMINSTRUCTIONTYPES 105
  3444. #define INST_INV 0
  3445. #define INST_ADD 1
  3446. #define INST_PUSH 2
  3447. #define INST_POP 3
  3448. #define INST_OR 4
  3449. #define INST_ADC 5
  3450. #define INST_SBB 6
  3451. #define INST_AND 7
  3452. #define INST_ES_ 8
  3453. #define INST_DAA 9
  3454. #define INST_SUB 10
  3455. #define INST_CS_ 11
  3456. #define INST_DAS 12
  3457. #define INST_XOR 13
  3458. #define INST_SS_ 14
  3459. #define INST_AAA 15
  3460. #define INST_CMP 16
  3461. #define INST_DS_ 17
  3462. #define INST_AAS 18
  3463. #define INST_INC 19
  3464. #define INST_DEC 20
  3465. #define INST_JO 21
  3466. #define INST_JNO 22
  3467. #define INST_JB 23
  3468. #define INST_JNB 24
  3469. #define INST_JE 25
  3470. #define INST_JNE 26
  3471. #define INST_JBE 27
  3472. #define INST_JNBE 28
  3473. #define INST_JS 29
  3474. #define INST_JNS 30
  3475. #define INST_JP 31
  3476. #define INST_JNP 32
  3477. #define INST_JL 33
  3478. #define INST_JNL 34
  3479. #define INST_JLE 35
  3480. #define INST_JNLE 36
  3481. #define INST_TEST 37
  3482. #define INST_XCHG 38
  3483. #define INST_MOV 39
  3484. #define INST_LEA 40
  3485. #define INST_CBW 41
  3486. #define INST_CWD 42
  3487. #define INST_CALL 43
  3488. #define INST_WAIT 44
  3489. #define INST_PUSHF 45
  3490. #define INST_POPF 46
  3491. #define INST_SAHF 47
  3492. #define INST_LAHF 48
  3493. #define INST_MOVS 49
  3494. #define INST_CMPS 50
  3495. #define INST_STOS 51
  3496. #define INST_LODS 52
  3497. #define INST_SCAS 53
  3498. #define INST_RET 54
  3499. #define INST_LES 55
  3500. #define INST_LDS 56
  3501. #define INST_INT 57
  3502. #define INST_INTO 58
  3503. #define INST_IRET 59
  3504. #define INST_ROL 60
  3505. #define INST_ROR 61
  3506. #define INST_RCL 62
  3507. #define INST_RCR 63
  3508. #define INST_SAL 64
  3509. #define INST_SHR 65
  3510. #define INST_SAR 66
  3511. #define INST_AAM 67
  3512. #define INST_AAD 68
  3513. #define INST_XLAT 69
  3514. #define INST_ESC 70
  3515. #define INST_LOOPNE 71
  3516. #define INST_LOOPE 72
  3517. #define INST_LOOP 73
  3518. #define INST_JCXZ 74
  3519. #define INST_IN 75
  3520. #define INST_OUT 76
  3521. #define INST_LOCK 77
  3522. #define INST_REP 78
  3523. #define INST_HLT 79
  3524. #define INST_CMC 80
  3525. #define INST_NOT 81
  3526. #define INST_NEG 82
  3527. #define INST_MUL 83
  3528. #define INST_IMUL 84
  3529. #define INST_DIV 85
  3530. #define INST_IDIV 86
  3531. #define INST_CLC 87
  3532. #define INST_STC 88
  3533. #define INST_CLI 89
  3534. #define INST_STI 90
  3535. #define INST_CLD 91
  3536. #define INST_STD 92
  3537. #define INST_JMP 93
  3538. #define INST_SEG 94
  3539. #define INST_PUSHA 95
  3540. #define INST_POPA 96
  3541. #define INST_DT 97
  3542. #define INST_OUTS 98
  3543. #define INST_ENTER 99
  3544. #define INST_LEAVE 100
  3545. #define INST_INS 101
  3546. #ifdef X86DEBUG
  3547. static const UCHAR *InstructionNames[NUMINSTRUCTIONTYPES] =
  3548. {
  3549. "Invalid ",
  3550. "ADD ",
  3551. "PUSH ",
  3552. "POP ",
  3553. "OR ",
  3554. "ADC ",
  3555. "SBB ",
  3556. "AND ",
  3557. "ES: ",
  3558. "DAA ",
  3559. "SUB ",
  3560. "CS: ",
  3561. "DAS ",
  3562. "XOR ",
  3563. "SS: ",
  3564. "AAA ",
  3565. "CMP ",
  3566. "DS: ",
  3567. "AAS ",
  3568. "INC ",
  3569. "DEC ",
  3570. "JO ",
  3571. "JNO ",
  3572. "JB ",
  3573. "JNB ",
  3574. "JE ",
  3575. "JNE ",
  3576. "JBE ",
  3577. "JNBE ",
  3578. "JS ",
  3579. "JNS ",
  3580. "JP ",
  3581. "JNP ",
  3582. "JL ",
  3583. "JNL ",
  3584. "JLE ",
  3585. "JNLE ",
  3586. "TEST ",
  3587. "XCHG ",
  3588. "MOV ",
  3589. "LEA ",
  3590. "CBW ",
  3591. "CWD ",
  3592. "CALL ",
  3593. "WAIT ",
  3594. "PUSHF ",
  3595. "POPF ",
  3596. "SAHF ",
  3597. "LAHF ",
  3598. "MOVS ",
  3599. "CMPS ",
  3600. "STOS ",
  3601. "LODS ",
  3602. "SCAS ",
  3603. "RET ",
  3604. "LES ",
  3605. "LDS ",
  3606. "INT ",
  3607. "INTO ",
  3608. "IRET ",
  3609. "ROL ",
  3610. "ROR ",
  3611. "RCL ",
  3612. "RCR ",
  3613. "SAL ",
  3614. "SHR ",
  3615. "SAR ",
  3616. "AAM ",
  3617. "AAD ",
  3618. "XLAT ",
  3619. "ESC ",
  3620. "LOOPNE ",
  3621. "LOOPE ",
  3622. "LOOP ",
  3623. "JCXZ ",
  3624. "IN ",
  3625. "OUT ",
  3626. "LOCK ",
  3627. "REP ",
  3628. "HLT ",
  3629. "CMC ",
  3630. "NOT ",
  3631. "NEG ",
  3632. "MUL ",
  3633. "IMUL ",
  3634. "DIV ",
  3635. "IDIV ",
  3636. "CLC ",
  3637. "STC ",
  3638. "CLI ",
  3639. "STI ",
  3640. "CLD ",
  3641. "STD ",
  3642. "JMP ",
  3643. " ",
  3644. "PUSHA ",
  3645. "POPA ",
  3646. "286DT ",
  3647. "OUTS ",
  3648. "ENTER ",
  3649. "LEAVE ",
  3650. "INS ",
  3651. };
  3652. #endif
  3653. static const VOID (*DecodeInstructionFunctionTable[NUMINSTRUCTIONTYPES])() =
  3654. {
  3655. InstInvalid,
  3656. InstADD,
  3657. InstPUSH,
  3658. InstPOP,
  3659. InstOR,
  3660. InstADC,
  3661. InstSBB,
  3662. InstAND,
  3663. NULL,
  3664. InstDAA,
  3665. InstSUB,
  3666. NULL,
  3667. InstDAS,
  3668. InstXOR,
  3669. NULL,
  3670. InstAAA,
  3671. InstCMP,
  3672. NULL,
  3673. InstAAS,
  3674. InstINC,
  3675. InstDEC,
  3676. InstJO,
  3677. InstJNO,
  3678. InstJB,
  3679. InstJNB,
  3680. InstJE,
  3681. InstJNE,
  3682. InstJBE,
  3683. InstJNBE,
  3684. InstJS,
  3685. InstJNS,
  3686. InstJP,
  3687. InstJNP,
  3688. InstJL,
  3689. InstJNL,
  3690. InstJLE,
  3691. InstJNLE,
  3692. InstTEST,
  3693. InstXCHG,
  3694. InstMOV,
  3695. InstLEA,
  3696. InstCBW,
  3697. InstCWD,
  3698. InstCALL,
  3699. InstWAIT,
  3700. InstPUSHF,
  3701. InstPOPF,
  3702. InstSAHF,
  3703. InstLAHF,
  3704. InstMOVS,
  3705. InstCMPS,
  3706. InstSTOS,
  3707. InstLODS,
  3708. InstSCAS,
  3709. InstRET,
  3710. InstLES,
  3711. InstLDS,
  3712. InstINT,
  3713. InstINTO,
  3714. InstIRET,
  3715. InstROL,
  3716. InstROR,
  3717. InstRCL,
  3718. InstRCR,
  3719. InstSAL,
  3720. InstSHR,
  3721. InstSAR,
  3722. InstAAM,
  3723. InstAAD,
  3724. InstXLAT,
  3725. InstESC,
  3726. InstLOOPNE,
  3727. InstLOOPE,
  3728. InstLOOP,
  3729. InstJCXZ,
  3730. InstIN,
  3731. InstOUT,
  3732. InstLOCK,
  3733. InstREP,
  3734. InstHLT,
  3735. InstCMC,
  3736. InstNOT,
  3737. InstNEG,
  3738. InstMUL,
  3739. InstIMUL,
  3740. InstDIV,
  3741. InstIDIV,
  3742. InstCLC,
  3743. InstSTC,
  3744. InstCLI,
  3745. InstSTI,
  3746. InstCLD,
  3747. InstSTD,
  3748. InstJMP,
  3749. InstSegmentOveride,
  3750. InstPUSHA,
  3751. InstPOPA,
  3752. InstDescriptorTable,
  3753. InstOUTS,
  3754. InstENTER,
  3755. InstLEAVE,
  3756. InstINS,
  3757. };
  3758. static const UCHAR DecodeInstructionTable[256][8] =
  3759. {
  3760. { INST_ADD , INST_ADD , INST_ADD , INST_ADD , INST_ADD , INST_ADD , INST_ADD , INST_ADD } , // 00
  3761. { INST_ADD , INST_ADD , INST_ADD , INST_ADD , INST_ADD , INST_ADD , INST_ADD , INST_ADD } , // 01
  3762. { INST_ADD , INST_ADD , INST_ADD , INST_ADD , INST_ADD , INST_ADD , INST_ADD , INST_ADD } , // 02
  3763. { INST_ADD , INST_ADD , INST_ADD , INST_ADD , INST_ADD , INST_ADD , INST_ADD , INST_ADD } , // 03
  3764. { INST_ADD , INST_ADD , INST_ADD , INST_ADD , INST_ADD , INST_ADD , INST_ADD , INST_ADD } , // 04
  3765. { INST_ADD , INST_ADD , INST_ADD , INST_ADD , INST_ADD , INST_ADD , INST_ADD , INST_ADD } , // 05
  3766. { INST_PUSH , INST_PUSH , INST_PUSH , INST_PUSH , INST_PUSH , INST_PUSH , INST_PUSH , INST_PUSH} , // 06
  3767. { INST_POP , INST_POP , INST_POP , INST_POP , INST_POP , INST_POP , INST_POP , INST_POP } , // 07
  3768. { INST_OR , INST_OR , INST_OR , INST_OR , INST_OR , INST_OR , INST_OR , INST_OR } , // 08
  3769. { INST_OR , INST_OR , INST_OR , INST_OR , INST_OR , INST_OR , INST_OR , INST_OR } , // 09
  3770. { INST_OR , INST_OR , INST_OR , INST_OR , INST_OR , INST_OR , INST_OR , INST_OR } , // 0A
  3771. { INST_OR , INST_OR , INST_OR , INST_OR , INST_OR , INST_OR , INST_OR , INST_OR } , // 0B
  3772. { INST_OR , INST_OR , INST_OR , INST_OR , INST_OR , INST_OR , INST_OR , INST_OR } , // 0C
  3773. { INST_OR , INST_OR , INST_OR , INST_OR , INST_OR , INST_OR , INST_OR , INST_OR } , // 0D
  3774. { INST_PUSH , INST_PUSH , INST_PUSH , INST_PUSH , INST_PUSH , INST_PUSH , INST_PUSH , INST_PUSH} , // 0E
  3775. { INST_DT , INST_DT , INST_DT , INST_DT , INST_DT , INST_DT , INST_DT , INST_DT } , // 0F
  3776. { INST_ADC , INST_ADC , INST_ADC , INST_ADC , INST_ADC , INST_ADC , INST_ADC , INST_ADC } , // 10
  3777. { INST_ADC , INST_ADC , INST_ADC , INST_ADC , INST_ADC , INST_ADC , INST_ADC , INST_ADC } , // 11
  3778. { INST_ADC , INST_ADC , INST_ADC , INST_ADC , INST_ADC , INST_ADC , INST_ADC , INST_ADC } , // 12
  3779. { INST_ADC , INST_ADC , INST_ADC , INST_ADC , INST_ADC , INST_ADC , INST_ADC , INST_ADC } , // 13
  3780. { INST_ADC , INST_ADC , INST_ADC , INST_ADC , INST_ADC , INST_ADC , INST_ADC , INST_ADC } , // 14
  3781. { INST_ADC , INST_ADC , INST_ADC , INST_ADC , INST_ADC , INST_ADC , INST_ADC , INST_ADC } , // 15
  3782. { INST_PUSH , INST_PUSH , INST_PUSH , INST_PUSH , INST_PUSH , INST_PUSH , INST_PUSH , INST_PUSH} , // 16
  3783. { INST_POP , INST_POP , INST_POP , INST_POP , INST_POP , INST_POP , INST_POP , INST_POP } , // 17
  3784. { INST_SBB , INST_SBB , INST_SBB , INST_SBB , INST_SBB , INST_SBB , INST_SBB , INST_SBB } , // 18
  3785. { INST_SBB , INST_SBB , INST_SBB , INST_SBB , INST_SBB , INST_SBB , INST_SBB , INST_SBB } , // 19
  3786. { INST_SBB , INST_SBB , INST_SBB , INST_SBB , INST_SBB , INST_SBB , INST_SBB , INST_SBB } , // 1A
  3787. { INST_SBB , INST_SBB , INST_SBB , INST_SBB , INST_SBB , INST_SBB , INST_SBB , INST_SBB } , // 1B
  3788. { INST_SBB , INST_SBB , INST_SBB , INST_SBB , INST_SBB , INST_SBB , INST_SBB , INST_SBB } , // 1C
  3789. { INST_SBB , INST_SBB , INST_SBB , INST_SBB , INST_SBB , INST_SBB , INST_SBB , INST_SBB } , // 1D
  3790. { INST_PUSH , INST_PUSH , INST_PUSH , INST_PUSH , INST_PUSH , INST_PUSH , INST_PUSH , INST_PUSH} , // 1E
  3791. { INST_POP , INST_POP , INST_POP , INST_POP , INST_POP , INST_POP , INST_POP , INST_POP } , // 1F
  3792. { INST_AND , INST_AND , INST_AND , INST_AND , INST_AND , INST_AND , INST_AND , INST_AND } , // 20
  3793. { INST_AND , INST_AND , INST_AND , INST_AND , INST_AND , INST_AND , INST_AND , INST_AND } , // 21
  3794. { INST_AND , INST_AND , INST_AND , INST_AND , INST_AND , INST_AND , INST_AND , INST_AND } , // 22
  3795. { INST_AND , INST_AND , INST_AND , INST_AND , INST_AND , INST_AND , INST_AND , INST_AND } , // 23
  3796. { INST_AND , INST_AND , INST_AND , INST_AND , INST_AND , INST_AND , INST_AND , INST_AND } , // 24
  3797. { INST_AND , INST_AND , INST_AND , INST_AND , INST_AND , INST_AND , INST_AND , INST_AND } , // 25
  3798. { INST_SEG , INST_SEG , INST_SEG , INST_SEG , INST_SEG , INST_SEG , INST_SEG , INST_SEG } , // 26
  3799. { INST_DAA , INST_DAA , INST_DAA , INST_DAA , INST_DAA , INST_DAA , INST_DAA , INST_DAA } , // 27
  3800. { INST_SUB , INST_SUB , INST_SUB , INST_SUB , INST_SUB , INST_SUB , INST_SUB , INST_SUB } , // 28
  3801. { INST_SUB , INST_SUB , INST_SUB , INST_SUB , INST_SUB , INST_SUB , INST_SUB , INST_SUB } , // 29
  3802. { INST_SUB , INST_SUB , INST_SUB , INST_SUB , INST_SUB , INST_SUB , INST_SUB , INST_SUB } , // 2A
  3803. { INST_SUB , INST_SUB , INST_SUB , INST_SUB , INST_SUB , INST_SUB , INST_SUB , INST_SUB } , // 2B
  3804. { INST_SUB , INST_SUB , INST_SUB , INST_SUB , INST_SUB , INST_SUB , INST_SUB , INST_SUB } , // 2C
  3805. { INST_SUB , INST_SUB , INST_SUB , INST_SUB , INST_SUB , INST_SUB , INST_SUB , INST_SUB } , // 2D
  3806. { INST_SEG , INST_SEG , INST_SEG , INST_SEG , INST_SEG , INST_SEG , INST_SEG , INST_SEG } , // 2E
  3807. { INST_DAS , INST_DAS , INST_DAS , INST_DAS , INST_DAS , INST_DAS , INST_DAS , INST_DAS } , // 2F
  3808. { INST_XOR , INST_XOR , INST_XOR , INST_XOR , INST_XOR , INST_XOR , INST_XOR , INST_XOR } , // 30
  3809. { INST_XOR , INST_XOR , INST_XOR , INST_XOR , INST_XOR , INST_XOR , INST_XOR , INST_XOR } , // 31
  3810. { INST_XOR , INST_XOR , INST_XOR , INST_XOR , INST_XOR , INST_XOR , INST_XOR , INST_XOR } , // 32
  3811. { INST_XOR , INST_XOR , INST_XOR , INST_XOR , INST_XOR , INST_XOR , INST_XOR , INST_XOR } , // 33
  3812. { INST_XOR , INST_XOR , INST_XOR , INST_XOR , INST_XOR , INST_XOR , INST_XOR , INST_XOR } , // 34
  3813. { INST_XOR , INST_XOR , INST_XOR , INST_XOR , INST_XOR , INST_XOR , INST_XOR , INST_XOR } , // 35
  3814. { INST_SEG , INST_SEG , INST_SEG , INST_SEG , INST_SEG , INST_SEG , INST_SEG , INST_SEG } , // 36
  3815. { INST_AAA , INST_AAA , INST_AAA , INST_AAA , INST_AAA , INST_AAA , INST_AAA , INST_AAA } , // 37
  3816. { INST_CMP , INST_CMP , INST_CMP , INST_CMP , INST_CMP , INST_CMP , INST_CMP , INST_CMP } , // 38
  3817. { INST_CMP , INST_CMP , INST_CMP , INST_CMP , INST_CMP , INST_CMP , INST_CMP , INST_CMP } , // 39
  3818. { INST_CMP , INST_CMP , INST_CMP , INST_CMP , INST_CMP , INST_CMP , INST_CMP , INST_CMP } , // 3A
  3819. { INST_CMP , INST_CMP , INST_CMP , INST_CMP , INST_CMP , INST_CMP , INST_CMP , INST_CMP } , // 3B
  3820. { INST_CMP , INST_CMP , INST_CMP , INST_CMP , INST_CMP , INST_CMP , INST_CMP , INST_CMP } , // 3C
  3821. { INST_CMP , INST_CMP , INST_CMP , INST_CMP , INST_CMP , INST_CMP , INST_CMP , INST_CMP } , // 3D
  3822. { INST_SEG , INST_SEG , INST_SEG , INST_SEG , INST_SEG , INST_SEG , INST_SEG , INST_SEG } , // 3E
  3823. { INST_AAS , INST_AAS , INST_AAS , INST_AAS , INST_AAS , INST_AAS , INST_AAS , INST_AAS } , // 3F
  3824. { INST_INC , INST_INC , INST_INC , INST_INC , INST_INC , INST_INC , INST_INC , INST_INC } , // 40
  3825. { INST_INC , INST_INC , INST_INC , INST_INC , INST_INC , INST_INC , INST_INC , INST_INC } , // 41
  3826. { INST_INC , INST_INC , INST_INC , INST_INC , INST_INC , INST_INC , INST_INC , INST_INC } , // 42
  3827. { INST_INC , INST_INC , INST_INC , INST_INC , INST_INC , INST_INC , INST_INC , INST_INC } , // 43
  3828. { INST_INC , INST_INC , INST_INC , INST_INC , INST_INC , INST_INC , INST_INC , INST_INC } , // 44
  3829. { INST_INC , INST_INC , INST_INC , INST_INC , INST_INC , INST_INC , INST_INC , INST_INC } , // 45
  3830. { INST_INC , INST_INC , INST_INC , INST_INC , INST_INC , INST_INC , INST_INC , INST_INC } , // 46
  3831. { INST_INC , INST_INC , INST_INC , INST_INC , INST_INC , INST_INC , INST_INC , INST_INC } , // 47
  3832. { INST_DEC , INST_DEC , INST_DEC , INST_DEC , INST_DEC , INST_DEC , INST_DEC , INST_DEC } , // 48
  3833. { INST_DEC , INST_DEC , INST_DEC , INST_DEC , INST_DEC , INST_DEC , INST_DEC , INST_DEC } , // 49
  3834. { INST_DEC , INST_DEC , INST_DEC , INST_DEC , INST_DEC , INST_DEC , INST_DEC , INST_DEC } , // 4A
  3835. { INST_DEC , INST_DEC , INST_DEC , INST_DEC , INST_DEC , INST_DEC , INST_DEC , INST_DEC } , // 4B
  3836. { INST_DEC , INST_DEC , INST_DEC , INST_DEC , INST_DEC , INST_DEC , INST_DEC , INST_DEC } , // 4C
  3837. { INST_DEC , INST_DEC , INST_DEC , INST_DEC , INST_DEC , INST_DEC , INST_DEC , INST_DEC } , // 4D
  3838. { INST_DEC , INST_DEC , INST_DEC , INST_DEC , INST_DEC , INST_DEC , INST_DEC , INST_DEC } , // 4E
  3839. { INST_DEC , INST_DEC , INST_DEC , INST_DEC , INST_DEC , INST_DEC , INST_DEC , INST_DEC } , // 4F
  3840. { INST_PUSH , INST_PUSH , INST_PUSH , INST_PUSH , INST_PUSH , INST_PUSH , INST_PUSH , INST_PUSH} , // 50
  3841. { INST_PUSH , INST_PUSH , INST_PUSH , INST_PUSH , INST_PUSH , INST_PUSH , INST_PUSH , INST_PUSH} , // 51
  3842. { INST_PUSH , INST_PUSH , INST_PUSH , INST_PUSH , INST_PUSH , INST_PUSH , INST_PUSH , INST_PUSH} , // 52
  3843. { INST_PUSH , INST_PUSH , INST_PUSH , INST_PUSH , INST_PUSH , INST_PUSH , INST_PUSH , INST_PUSH} , // 53
  3844. { INST_PUSH , INST_PUSH , INST_PUSH , INST_PUSH , INST_PUSH , INST_PUSH , INST_PUSH , INST_PUSH} , // 54
  3845. { INST_PUSH , INST_PUSH , INST_PUSH , INST_PUSH , INST_PUSH , INST_PUSH , INST_PUSH , INST_PUSH} , // 55
  3846. { INST_PUSH , INST_PUSH , INST_PUSH , INST_PUSH , INST_PUSH , INST_PUSH , INST_PUSH , INST_PUSH} , // 56
  3847. { INST_PUSH , INST_PUSH , INST_PUSH , INST_PUSH , INST_PUSH , INST_PUSH , INST_PUSH , INST_PUSH} , // 57
  3848. { INST_POP , INST_POP , INST_POP , INST_POP , INST_POP , INST_POP , INST_POP , INST_POP } , // 58
  3849. { INST_POP , INST_POP , INST_POP , INST_POP , INST_POP , INST_POP , INST_POP , INST_POP } , // 59
  3850. { INST_POP , INST_POP , INST_POP , INST_POP , INST_POP , INST_POP , INST_POP , INST_POP } , // 5A
  3851. { INST_POP , INST_POP , INST_POP , INST_POP , INST_POP , INST_POP , INST_POP , INST_POP } , // 5B
  3852. { INST_POP , INST_POP , INST_POP , INST_POP , INST_POP , INST_POP , INST_POP , INST_POP } , // 5C
  3853. { INST_POP , INST_POP , INST_POP , INST_POP , INST_POP , INST_POP , INST_POP , INST_POP } , // 5D
  3854. { INST_POP , INST_POP , INST_POP , INST_POP , INST_POP , INST_POP , INST_POP , INST_POP } , // 5E
  3855. { INST_POP , INST_POP , INST_POP , INST_POP , INST_POP , INST_POP , INST_POP , INST_POP } , // 5F
  3856. { INST_PUSHA , INST_PUSHA , INST_PUSHA , INST_PUSHA , INST_PUSHA , INST_PUSHA , INST_PUSHA , INST_PUSHA} , // 60
  3857. { INST_POPA , INST_POPA , INST_POPA , INST_POPA , INST_POPA , INST_POPA , INST_POPA , INST_POPA} , // 61
  3858. { INST_INV , INST_INV , INST_INV , INST_INV , INST_INV , INST_INV , INST_INV , INST_INV } , // 62
  3859. { INST_INV , INST_INV , INST_INV , INST_INV , INST_INV , INST_INV , INST_INV , INST_INV } , // 63
  3860. { INST_INV , INST_INV , INST_INV , INST_INV , INST_INV , INST_INV , INST_INV , INST_INV } , // 64
  3861. { INST_INV , INST_INV , INST_INV , INST_INV , INST_INV , INST_INV , INST_INV , INST_INV } , // 65
  3862. { INST_INV , INST_INV , INST_INV , INST_INV , INST_INV , INST_INV , INST_INV , INST_INV } , // 66
  3863. { INST_INV , INST_INV , INST_INV , INST_INV , INST_INV , INST_INV , INST_INV , INST_INV } , // 67
  3864. { INST_PUSH , INST_PUSH , INST_PUSH , INST_PUSH , INST_PUSH , INST_PUSH , INST_PUSH , INST_PUSH} , // 68
  3865. { INST_IMUL , INST_IMUL , INST_IMUL , INST_IMUL , INST_IMUL , INST_IMUL , INST_IMUL , INST_IMUL} , // 69
  3866. { INST_PUSH , INST_PUSH , INST_PUSH , INST_PUSH , INST_PUSH , INST_PUSH , INST_PUSH , INST_PUSH} , // 6A
  3867. { INST_IMUL , INST_IMUL , INST_IMUL , INST_IMUL , INST_IMUL , INST_IMUL , INST_IMUL , INST_IMUL} , // 6B
  3868. { INST_INS , INST_INS , INST_INS , INST_INS , INST_INS , INST_INS , INST_INS , INST_INS } , // 6C
  3869. { INST_INS , INST_INS , INST_INS , INST_INS , INST_INS , INST_INS , INST_INS , INST_INS } , // 6D
  3870. { INST_OUTS , INST_OUTS , INST_OUTS , INST_OUTS , INST_OUTS , INST_OUTS , INST_OUTS , INST_OUTS} , // 6E
  3871. { INST_OUTS , INST_OUTS , INST_OUTS , INST_OUTS , INST_OUTS , INST_OUTS , INST_OUTS , INST_OUTS} , // 6F
  3872. { INST_JO , INST_JO , INST_JO , INST_JO , INST_JO , INST_JO , INST_JO , INST_JO } , // 70
  3873. { INST_JNO , INST_JNO , INST_JNO , INST_JNO , INST_JNO , INST_JNO , INST_JNO , INST_JNO } , // 71
  3874. { INST_JB , INST_JB , INST_JB , INST_JB , INST_JB , INST_JB , INST_JB , INST_JB } , // 72
  3875. { INST_JNB , INST_JNB , INST_JNB , INST_JNB , INST_JNB , INST_JNB , INST_JNB , INST_JNB } , // 73
  3876. { INST_JE , INST_JE , INST_JE , INST_JE , INST_JE , INST_JE , INST_JE , INST_JE } , // 74
  3877. { INST_JNE , INST_JNE , INST_JNE , INST_JNE , INST_JNE , INST_JNE , INST_JNE , INST_JNE } , // 75
  3878. { INST_JBE , INST_JBE , INST_JBE , INST_JBE , INST_JBE , INST_JBE , INST_JBE , INST_JBE } , // 76
  3879. { INST_JNBE , INST_JNBE , INST_JNBE , INST_JNBE , INST_JNBE , INST_JNBE , INST_JNBE , INST_JNBE} , // 77
  3880. { INST_JS , INST_JS , INST_JS , INST_JS , INST_JS , INST_JS , INST_JS , INST_JS } , // 78
  3881. { INST_JNS , INST_JNS , INST_JNS , INST_JNS , INST_JNS , INST_JNS , INST_JNS , INST_JNS } , // 79
  3882. { INST_JP , INST_JP , INST_JP , INST_JP , INST_JP , INST_JP , INST_JP , INST_JP } , // 7A
  3883. { INST_JNP , INST_JNP , INST_JNP , INST_JNP , INST_JNP , INST_JNP , INST_JNP , INST_JNP } , // 7B
  3884. { INST_JL , INST_JL , INST_JL , INST_JL , INST_JL , INST_JL , INST_JL , INST_JL } , // 7C
  3885. { INST_JNL , INST_JNL , INST_JNL , INST_JNL , INST_JNL , INST_JNL , INST_JNL , INST_JNL } , // 7D
  3886. { INST_JLE , INST_JLE , INST_JLE , INST_JLE , INST_JLE , INST_JLE , INST_JLE , INST_JLE } , // 7E
  3887. { INST_JNLE , INST_JNLE , INST_JNLE , INST_JNLE , INST_JNLE , INST_JNLE , INST_JNLE , INST_JNLE} , // 7F
  3888. { INST_ADD , INST_OR , INST_ADC , INST_SBB , INST_AND , INST_SUB , INST_XOR , INST_CMP } , // 80
  3889. { INST_ADD , INST_OR , INST_ADC , INST_SBB , INST_AND , INST_SUB , INST_XOR , INST_CMP } , // 81
  3890. { INST_ADD , INST_OR , INST_ADC , INST_SBB , INST_AND , INST_SUB , INST_XOR , INST_CMP } , // 82
  3891. { INST_ADD , INST_OR , INST_ADC , INST_SBB , INST_AND , INST_SUB , INST_XOR , INST_CMP } , // 83
  3892. { INST_TEST , INST_TEST , INST_TEST , INST_TEST , INST_TEST , INST_TEST , INST_TEST , INST_TEST} , // 84
  3893. { INST_TEST , INST_TEST , INST_TEST , INST_TEST , INST_TEST , INST_TEST , INST_TEST , INST_TEST} , // 85
  3894. { INST_XCHG , INST_XCHG , INST_XCHG , INST_XCHG , INST_XCHG , INST_XCHG , INST_XCHG , INST_XCHG} , // 86
  3895. { INST_XCHG , INST_XCHG , INST_XCHG , INST_XCHG , INST_XCHG , INST_XCHG , INST_XCHG , INST_XCHG} , // 87
  3896. { INST_MOV , INST_MOV , INST_MOV , INST_MOV , INST_MOV , INST_MOV , INST_MOV , INST_MOV } , // 88
  3897. { INST_MOV , INST_MOV , INST_MOV , INST_MOV , INST_MOV , INST_MOV , INST_MOV , INST_MOV } , // 89
  3898. { INST_MOV , INST_MOV , INST_MOV , INST_MOV , INST_MOV , INST_MOV , INST_MOV , INST_MOV } , // 8A
  3899. { INST_MOV , INST_MOV , INST_MOV , INST_MOV , INST_MOV , INST_MOV , INST_MOV , INST_MOV } , // 8B
  3900. { INST_MOV , INST_MOV , INST_MOV , INST_MOV , INST_INV , INST_INV , INST_INV , INST_INV } , // 8C
  3901. { INST_LEA , INST_LEA , INST_LEA , INST_LEA , INST_LEA , INST_LEA , INST_LEA , INST_LEA } , // 8D
  3902. { INST_MOV , INST_MOV , INST_MOV , INST_MOV , INST_INV , INST_INV , INST_INV , INST_INV } , // 8E
  3903. { INST_POP , INST_INV , INST_INV , INST_INV , INST_INV , INST_INV , INST_INV , INST_INV } , // 8F
  3904. { INST_XCHG , INST_XCHG , INST_XCHG , INST_XCHG , INST_XCHG , INST_XCHG , INST_XCHG , INST_XCHG} , // 90
  3905. { INST_XCHG , INST_XCHG , INST_XCHG , INST_XCHG , INST_XCHG , INST_XCHG , INST_XCHG , INST_XCHG} , // 91
  3906. { INST_XCHG , INST_XCHG , INST_XCHG , INST_XCHG , INST_XCHG , INST_XCHG , INST_XCHG , INST_XCHG} , // 92
  3907. { INST_XCHG , INST_XCHG , INST_XCHG , INST_XCHG , INST_XCHG , INST_XCHG , INST_XCHG , INST_XCHG} , // 93
  3908. { INST_XCHG , INST_XCHG , INST_XCHG , INST_XCHG , INST_XCHG , INST_XCHG , INST_XCHG , INST_XCHG} , // 94
  3909. { INST_XCHG , INST_XCHG , INST_XCHG , INST_XCHG , INST_XCHG , INST_XCHG , INST_XCHG , INST_XCHG} , // 95
  3910. { INST_XCHG , INST_XCHG , INST_XCHG , INST_XCHG , INST_XCHG , INST_XCHG , INST_XCHG , INST_XCHG} , // 96
  3911. { INST_XCHG , INST_XCHG , INST_XCHG , INST_XCHG , INST_XCHG , INST_XCHG , INST_XCHG , INST_XCHG} , // 97
  3912. { INST_CBW , INST_CBW , INST_CBW , INST_CBW , INST_CBW , INST_CBW , INST_CBW , INST_CBW } , // 98
  3913. { INST_CWD , INST_CWD , INST_CWD , INST_CWD , INST_CWD , INST_CWD , INST_CWD , INST_CWD } , // 99
  3914. { INST_CALL , INST_CALL , INST_CALL , INST_CALL , INST_CALL , INST_CALL , INST_CALL , INST_CALL} , // 9A
  3915. { INST_WAIT , INST_WAIT , INST_WAIT , INST_WAIT , INST_WAIT , INST_WAIT , INST_WAIT , INST_WAIT} , // 9B
  3916. { INST_PUSHF , INST_PUSHF , INST_PUSHF , INST_PUSHF , INST_PUSHF , INST_PUSHF , INST_PUSHF , INST_PUSHF} , // 9C
  3917. { INST_POPF , INST_POPF , INST_POPF , INST_POPF , INST_POPF , INST_POPF , INST_POPF , INST_POPF} , // 9D
  3918. { INST_SAHF , INST_SAHF , INST_SAHF , INST_SAHF , INST_SAHF , INST_SAHF , INST_SAHF , INST_SAHF} , // 9E
  3919. { INST_LAHF , INST_LAHF , INST_LAHF , INST_LAHF , INST_LAHF , INST_LAHF , INST_LAHF , INST_LAHF} , // 9F
  3920. { INST_MOV , INST_MOV , INST_MOV , INST_MOV , INST_MOV , INST_MOV , INST_MOV , INST_MOV } , // A0
  3921. { INST_MOV , INST_MOV , INST_MOV , INST_MOV , INST_MOV , INST_MOV , INST_MOV , INST_MOV } , // A1
  3922. { INST_MOV , INST_MOV , INST_MOV , INST_MOV , INST_MOV , INST_MOV , INST_MOV , INST_MOV } , // A2
  3923. { INST_MOV , INST_MOV , INST_MOV , INST_MOV , INST_MOV , INST_MOV , INST_MOV , INST_MOV } , // A3
  3924. { INST_MOVS , INST_MOVS , INST_MOVS , INST_MOVS , INST_MOVS , INST_MOVS , INST_MOVS , INST_MOVS} , // A4
  3925. { INST_MOVS , INST_MOVS , INST_MOVS , INST_MOVS , INST_MOVS , INST_MOVS , INST_MOVS , INST_MOVS} , // A5
  3926. { INST_CMPS , INST_CMPS , INST_CMPS , INST_CMPS , INST_CMPS , INST_CMPS , INST_CMPS , INST_CMPS} , // A6
  3927. { INST_CMPS , INST_CMPS , INST_CMPS , INST_CMPS , INST_CMPS , INST_CMPS , INST_CMPS , INST_CMPS} , // A7
  3928. { INST_TEST , INST_TEST , INST_TEST , INST_TEST , INST_TEST , INST_TEST , INST_TEST , INST_TEST} , // A8
  3929. { INST_TEST , INST_TEST , INST_TEST , INST_TEST , INST_TEST , INST_TEST , INST_TEST , INST_TEST} , // A9
  3930. { INST_STOS , INST_STOS , INST_STOS , INST_STOS , INST_STOS , INST_STOS , INST_STOS , INST_STOS} , // AA
  3931. { INST_STOS , INST_STOS , INST_STOS , INST_STOS , INST_STOS , INST_STOS , INST_STOS , INST_STOS} , // AB
  3932. { INST_LODS , INST_LODS , INST_LODS , INST_LODS , INST_LODS , INST_LODS , INST_LODS , INST_LODS} , // AC
  3933. { INST_LODS , INST_LODS , INST_LODS , INST_LODS , INST_LODS , INST_LODS , INST_LODS , INST_LODS} , // AD
  3934. { INST_SCAS , INST_SCAS , INST_SCAS , INST_SCAS , INST_SCAS , INST_SCAS , INST_SCAS , INST_SCAS} , // AE
  3935. { INST_SCAS , INST_SCAS , INST_SCAS , INST_SCAS , INST_SCAS , INST_SCAS , INST_SCAS , INST_SCAS} , // AF
  3936. { INST_MOV , INST_MOV , INST_MOV , INST_MOV , INST_MOV , INST_MOV , INST_MOV , INST_MOV } , // B0
  3937. { INST_MOV , INST_MOV , INST_MOV , INST_MOV , INST_MOV , INST_MOV , INST_MOV , INST_MOV } , // B1
  3938. { INST_MOV , INST_MOV , INST_MOV , INST_MOV , INST_MOV , INST_MOV , INST_MOV , INST_MOV } , // B2
  3939. { INST_MOV , INST_MOV , INST_MOV , INST_MOV , INST_MOV , INST_MOV , INST_MOV , INST_MOV } , // B3
  3940. { INST_MOV , INST_MOV , INST_MOV , INST_MOV , INST_MOV , INST_MOV , INST_MOV , INST_MOV } , // B4
  3941. { INST_MOV , INST_MOV , INST_MOV , INST_MOV , INST_MOV , INST_MOV , INST_MOV , INST_MOV } , // B5
  3942. { INST_MOV , INST_MOV , INST_MOV , INST_MOV , INST_MOV , INST_MOV , INST_MOV , INST_MOV } , // B6
  3943. { INST_MOV , INST_MOV , INST_MOV , INST_MOV , INST_MOV , INST_MOV , INST_MOV , INST_MOV } , // B7
  3944. { INST_MOV , INST_MOV , INST_MOV , INST_MOV , INST_MOV , INST_MOV , INST_MOV , INST_MOV } , // B8
  3945. { INST_MOV , INST_MOV , INST_MOV , INST_MOV , INST_MOV , INST_MOV , INST_MOV , INST_MOV } , // B9
  3946. { INST_MOV , INST_MOV , INST_MOV , INST_MOV , INST_MOV , INST_MOV , INST_MOV , INST_MOV } , // BA
  3947. { INST_MOV , INST_MOV , INST_MOV , INST_MOV , INST_MOV , INST_MOV , INST_MOV , INST_MOV } , // BB
  3948. { INST_MOV , INST_MOV , INST_MOV , INST_MOV , INST_MOV , INST_MOV , INST_MOV , INST_MOV } , // BC
  3949. { INST_MOV , INST_MOV , INST_MOV , INST_MOV , INST_MOV , INST_MOV , INST_MOV , INST_MOV } , // BD
  3950. { INST_MOV , INST_MOV , INST_MOV , INST_MOV , INST_MOV , INST_MOV , INST_MOV , INST_MOV } , // BE
  3951. { INST_MOV , INST_MOV , INST_MOV , INST_MOV , INST_MOV , INST_MOV , INST_MOV , INST_MOV } , // BF
  3952. { INST_ROL , INST_ROR , INST_RCL , INST_RCR , INST_SAL , INST_SHR , INST_INV , INST_SAR } , // C0
  3953. { INST_ROL , INST_ROR , INST_RCL , INST_RCR , INST_SAL , INST_SHR , INST_INV , INST_SAR } , // C1
  3954. { INST_RET , INST_RET , INST_RET , INST_RET , INST_RET , INST_RET , INST_RET , INST_RET } , // C2
  3955. { INST_RET , INST_RET , INST_RET , INST_RET , INST_RET , INST_RET , INST_RET , INST_RET } , // C3
  3956. { INST_LES , INST_LES , INST_LES , INST_LES , INST_LES , INST_LES , INST_LES , INST_LES } , // C4
  3957. { INST_LDS , INST_LDS , INST_LDS , INST_LDS , INST_LDS , INST_LDS , INST_LDS , INST_LDS } , // C5
  3958. { INST_MOV , INST_INV , INST_INV , INST_INV , INST_INV , INST_INV , INST_INV , INST_INV } , // C6
  3959. { INST_MOV , INST_INV , INST_INV , INST_INV , INST_INV , INST_INV , INST_INV , INST_INV } , // C7
  3960. { INST_ENTER , INST_ENTER , INST_ENTER , INST_ENTER , INST_ENTER , INST_ENTER , INST_ENTER , INST_ENTER} , // C8
  3961. { INST_LEAVE , INST_LEAVE , INST_LEAVE , INST_LEAVE , INST_LEAVE , INST_LEAVE , INST_LEAVE , INST_LEAVE} , // C9
  3962. { INST_RET , INST_RET , INST_RET , INST_RET , INST_RET , INST_RET , INST_RET , INST_RET } , // CA
  3963. { INST_RET , INST_RET , INST_RET , INST_RET , INST_RET , INST_RET , INST_RET , INST_RET } , // CB
  3964. { INST_INT , INST_INT , INST_INT , INST_INT , INST_INT , INST_INT , INST_INT , INST_INT } , // CC
  3965. { INST_INT , INST_INT , INST_INT , INST_INT , INST_INT , INST_INT , INST_INT , INST_INT } , // CD
  3966. { INST_INTO , INST_INTO , INST_INTO , INST_INTO , INST_INTO , INST_INTO , INST_INTO , INST_INTO} , // CE
  3967. { INST_IRET , INST_IRET , INST_IRET , INST_IRET , INST_IRET , INST_IRET , INST_IRET , INST_IRET} , // CF
  3968. { INST_ROL , INST_ROR , INST_RCL , INST_RCR , INST_SAL , INST_SHR , INST_INV , INST_SAR } , // D0
  3969. { INST_ROL , INST_ROR , INST_RCL , INST_RCR , INST_SAL , INST_SHR , INST_INV , INST_SAR } , // D1
  3970. { INST_ROL , INST_ROR , INST_RCL , INST_RCR , INST_SAL , INST_SHR , INST_INV , INST_SAR } , // D2
  3971. { INST_ROL , INST_ROR , INST_RCL , INST_RCR , INST_SAL , INST_SHR , INST_INV , INST_SAR } , // D3
  3972. { INST_AAM , INST_AAM , INST_AAM , INST_AAM , INST_AAM , INST_AAM , INST_AAM , INST_AAM } , // D4
  3973. { INST_AAD , INST_AAD , INST_AAD , INST_AAD , INST_AAD , INST_AAD , INST_AAD , INST_AAD } , // D5
  3974. { INST_INV , INST_INV , INST_INV , INST_INV , INST_INV , INST_INV , INST_INV , INST_INV } , // D6
  3975. { INST_XLAT , INST_XLAT , INST_XLAT , INST_XLAT , INST_XLAT , INST_XLAT , INST_XLAT , INST_XLAT} , // D7
  3976. { INST_ESC , INST_ESC , INST_ESC , INST_ESC , INST_ESC , INST_ESC , INST_ESC , INST_ESC } , // D8
  3977. { INST_ESC , INST_ESC , INST_ESC , INST_ESC , INST_ESC , INST_ESC , INST_ESC , INST_ESC } , // D9
  3978. { INST_ESC , INST_ESC , INST_ESC , INST_ESC , INST_ESC , INST_ESC , INST_ESC , INST_ESC } , // DA
  3979. { INST_ESC , INST_ESC , INST_ESC , INST_ESC , INST_ESC , INST_ESC , INST_ESC , INST_ESC } , // DB
  3980. { INST_ESC , INST_ESC , INST_ESC , INST_ESC , INST_ESC , INST_ESC , INST_ESC , INST_ESC } , // DC
  3981. { INST_ESC , INST_ESC , INST_ESC , INST_ESC , INST_ESC , INST_ESC , INST_ESC , INST_ESC } , // DD
  3982. { INST_ESC , INST_ESC , INST_ESC , INST_ESC , INST_ESC , INST_ESC , INST_ESC , INST_ESC } , // DE
  3983. { INST_ESC , INST_ESC , INST_ESC , INST_ESC , INST_ESC , INST_ESC , INST_ESC , INST_ESC } , // DF
  3984. { INST_LOOPNE, INST_LOOPNE, INST_LOOPNE, INST_LOOPNE, INST_LOOPNE, INST_LOOPNE, INST_LOOPNE, INST_LOOPNE} , // E0
  3985. { INST_LOOPE , INST_LOOPE , INST_LOOPE , INST_LOOPE , INST_LOOPE , INST_LOOPE , INST_LOOPE , INST_LOOPE} , // E1
  3986. { INST_LOOP , INST_LOOP , INST_LOOP , INST_LOOP , INST_LOOP , INST_LOOP , INST_LOOP , INST_LOOP} , // E2
  3987. { INST_JCXZ , INST_JCXZ , INST_JCXZ , INST_JCXZ , INST_JCXZ , INST_JCXZ , INST_JCXZ , INST_JCXZ} , // E3
  3988. { INST_IN , INST_IN , INST_IN , INST_IN , INST_IN , INST_IN , INST_IN , INST_IN } , // E4
  3989. { INST_IN , INST_IN , INST_IN , INST_IN , INST_IN , INST_IN , INST_IN , INST_IN } , // E5
  3990. { INST_OUT , INST_OUT , INST_OUT , INST_OUT , INST_OUT , INST_OUT , INST_OUT , INST_OUT } , // E6
  3991. { INST_OUT , INST_OUT , INST_OUT , INST_OUT , INST_OUT , INST_OUT , INST_OUT , INST_OUT } , // E7
  3992. { INST_CALL , INST_CALL , INST_CALL , INST_CALL , INST_CALL , INST_CALL , INST_CALL , INST_CALL} , // E8
  3993. { INST_JMP , INST_JMP , INST_JMP , INST_JMP , INST_JMP , INST_JMP , INST_JMP , INST_JMP } , // E9
  3994. { INST_JMP , INST_JMP , INST_JMP , INST_JMP , INST_JMP , INST_JMP , INST_JMP , INST_JMP } , // EA
  3995. { INST_JMP , INST_JMP , INST_JMP , INST_JMP , INST_JMP , INST_JMP , INST_JMP , INST_JMP } , // EB
  3996. { INST_IN , INST_IN , INST_IN , INST_IN , INST_IN , INST_IN , INST_IN , INST_IN } , // EC
  3997. { INST_IN , INST_IN , INST_IN , INST_IN , INST_IN , INST_IN , INST_IN , INST_IN } , // ED
  3998. { INST_OUT , INST_OUT , INST_OUT , INST_OUT , INST_OUT , INST_OUT , INST_OUT , INST_OUT } , // EE
  3999. { INST_OUT , INST_OUT , INST_OUT , INST_OUT , INST_OUT , INST_OUT , INST_OUT , INST_OUT } , // EF
  4000. { INST_LOCK , INST_LOCK , INST_LOCK , INST_LOCK , INST_LOCK , INST_LOCK , INST_LOCK , INST_LOCK} , // F0
  4001. { INST_INV , INST_INV , INST_INV , INST_INV , INST_INV , INST_INV , INST_INV , INST_INV } , // F1
  4002. { INST_REP , INST_REP , INST_REP , INST_REP , INST_REP , INST_REP , INST_REP , INST_REP } , // F2
  4003. { INST_REP , INST_REP , INST_REP , INST_REP , INST_REP , INST_REP , INST_REP , INST_REP } , // F3
  4004. { INST_HLT , INST_HLT , INST_HLT , INST_HLT , INST_HLT , INST_HLT , INST_HLT , INST_HLT } , // F4
  4005. { INST_CMC , INST_CMC , INST_CMC , INST_CMC , INST_CMC , INST_CMC , INST_CMC , INST_CMC } , // F5
  4006. { INST_TEST , INST_INV , INST_NOT , INST_NEG , INST_MUL , INST_IMUL , INST_DIV , INST_IDIV} , // F6
  4007. { INST_TEST , INST_INV , INST_NOT , INST_NEG , INST_MUL , INST_IMUL , INST_DIV , INST_IDIV} , // F7
  4008. { INST_CLC , INST_CLC , INST_CLC , INST_CLC , INST_CLC , INST_CLC , INST_CLC , INST_CLC } , // F8
  4009. { INST_STC , INST_STC , INST_STC , INST_STC , INST_STC , INST_STC , INST_STC , INST_STC } , // F9
  4010. { INST_CLI , INST_CLI , INST_CLI , INST_CLI , INST_CLI , INST_CLI , INST_CLI , INST_CLI } , // FA
  4011. { INST_STI , INST_STI , INST_STI , INST_STI , INST_STI , INST_STI , INST_STI , INST_STI } , // FB
  4012. { INST_CLD , INST_CLD , INST_CLD , INST_CLD , INST_CLD , INST_CLD , INST_CLD , INST_CLD } , // FC
  4013. { INST_STD , INST_STD , INST_STD , INST_STD , INST_STD , INST_STD , INST_STD , INST_STD } , // FD
  4014. { INST_INC , INST_DEC , INST_INV , INST_INV , INST_INV , INST_INV , INST_INV , INST_INV } , // FE
  4015. { INST_INC , INST_DEC , INST_CALL , INST_CALL , INST_JMP , INST_JMP , INST_PUSH , INST_INV } , // FF
  4016. };
  4017. //
  4018. // Debugging functions
  4019. //
  4020. #ifdef X86DEBUG1
  4021. static VOID DisplayProcessorState()
  4022. {
  4023. UCHAR S[512];
  4024. PrintProcessorState(S);
  4025. DISPLAY(S);
  4026. }
  4027. static VOID DisplayCurrentInstruction()
  4028. {
  4029. UCHAR S[256];
  4030. ULONG i;
  4031. ULONG Column;
  4032. //
  4033. // Print Instruction Address
  4034. //
  4035. sprintf(S,"%04X:%04X ",CS,CurrentIP.X);
  4036. DISPLAY(S);
  4037. for(i=0;i<7;i++)
  4038. if ((CurrentIP.X + i) < IP)
  4039. {
  4040. sprintf(S,"%02X",CodeMem(CurrentIP.X+i));
  4041. DISPLAY(S);
  4042. }
  4043. else
  4044. DISPLAY(" ");
  4045. //
  4046. // Print Instruction Opcode
  4047. //
  4048. if (OperationCodeByte==0x26)
  4049. {
  4050. sprintf(S,"ES: ");
  4051. DISPLAY(S);
  4052. }
  4053. else if (OperationCodeByte==0x2E)
  4054. {
  4055. sprintf(S,"CS: ");
  4056. DISPLAY(S);
  4057. }
  4058. else if (OperationCodeByte==0x36)
  4059. {
  4060. sprintf(S,"SS: ");
  4061. DISPLAY(S);
  4062. }
  4063. else if (OperationCodeByte==0x3E)
  4064. {
  4065. sprintf(S,"DS: ");
  4066. DISPLAY(S);
  4067. }
  4068. else
  4069. {
  4070. sprintf(S,"%s",InstructionNames[DecodeInstructionTable[OperationCodeByte][InstructionSubIndex]]);
  4071. DISPLAY(S);
  4072. //
  4073. // Print Instruction Operands
  4074. //
  4075. Column = 0;
  4076. if (OperationCodeByte == 0xe8 ||
  4077. OperationCodeByte == 0xe9 ||
  4078. OperationCodeByte == 0xeb ||
  4079. (OperationCodeByte >= 0x70 && OperationCodeByte <= 0x7F))
  4080. {
  4081. sprintf(S,"%04X",IP+GetOperand(LSRC,0));
  4082. DISPLAY(S);
  4083. Column = Column + strlen(S);
  4084. }
  4085. else
  4086. {
  4087. if (LSRC->OperandType != NullOperand)
  4088. {
  4089. PrintOperandName(LSRC,S);
  4090. DISPLAY(S);
  4091. Column = Column + strlen(S);
  4092. }
  4093. if (RSRC->OperandType != NullOperand)
  4094. {
  4095. DISPLAY(",");
  4096. PrintOperandName(RSRC,S);
  4097. DISPLAY(S);
  4098. Column = Column + strlen(S) + 1;
  4099. }
  4100. }
  4101. for(i=Column;i<35;i++)
  4102. DISPLAY(" ");
  4103. //
  4104. // Print Memory Operand Value
  4105. //
  4106. if (LSRC->OperandType == Memory8Operand || LSRC->OperandType==Memory16Operand)
  4107. {
  4108. PrintMemorySegmentName(LSRC,S);
  4109. DISPLAY(S);
  4110. sprintf(S,":%04X",LSRC->MemoryOffset.X);
  4111. DISPLAY(S);
  4112. DISPLAY("=");
  4113. PrintOperandValue(LSRC,S);
  4114. DISPLAY(S);
  4115. }
  4116. if (RSRC->OperandType == Memory8Operand || RSRC->OperandType==Memory16Operand)
  4117. {
  4118. PrintMemorySegmentName(RSRC,S);
  4119. DISPLAY(S);
  4120. sprintf(S,":%04X",RSRC->MemoryOffset.X);
  4121. DISPLAY(S);
  4122. DISPLAY("=");
  4123. PrintOperandValue(RSRC,S);
  4124. DISPLAY(S);
  4125. }
  4126. }
  4127. DISPLAY("\n\r");
  4128. }
  4129. /***************************************************************************/
  4130. static VOID DecodeInstruction()
  4131. {
  4132. LSRC->OperandType = NullOperand;
  4133. RSRC->OperandType = NullOperand;
  4134. CurrentIP.X = IP;
  4135. OperationCodeByte = CodeMem(IP); IP++;
  4136. if (OperationCodeByte == 0x0f)
  4137. {
  4138. ExtendedOperationCodeByte = CodeMem(IP); IP++;
  4139. if (ExtendedOperationCodeByte == 0x01)
  4140. GetMemory16OrRegister16Operand(LSRC);
  4141. }
  4142. else
  4143. {
  4144. if (AddressModeByteRequired[DecodeOperandsTable[OperationCodeByte][0]] ||
  4145. AddressModeByteRequired[DecodeOperandsTable[OperationCodeByte][1]] )
  4146. {
  4147. GetAddressModeByte();
  4148. InstructionSubIndex = reg;
  4149. }
  4150. else
  4151. InstructionSubIndex = 0;
  4152. (DecodeOperandFunctionTable[DecodeOperandsTable[OperationCodeByte][0]])(LSRC);
  4153. (DecodeOperandFunctionTable[DecodeOperandsTable[OperationCodeByte][1]])(RSRC);
  4154. }
  4155. }
  4156. /***************************************************************************/
  4157. static VOID ExecuteInstruction()
  4158. {
  4159. ULONG SavedSegmentOveridePrefix;
  4160. ULONG SavedRepeatPrefix;
  4161. ULONG SavedLockPrefix;
  4162. if (SegmentOveridePrefix==TRUE ||
  4163. RepeatPrefix==TRUE ||
  4164. LockPrefix==TRUE )
  4165. {
  4166. SavedSegmentOveridePrefix = SegmentOveridePrefix;
  4167. SavedRepeatPrefix = RepeatPrefix;
  4168. SavedLockPrefix = LockPrefix;
  4169. (DecodeInstructionFunctionTable[DecodeInstructionTable[OperationCodeByte][InstructionSubIndex]])();
  4170. if (SavedSegmentOveridePrefix==SegmentOveridePrefix &&
  4171. SavedRepeatPrefix==RepeatPrefix &&
  4172. SavedLockPrefix==LockPrefix )
  4173. {
  4174. SegmentOveridePrefix = FALSE;
  4175. RepeatPrefix = FALSE;
  4176. LockPrefix = FALSE;
  4177. }
  4178. }
  4179. else
  4180. {
  4181. (DecodeInstructionFunctionTable[DecodeInstructionTable[OperationCodeByte][InstructionSubIndex]])();
  4182. }
  4183. }
  4184. /***************************************************************************/
  4185. static VOID CommandMode()
  4186. {
  4187. UCHAR ch;
  4188. UCHAR Command[256];
  4189. ULONG Done = FALSE;
  4190. REGISTER32 SavedCurrentIP;
  4191. USHORT SavedIP;
  4192. USHORT SavedCS;
  4193. USHORT i;
  4194. USHORT j;
  4195. UCHAR Value;
  4196. ULONG DefaultSegment;
  4197. ULONG DefaultParameter;
  4198. USHORT DataSegment;
  4199. USHORT DataAddress;
  4200. USHORT Parameter;
  4201. UCHAR CommandType;
  4202. SavedCurrentIP = CurrentIP;
  4203. SavedIP = IP;
  4204. SavedCS = CS;
  4205. DisplayProcessorState();
  4206. DecodeInstruction();
  4207. DisplayCurrentInstruction();
  4208. CurrentIP = SavedCurrentIP;
  4209. IP = SavedIP;
  4210. do
  4211. {
  4212. DISPLAY("-");
  4213. i=0;
  4214. do
  4215. {
  4216. GETCHAR(ch);
  4217. PUTCHAR(ch);
  4218. if (ch==0x08 && i>0)
  4219. i--;
  4220. else if (ch>=32 && ch<=127)
  4221. {
  4222. Command[i++] = ch;
  4223. }
  4224. }
  4225. while(ch!=0x0d);
  4226. Command[i] = 0;
  4227. DISPLAY("\n\r");
  4228. DefaultSegment = TRUE;
  4229. DataSegment = 0;
  4230. i=0;
  4231. for(;(Command[i]==' ' || Command[i]==':') && Command[i]!=0;i++);
  4232. for(j=i;Command[i]!=' ' && Command[i]!=':' && Command[i]!=0;i++);
  4233. CommandType = Command[j];
  4234. for(;(Command[i]==' ' || Command[i]==':') && Command[i]!=0;i++);
  4235. for(j=i;Command[i]!=' ' && Command[i]!=':' && Command[i]!=0;i++);
  4236. if (Command[i]==':')
  4237. {
  4238. DefaultSegment = FALSE;
  4239. Command[i]=0;
  4240. i++;
  4241. if (strcmp(&(Command[j]),"ds")==0 || strcmp(&(Command[j]),"DS")==0)
  4242. DataSegment = DS;
  4243. else if (strcmp(&(Command[j]),"es")==0 || strcmp(&(Command[j]),"ES")==0)
  4244. DataSegment = ES;
  4245. else if (strcmp(&(Command[j]),"ss")==0 || strcmp(&(Command[j]),"SS")==0)
  4246. DataSegment = SS;
  4247. else if (strcmp(&(Command[j]),"cs")==0 || strcmp(&(Command[j]),"CS")==0)
  4248. DataSegment = SavedCS;
  4249. else
  4250. DataSegment = atoh(&(Command[j]));
  4251. for(;(Command[i]==' ' || Command[i]==':') && Command[i]!=0;i++);
  4252. for(;Command[i]==' ' && Command[i]==':' && Command[i]!=0;i++);
  4253. for(j=i;(Command[i]!=' ' || Command[i]!=':') && Command[i]!=0;i++);
  4254. }
  4255. if (Command[j]==0)
  4256. {
  4257. DefaultParameter = TRUE;
  4258. Parameter = 0;
  4259. }
  4260. else
  4261. {
  4262. DefaultParameter = FALSE;
  4263. Parameter = atoh(&(Command[j]));
  4264. }
  4265. switch(CommandType)
  4266. {
  4267. case 'a' :
  4268. case 'A' : DISPLAY("Address Trace\n\r");
  4269. for(i=0;i<ADDRESSTRACESIZE;i+=2)
  4270. {
  4271. PRINT3(" Jump FAR from %04X:%04X to ",AddressTrace[AddressTracePosition]>>16,AddressTrace[AddressTracePosition]&0xffff);
  4272. DISPLAY(PrintMessage);
  4273. AddressTracePosition = (AddressTracePosition + 1) % ADDRESSTRACESIZE;
  4274. PRINT3("%04X:%04X\n\r",AddressTrace[AddressTracePosition]>>16,AddressTrace[AddressTracePosition]&0xffff);
  4275. DISPLAY(PrintMessage);
  4276. AddressTracePosition = (AddressTracePosition + 1) % ADDRESSTRACESIZE;
  4277. }
  4278. DISPLAY("\n\r");
  4279. break;
  4280. case 'g' :
  4281. case 'G' : GoFlag = TRUE;
  4282. if (!DefaultSegment)
  4283. StopSegment = DataSegment;
  4284. if (!DefaultParameter)
  4285. StopOffset = Parameter;
  4286. Done = TRUE;
  4287. break;
  4288. case 'u' :
  4289. case 'U' : if (!DefaultSegment)
  4290. {
  4291. CS = DataSegment;
  4292. CSCacheRegister = GetSegmentCacheRegister(CS);
  4293. }
  4294. if (!DefaultParameter)
  4295. IP = Parameter;
  4296. for(i=0;i<20;i++)
  4297. {
  4298. DecodeInstruction();
  4299. DisplayCurrentInstruction();
  4300. }
  4301. break;
  4302. case 't' :
  4303. case 'T' : if (!DefaultSegment)
  4304. SavedCS = DataSegment;
  4305. if (!DefaultParameter)
  4306. SavedIP = Parameter;
  4307. Done = TRUE;
  4308. GoFlag = FALSE;
  4309. break;
  4310. case 'd' :
  4311. case 'D' : if (DefaultSegment)
  4312. DataSegment = DS;
  4313. if (!DefaultParameter)
  4314. DataAddress = Parameter;
  4315. for(i=0;i<8;i++)
  4316. {
  4317. PRINT3("%04X:%04X ",DataSegment,DataAddress+i*16);
  4318. DISPLAY(PrintMessage);
  4319. for(j=0;j<16;j++)
  4320. {
  4321. Value = GetMemImmediate(DataSegment,DataAddress+i*16+j);
  4322. PRINT2("%02X ",Value);
  4323. DISPLAY(PrintMessage);
  4324. }
  4325. DISPLAY(" ");
  4326. for(j=0;j<16;j++)
  4327. {
  4328. Value = GetMemImmediate(DataSegment,DataAddress+i*16+j);
  4329. if (Value<32 || Value >=128)
  4330. Value = '.';
  4331. PRINT2("%c",Value);
  4332. DISPLAY(PrintMessage);
  4333. }
  4334. DISPLAY("\n\r");
  4335. }
  4336. break;
  4337. case 'r' :
  4338. case 'R' : CurrentIP = SavedCurrentIP;
  4339. IP = SavedIP;
  4340. CS = SavedCS;
  4341. DisplayProcessorState();
  4342. DecodeInstruction();
  4343. DisplayCurrentInstruction();
  4344. CurrentIP = SavedCurrentIP;
  4345. IP = SavedIP;
  4346. CS = SavedCS;
  4347. break;
  4348. case 'm' :
  4349. case 'M' : msw = 0;
  4350. Flags.X = 0;
  4351. break;
  4352. case 'i' :
  4353. case 'I' : if (!DefaultParameter)
  4354. {
  4355. PRINT3("in %04X = %02X\n\r",Parameter,inp(Parameter));
  4356. DISPLAY(PrintMessage);
  4357. }
  4358. break;
  4359. case 'o' :
  4360. case 'O' : if (!DefaultSegment && !DefaultParameter)
  4361. {
  4362. outp(DataSegment,Parameter);
  4363. PRINT3("out %04X,%02X\n\r",DataSegment,Parameter);
  4364. DISPLAY(PrintMessage);
  4365. }
  4366. break;
  4367. }
  4368. }
  4369. while (Done == FALSE);
  4370. CurrentIP = SavedCurrentIP;
  4371. IP = SavedIP;
  4372. CS = SavedCS;
  4373. CSCacheRegister = GetSegmentCacheRegister(CS);
  4374. }
  4375. #endif
  4376. static VOID Interpreter()
  4377. /*++
  4378. Routine Description:
  4379. This function is the main loop for the emulator. It decodes operands
  4380. and executes the instructions until the exit condition is met, or an
  4381. error occurs.
  4382. Arguments:
  4383. None.
  4384. Return Value:
  4385. None.
  4386. --*/
  4387. {
  4388. ULONG SavedSegmentOveridePrefix; // Saved state of the SegmentOveridePrefix variable.
  4389. ULONG SavedRepeatPrefix; // Saved state of the RepeatPrefix variable.
  4390. ULONG SavedLockPrefix; // Saved state of the LockPrefix variable.
  4391. ULONG TrapFlagSet;
  4392. ExitFlag = FALSE;
  4393. //
  4394. // Loop until the exit condition is met.
  4395. //
  4396. while(ExitFlag==FALSE)
  4397. {
  4398. #ifdef X86DEBUG1
  4399. //
  4400. // See if there is input on the debug serial port
  4401. //
  4402. if (inp(0x3f8+5) & 0x0001)
  4403. GoFlag = FALSE;
  4404. #endif
  4405. #ifdef X86DEBUG1
  4406. //
  4407. // See if a break point has been reached.
  4408. //
  4409. if (CS==StopSegment && IP==StopOffset)
  4410. GoFlag = FALSE;
  4411. if (GoFlag == FALSE)
  4412. CommandMode();
  4413. #endif
  4414. //
  4415. // See if the exit condition has been met.
  4416. //
  4417. if (CS==ExitSegment && IP==ExitOffset)
  4418. {
  4419. ExitFlag = TRUE;
  4420. return;
  4421. }
  4422. //
  4423. // Check the condition of the trap flag. Execute the current instruction
  4424. // and then check to see if the trap flag was set before the instruction
  4425. // was executed.
  4426. //
  4427. if (TF)
  4428. TrapFlagSet = TRUE;
  4429. else
  4430. TrapFlagSet = FALSE;
  4431. //
  4432. // Initialize source operand variables and save the instruction pointer.
  4433. //
  4434. LSRC->OperandType = NullOperand;
  4435. RSRC->OperandType = NullOperand;
  4436. CurrentIP.X = IP;
  4437. //
  4438. // Read the operation code byte from memory
  4439. //
  4440. OperationCodeByte = CodeMem(IP); IP++;
  4441. //
  4442. // Decode the left and right operands
  4443. //
  4444. if (OperationCodeByte == 0x0f)
  4445. {
  4446. //
  4447. // This is a 286 Protected Mode Instructions
  4448. //
  4449. ExtendedOperationCodeByte = CodeMem(IP); IP++;
  4450. if (ExtendedOperationCodeByte == 0x01)
  4451. GetMemory16OrRegister16Operand(LSRC);
  4452. }
  4453. else
  4454. {
  4455. //
  4456. // See if an address mode byte needs to be parsed and compute the sub index
  4457. // into the instruction decoding table.
  4458. //
  4459. if (AddressModeByteRequired[DecodeOperandsTable[OperationCodeByte][0]] ||
  4460. AddressModeByteRequired[DecodeOperandsTable[OperationCodeByte][1]] )
  4461. {
  4462. GetAddressModeByte();
  4463. InstructionSubIndex = reg;
  4464. }
  4465. else
  4466. InstructionSubIndex = 0;
  4467. //
  4468. // Call address decoding function for the left operand
  4469. //
  4470. (DecodeOperandFunctionTable[DecodeOperandsTable[OperationCodeByte][0]])(LSRC);
  4471. //
  4472. // Call address decoding function for the right operand
  4473. //
  4474. (DecodeOperandFunctionTable[DecodeOperandsTable[OperationCodeByte][1]])(RSRC);
  4475. }
  4476. //
  4477. // Execute the instruction
  4478. //
  4479. if (SegmentOveridePrefix==TRUE ||
  4480. RepeatPrefix==TRUE ||
  4481. LockPrefix==TRUE )
  4482. {
  4483. //
  4484. // Prefix instructions have been parsed, so handle this in a special case.
  4485. // Save the state of the prefix variables.
  4486. //
  4487. SavedSegmentOveridePrefix = SegmentOveridePrefix;
  4488. SavedRepeatPrefix = RepeatPrefix;
  4489. SavedLockPrefix = LockPrefix;
  4490. //
  4491. // Call function to execute the instruction
  4492. //
  4493. (DecodeInstructionFunctionTable[DecodeInstructionTable[OperationCodeByte][InstructionSubIndex]])();
  4494. //
  4495. // See if this was another prefix instruction by comparing the state of the
  4496. // prefix variables before and after the current instruction has been executed.
  4497. //
  4498. if (SavedSegmentOveridePrefix==SegmentOveridePrefix &&
  4499. SavedRepeatPrefix==RepeatPrefix &&
  4500. SavedLockPrefix==LockPrefix )
  4501. {
  4502. //
  4503. // If the state did not change, then the current instruction is not a prefix
  4504. // instruction, so all the prefix variables should be cleared.
  4505. //
  4506. SegmentOveridePrefix = FALSE;
  4507. RepeatPrefix = FALSE;
  4508. LockPrefix = FALSE;
  4509. }
  4510. }
  4511. else
  4512. {
  4513. //
  4514. // Call function to execute the instruction
  4515. //
  4516. (DecodeInstructionFunctionTable[DecodeInstructionTable[OperationCodeByte][InstructionSubIndex]])();
  4517. }
  4518. //
  4519. // If the trap flag was set then exit the emulator.
  4520. //
  4521. if (TrapFlagSet)
  4522. {
  4523. ErrorCode = x86BiosTrapFlagAsserted;
  4524. ExitFlag = TRUE;
  4525. }
  4526. }
  4527. }
  4528. static VOID x86FarCall(
  4529. USHORT pCS,
  4530. USHORT pIP
  4531. )
  4532. /*++
  4533. Routine Description:
  4534. This function makes a far call to the instruction at pCS:pIP. The
  4535. emulator will exit when the far call returns. To set up the exit
  4536. condition, a far call instruction is built at 0000:0501. CS and IP
  4537. are then initialized to 0000:0501, and the exit condition is intialized
  4538. to 0000:0506. When the emulator returns from the far call constructed at
  4539. 0000:0501, it will attempt to execute the instruction at 0000:0506, but
  4540. the exit condition has been met, so the emulator exits.
  4541. Arguments:
  4542. pCS - Segment of the far call.
  4543. pIP - Offset of the far call.
  4544. Return Value:
  4545. None.
  4546. --*/
  4547. {
  4548. //
  4549. // Build the far call instruction.
  4550. //
  4551. PutAbsoluteMem(0x00501,0x9a);
  4552. PutAbsoluteMem(0x00502,pIP);
  4553. PutAbsoluteMem(0x00503,pIP >> 8);
  4554. PutAbsoluteMem(0x00504,pCS);
  4555. PutAbsoluteMem(0x00505,pCS >> 8);
  4556. //
  4557. // Initialize the exit condition.
  4558. //
  4559. ExitSegment = 0x0000;
  4560. ExitOffset = 0x0506;
  4561. //
  4562. // Initialize the instruction pointer.
  4563. //
  4564. CS = 0x0000;
  4565. CSCacheRegister = GetSegmentCacheRegister(CS);
  4566. IP = 0x0501;
  4567. //
  4568. // Start the emulator
  4569. //
  4570. Interpreter();
  4571. }
  4572. X86BIOS_STATUS X86BiosInitializeAdapter(
  4573. ULONG Address
  4574. )
  4575. /*++
  4576. Routine Description:
  4577. This function attempts to initialize the adapter whose BIOS starts at
  4578. Address. First, a BIOS signature is verified. If the byte stored at
  4579. Address is 0x55 and the byte stored at Address+1 is 0xAA, then a
  4580. correct BIOS signature is present. Then, the byte at Address+2 encodes
  4581. the length of the BIOS across which a check sum should be performed. If
  4582. this check sum is verified, then a far call is made the Address+3.
  4583. Arguments:
  4584. Address - 20 bit base address of the adapter BIOS to be initialize.
  4585. Return Value:
  4586. None.
  4587. --*/
  4588. {
  4589. ULONG i;
  4590. ErrorCode = x86BiosSuccess;
  4591. //
  4592. // Check for a valid adapter BIOS signature.
  4593. //
  4594. if (GetAbsoluteMem(Address)!=0x55 || GetAbsoluteMem(Address+1)!=0xAA)
  4595. {
  4596. ErrorCode = x86BiosNoVideoBios;
  4597. return(ErrorCode);
  4598. }
  4599. //
  4600. // Perform checksum using byte 2 as the length of bios to perform check sum across
  4601. // If not correct set ErrorCode to InvalidBiosChecksum.
  4602. //
  4603. if (ErrorCode==x86BiosSuccess)
  4604. {
  4605. //
  4606. // Not implemented yet.
  4607. //
  4608. }
  4609. if (ErrorCode==x86BiosSuccess)
  4610. {
  4611. //
  4612. // Make a far call to Address + 3.
  4613. //
  4614. Address+=3;
  4615. x86FarCall(Address >>4,Address&0x000f);
  4616. }
  4617. //
  4618. // If an error occurred, send some info out the debug port.
  4619. //
  4620. if (ErrorCode!=x86BiosSuccess)
  4621. {
  4622. KdPrint(("x86Int() : ErrorCode = %d\n",ErrorCode));
  4623. KdPrint((" ISA I/O Virtul Base = %08X\n",BiosIsaIoBaseAddress));
  4624. KdPrint((" ISA Memory Virtual Base = %08x\n",ISABaseAddress));
  4625. KdPrint((" Main Memory [0-0x800] = %08X\n",VDMBaseAddress));
  4626. KdPrint((" CS:IP = %04X:%04X\n ",CS,CurrentIP.X));
  4627. for(i=0;i<16;i++)
  4628. KdPrint(("%02X ",GetMemImmediate(CS,CurrentIP.X+i)));
  4629. KdPrint(("\n"));
  4630. }
  4631. return(ErrorCode);
  4632. }
  4633. X86BIOS_STATUS X86BiosExecuteInt(
  4634. USHORT Type,
  4635. PX86BIOS_CONTEXT Arguments
  4636. )
  4637. /*++
  4638. Routine Description:
  4639. This function executes an INT call. It assumes that the interrupt
  4640. vector table has already been initialized, and that the INT vector
  4641. for Type is valid. The values for the registers AX,BX,CX,DX,SI,DI, and
  4642. BP are passed in Arguments. These registers are initialized to
  4643. their new values, and an INT instruction is constructed at 0000:0506.
  4644. The exit condition is initialized to 0000:0508. After the INT call
  4645. completes, the new values of AX,BX,CX,DX,SI,DI,BP are placed back into
  4646. the Arguments data structure.
  4647. Arguments:
  4648. Type - 8 bit interrupt type.
  4649. Arguments - Data structure used to pass in and pass out the values
  4650. of the registers AX,BX,CX,DX,SI,DI, and BP.
  4651. Return Value:
  4652. Success if no error were encountered. Otherwise, an error code from
  4653. the emulator.
  4654. --*/
  4655. {
  4656. ULONG i;
  4657. ErrorCode = x86BiosSuccess;
  4658. //
  4659. // Initialize register values
  4660. //
  4661. EAX = Arguments->Eax;
  4662. EBX = Arguments->Ebx;
  4663. ECX = Arguments->Ecx;
  4664. EDX = Arguments->Edx;
  4665. ESI = Arguments->Esi;
  4666. EDI = Arguments->Edi;
  4667. EBP = Arguments->Ebp;
  4668. ES = 0;
  4669. DS = 0;
  4670. Flags.X = 0;
  4671. //
  4672. // Build INT Type instruction.
  4673. //
  4674. PutAbsoluteMem(0x00506,0xcd);
  4675. PutAbsoluteMem(0x00507,Type);
  4676. //
  4677. // Initialize exit condition.
  4678. //
  4679. ExitSegment = 0x0000;
  4680. ExitOffset = 0x0508;
  4681. //
  4682. // Initialize instruction pointer.
  4683. //
  4684. CS = 0x0000;
  4685. CSCacheRegister = GetSegmentCacheRegister(CS);
  4686. IP = 0x0506;
  4687. //
  4688. // Start the emulator.
  4689. //
  4690. Interpreter();
  4691. //
  4692. // Copy the new register values back into Arguments.
  4693. //
  4694. Arguments->Eax = EAX;
  4695. Arguments->Ebx = EBX;
  4696. Arguments->Ecx = ECX;
  4697. Arguments->Edx = EDX;
  4698. Arguments->Esi = ESI;
  4699. Arguments->Edi = EDI;
  4700. Arguments->Ebp = EBP;
  4701. //
  4702. // If an error occurred, send some info out the debug port.
  4703. //
  4704. if (ErrorCode!=x86BiosSuccess) {
  4705. DbgPrint(("x86Int() : ErrorCode = %d\n",ErrorCode));
  4706. DbgPrint((" ISA I/O Virtul Base = %08X\n",BiosIsaIoBaseAddress));
  4707. DbgPrint((" ISA Memory Virtual Base = %08x\n",ISABaseAddress));
  4708. DbgPrint((" Main Memory [0-0x800] = %08X\n",VDMBaseAddress));
  4709. DbgPrint((" CS:IP = %04X:%04X\n ",CS,CurrentIP.X));
  4710. for(i=0;i<16;i++)
  4711. DbgPrint(("%02X ",GetMemImmediate(CS,CurrentIP.X+i)));
  4712. DbgPrint(("\n"));
  4713. DbgBreakPoint();
  4714. }
  4715. return(ErrorCode);
  4716. }
  4717. VOID X86BiosInitialize(
  4718. ULONG IsaIoVirtualBase,
  4719. ULONG IsaMemoryVirtualBase
  4720. )
  4721. /*++
  4722. Routine Description:
  4723. This function initialize the state of the 80286 processor, and the
  4724. state of the available memory.
  4725. Arguments:
  4726. IsaIoVirtualBase - Noncached virtual address range that is 64KB long
  4727. and is mapped to the system's ISA I/O range.
  4728. IsaMemoryVirtualBase - Noncached virtual address ranges that is 1MB
  4729. long ans is mapped to the system's ISA memory
  4730. range.
  4731. Return Value:
  4732. Success if no error were encountered. Otherwise, an error code from
  4733. the emulator.
  4734. --*/
  4735. {
  4736. ULONG i;
  4737. //
  4738. // Initialize state of the 80286 processor.
  4739. //
  4740. SegmentOveridePrefix = FALSE;
  4741. RepeatPrefix = FALSE;
  4742. LockPrefix = FALSE;
  4743. IP = 0;
  4744. CS = 0;
  4745. CSCacheRegister = GetSegmentCacheRegister(CS);
  4746. DS = 0;
  4747. SS = 0;
  4748. SSCacheRegister = GetSegmentCacheRegister(SS);
  4749. ES = 0;
  4750. AX = 0;
  4751. BX = 0;
  4752. CX = 0;
  4753. DX = 0;
  4754. SP = 0;
  4755. BP = 0;
  4756. SI = 0;
  4757. DI = 0;
  4758. Flags.X = 0;
  4759. msw = 0;
  4760. gdtBase = 0;
  4761. gdtLimit = 0;
  4762. idtBase = 0;
  4763. idtLimit = 0;
  4764. //
  4765. // Initialize the variables used to perform I/O and memory operations.
  4766. //
  4767. BiosIsaIoBaseAddress = IsaIoVirtualBase;
  4768. ISABaseAddress = IsaMemoryVirtualBase;
  4769. VDMBaseAddress = (ULONG)(&(MemoryArray[0]));
  4770. //
  4771. // Intiialize all 256 INT vector to jump to 0000:0500
  4772. //
  4773. for(i=0;i<256;i++)
  4774. {
  4775. PutAbsoluteMem(i*4+0,0x00); // Fill in all INT vectors to jump to 0x00500
  4776. PutAbsoluteMem(i*4+1,0x05);
  4777. PutAbsoluteMem(i*4+2,0x00);
  4778. PutAbsoluteMem(i*4+3,0x00);
  4779. }
  4780. //
  4781. // Place an IRET instruction at 0000:0500.
  4782. // This way, if an INT call is made that does not exist, the emulator
  4783. // will just immediatly reach its exit condition and return.
  4784. //
  4785. PutAbsoluteMem(0x00500,0xcf);
  4786. //
  4787. // Intialize the spack pointer to the top of the available memory.
  4788. //
  4789. SS = 0x0000;
  4790. SP = 0x07fe;
  4791. }