jslinux/cpux86-ta.js

9715 lines
392 KiB
JavaScript
Raw Normal View History

/*
Fabrix - An annotated version of the original JSLinux Copyright (c) 2011 Fabrice Bellard
==================================================================================================
A x86 CPU (circa 486 sans FPU) Emulator
Useful references:
======================================================================
http://pdos.csail.mit.edu/6.828/2005/readings/i386/ <-- super useful
http://ref.x86asm.net/coder32.html#xC4
2011-12-20 21:20:23 +08:00
http://en.wikibooks.org/wiki/X86_Assembly/X86_Architecture
2011-12-17 20:22:50 +08:00
http://en.wikipedia.org/wiki/X86
http://en.wikipedia.org/wiki/Control_register
http://en.wikipedia.org/wiki/X86_assembly_language
http://en.wikipedia.org/wiki/Translation_lookaside_buffer
http://bellard.org/jslinux/tech.html :
"""
The exact restrictions of the emulated CPU are:
- No FPU/MMX/SSE
- No segment limit and right checks when accessing memory (Linux does not rely on them for memory protection,
so it is not an issue. The x86 emulator of QEMU has the same restriction).
- No single-stepping
I added some tricks which are not present in QEMU to be more precise
when emulating unaligned load/stores at page boundaries. The condition
code emulation is also more efficient than the one in QEMU.
"""
Memory Modes
=====================================================================
The x86 transforms logical addresses (i.e., addresses as viewed by
programmers) into physical address (i.e., actual addresses in physical
memory) in two steps:
- Segment translation, in which a logical address (consisting of a
segment selector and segment offset) are converted to a linear
address.
- Page translation, in which a linear address is converted to
a physical address. This step is optional, at the discretion of
systems-software designers.
Paged Memory
--------------
A page table is simply an array of 32-bit page specifiers. A page
table is itself a page, and therefore contains 4 Kilobytes of memory
or at most 1K 32-bit entries. Two levels of tables are used to
address a page of memory. At the higher level is a page directory. The
page directory addresses up to 1K page tables of the second level. A
page table of the second level addresses up to 1K pages. All the
tables addressed by one page directory, therefore, can address 1M
pages (2^(20)). Because each page contains 4K bytes 2^(12) bytes), the
tables of one page directory can span the entire physical address
space of the 80386 (2^(20) times 2^(12) = 2^(32)).
2011-12-17 20:22:50 +08:00
Hints for Bit Twiddling
=========================================================
2011-12-23 21:44:05 +08:00
X & (2^N-1) = mask for lower N bits of X
X & -2^N = mask for upper N bits of X (for two's complement)
X & 3 = mask for lower 2 bits for X
X & 7 = mask for lower 7 bits for X
X & -4096 = mask for upper 20 bits for X
2011-12-17 20:22:50 +08:00
((x << 16) >> 16) = clears top 16bits, enforces word-size data
((x << 24) >> 24) = clears top 24bits, enforces byte-size data
2011-12-23 21:44:05 +08:00
(1<<0 | 1<<4 | 1<<7) = sets bits 0,4,7 to 1, rest to 0
*/
/* Parity Check by LUT:
2011-12-23 21:44:05 +08:00
static const bool ParityTable256[256] = {
# define P2(n) n, n^1, n^1, n
# define P4(n) P2(n), P2(n^1), P2(n^1), P2(n)
# define P6(n) P4(n), P4(n^1), P4(n^1), P4(n)
P6(0), P6(1), P6(1), P6(0) };
unsigned char b; // byte value to compute the parity of
bool parity = ParityTable256[b];
// OR, for 32-bit words: unsigned int v; v ^= v >> 16; v ^= v >> 8; bool parity = ParityTable256[v & 0xff];
// Variation: unsigned char * p = (unsigned char *) &v; parity = ParityTable256[p[0] ^ p[1] ^ p[2] ^ p[3]];
*/
var parity_LUT = [1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1];
2011-12-23 21:44:05 +08:00
var shift16_LUT = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14];
var shift8_LUT = [0, 1, 2, 3, 4, 5, 6, 7, 8, 0, 1, 2, 3, 4, 5, 6, 7, 8, 0, 1, 2, 3, 4, 5, 6, 7, 8, 0, 1, 2, 3, 4];
2011-12-17 13:13:37 +08:00
2011-12-17 12:16:10 +08:00
function CPU_X86() {
2011-12-17 17:17:40 +08:00
var i, tlb_size;
/*
AX/EAX/RAX: Accumulator
BX/EBX/RBX: Base index (for use with arrays)
CX/ECX/RCX: Counter
DX/EDX/RDX: Data/general
SI/ESI/RSI: Source index for string operations.
DI/EDI/RDI: Destination index for string operations.
SP/ESP/RSP: Stack pointer for top address of the stack.
BP/EBP/RBP: Stack base pointer for holding the address of the current stack frame.
*/
this.regs = new Array(); // EAX, EBX, ECX, EDX, ESI, EDI, ESP, EBP 32bit registers
2011-12-17 17:17:40 +08:00
for (i = 0; i < 8; i++) {
this.regs[i] = 0;
}
/* IP/EIP/RIP: Instruction pointer. Holds the program counter, the current instruction address. */
this.eip = 0; //instruction pointer
this.cc_op = 0; // current op
this.cc_dst = 0; // current dest
this.cc_src = 0; // current src
this.cc_op2 = 0; // current op, byte2
this.cc_dst2 = 0; // current dest, byte2
2011-12-23 01:49:18 +08:00
this.df = 1; // Direction Flag
2011-12-20 21:20:23 +08:00
/*
2011-12-21 09:18:08 +08:00
0. CF : Carry Flag. Set if the last arithmetic operation carried (addition) or borrowed (subtraction) a
2011-12-20 21:20:23 +08:00
bit beyond the size of the register. This is then checked when the operation is followed with
an add-with-carry or subtract-with-borrow to deal with values too large for just one register to contain.
2011-12-21 09:18:08 +08:00
2. PF : Parity Flag. Set if the number of set bits in the least significant byte is a multiple of 2.
4. AF : Adjust Flag. Carry of Binary Code Decimal (BCD) numbers arithmetic operations.
6. ZF : Zero Flag. Set if the result of an operation is Zero (0).
7. SF : Sign Flag. Set if the result of an operation is negative.
8. TF : Trap Flag. Set if step by step debugging.
9. IF : Interruption Flag. Set if interrupts are enabled.
10. DF : Direction Flag. Stream direction. If set, string operations will decrement their pointer rather
2011-12-20 21:20:23 +08:00
than incrementing it, reading memory backwards.
2011-12-21 09:18:08 +08:00
11. OF : Overflow Flag. Set if signed arithmetic operations result in a value too large for the register to contain.
12-13. IOPL : I/O Privilege Level field (2 bits). I/O Privilege Level of the current process.
2011-12-21 09:18:08 +08:00
14. NT : Nested Task flag. Controls chaining of interrupts. Set if the current process is linked to the next process.
16. RF : Resume Flag. Response to debug exceptions.
17. VM : Virtual-8086 Mode. Set if in 8086 compatibility mode.
18. AC : Alignment Check. Set if alignment checking of memory references is done.
19. VIF : Virtual Interrupt Flag. Virtual image of IF.
20. VIP : Virtual Interrupt Pending flag. Set if an interrupt is pending.
21. ID : Identification Flag. Support for CPUID instruction if can be set.
2011-12-20 21:20:23 +08:00
*/
this.eflags = 0x2; // EFLAG register
2011-12-20 21:20:23 +08:00
2011-12-17 12:16:10 +08:00
this.cycle_count = 0;
2011-12-17 17:17:40 +08:00
this.hard_irq = 0;
this.hard_intno = -1;
this.cpl = 0; //cpu privilege level
/*
Control Registers
==========================================================================================
*/
/* CR0
---
31 PG Paging If 1, enable paging and use the CR3 register, else disable paging
30 CD Cache disable Globally enables/disable the memory cache
29 NW Not-write through Globally enables/disable write-back caching
18 AM Alignment mask Alignment check enabled if AM set, AC flag (in EFLAGS register) set, and privilege level is 3
16 WP Write protect Determines whether the CPU can write to pages marked read-only
5 NE Numeric error Enable internal x87 floating point error reporting when set, else enables PC style x87 error detection
4 ET Extension type On the 386, it allowed to specify whether the external math coprocessor was an 80287 or 80387
3 TS Task switched Allows saving x87 task context only after x87 instruction used after task switch
2 EM Emulation If set, no x87 floating point unit present, if clear, x87 FPU present
1 MP Monitor co-processor Controls interaction of WAIT/FWAIT instructions with TS flag in CR0
0 PE Protected Mode Enable If 1, system is in protected mode, else system is in real mode
*/
this.cr0 = (1 << 0); //PE-mode ON
/* CR2
---
Page Fault Linear Address (PFLA) When a page fault occurs,
the address the program attempted to access is stored in the
CR2 register. */
this.cr2 = 0;
/* CR3
---
Used when virtual addressing is enabled, hence when the PG
bit is set in CR0. CR3 enables the processor to translate
virtual addresses into physical addresses by locating the page
2011-12-23 20:24:16 +08:00
directory and page tables for the current task.
Typically, the upper 20 bits of CR3 become the page directory
base register (PDBR), which stores the physical address of the
first page directory entry. */
this.cr3 = 0;
/* CR4
---
Used in protected mode to control operations such as virtual-8086 support, enabling I/O breakpoints,
page size extension and machine check exceptions.
2011-12-21 09:18:08 +08:00
Bit Name Full Name Description
18 OSXSAVE XSAVE and Processor Extended States Enable
17 PCIDE PCID Enable If set, enables process-context identifiers (PCIDs).
14 SMXE SMX Enable
13 VMXE VMX Enable
10 OSXMMEXCPT Operating System Support for Unmasked SIMD Floating-Point Exceptions If set, enables unmasked SSE exceptions.
9 OSFXSR Operating system support for FXSAVE and FXSTOR instructions If set, enables SSE instructions and fast FPU save & restore
8 PCE Performance-Monitoring Counter enable
If set, RDPMC can be executed at any privilege level, else RDPMC can only be used in ring 0.
2011-12-21 09:18:08 +08:00
7 PGE Page Global Enabled If set, address translations (PDE or PTE records) may be shared between address spaces.
6 MCE Machine Check Exception If set, enables machine check interrupts to occur.
5 PAE Physical Address Extension
If set, changes page table layout to translate 32-bit virtual addresses into extended 36-bit physical addresses.
2011-12-21 09:18:08 +08:00
4 PSE Page Size Extensions If unset, page size is 4 KB, else page size is increased to 4 MB (ignored with PAE set).
3 DE Debugging Extensions
2 TSD Time Stamp Disable
If set, RDTSC instruction can only be executed when in ring 0, otherwise RDTSC can be used at any privilege level.
2011-12-21 09:18:08 +08:00
1 PVI Protected-mode Virtual Interrupts If set, enables support for the virtual interrupt flag (VIF) in protected mode.
0 VME Virtual 8086 Mode Extensions If set, enables support for the virtual interrupt flag (VIF) in virtual-8086 mode.
*/
this.cr4 = 0;
/*
Segment registers:
--------------------
2011-12-21 10:28:01 +08:00
ES: Extra
CS: Code
SS: Stack
2011-12-21 10:28:01 +08:00
DS: Data
FS: Extra
GS: Extra
In memory addressing for Intel x86 computer architectures,
segment descriptors are a part of the segmentation unit, used for
translating a logical address to a linear address. Segment descriptors
describe the memory segment referred to in the logical address.
The segment descriptor (8 bytes long in 80286) contains the following
fields:
- A segment base address
- The segment limit which specifies the segment limit
- Access rights byte containing the protection mechanism information
- Control bits
*/
/* NOTE: Only segs 0->5 appear to be used in the code, so only ES->GS */
this.segs = new Array(); // [" ES", " CS", " SS", " DS", " FS", " GS", "LDT", " TR"]
for (i = 0; i < 7; i++) {
this.segs[i] = {selector: 0, base: 0, limit: 0, flags: 0};
}
this.segs[2].flags = (1 << 22); // SS
this.segs[1].flags = (1 << 22); // CS
/* Interrupt Descriptor Table
---------------------------
The interrupt descriptor table (IDT) associates each interrupt
or exception identifier with a descriptor for the instructions
that service the associated event. Like the GDT and LDTs, the
IDT is an array of 8-byte descriptors. Unlike the GDT and LDTs,
the first entry of the IDT may contain a descriptor.
2011-12-17 13:13:37 +08:00
To form an index into the IDT, the processor multiplies the
interrupt or exception identifier by eight. Because there are
only 256 identifiers, the IDT need not contain more than 256
descriptors. It can contain fewer than 256 entries; entries are
required only for interrupt identifiers that are actually used. */
this.idt = {base: 0, limit: 0};
// The Global Descriptor Table
this.gdt = {base: 0, limit: 0};
// The Local Descriptor Table
this.ldt = {selector: 0, base: 0, limit: 0, flags: 0};
/* Task Register
--------------
The task register (TR) identifies the currently executing task
by pointing to the TSS.
The task register has both a "visible" portion (i.e., can be
read and changed by instructions) and an "invisible" portion
(maintained by the processor to correspond to the visible
portion; cannot be read by any instruction). The selector in
the visible portion selects a TSS descriptor in the GDT. The
processor uses the invisible portion to cache the base and
limit values from the TSS descriptor. Holding the base and
limit in a register makes execution of the task more efficient,
because the processor does not need to repeatedly fetch these
values from memory when it references the TSS of the current
task.
The instructions LTR and STR are used to modify and read the
visible portion of the task register. Both instructions take
one operand, a 16-bit selector located in memory or in a
general register.
LTR (Load task register) loads the visible portion of the task
register with the selector operand, which must select a TSS
descriptor in the GDT. LTR also loads the invisible portion
with information from the TSS descriptor selected by the
operand. LTR is a privileged instruction; it may be executed
only when CPL is zero. LTR is generally used during system
initialization to give an initial value to the task register;
thereafter, the contents of TR are changed by task switch
operations.
STR (Store task register) stores the visible portion of the task
register in a general register or memory word. STR is not privileged.
All the information the processor needs in order to manage a
task is stored in a special type of segment, a task state
segment (TSS). The fields of a TSS belong to two classes:
1. A dynamic set that the processor updates with each switch from the
task. This set includes the fields that store:
- The general registers (EAX, ECX, EDX, EBX, ESP, EBP, ESI, EDI).
- The segment registers (ES, CS, SS, DS, FS, GS).
- The flags register (EFLAGS).
- The instruction pointer (EIP).
- The selector of the TSS of the previously executing task (updated only when a return is expected).
2. A static set that the processor reads but does not change. This
set includes the fields that store:
- The selector of the task's LDT.
- The register (PDBR) that contains the base address of the task's
page directory (read only when paging is enabled).
- Pointers to the stacks for privilege levels 0-2.
- The T-bit (debug trap bit) which causes the processor to raise a
debug exception when a task switch occurs.
- The I/O map base
*/
this.tr = {selector: 0, base: 0, limit: 0, flags: 0};
2011-12-17 12:16:10 +08:00
this.halted = 0;
this.phys_mem = null; //pointer to raw memory buffer allocated by browser
2011-12-17 17:17:40 +08:00
/*
A translation lookaside buffer (TLB) is a CPU cache that memory
management hardware uses to improve virtual address translation
speed.
A TLB has a fixed number of slots that contain page table
entries, which map virtual addresses to physical addresses. The
virtual memory is the space seen from a process. This space is
segmented in pages of a prefixed size. The page table
(generally loaded in memory) keeps track of where the virtual
pages are loaded in the physical memory. The TLB is a cache of
the page table; that is, only a subset of its content are
stored.
*/
tlb_size = 0x100000; //2^20=1048576 * 4096 ~= 4GB total memory possible
2011-12-17 17:17:40 +08:00
this.tlb_read_kernel = new Int32Array(tlb_size);
this.tlb_write_kernel = new Int32Array(tlb_size);
this.tlb_read_user = new Int32Array(tlb_size);
this.tlb_write_user = new Int32Array(tlb_size);
for (i = 0; i < tlb_size; i++) {
2011-12-17 13:13:37 +08:00
this.tlb_read_kernel[i] = -1;
2011-12-17 12:16:10 +08:00
this.tlb_write_kernel[i] = -1;
2011-12-17 13:13:37 +08:00
this.tlb_read_user[i] = -1;
this.tlb_write_user[i] = -1;
2011-12-17 12:16:10 +08:00
}
this.tlb_pages = new Int32Array(2048);
this.tlb_pages_count = 0;
}
/* Allocates a memory chunnk new_mem_size bytes long and makes 8,16,32 bit array references into it */
2011-12-17 13:13:37 +08:00
CPU_X86.prototype.phys_mem_resize = function(new_mem_size) {
this.mem_size = new_mem_size;
new_mem_size += ((15 + 3) & ~3);
this.phys_mem = new ArrayBuffer(new_mem_size);
this.phys_mem8 = new Uint8Array(this.phys_mem, 0, new_mem_size);
2011-12-17 13:13:37 +08:00
this.phys_mem16 = new Uint16Array(this.phys_mem, 0, new_mem_size / 2);
this.phys_mem32 = new Int32Array(this.phys_mem, 0, new_mem_size / 4);
2011-12-17 12:16:10 +08:00
};
2011-12-17 13:13:37 +08:00
/* Raw, low level memory access routines to alter the host-stored memory, these are called by the higher-level
memory access emulation routines */
CPU_X86.prototype.ld8_phys = function(mem8_loc) { return this.phys_mem8[mem8_loc]; };
CPU_X86.prototype.st8_phys = function(mem8_loc, x) { this.phys_mem8[mem8_loc] = x; };
CPU_X86.prototype.ld32_phys = function(mem8_loc) { return this.phys_mem32[mem8_loc >> 2]; };
CPU_X86.prototype.st32_phys = function(mem8_loc, x) { this.phys_mem32[mem8_loc >> 2] = x; };
2011-12-17 13:13:37 +08:00
2011-12-23 21:44:05 +08:00
/*
TLB Routines
==========================================================================================
*/
2011-12-23 20:24:16 +08:00
CPU_X86.prototype.tlb_set_page = function(mem8_loc, page_val, set_write_tlb, set_user_tlb) {
2011-12-21 10:43:53 +08:00
var i, x, j;
2011-12-23 20:24:16 +08:00
page_val &= -4096; // only top 20bits matter
mem8_loc &= -4096; // only top 20bits matter
x = mem8_loc ^ page_val; // XOR used to simulate hashing
i = mem8_loc >>> 12; // top 20bits point to TLB
2011-12-17 12:16:10 +08:00
if (this.tlb_read_kernel[i] == -1) {
if (this.tlb_pages_count >= 2048) {
this.tlb_flush_all1((i - 1) & 0xfffff);
}
this.tlb_pages[this.tlb_pages_count++] = i;
}
2011-12-21 10:43:53 +08:00
this.tlb_read_kernel[i] = x;
2011-12-23 20:24:16 +08:00
if (set_write_tlb) {
2011-12-21 10:43:53 +08:00
this.tlb_write_kernel[i] = x;
2011-12-17 12:16:10 +08:00
} else {
this.tlb_write_kernel[i] = -1;
}
2011-12-23 20:24:16 +08:00
if (set_user_tlb) {
2011-12-21 10:43:53 +08:00
this.tlb_read_user[i] = x;
2011-12-23 20:24:16 +08:00
if (set_write_tlb) {
2011-12-21 10:43:53 +08:00
this.tlb_write_user[i] = x;
2011-12-17 12:16:10 +08:00
} else {
this.tlb_write_user[i] = -1;
}
} else {
this.tlb_read_user[i] = -1;
this.tlb_write_user[i] = -1;
}
};
2011-12-17 13:13:37 +08:00
CPU_X86.prototype.tlb_flush_page = function(mem8_loc) {
2011-12-17 12:16:10 +08:00
var i;
i = mem8_loc >>> 12;
2011-12-17 12:16:10 +08:00
this.tlb_read_kernel[i] = -1;
this.tlb_write_kernel[i] = -1;
this.tlb_read_user[i] = -1;
this.tlb_write_user[i] = -1;
};
2011-12-17 13:13:37 +08:00
2011-12-17 12:16:10 +08:00
CPU_X86.prototype.tlb_flush_all = function() {
2011-12-23 20:24:16 +08:00
var i, j, n, tlb_pages;
tlb_pages = this.tlb_pages;
2011-12-17 12:16:10 +08:00
n = this.tlb_pages_count;
for (j = 0; j < n; j++) {
2011-12-23 20:24:16 +08:00
i = tlb_pages[j];
2011-12-17 12:16:10 +08:00
this.tlb_read_kernel[i] = -1;
this.tlb_write_kernel[i] = -1;
this.tlb_read_user[i] = -1;
this.tlb_write_user[i] = -1;
}
this.tlb_pages_count = 0;
};
2011-12-17 13:13:37 +08:00
2011-12-17 12:16:10 +08:00
CPU_X86.prototype.tlb_flush_all1 = function(la) {
2011-12-23 20:24:16 +08:00
var i, j, n, tlb_pages, new_n;
tlb_pages = this.tlb_pages;
2011-12-17 12:16:10 +08:00
n = this.tlb_pages_count;
2011-12-23 20:24:16 +08:00
new_n = 0;
2011-12-17 12:16:10 +08:00
for (j = 0; j < n; j++) {
2011-12-23 20:24:16 +08:00
i = tlb_pages[j];
2011-12-17 12:16:10 +08:00
if (i == la) {
2011-12-23 20:24:16 +08:00
tlb_pages[new_n++] = i;
2011-12-17 12:16:10 +08:00
} else {
this.tlb_read_kernel[i] = -1;
this.tlb_write_kernel[i] = -1;
this.tlb_read_user[i] = -1;
this.tlb_write_user[i] = -1;
}
}
2011-12-23 20:24:16 +08:00
this.tlb_pages_count = new_n;
2011-12-17 12:16:10 +08:00
};
2011-12-17 13:13:37 +08:00
2011-12-23 21:44:05 +08:00
/*
String / Logging Routines
==========================================================================================
*/
/* writes ASCII string in na into memory location mem8_loc */
CPU_X86.prototype.write_string = function(mem8_loc, str) {
2011-12-17 12:16:10 +08:00
var i;
for (i = 0; i < str.length; i++) {
this.st8_phys(mem8_loc++, str.charCodeAt(i) & 0xff);
2011-12-17 12:16:10 +08:00
}
this.st8_phys(mem8_loc, 0);
2011-12-17 12:16:10 +08:00
};
2011-12-23 21:44:05 +08:00
/* Represents numeric value ga as n-digit HEX */
2011-12-21 10:43:53 +08:00
function hex_rep(x, n) {
2011-12-17 12:16:10 +08:00
var i, s;
var h = "0123456789ABCDEF";
s = "";
for (i = n - 1; i >= 0; i--) {
2011-12-21 10:43:53 +08:00
s = s + h[(x >>> (i * 4)) & 15];
2011-12-17 12:16:10 +08:00
}
return s;
}
2011-12-17 13:13:37 +08:00
function _4_bytes_(n) { return hex_rep(n, 8);} // Represents 8-hex bytes of n
function _2_bytes_(n) { return hex_rep(n, 2);} // Represents 4-hex bytes of n
function _1_byte_(n) { return hex_rep(n, 4);} // Represents 2-hex bytes of n
2011-12-17 12:16:10 +08:00
CPU_X86.prototype.dump_short = function() {
console.log(" EIP=" + _4_bytes_(this.eip) + " EAX=" + _4_bytes_(this.regs[0])
+ " ECX=" + _4_bytes_(this.regs[1]) + " EDX=" + _4_bytes_(this.regs[2]) + " EBX=" + _4_bytes_(this.regs[3]));
console.log(" EFL=" + _4_bytes_(this.eflags) + " ESP=" + _4_bytes_(this.regs[4])
+ " EBP=" + _4_bytes_(this.regs[5]) + " ESI=" + _4_bytes_(this.regs[6]) + " EDI=" + _4_bytes_(this.regs[7]));
2011-12-17 12:16:10 +08:00
};
CPU_X86.prototype.dump = function() {
var i, sa, str;
2011-12-17 12:16:10 +08:00
var ta = [" ES", " CS", " SS", " DS", " FS", " GS", "LDT", " TR"];
this.dump_short();
console.log("TSC=" + _4_bytes_(this.cycle_count) + " OP=" + _2_bytes_(this.cc_op)
+ " SRC=" + _4_bytes_(this.cc_src) + " DST=" + _4_bytes_(this.cc_dst)
+ " OP2=" + _2_bytes_(this.cc_op2) + " DST2=" + _4_bytes_(this.cc_dst2));
console.log("CPL=" + this.cpl + " CR0=" + _4_bytes_(this.cr0)
+ " CR2=" + _4_bytes_(this.cr2) + " CR3=" + _4_bytes_(this.cr3) + " CR4=" + _4_bytes_(this.cr4));
str = "";
2011-12-17 12:16:10 +08:00
for (i = 0; i < 8; i++) {
if (i == 6)
sa = this.ldt;
else if (i == 7)
sa = this.tr;
else
sa = this.segs[i];
str += ta[i] + "=" + _1_byte_(sa.selector) + " " + _4_bytes_(sa.base) + " "
+ _4_bytes_(sa.limit) + " " + _1_byte_((sa.flags >> 8) & 0xf0ff);
2011-12-17 12:16:10 +08:00
if (i & 1) {
console.log(str);
str = "";
2011-12-17 12:16:10 +08:00
} else {
str += " ";
2011-12-17 12:16:10 +08:00
}
}
sa = this.gdt;
str = "GDT= " + _4_bytes_(sa.base) + " " + _4_bytes_(sa.limit) + " ";
2011-12-17 12:16:10 +08:00
sa = this.idt;
str += "IDT= " + _4_bytes_(sa.base) + " " + _4_bytes_(sa.limit);
console.log(str);
2011-12-17 12:16:10 +08:00
};
2011-12-23 21:44:05 +08:00
/*
The Beast
==========================================================================================
*/
2011-12-23 21:15:54 +08:00
CPU_X86.prototype.exec_internal = function(N_cycles, interrupt) {
/*
2011-12-23 20:24:16 +08:00
x,y,z,v are either just general non-local values or their exact specialization is unclear,
esp. x,y look like they're used for everything
I don't know what 'v' should be called, it's not clear yet
*/
var cpu, mem8_loc, regs;
2011-12-17 16:20:47 +08:00
var _src, _dst, _op, _op2, _dst2;
2011-12-23 20:24:16 +08:00
var CS_flags, mem8, reg_idx0, OPbyte, reg_idx1, x, y, z, conditional_var, cycles_left, exit_code, v;
var CS_base, SS_base, SS_mask, FS_usage_flag, init_CS_flags, iopl;//io privilege level
2011-12-21 10:43:53 +08:00
var phys_mem8, last_tlb_val;
2011-12-17 15:55:29 +08:00
var phys_mem16, phys_mem32;
2011-12-17 17:17:40 +08:00
var tlb_read_kernel, tlb_write_kernel, tlb_read_user, tlb_write_user, _tlb_read_, _tlb_write_;
/* Storing XOR values as small lookup table is software equivalent of a Translation Lookaside Buffer (TLB) */
function __ld_8bits_mem8_read() {
var tlb_lookup;
do_tlb_set_page(mem8_loc, 0, cpu.cpl == 3);
tlb_lookup = _tlb_read_[mem8_loc >>> 12] ^ mem8_loc;
return phys_mem8[tlb_lookup];
2011-12-17 12:16:10 +08:00
}
function ld_8bits_mem8_read() {
2011-12-21 10:43:53 +08:00
var last_tlb_val;
return (((last_tlb_val = _tlb_read_[mem8_loc >>> 12]) == -1) ? __ld_8bits_mem8_read() : phys_mem8[mem8_loc ^ last_tlb_val]);
2011-12-17 12:16:10 +08:00
}
function __ld_16bits_mem8_read() {
2011-12-21 10:43:53 +08:00
var x;
x = ld_8bits_mem8_read();
mem8_loc++;
2011-12-21 10:43:53 +08:00
x |= ld_8bits_mem8_read() << 8;
mem8_loc--;
2011-12-21 10:43:53 +08:00
return x;
2011-12-17 12:16:10 +08:00
}
function ld_16bits_mem8_read() {
2011-12-21 10:43:53 +08:00
var last_tlb_val;
return (((last_tlb_val = _tlb_read_[mem8_loc >>> 12]) | mem8_loc) & 1 ? __ld_16bits_mem8_read() : phys_mem16[(mem8_loc ^ last_tlb_val) >> 1]);
2011-12-17 12:16:10 +08:00
}
function __ld_32bits_mem8_read() {
2011-12-21 10:43:53 +08:00
var x;
x = ld_8bits_mem8_read();
mem8_loc++;
2011-12-21 10:43:53 +08:00
x |= ld_8bits_mem8_read() << 8;
mem8_loc++;
2011-12-21 10:43:53 +08:00
x |= ld_8bits_mem8_read() << 16;
mem8_loc++;
2011-12-21 10:43:53 +08:00
x |= ld_8bits_mem8_read() << 24;
mem8_loc -= 3;
2011-12-21 10:43:53 +08:00
return x;
2011-12-17 12:16:10 +08:00
}
function ld_32bits_mem8_read() {
2011-12-21 10:43:53 +08:00
var last_tlb_val;
return (((last_tlb_val = _tlb_read_[mem8_loc >>> 12]) | mem8_loc) & 3 ? __ld_32bits_mem8_read() : phys_mem32[(mem8_loc ^ last_tlb_val) >> 2]);
2011-12-17 12:16:10 +08:00
}
function __ld_8bits_mem8_write() {
var tlb_lookup;
do_tlb_set_page(mem8_loc, 1, cpu.cpl == 3);
tlb_lookup = _tlb_write_[mem8_loc >>> 12] ^ mem8_loc;
return phys_mem8[tlb_lookup];
2011-12-17 12:16:10 +08:00
}
function ld_8bits_mem8_write() {
var tlb_lookup;
return ((tlb_lookup = _tlb_write_[mem8_loc >>> 12]) == -1) ? __ld_8bits_mem8_write() : phys_mem8[mem8_loc ^ tlb_lookup];
2011-12-17 12:16:10 +08:00
}
function __ld_16bits_mem8_write() {
2011-12-21 10:43:53 +08:00
var x;
x = ld_8bits_mem8_write();
mem8_loc++;
2011-12-21 10:43:53 +08:00
x |= ld_8bits_mem8_write() << 8;
mem8_loc--;
2011-12-21 10:43:53 +08:00
return x;
2011-12-17 12:16:10 +08:00
}
function ld_16bits_mem8_write() {
var tlb_lookup;
return ((tlb_lookup = _tlb_write_[mem8_loc >>> 12]) | mem8_loc) & 1 ? __ld_16bits_mem8_write() : phys_mem16[(mem8_loc ^ tlb_lookup) >> 1];
2011-12-17 12:16:10 +08:00
}
function __ld_32bits_mem8_write() {
2011-12-21 10:43:53 +08:00
var x;
x = ld_8bits_mem8_write();
mem8_loc++;
2011-12-21 10:43:53 +08:00
x |= ld_8bits_mem8_write() << 8;
mem8_loc++;
2011-12-21 10:43:53 +08:00
x |= ld_8bits_mem8_write() << 16;
mem8_loc++;
2011-12-21 10:43:53 +08:00
x |= ld_8bits_mem8_write() << 24;
mem8_loc -= 3;
2011-12-21 10:43:53 +08:00
return x;
2011-12-17 12:16:10 +08:00
}
function ld_32bits_mem8_write() {
var tlb_lookup;
return ((tlb_lookup = _tlb_write_[mem8_loc >>> 12]) | mem8_loc) & 3 ? __ld_32bits_mem8_write() : phys_mem32[(mem8_loc ^ tlb_lookup) >> 2];
2011-12-17 12:16:10 +08:00
}
function __st8_mem8_write(x) {
var tlb_lookup;
do_tlb_set_page(mem8_loc, 1, cpu.cpl == 3);
tlb_lookup = _tlb_write_[mem8_loc >>> 12] ^ mem8_loc;
phys_mem8[tlb_lookup] = x;
2011-12-17 12:16:10 +08:00
}
function st8_mem8_write(x) {
2011-12-21 10:43:53 +08:00
var last_tlb_val;
2011-12-17 12:16:10 +08:00
{
2011-12-21 10:43:53 +08:00
last_tlb_val = _tlb_write_[mem8_loc >>> 12];
if (last_tlb_val == -1) {
__st8_mem8_write(x);
2011-12-17 12:16:10 +08:00
} else {
2011-12-21 10:43:53 +08:00
phys_mem8[mem8_loc ^ last_tlb_val] = x;
2011-12-17 12:16:10 +08:00
}
}
}
function __st16_mem8_write(x) {
st8_mem8_write(x);
mem8_loc++;
st8_mem8_write(x >> 8);
mem8_loc--;
2011-12-17 12:16:10 +08:00
}
function st16_mem8_write(x) {
2011-12-21 10:43:53 +08:00
var last_tlb_val;
2011-12-17 12:16:10 +08:00
{
2011-12-21 10:43:53 +08:00
last_tlb_val = _tlb_write_[mem8_loc >>> 12];
if ((last_tlb_val | mem8_loc) & 1) {
__st16_mem8_write(x);
2011-12-17 12:16:10 +08:00
} else {
2011-12-21 10:43:53 +08:00
phys_mem16[(mem8_loc ^ last_tlb_val) >> 1] = x;
2011-12-17 12:16:10 +08:00
}
}
}
function __st32_mem8_write(x) {
st8_mem8_write(x);
mem8_loc++;
st8_mem8_write(x >> 8);
mem8_loc++;
st8_mem8_write(x >> 16);
mem8_loc++;
st8_mem8_write(x >> 24);
mem8_loc -= 3;
2011-12-17 12:16:10 +08:00
}
function st32_mem8_write(x) {
2011-12-21 10:43:53 +08:00
var last_tlb_val;
2011-12-17 12:16:10 +08:00
{
2011-12-21 10:43:53 +08:00
last_tlb_val = _tlb_write_[mem8_loc >>> 12];
if ((last_tlb_val | mem8_loc) & 3) {
__st32_mem8_write(x);
2011-12-17 12:16:10 +08:00
} else {
2011-12-21 10:43:53 +08:00
phys_mem32[(mem8_loc ^ last_tlb_val) >> 2] = x;
2011-12-17 12:16:10 +08:00
}
}
}
function __ld8_mem8_kernel_read() {
var tlb_lookup;
do_tlb_set_page(mem8_loc, 0, 0);
tlb_lookup = tlb_read_kernel[mem8_loc >>> 12] ^ mem8_loc;
return phys_mem8[tlb_lookup];
2011-12-17 12:16:10 +08:00
}
function ld8_mem8_kernel_read() {
var tlb_lookup;
return ((tlb_lookup = tlb_read_kernel[mem8_loc >>> 12]) == -1) ? __ld8_mem8_kernel_read() : phys_mem8[mem8_loc ^ tlb_lookup];
2011-12-17 12:16:10 +08:00
}
function __ld16_mem8_kernel_read() {
2011-12-21 10:43:53 +08:00
var x;
x = ld8_mem8_kernel_read();
mem8_loc++;
x |= ld8_mem8_kernel_read() << 8;
mem8_loc--;
2011-12-21 10:43:53 +08:00
return x;
2011-12-17 12:16:10 +08:00
}
function ld16_mem8_kernel_read() {
var tlb_lookup;
return ((tlb_lookup = tlb_read_kernel[mem8_loc >>> 12]) | mem8_loc) & 1 ? __ld16_mem8_kernel_read() : phys_mem16[(mem8_loc ^ tlb_lookup) >> 1];
2011-12-17 12:16:10 +08:00
}
function __ld32_mem8_kernel_read() {
2011-12-21 10:43:53 +08:00
var x;
x = ld8_mem8_kernel_read();
mem8_loc++;
x |= ld8_mem8_kernel_read() << 8;
mem8_loc++;
x |= ld8_mem8_kernel_read() << 16;
mem8_loc++;
x |= ld8_mem8_kernel_read() << 24;
mem8_loc -= 3;
2011-12-21 10:43:53 +08:00
return x;
2011-12-17 12:16:10 +08:00
}
function ld32_mem8_kernel_read() {
var tlb_lookup;
return ((tlb_lookup = tlb_read_kernel[mem8_loc >>> 12]) | mem8_loc) & 3 ? __ld32_mem8_kernel_read() : phys_mem32[(mem8_loc ^ tlb_lookup) >> 2];
2011-12-17 12:16:10 +08:00
}
function __st8_mem8_kernel_write(x) {
var tlb_lookup;
do_tlb_set_page(mem8_loc, 1, 0);
tlb_lookup = tlb_write_kernel[mem8_loc >>> 12] ^ mem8_loc;
phys_mem8[tlb_lookup] = x;
}
function st8_mem8_kernel_write(x) {
var tlb_lookup;
tlb_lookup = tlb_write_kernel[mem8_loc >>> 12];
if (tlb_lookup == -1) {
__st8_mem8_kernel_write(x);
2011-12-17 12:16:10 +08:00
} else {
phys_mem8[mem8_loc ^ tlb_lookup] = x;
2011-12-17 12:16:10 +08:00
}
}
function __st16_mem8_kernel_write(x) {
st8_mem8_kernel_write(x);
mem8_loc++;
st8_mem8_kernel_write(x >> 8);
mem8_loc--;
2011-12-17 12:16:10 +08:00
}
function st16_mem8_kernel_write(x) {
var tlb_lookup;
tlb_lookup = tlb_write_kernel[mem8_loc >>> 12];
if ((tlb_lookup | mem8_loc) & 1) {
__st16_mem8_kernel_write(x);
2011-12-17 12:16:10 +08:00
} else {
phys_mem16[(mem8_loc ^ tlb_lookup) >> 1] = x;
2011-12-17 12:16:10 +08:00
}
}
function __st32_mem8_kernel_write(x) {
st8_mem8_kernel_write(x);
mem8_loc++;
st8_mem8_kernel_write(x >> 8);
mem8_loc++;
st8_mem8_kernel_write(x >> 16);
mem8_loc++;
st8_mem8_kernel_write(x >> 24);
mem8_loc -= 3;
2011-12-17 12:16:10 +08:00
}
function st32_mem8_kernel_write(x) {
var tlb_lookup;
tlb_lookup = tlb_write_kernel[mem8_loc >>> 12];
if ((tlb_lookup | mem8_loc) & 3) {
__st32_mem8_kernel_write(x);
2011-12-17 12:16:10 +08:00
} else {
phys_mem32[(mem8_loc ^ tlb_lookup) >> 2] = x;
2011-12-17 12:16:10 +08:00
}
}
2011-12-23 20:24:16 +08:00
var eip, physmem8_ptr, Lb, initial_mem_ptr, Nb;
2011-12-23 01:49:18 +08:00
function ld16_mem8_direct() {
var x, y;
2011-12-23 20:24:16 +08:00
x = phys_mem8[physmem8_ptr++];
y = phys_mem8[physmem8_ptr++];
return x | (y << 8);
2011-12-17 12:16:10 +08:00
}
2011-12-23 20:24:16 +08:00
/*
Segmented Memory Mode Routines
================================================================================
Segmented Memory
-----------------
x86 memory segmentation refers to the implementation of memory
segmentation on the x86 architecture. Memory is divided into portions
that may be addressed by a single index register without changing a
16-bit segment selector. In real mode or V86 mode, a segment is always
64 kilobytes in size (using 16-bit offsets). In protected mode, a
segment can have variable length. Segments can overlap.
Within the x86 architectures, when operating in the real (compatible)
mode, physical address is computed as:
Address = 16*segment + offset
The 16-bit segment register is shifted
left by 4 bits and added to a 16-bit offset, resulting in a 20-bit
address.
When the 80386 is used to execute software designed for architectures
that don't have segments, it may be expedient to effectively "turn
off" the segmentation features of the 80386. The 80386 does not have a
mode that disables segmentation, but the same effect can be achieved
by initially loading the segment registers with selectors for
descriptors that encompass the entire 32-bit linear address
space. Once loaded, the segment registers don't need to be
changed. The 32-bit offsets used by 80386 instructions are adequate to
address the entire linear-address space.
*/
/*
segment translation routine (I believe):
Translates Logical Memory Address to Linear Memory Address
*/
function segment_translation(mem8) {
var base, mem8_loc, Qb, Rb, Sb, Tb;
2011-12-21 10:28:01 +08:00
if (FS_usage_flag && (CS_flags & (0x000f | 0x0080)) == 0) {
2011-12-18 21:19:08 +08:00
switch ((mem8 & 7) | ((mem8 >> 3) & 0x18)) {
2011-12-17 12:16:10 +08:00
case 0x04:
2011-12-23 20:24:16 +08:00
Qb = phys_mem8[physmem8_ptr++];
2011-12-17 12:16:10 +08:00
base = Qb & 7;
if (base == 5) {
{
2011-12-23 20:24:16 +08:00
mem8_loc = phys_mem8[physmem8_ptr] | (phys_mem8[physmem8_ptr + 1] << 8) | (phys_mem8[physmem8_ptr + 2] << 16) | (phys_mem8[physmem8_ptr + 3] << 24);
physmem8_ptr += 4;
2011-12-17 12:16:10 +08:00
}
} else {
mem8_loc = regs[base];
2011-12-17 12:16:10 +08:00
}
Rb = (Qb >> 3) & 7;
if (Rb != 4) {
mem8_loc = (mem8_loc + (regs[Rb] << (Qb >> 6))) >> 0;
2011-12-17 12:16:10 +08:00
}
break;
case 0x0c:
2011-12-23 20:24:16 +08:00
Qb = phys_mem8[physmem8_ptr++];
mem8_loc = ((phys_mem8[physmem8_ptr++] << 24) >> 24);
2011-12-17 12:16:10 +08:00
base = Qb & 7;
mem8_loc = (mem8_loc + regs[base]) >> 0;
2011-12-17 12:16:10 +08:00
Rb = (Qb >> 3) & 7;
if (Rb != 4) {
mem8_loc = (mem8_loc + (regs[Rb] << (Qb >> 6))) >> 0;
2011-12-17 12:16:10 +08:00
}
break;
case 0x14:
2011-12-23 20:24:16 +08:00
Qb = phys_mem8[physmem8_ptr++];
2011-12-17 12:16:10 +08:00
{
2011-12-23 20:24:16 +08:00
mem8_loc = phys_mem8[physmem8_ptr] | (phys_mem8[physmem8_ptr + 1] << 8) | (phys_mem8[physmem8_ptr + 2] << 16) | (phys_mem8[physmem8_ptr + 3] << 24);
physmem8_ptr += 4;
2011-12-17 12:16:10 +08:00
}
base = Qb & 7;
mem8_loc = (mem8_loc + regs[base]) >> 0;
2011-12-17 12:16:10 +08:00
Rb = (Qb >> 3) & 7;
if (Rb != 4) {
mem8_loc = (mem8_loc + (regs[Rb] << (Qb >> 6))) >> 0;
2011-12-17 12:16:10 +08:00
}
break;
case 0x05:
{
2011-12-23 20:24:16 +08:00
mem8_loc = phys_mem8[physmem8_ptr] | (phys_mem8[physmem8_ptr + 1] << 8) | (phys_mem8[physmem8_ptr + 2] << 16) | (phys_mem8[physmem8_ptr + 3] << 24);
physmem8_ptr += 4;
2011-12-17 12:16:10 +08:00
}
break;
case 0x00:
case 0x01:
case 0x02:
case 0x03:
case 0x06:
case 0x07:
2011-12-18 21:19:08 +08:00
base = mem8 & 7;
mem8_loc = regs[base];
2011-12-17 12:16:10 +08:00
break;
case 0x08:
case 0x09:
case 0x0a:
case 0x0b:
case 0x0d:
case 0x0e:
case 0x0f:
2011-12-23 20:24:16 +08:00
mem8_loc = ((phys_mem8[physmem8_ptr++] << 24) >> 24);
2011-12-18 21:19:08 +08:00
base = mem8 & 7;
mem8_loc = (mem8_loc + regs[base]) >> 0;
2011-12-17 12:16:10 +08:00
break;
case 0x10:
case 0x11:
case 0x12:
case 0x13:
case 0x15:
case 0x16:
case 0x17:
default:
{
2011-12-23 20:24:16 +08:00
mem8_loc = phys_mem8[physmem8_ptr] | (phys_mem8[physmem8_ptr + 1] << 8) | (phys_mem8[physmem8_ptr + 2] << 16) | (phys_mem8[physmem8_ptr + 3] << 24);
physmem8_ptr += 4;
2011-12-17 12:16:10 +08:00
}
2011-12-18 21:19:08 +08:00
base = mem8 & 7;
mem8_loc = (mem8_loc + regs[base]) >> 0;
2011-12-17 12:16:10 +08:00
break;
}
return mem8_loc;
2011-12-21 10:28:01 +08:00
} else if (CS_flags & 0x0080) {
2011-12-18 21:19:08 +08:00
if ((mem8 & 0xc7) == 0x06) {
2011-12-23 01:49:18 +08:00
mem8_loc = ld16_mem8_direct();
2011-12-17 12:16:10 +08:00
Tb = 3;
} else {
2011-12-18 21:19:08 +08:00
switch (mem8 >> 6) {
2011-12-17 12:16:10 +08:00
case 0:
mem8_loc = 0;
2011-12-17 12:16:10 +08:00
break;
case 1:
2011-12-23 20:24:16 +08:00
mem8_loc = ((phys_mem8[physmem8_ptr++] << 24) >> 24);
2011-12-17 12:16:10 +08:00
break;
default:
2011-12-23 01:49:18 +08:00
mem8_loc = ld16_mem8_direct();
2011-12-17 12:16:10 +08:00
break;
}
2011-12-18 21:19:08 +08:00
switch (mem8 & 7) {
2011-12-17 12:16:10 +08:00
case 0:
mem8_loc = (mem8_loc + regs[3] + regs[6]) & 0xffff;
2011-12-17 12:16:10 +08:00
Tb = 3;
break;
case 1:
mem8_loc = (mem8_loc + regs[3] + regs[7]) & 0xffff;
2011-12-17 12:16:10 +08:00
Tb = 3;
break;
case 2:
mem8_loc = (mem8_loc + regs[5] + regs[6]) & 0xffff;
2011-12-17 12:16:10 +08:00
Tb = 2;
break;
case 3:
mem8_loc = (mem8_loc + regs[5] + regs[7]) & 0xffff;
2011-12-17 12:16:10 +08:00
Tb = 2;
break;
case 4:
mem8_loc = (mem8_loc + regs[6]) & 0xffff;
2011-12-17 12:16:10 +08:00
Tb = 3;
break;
case 5:
mem8_loc = (mem8_loc + regs[7]) & 0xffff;
2011-12-17 12:16:10 +08:00
Tb = 3;
break;
case 6:
mem8_loc = (mem8_loc + regs[5]) & 0xffff;
2011-12-17 12:16:10 +08:00
Tb = 2;
break;
case 7:
default:
mem8_loc = (mem8_loc + regs[3]) & 0xffff;
2011-12-17 12:16:10 +08:00
Tb = 3;
break;
}
}
2011-12-21 10:28:01 +08:00
Sb = CS_flags & 0x000f;
2011-12-17 12:16:10 +08:00
if (Sb == 0) {
Sb = Tb;
} else {
Sb--;
}
mem8_loc = (mem8_loc + cpu.segs[Sb].base) >> 0;
return mem8_loc;
2011-12-17 12:16:10 +08:00
} else {
2011-12-18 21:19:08 +08:00
switch ((mem8 & 7) | ((mem8 >> 3) & 0x18)) {
2011-12-17 12:16:10 +08:00
case 0x04:
2011-12-23 20:24:16 +08:00
Qb = phys_mem8[physmem8_ptr++];
2011-12-17 12:16:10 +08:00
base = Qb & 7;
if (base == 5) {
{
2011-12-23 20:24:16 +08:00
mem8_loc = phys_mem8[physmem8_ptr] | (phys_mem8[physmem8_ptr + 1] << 8) | (phys_mem8[physmem8_ptr + 2] << 16) | (phys_mem8[physmem8_ptr + 3] << 24);
physmem8_ptr += 4;
2011-12-17 12:16:10 +08:00
}
base = 0;
} else {
mem8_loc = regs[base];
2011-12-17 12:16:10 +08:00
}
Rb = (Qb >> 3) & 7;
if (Rb != 4) {
mem8_loc = (mem8_loc + (regs[Rb] << (Qb >> 6))) >> 0;
2011-12-17 12:16:10 +08:00
}
break;
case 0x0c:
2011-12-23 20:24:16 +08:00
Qb = phys_mem8[physmem8_ptr++];
mem8_loc = ((phys_mem8[physmem8_ptr++] << 24) >> 24);
2011-12-17 12:16:10 +08:00
base = Qb & 7;
mem8_loc = (mem8_loc + regs[base]) >> 0;
2011-12-17 12:16:10 +08:00
Rb = (Qb >> 3) & 7;
if (Rb != 4) {
mem8_loc = (mem8_loc + (regs[Rb] << (Qb >> 6))) >> 0;
2011-12-17 12:16:10 +08:00
}
break;
case 0x14:
2011-12-23 20:24:16 +08:00
Qb = phys_mem8[physmem8_ptr++];
2011-12-17 12:16:10 +08:00
{
2011-12-23 20:24:16 +08:00
mem8_loc = phys_mem8[physmem8_ptr] | (phys_mem8[physmem8_ptr + 1] << 8) | (phys_mem8[physmem8_ptr + 2] << 16) | (phys_mem8[physmem8_ptr + 3] << 24);
physmem8_ptr += 4;
2011-12-17 12:16:10 +08:00
}
base = Qb & 7;
mem8_loc = (mem8_loc + regs[base]) >> 0;
2011-12-17 12:16:10 +08:00
Rb = (Qb >> 3) & 7;
if (Rb != 4) {
mem8_loc = (mem8_loc + (regs[Rb] << (Qb >> 6))) >> 0;
2011-12-17 12:16:10 +08:00
}
break;
case 0x05:
{
2011-12-23 20:24:16 +08:00
mem8_loc = phys_mem8[physmem8_ptr] | (phys_mem8[physmem8_ptr + 1] << 8) | (phys_mem8[physmem8_ptr + 2] << 16) | (phys_mem8[physmem8_ptr + 3] << 24);
physmem8_ptr += 4;
2011-12-17 12:16:10 +08:00
}
base = 0;
break;
case 0x00:
case 0x01:
case 0x02:
case 0x03:
case 0x06:
case 0x07:
2011-12-18 21:19:08 +08:00
base = mem8 & 7;
mem8_loc = regs[base];
2011-12-17 12:16:10 +08:00
break;
case 0x08:
case 0x09:
case 0x0a:
case 0x0b:
case 0x0d:
case 0x0e:
case 0x0f:
2011-12-23 20:24:16 +08:00
mem8_loc = ((phys_mem8[physmem8_ptr++] << 24) >> 24);
2011-12-18 21:19:08 +08:00
base = mem8 & 7;
mem8_loc = (mem8_loc + regs[base]) >> 0;
2011-12-17 12:16:10 +08:00
break;
case 0x10:
case 0x11:
case 0x12:
case 0x13:
case 0x15:
case 0x16:
case 0x17:
default:
{
2011-12-23 20:24:16 +08:00
mem8_loc = phys_mem8[physmem8_ptr] | (phys_mem8[physmem8_ptr + 1] << 8) | (phys_mem8[physmem8_ptr + 2] << 16) | (phys_mem8[physmem8_ptr + 3] << 24);
physmem8_ptr += 4;
2011-12-17 12:16:10 +08:00
}
2011-12-18 21:19:08 +08:00
base = mem8 & 7;
mem8_loc = (mem8_loc + regs[base]) >> 0;
2011-12-17 12:16:10 +08:00
break;
}
2011-12-21 10:28:01 +08:00
Sb = CS_flags & 0x000f;
2011-12-17 12:16:10 +08:00
if (Sb == 0) {
if (base == 4 || base == 5)
Sb = 2;
else
Sb = 3;
} else {
Sb--;
}
mem8_loc = (mem8_loc + cpu.segs[Sb].base) >> 0;
return mem8_loc;
2011-12-17 12:16:10 +08:00
}
}
2011-12-23 20:24:16 +08:00
function segmented_mem8_loc_for_MOV() {
var mem8_loc, Sb;
2011-12-21 10:28:01 +08:00
if (CS_flags & 0x0080) {
2011-12-23 01:49:18 +08:00
mem8_loc = ld16_mem8_direct();
2011-12-17 12:16:10 +08:00
} else {
{
2011-12-23 20:24:16 +08:00
mem8_loc = phys_mem8[physmem8_ptr] | (phys_mem8[physmem8_ptr + 1] << 8) | (phys_mem8[physmem8_ptr + 2] << 16) | (phys_mem8[physmem8_ptr + 3] << 24);
physmem8_ptr += 4;
2011-12-17 12:16:10 +08:00
}
}
2011-12-21 10:28:01 +08:00
Sb = CS_flags & 0x000f;
2011-12-17 12:16:10 +08:00
if (Sb == 0)
Sb = 3;
else
Sb--;
mem8_loc = (mem8_loc + cpu.segs[Sb].base) >> 0;
return mem8_loc;
2011-12-17 12:16:10 +08:00
}
2011-12-23 20:24:16 +08:00
/*
Register Manipulation
==========================================================================================
*/
function set_word_in_register(reg_idx1, x) {
/*
if arg[0] is = 1xx then set register xx's upper two bytes to two bytes in arg[1]
if arg[0] is = 0xx then set register xx's lower two bytes to two bytes in arg[1]
*/
2011-12-23 20:24:16 +08:00
if (reg_idx1 & 4)
regs[reg_idx1 & 3] = (regs[reg_idx1 & 3] & -65281) | ((x & 0xff) << 8);
2011-12-17 12:16:10 +08:00
else
2011-12-23 20:24:16 +08:00
regs[reg_idx1 & 3] = (regs[reg_idx1 & 3] & -256) | (x & 0xff);
2011-12-17 12:16:10 +08:00
}
2011-12-23 20:24:16 +08:00
function set_lower_word_in_register(reg_idx1, x) {
regs[reg_idx1] = (regs[reg_idx1] & -65536) | (x & 0xffff);
2011-12-17 12:16:10 +08:00
}
2011-12-23 20:24:16 +08:00
/*
Arithmetic Operations
==========================================================================================
*/
function do_32bit_math(conditional_var, Yb, Zb) {
2011-12-17 12:16:10 +08:00
var ac;
switch (conditional_var) {
2011-12-17 12:16:10 +08:00
case 0:
2011-12-17 13:13:37 +08:00
_src = Zb;
2011-12-17 12:16:10 +08:00
Yb = (Yb + Zb) >> 0;
2011-12-17 16:14:24 +08:00
_dst = Yb;
_op = 2;
2011-12-17 12:16:10 +08:00
break;
case 1:
Yb = Yb | Zb;
2011-12-17 16:14:24 +08:00
_dst = Yb;
_op = 14;
2011-12-17 12:16:10 +08:00
break;
case 2:
2011-12-18 20:40:30 +08:00
ac = check_carry();
2011-12-17 13:13:37 +08:00
_src = Zb;
2011-12-17 12:16:10 +08:00
Yb = (Yb + Zb + ac) >> 0;
2011-12-17 16:14:24 +08:00
_dst = Yb;
_op = ac ? 5 : 2;
2011-12-17 12:16:10 +08:00
break;
case 3:
2011-12-18 20:40:30 +08:00
ac = check_carry();
2011-12-17 13:13:37 +08:00
_src = Zb;
2011-12-17 12:16:10 +08:00
Yb = (Yb - Zb - ac) >> 0;
2011-12-17 16:14:24 +08:00
_dst = Yb;
_op = ac ? 11 : 8;
2011-12-17 12:16:10 +08:00
break;
case 4:
Yb = Yb & Zb;
2011-12-17 16:14:24 +08:00
_dst = Yb;
_op = 14;
2011-12-17 12:16:10 +08:00
break;
case 5:
2011-12-17 13:13:37 +08:00
_src = Zb;
2011-12-17 12:16:10 +08:00
Yb = (Yb - Zb) >> 0;
2011-12-17 16:14:24 +08:00
_dst = Yb;
_op = 8;
2011-12-17 12:16:10 +08:00
break;
case 6:
Yb = Yb ^ Zb;
2011-12-17 16:14:24 +08:00
_dst = Yb;
_op = 14;
2011-12-17 12:16:10 +08:00
break;
case 7:
2011-12-17 13:13:37 +08:00
_src = Zb;
2011-12-17 16:14:24 +08:00
_dst = (Yb - Zb) >> 0;
_op = 8;
2011-12-17 12:16:10 +08:00
break;
default:
throw "arith" + cc + ": invalid op";
}
return Yb;
}
function do_16bit_math(conditional_var, Yb, Zb) {
2011-12-17 12:16:10 +08:00
var ac;
switch (conditional_var) {
2011-12-17 12:16:10 +08:00
case 0:
2011-12-17 13:13:37 +08:00
_src = Zb;
2011-12-17 12:16:10 +08:00
Yb = (((Yb + Zb) << 16) >> 16);
2011-12-17 16:14:24 +08:00
_dst = Yb;
_op = 1;
2011-12-17 12:16:10 +08:00
break;
case 1:
Yb = (((Yb | Zb) << 16) >> 16);
2011-12-17 16:14:24 +08:00
_dst = Yb;
_op = 13;
2011-12-17 12:16:10 +08:00
break;
case 2:
2011-12-18 20:40:30 +08:00
ac = check_carry();
2011-12-17 13:13:37 +08:00
_src = Zb;
2011-12-17 12:16:10 +08:00
Yb = (((Yb + Zb + ac) << 16) >> 16);
2011-12-17 16:14:24 +08:00
_dst = Yb;
_op = ac ? 4 : 1;
2011-12-17 12:16:10 +08:00
break;
case 3:
2011-12-18 20:40:30 +08:00
ac = check_carry();
2011-12-17 13:13:37 +08:00
_src = Zb;
2011-12-17 12:16:10 +08:00
Yb = (((Yb - Zb - ac) << 16) >> 16);
2011-12-17 16:14:24 +08:00
_dst = Yb;
_op = ac ? 10 : 7;
2011-12-17 12:16:10 +08:00
break;
case 4:
Yb = (((Yb & Zb) << 16) >> 16);
2011-12-17 16:14:24 +08:00
_dst = Yb;
_op = 13;
2011-12-17 12:16:10 +08:00
break;
case 5:
2011-12-17 13:13:37 +08:00
_src = Zb;
2011-12-17 12:16:10 +08:00
Yb = (((Yb - Zb) << 16) >> 16);
2011-12-17 16:14:24 +08:00
_dst = Yb;
_op = 7;
2011-12-17 12:16:10 +08:00
break;
case 6:
Yb = (((Yb ^ Zb) << 16) >> 16);
2011-12-17 16:14:24 +08:00
_dst = Yb;
_op = 13;
2011-12-17 12:16:10 +08:00
break;
case 7:
2011-12-17 13:13:37 +08:00
_src = Zb;
2011-12-17 16:14:24 +08:00
_dst = (((Yb - Zb) << 16) >> 16);
_op = 7;
2011-12-17 12:16:10 +08:00
break;
default:
throw "arith" + cc + ": invalid op";
}
return Yb;
}
2011-12-23 01:49:18 +08:00
function increment_16bit(x) {
2011-12-17 16:14:24 +08:00
if (_op < 25) {
2011-12-17 16:20:47 +08:00
_op2 = _op;
_dst2 = _dst;
2011-12-17 12:16:10 +08:00
}
2011-12-21 10:43:53 +08:00
_dst = (((x + 1) << 16) >> 16);
2011-12-17 16:14:24 +08:00
_op = 26;
return _dst;
2011-12-17 12:16:10 +08:00
}
2011-12-23 01:49:18 +08:00
function decrement_16bit(x) {
2011-12-17 16:14:24 +08:00
if (_op < 25) {
2011-12-17 16:20:47 +08:00
_op2 = _op;
_dst2 = _dst;
2011-12-17 12:16:10 +08:00
}
2011-12-21 10:43:53 +08:00
_dst = (((x - 1) << 16) >> 16);
2011-12-17 16:14:24 +08:00
_op = 29;
return _dst;
2011-12-17 12:16:10 +08:00
}
function do_8bit_math(conditional_var, Yb, Zb) {
2011-12-17 12:16:10 +08:00
var ac;
switch (conditional_var) {
2011-12-17 12:16:10 +08:00
case 0:
2011-12-17 13:13:37 +08:00
_src = Zb;
2011-12-17 12:16:10 +08:00
Yb = (((Yb + Zb) << 24) >> 24);
2011-12-17 16:14:24 +08:00
_dst = Yb;
_op = 0;
2011-12-17 12:16:10 +08:00
break;
case 1:
Yb = (((Yb | Zb) << 24) >> 24);
2011-12-17 16:14:24 +08:00
_dst = Yb;
_op = 12;
2011-12-17 12:16:10 +08:00
break;
case 2:
2011-12-18 20:40:30 +08:00
ac = check_carry();
2011-12-17 13:13:37 +08:00
_src = Zb;
2011-12-17 12:16:10 +08:00
Yb = (((Yb + Zb + ac) << 24) >> 24);
2011-12-17 16:14:24 +08:00
_dst = Yb;
_op = ac ? 3 : 0;
2011-12-17 12:16:10 +08:00
break;
case 3:
2011-12-18 20:40:30 +08:00
ac = check_carry();
2011-12-17 13:13:37 +08:00
_src = Zb;
2011-12-17 12:16:10 +08:00
Yb = (((Yb - Zb - ac) << 24) >> 24);
2011-12-17 16:14:24 +08:00
_dst = Yb;
_op = ac ? 9 : 6;
2011-12-17 12:16:10 +08:00
break;
case 4:
Yb = (((Yb & Zb) << 24) >> 24);
2011-12-17 16:14:24 +08:00
_dst = Yb;
_op = 12;
2011-12-17 12:16:10 +08:00
break;
case 5:
2011-12-17 13:13:37 +08:00
_src = Zb;
2011-12-17 12:16:10 +08:00
Yb = (((Yb - Zb) << 24) >> 24);
2011-12-17 16:14:24 +08:00
_dst = Yb;
_op = 6;
2011-12-17 12:16:10 +08:00
break;
case 6:
Yb = (((Yb ^ Zb) << 24) >> 24);
2011-12-17 16:14:24 +08:00
_dst = Yb;
_op = 12;
2011-12-17 12:16:10 +08:00
break;
case 7:
2011-12-17 13:13:37 +08:00
_src = Zb;
2011-12-17 16:14:24 +08:00
_dst = (((Yb - Zb) << 24) >> 24);
_op = 6;
2011-12-17 12:16:10 +08:00
break;
default:
throw "arith" + cc + ": invalid op";
}
return Yb;
}
2011-12-23 01:49:18 +08:00
function increment_8bit(x) {
2011-12-17 16:14:24 +08:00
if (_op < 25) {
2011-12-17 16:20:47 +08:00
_op2 = _op;
_dst2 = _dst;
2011-12-17 12:16:10 +08:00
}
2011-12-21 10:43:53 +08:00
_dst = (((x + 1) << 24) >> 24);
2011-12-17 16:14:24 +08:00
_op = 25;
return _dst;
2011-12-17 12:16:10 +08:00
}
2011-12-23 01:49:18 +08:00
function decrement_8bit(x) {
2011-12-17 16:14:24 +08:00
if (_op < 25) {
2011-12-17 16:20:47 +08:00
_op2 = _op;
_dst2 = _dst;
2011-12-17 12:16:10 +08:00
}
2011-12-21 10:43:53 +08:00
_dst = (((x - 1) << 24) >> 24);
2011-12-17 16:14:24 +08:00
_op = 28;
return _dst;
2011-12-17 12:16:10 +08:00
}
function shift8(conditional_var, Yb, Zb) {
2011-12-17 12:16:10 +08:00
var kc, ac;
switch (conditional_var) {
2011-12-17 12:16:10 +08:00
case 0:
if (Zb & 0x1f) {
Zb &= 0x7;
Yb &= 0xff;
kc = Yb;
Yb = (Yb << Zb) | (Yb >>> (8 - Zb));
2011-12-23 21:15:54 +08:00
_src = conditional_flags_for_rot_shift_ops();
2011-12-17 13:13:37 +08:00
_src |= (Yb & 0x0001) | (((kc ^ Yb) << 4) & 0x0800);
2011-12-17 16:14:24 +08:00
_dst = ((_src >> 6) & 1) ^ 1;
_op = 24;
2011-12-17 12:16:10 +08:00
}
break;
case 1:
if (Zb & 0x1f) {
Zb &= 0x7;
Yb &= 0xff;
kc = Yb;
Yb = (Yb >>> Zb) | (Yb << (8 - Zb));
2011-12-23 21:15:54 +08:00
_src = conditional_flags_for_rot_shift_ops();
2011-12-17 13:13:37 +08:00
_src |= ((Yb >> 7) & 0x0001) | (((kc ^ Yb) << 4) & 0x0800);
2011-12-17 16:14:24 +08:00
_dst = ((_src >> 6) & 1) ^ 1;
_op = 24;
2011-12-17 12:16:10 +08:00
}
break;
case 2:
2011-12-23 21:44:05 +08:00
Zb = shift8_LUT[Zb & 0x1f];
2011-12-17 12:16:10 +08:00
if (Zb) {
Yb &= 0xff;
kc = Yb;
2011-12-18 20:40:30 +08:00
ac = check_carry();
2011-12-17 12:16:10 +08:00
Yb = (Yb << Zb) | (ac << (Zb - 1));
if (Zb > 1)
Yb |= kc >>> (9 - Zb);
2011-12-23 21:15:54 +08:00
_src = conditional_flags_for_rot_shift_ops();
2011-12-17 13:13:37 +08:00
_src |= (((kc ^ Yb) << 4) & 0x0800) | ((kc >> (8 - Zb)) & 0x0001);
2011-12-17 16:14:24 +08:00
_dst = ((_src >> 6) & 1) ^ 1;
_op = 24;
2011-12-17 12:16:10 +08:00
}
break;
case 3:
2011-12-23 21:44:05 +08:00
Zb = shift8_LUT[Zb & 0x1f];
2011-12-17 12:16:10 +08:00
if (Zb) {
Yb &= 0xff;
kc = Yb;
2011-12-18 20:40:30 +08:00
ac = check_carry();
2011-12-17 12:16:10 +08:00
Yb = (Yb >>> Zb) | (ac << (8 - Zb));
if (Zb > 1)
Yb |= kc << (9 - Zb);
2011-12-23 21:15:54 +08:00
_src = conditional_flags_for_rot_shift_ops();
2011-12-17 13:13:37 +08:00
_src |= (((kc ^ Yb) << 4) & 0x0800) | ((kc >> (Zb - 1)) & 0x0001);
2011-12-17 16:14:24 +08:00
_dst = ((_src >> 6) & 1) ^ 1;
_op = 24;
2011-12-17 12:16:10 +08:00
}
break;
case 4:
case 6:
Zb &= 0x1f;
if (Zb) {
2011-12-17 13:13:37 +08:00
_src = Yb << (Zb - 1);
2011-12-17 16:14:24 +08:00
_dst = Yb = (((Yb << Zb) << 24) >> 24);
_op = 15;
2011-12-17 12:16:10 +08:00
}
break;
case 5:
Zb &= 0x1f;
if (Zb) {
Yb &= 0xff;
2011-12-17 13:13:37 +08:00
_src = Yb >>> (Zb - 1);
2011-12-17 16:14:24 +08:00
_dst = Yb = (((Yb >>> Zb) << 24) >> 24);
_op = 18;
2011-12-17 12:16:10 +08:00
}
break;
case 7:
Zb &= 0x1f;
if (Zb) {
Yb = (Yb << 24) >> 24;
2011-12-17 13:13:37 +08:00
_src = Yb >> (Zb - 1);
2011-12-17 16:14:24 +08:00
_dst = Yb = (((Yb >> Zb) << 24) >> 24);
_op = 18;
2011-12-17 12:16:10 +08:00
}
break;
default:
throw "unsupported shift8=" + conditional_var;
2011-12-17 12:16:10 +08:00
}
return Yb;
}
function shift16(conditional_var, Yb, Zb) {
2011-12-17 12:16:10 +08:00
var kc, ac;
switch (conditional_var) {
2011-12-17 12:16:10 +08:00
case 0:
if (Zb & 0x1f) {
Zb &= 0xf;
Yb &= 0xffff;
kc = Yb;
Yb = (Yb << Zb) | (Yb >>> (16 - Zb));
2011-12-23 21:15:54 +08:00
_src = conditional_flags_for_rot_shift_ops();
2011-12-17 13:13:37 +08:00
_src |= (Yb & 0x0001) | (((kc ^ Yb) >> 4) & 0x0800);
2011-12-17 16:14:24 +08:00
_dst = ((_src >> 6) & 1) ^ 1;
_op = 24;
2011-12-17 12:16:10 +08:00
}
break;
case 1:
if (Zb & 0x1f) {
Zb &= 0xf;
Yb &= 0xffff;
kc = Yb;
Yb = (Yb >>> Zb) | (Yb << (16 - Zb));
2011-12-23 21:15:54 +08:00
_src = conditional_flags_for_rot_shift_ops();
2011-12-17 13:13:37 +08:00
_src |= ((Yb >> 15) & 0x0001) | (((kc ^ Yb) >> 4) & 0x0800);
2011-12-17 16:14:24 +08:00
_dst = ((_src >> 6) & 1) ^ 1;
_op = 24;
2011-12-17 12:16:10 +08:00
}
break;
case 2:
2011-12-23 21:44:05 +08:00
Zb = shift16_LUT[Zb & 0x1f];
2011-12-17 12:16:10 +08:00
if (Zb) {
Yb &= 0xffff;
kc = Yb;
2011-12-18 20:40:30 +08:00
ac = check_carry();
2011-12-17 12:16:10 +08:00
Yb = (Yb << Zb) | (ac << (Zb - 1));
if (Zb > 1)
Yb |= kc >>> (17 - Zb);
2011-12-23 21:15:54 +08:00
_src = conditional_flags_for_rot_shift_ops();
2011-12-17 13:13:37 +08:00
_src |= (((kc ^ Yb) >> 4) & 0x0800) | ((kc >> (16 - Zb)) & 0x0001);
2011-12-17 16:14:24 +08:00
_dst = ((_src >> 6) & 1) ^ 1;
_op = 24;
2011-12-17 12:16:10 +08:00
}
break;
case 3:
2011-12-23 21:44:05 +08:00
Zb = shift16_LUT[Zb & 0x1f];
2011-12-17 12:16:10 +08:00
if (Zb) {
Yb &= 0xffff;
kc = Yb;
2011-12-18 20:40:30 +08:00
ac = check_carry();
2011-12-17 12:16:10 +08:00
Yb = (Yb >>> Zb) | (ac << (16 - Zb));
if (Zb > 1)
Yb |= kc << (17 - Zb);
2011-12-23 21:15:54 +08:00
_src = conditional_flags_for_rot_shift_ops();
2011-12-17 13:13:37 +08:00
_src |= (((kc ^ Yb) >> 4) & 0x0800) | ((kc >> (Zb - 1)) & 0x0001);
2011-12-17 16:14:24 +08:00
_dst = ((_src >> 6) & 1) ^ 1;
_op = 24;
2011-12-17 12:16:10 +08:00
}
break;
case 4:
case 6:
Zb &= 0x1f;
if (Zb) {
2011-12-17 13:13:37 +08:00
_src = Yb << (Zb - 1);
2011-12-17 16:14:24 +08:00
_dst = Yb = (((Yb << Zb) << 16) >> 16);
_op = 16;
2011-12-17 12:16:10 +08:00
}
break;
case 5:
Zb &= 0x1f;
if (Zb) {
Yb &= 0xffff;
2011-12-17 13:13:37 +08:00
_src = Yb >>> (Zb - 1);
2011-12-17 16:14:24 +08:00
_dst = Yb = (((Yb >>> Zb) << 16) >> 16);
_op = 19;
2011-12-17 12:16:10 +08:00
}
break;
case 7:
Zb &= 0x1f;
if (Zb) {
Yb = (Yb << 16) >> 16;
2011-12-17 13:13:37 +08:00
_src = Yb >> (Zb - 1);
2011-12-17 16:14:24 +08:00
_dst = Yb = (((Yb >> Zb) << 16) >> 16);
_op = 19;
2011-12-17 12:16:10 +08:00
}
break;
default:
throw "unsupported shift16=" + conditional_var;
2011-12-17 12:16:10 +08:00
}
return Yb;
}
2011-12-23 01:49:18 +08:00
function shift32(conditional_var, Yb, Zb) {
2011-12-17 12:16:10 +08:00
var kc, ac;
switch (conditional_var) {
2011-12-17 12:16:10 +08:00
case 0:
Zb &= 0x1f;
if (Zb) {
kc = Yb;
Yb = (Yb << Zb) | (Yb >>> (32 - Zb));
2011-12-23 21:15:54 +08:00
_src = conditional_flags_for_rot_shift_ops();
2011-12-17 13:13:37 +08:00
_src |= (Yb & 0x0001) | (((kc ^ Yb) >> 20) & 0x0800);
2011-12-17 16:14:24 +08:00
_dst = ((_src >> 6) & 1) ^ 1;
_op = 24;
2011-12-17 12:16:10 +08:00
}
break;
case 1:
Zb &= 0x1f;
if (Zb) {
kc = Yb;
Yb = (Yb >>> Zb) | (Yb << (32 - Zb));
2011-12-23 21:15:54 +08:00
_src = conditional_flags_for_rot_shift_ops();
2011-12-17 13:13:37 +08:00
_src |= ((Yb >> 31) & 0x0001) | (((kc ^ Yb) >> 20) & 0x0800);
2011-12-17 16:14:24 +08:00
_dst = ((_src >> 6) & 1) ^ 1;
_op = 24;
2011-12-17 12:16:10 +08:00
}
break;
case 2:
Zb &= 0x1f;
if (Zb) {
kc = Yb;
2011-12-18 20:40:30 +08:00
ac = check_carry();
2011-12-17 12:16:10 +08:00
Yb = (Yb << Zb) | (ac << (Zb - 1));
if (Zb > 1)
Yb |= kc >>> (33 - Zb);
2011-12-23 21:15:54 +08:00
_src = conditional_flags_for_rot_shift_ops();
2011-12-17 13:13:37 +08:00
_src |= (((kc ^ Yb) >> 20) & 0x0800) | ((kc >> (32 - Zb)) & 0x0001);
2011-12-17 16:14:24 +08:00
_dst = ((_src >> 6) & 1) ^ 1;
_op = 24;
2011-12-17 12:16:10 +08:00
}
break;
case 3:
Zb &= 0x1f;
if (Zb) {
kc = Yb;
2011-12-18 20:40:30 +08:00
ac = check_carry();
2011-12-17 12:16:10 +08:00
Yb = (Yb >>> Zb) | (ac << (32 - Zb));
if (Zb > 1)
Yb |= kc << (33 - Zb);
2011-12-23 21:15:54 +08:00
_src = conditional_flags_for_rot_shift_ops();
2011-12-17 13:13:37 +08:00
_src |= (((kc ^ Yb) >> 20) & 0x0800) | ((kc >> (Zb - 1)) & 0x0001);
2011-12-17 16:14:24 +08:00
_dst = ((_src >> 6) & 1) ^ 1;
_op = 24;
2011-12-17 12:16:10 +08:00
}
break;
case 4:
case 6:
Zb &= 0x1f;
if (Zb) {
2011-12-17 13:13:37 +08:00
_src = Yb << (Zb - 1);
2011-12-17 16:14:24 +08:00
_dst = Yb = Yb << Zb;
_op = 17;
2011-12-17 12:16:10 +08:00
}
break;
case 5:
Zb &= 0x1f;
if (Zb) {
2011-12-17 13:13:37 +08:00
_src = Yb >>> (Zb - 1);
2011-12-17 16:14:24 +08:00
_dst = Yb = Yb >>> Zb;
_op = 20;
2011-12-17 12:16:10 +08:00
}
break;
case 7:
Zb &= 0x1f;
if (Zb) {
2011-12-17 13:13:37 +08:00
_src = Yb >> (Zb - 1);
2011-12-17 16:14:24 +08:00
_dst = Yb = Yb >> Zb;
_op = 20;
2011-12-17 12:16:10 +08:00
}
break;
default:
throw "unsupported shift32=" + conditional_var;
2011-12-17 12:16:10 +08:00
}
return Yb;
}
2011-12-23 01:49:18 +08:00
2011-12-23 20:24:16 +08:00
/*
Bit Twiddling Functions
==========================================================================================
*/
2011-12-23 01:49:18 +08:00
function oc(conditional_var, Yb, Zb, pc) {
2011-12-17 12:16:10 +08:00
var qc;
pc &= 0x1f;
if (pc) {
if (conditional_var == 0) {
2011-12-17 12:16:10 +08:00
Zb &= 0xffff;
qc = Zb | (Yb << 16);
2011-12-17 13:13:37 +08:00
_src = qc >> (32 - pc);
2011-12-17 12:16:10 +08:00
qc <<= pc;
if (pc > 16)
qc |= Zb << (pc - 16);
2011-12-17 16:14:24 +08:00
Yb = _dst = qc >> 16;
_op = 19;
2011-12-17 12:16:10 +08:00
} else {
qc = (Yb & 0xffff) | (Zb << 16);
2011-12-17 13:13:37 +08:00
_src = qc >> (pc - 1);
2011-12-17 12:16:10 +08:00
qc >>= pc;
if (pc > 16)
qc |= Zb << (32 - pc);
2011-12-17 16:14:24 +08:00
Yb = _dst = (((qc) << 16) >> 16);
_op = 19;
2011-12-17 12:16:10 +08:00
}
}
return Yb;
}
function rc(Yb, Zb, pc) {
pc &= 0x1f;
if (pc) {
2011-12-17 13:13:37 +08:00
_src = Yb << (pc - 1);
2011-12-17 16:14:24 +08:00
_dst = Yb = (Yb << pc) | (Zb >>> (32 - pc));
_op = 17;
2011-12-17 12:16:10 +08:00
}
return Yb;
}
function sc(Yb, Zb, pc) {
pc &= 0x1f;
if (pc) {
2011-12-17 13:13:37 +08:00
_src = Yb >> (pc - 1);
2011-12-17 16:14:24 +08:00
_dst = Yb = (Yb >>> pc) | (Zb << (32 - pc));
_op = 20;
2011-12-17 12:16:10 +08:00
}
return Yb;
}
function tc(Yb, Zb) {
Zb &= 0xf;
2011-12-17 13:13:37 +08:00
_src = Yb >> Zb;
2011-12-17 16:14:24 +08:00
_op = 19;
2011-12-17 12:16:10 +08:00
}
function uc(Yb, Zb) {
Zb &= 0x1f;
2011-12-17 13:13:37 +08:00
_src = Yb >> Zb;
2011-12-17 16:14:24 +08:00
_op = 20;
2011-12-17 12:16:10 +08:00
}
function vc(conditional_var, Yb, Zb) {
2011-12-17 12:16:10 +08:00
var wc;
Zb &= 0xf;
2011-12-17 13:13:37 +08:00
_src = Yb >> Zb;
2011-12-17 12:16:10 +08:00
wc = 1 << Zb;
switch (conditional_var) {
2011-12-17 12:16:10 +08:00
case 1:
Yb |= wc;
break;
case 2:
Yb &= ~wc;
break;
case 3:
default:
Yb ^= wc;
break;
}
2011-12-17 16:14:24 +08:00
_op = 19;
2011-12-17 12:16:10 +08:00
return Yb;
}
function xc(conditional_var, Yb, Zb) {
2011-12-17 12:16:10 +08:00
var wc;
Zb &= 0x1f;
2011-12-17 13:13:37 +08:00
_src = Yb >> Zb;
2011-12-17 12:16:10 +08:00
wc = 1 << Zb;
switch (conditional_var) {
2011-12-17 12:16:10 +08:00
case 1:
Yb |= wc;
break;
case 2:
Yb &= ~wc;
break;
case 3:
default:
Yb ^= wc;
break;
}
2011-12-17 16:14:24 +08:00
_op = 20;
2011-12-17 12:16:10 +08:00
return Yb;
}
function yc(Yb, Zb) {
Zb &= 0xffff;
if (Zb) {
Yb = 0;
while ((Zb & 1) == 0) {
Yb++;
Zb >>= 1;
}
2011-12-17 16:14:24 +08:00
_dst = 1;
2011-12-17 12:16:10 +08:00
} else {
2011-12-17 16:14:24 +08:00
_dst = 0;
2011-12-17 12:16:10 +08:00
}
2011-12-17 16:14:24 +08:00
_op = 14;
2011-12-17 12:16:10 +08:00
return Yb;
}
function zc(Yb, Zb) {
if (Zb) {
Yb = 0;
while ((Zb & 1) == 0) {
Yb++;
Zb >>= 1;
}
2011-12-17 16:14:24 +08:00
_dst = 1;
2011-12-17 12:16:10 +08:00
} else {
2011-12-17 16:14:24 +08:00
_dst = 0;
2011-12-17 12:16:10 +08:00
}
2011-12-17 16:14:24 +08:00
_op = 14;
2011-12-17 12:16:10 +08:00
return Yb;
}
function Ac(Yb, Zb) {
Zb &= 0xffff;
if (Zb) {
Yb = 15;
while ((Zb & 0x8000) == 0) {
Yb--;
Zb <<= 1;
}
2011-12-17 16:14:24 +08:00
_dst = 1;
2011-12-17 12:16:10 +08:00
} else {
2011-12-17 16:14:24 +08:00
_dst = 0;
2011-12-17 12:16:10 +08:00
}
2011-12-17 16:14:24 +08:00
_op = 14;
2011-12-17 12:16:10 +08:00
return Yb;
}
function Bc(Yb, Zb) {
if (Zb) {
Yb = 31;
while (Zb >= 0) {
Yb--;
Zb <<= 1;
}
2011-12-17 16:14:24 +08:00
_dst = 1;
2011-12-17 12:16:10 +08:00
} else {
2011-12-17 16:14:24 +08:00
_dst = 0;
2011-12-17 12:16:10 +08:00
}
2011-12-17 16:14:24 +08:00
_op = 14;
2011-12-17 12:16:10 +08:00
return Yb;
}
function Cc(OPbyte) {
2011-12-17 12:16:10 +08:00
var a, q, r;
2011-12-17 16:08:25 +08:00
a = regs[0] & 0xffff;
OPbyte &= 0xff;
if ((a >> 8) >= OPbyte)
abort(0);
q = (a / OPbyte) >> 0;
r = (a % OPbyte);
2011-12-23 20:24:16 +08:00
set_lower_word_in_register(0, (q & 0xff) | (r << 8));
2011-12-17 12:16:10 +08:00
}
function Ec(OPbyte) {
2011-12-17 12:16:10 +08:00
var a, q, r;
2011-12-17 16:08:25 +08:00
a = (regs[0] << 16) >> 16;
OPbyte = (OPbyte << 24) >> 24;
if (OPbyte == 0)
abort(0);
q = (a / OPbyte) >> 0;
2011-12-17 12:16:10 +08:00
if (((q << 24) >> 24) != q)
abort(0);
r = (a % OPbyte);
2011-12-23 20:24:16 +08:00
set_lower_word_in_register(0, (q & 0xff) | (r << 8));
2011-12-17 12:16:10 +08:00
}
function Fc(OPbyte) {
2011-12-17 12:16:10 +08:00
var a, q, r;
2011-12-17 16:08:25 +08:00
a = (regs[2] << 16) | (regs[0] & 0xffff);
OPbyte &= 0xffff;
if ((a >>> 16) >= OPbyte)
abort(0);
q = (a / OPbyte) >> 0;
r = (a % OPbyte);
2011-12-23 20:24:16 +08:00
set_lower_word_in_register(0, q);
set_lower_word_in_register(2, r);
2011-12-17 12:16:10 +08:00
}
function Gc(OPbyte) {
2011-12-17 12:16:10 +08:00
var a, q, r;
2011-12-17 16:08:25 +08:00
a = (regs[2] << 16) | (regs[0] & 0xffff);
OPbyte = (OPbyte << 16) >> 16;
if (OPbyte == 0)
abort(0);
q = (a / OPbyte) >> 0;
2011-12-17 12:16:10 +08:00
if (((q << 16) >> 16) != q)
abort(0);
r = (a % OPbyte);
2011-12-23 20:24:16 +08:00
set_lower_word_in_register(0, q);
set_lower_word_in_register(2, r);
2011-12-17 12:16:10 +08:00
}
function Hc(Ic, Jc, OPbyte) {
2011-12-17 12:16:10 +08:00
var a, i, Kc;
Ic = Ic >>> 0;
Jc = Jc >>> 0;
OPbyte = OPbyte >>> 0;
if (Ic >= OPbyte) {
abort(0);
2011-12-17 12:16:10 +08:00
}
if (Ic >= 0 && Ic <= 0x200000) {
a = Ic * 4294967296 + Jc;
v = (a % OPbyte) >> 0;
return (a / OPbyte) >> 0;
2011-12-17 12:16:10 +08:00
} else {
for (i = 0; i < 32; i++) {
Kc = Ic >> 31;
Ic = ((Ic << 1) | (Jc >>> 31)) >>> 0;
if (Kc || Ic >= OPbyte) {
Ic = Ic - OPbyte;
2011-12-17 12:16:10 +08:00
Jc = (Jc << 1) | 1;
} else {
Jc = Jc << 1;
}
}
v = Ic >> 0;
2011-12-17 12:16:10 +08:00
return Jc;
}
}
function Lc(Ic, Jc, OPbyte) {
2011-12-17 12:16:10 +08:00
var Mc, Nc, q;
if (Ic < 0) {
Mc = 1;
Ic = ~Ic;
Jc = (-Jc) >> 0;
if (Jc == 0)
Ic = (Ic + 1) >> 0;
} else {
Mc = 0;
}
if (OPbyte < 0) {
OPbyte = (-OPbyte) >> 0;
2011-12-17 12:16:10 +08:00
Nc = 1;
} else {
Nc = 0;
}
q = Hc(Ic, Jc, OPbyte);
2011-12-17 12:16:10 +08:00
Nc ^= Mc;
if (Nc) {
if ((q >>> 0) > 0x80000000)
abort(0);
2011-12-17 12:16:10 +08:00
q = (-q) >> 0;
} else {
if ((q >>> 0) >= 0x80000000)
abort(0);
2011-12-17 12:16:10 +08:00
}
if (Mc) {
v = (-v) >> 0;
2011-12-17 12:16:10 +08:00
}
return q;
}
function Oc(a, OPbyte) {
2011-12-17 12:16:10 +08:00
var qc;
a &= 0xff;
OPbyte &= 0xff;
qc = (regs[0] & 0xff) * (OPbyte & 0xff);
2011-12-17 13:13:37 +08:00
_src = qc >> 8;
2011-12-17 16:14:24 +08:00
_dst = (((qc) << 24) >> 24);
_op = 21;
2011-12-17 12:16:10 +08:00
return qc;
}
function Pc(a, OPbyte) {
2011-12-17 12:16:10 +08:00
var qc;
a = (((a) << 24) >> 24);
OPbyte = (((OPbyte) << 24) >> 24);
qc = (a * OPbyte) >> 0;
2011-12-17 16:14:24 +08:00
_dst = (((qc) << 24) >> 24);
_src = (qc != _dst) >> 0;
_op = 21;
2011-12-17 12:16:10 +08:00
return qc;
}
function Qc(a, OPbyte) {
2011-12-17 12:16:10 +08:00
var qc;
qc = ((a & 0xffff) * (OPbyte & 0xffff)) >> 0;
2011-12-17 13:13:37 +08:00
_src = qc >>> 16;
2011-12-17 16:14:24 +08:00
_dst = (((qc) << 16) >> 16);
_op = 22;
2011-12-17 12:16:10 +08:00
return qc;
}
function Rc(a, OPbyte) {
2011-12-17 12:16:10 +08:00
var qc;
a = (a << 16) >> 16;
OPbyte = (OPbyte << 16) >> 16;
qc = (a * OPbyte) >> 0;
2011-12-17 16:14:24 +08:00
_dst = (((qc) << 16) >> 16);
_src = (qc != _dst) >> 0;
_op = 22;
2011-12-17 12:16:10 +08:00
return qc;
}
function Sc(a, OPbyte) {
2011-12-17 12:16:10 +08:00
var r, Jc, Ic, Tc, Uc, m;
a = a >>> 0;
OPbyte = OPbyte >>> 0;
r = a * OPbyte;
2011-12-17 12:16:10 +08:00
if (r <= 0xffffffff) {
v = 0;
2011-12-17 12:16:10 +08:00
r &= -1;
} else {
Jc = a & 0xffff;
Ic = a >>> 16;
Tc = OPbyte & 0xffff;
Uc = OPbyte >>> 16;
2011-12-17 12:16:10 +08:00
r = Jc * Tc;
v = Ic * Uc;
2011-12-17 12:16:10 +08:00
m = Jc * Uc;
r += (((m & 0xffff) << 16) >>> 0);
v += (m >>> 16);
2011-12-17 12:16:10 +08:00
if (r >= 4294967296) {
r -= 4294967296;
v++;
2011-12-17 12:16:10 +08:00
}
m = Ic * Tc;
r += (((m & 0xffff) << 16) >>> 0);
v += (m >>> 16);
2011-12-17 12:16:10 +08:00
if (r >= 4294967296) {
r -= 4294967296;
v++;
2011-12-17 12:16:10 +08:00
}
r &= -1;
v &= -1;
2011-12-17 12:16:10 +08:00
}
return r;
}
function Vc(a, OPbyte) {
_dst = Sc(a, OPbyte);
_src = v;
2011-12-17 16:14:24 +08:00
_op = 23;
return _dst;
2011-12-17 12:16:10 +08:00
}
function Wc(a, OPbyte) {
2011-12-17 12:16:10 +08:00
var s, r;
s = 0;
if (a < 0) {
a = -a;
s = 1;
}
if (OPbyte < 0) {
OPbyte = -OPbyte;
2011-12-17 12:16:10 +08:00
s ^= 1;
}
r = Sc(a, OPbyte);
2011-12-17 12:16:10 +08:00
if (s) {
v = ~v;
2011-12-17 12:16:10 +08:00
r = (-r) >> 0;
if (r == 0) {
v = (v + 1) >> 0;
2011-12-17 12:16:10 +08:00
}
}
2011-12-17 16:14:24 +08:00
_dst = r;
_src = (v - (r >> 31)) >> 0;
2011-12-17 16:14:24 +08:00
_op = 23;
2011-12-17 12:16:10 +08:00
return r;
}
2011-12-18 20:40:30 +08:00
function check_carry() {
2011-12-23 21:15:54 +08:00
var Yb, qc, current_op, relevant_dst;
2011-12-17 16:14:24 +08:00
if (_op >= 25) {
2011-12-23 21:15:54 +08:00
current_op = _op2;
relevant_dst = _dst2;
2011-12-17 12:16:10 +08:00
} else {
2011-12-23 21:15:54 +08:00
current_op = _op;
relevant_dst = _dst;
2011-12-17 12:16:10 +08:00
}
2011-12-23 21:15:54 +08:00
switch (current_op) {
2011-12-17 12:16:10 +08:00
case 0:
2011-12-23 21:15:54 +08:00
qc = (relevant_dst & 0xff) < (_src & 0xff);
2011-12-17 12:16:10 +08:00
break;
case 1:
2011-12-23 21:15:54 +08:00
qc = (relevant_dst & 0xffff) < (_src & 0xffff);
2011-12-17 12:16:10 +08:00
break;
case 2:
2011-12-23 21:15:54 +08:00
qc = (relevant_dst >>> 0) < (_src >>> 0);
2011-12-17 12:16:10 +08:00
break;
case 3:
2011-12-23 21:15:54 +08:00
qc = (relevant_dst & 0xff) <= (_src & 0xff);
2011-12-17 12:16:10 +08:00
break;
case 4:
2011-12-23 21:15:54 +08:00
qc = (relevant_dst & 0xffff) <= (_src & 0xffff);
2011-12-17 12:16:10 +08:00
break;
case 5:
2011-12-23 21:15:54 +08:00
qc = (relevant_dst >>> 0) <= (_src >>> 0);
2011-12-17 12:16:10 +08:00
break;
case 6:
2011-12-23 21:15:54 +08:00
qc = ((relevant_dst + _src) & 0xff) < (_src & 0xff);
2011-12-17 12:16:10 +08:00
break;
case 7:
2011-12-23 21:15:54 +08:00
qc = ((relevant_dst + _src) & 0xffff) < (_src & 0xffff);
2011-12-17 12:16:10 +08:00
break;
case 8:
2011-12-23 21:15:54 +08:00
qc = ((relevant_dst + _src) >>> 0) < (_src >>> 0);
2011-12-17 12:16:10 +08:00
break;
case 9:
2011-12-23 21:15:54 +08:00
Yb = (relevant_dst + _src + 1) & 0xff;
2011-12-17 13:13:37 +08:00
qc = Yb <= (_src & 0xff);
2011-12-17 12:16:10 +08:00
break;
case 10:
2011-12-23 21:15:54 +08:00
Yb = (relevant_dst + _src + 1) & 0xffff;
2011-12-17 13:13:37 +08:00
qc = Yb <= (_src & 0xffff);
2011-12-17 12:16:10 +08:00
break;
case 11:
2011-12-23 21:15:54 +08:00
Yb = (relevant_dst + _src + 1) >>> 0;
2011-12-17 13:13:37 +08:00
qc = Yb <= (_src >>> 0);
2011-12-17 12:16:10 +08:00
break;
case 12:
case 13:
case 14:
qc = 0;
break;
case 15:
2011-12-17 13:13:37 +08:00
qc = (_src >> 7) & 1;
2011-12-17 12:16:10 +08:00
break;
case 16:
2011-12-17 13:13:37 +08:00
qc = (_src >> 15) & 1;
2011-12-17 12:16:10 +08:00
break;
case 17:
2011-12-17 13:13:37 +08:00
qc = (_src >> 31) & 1;
2011-12-17 12:16:10 +08:00
break;
case 18:
case 19:
case 20:
2011-12-17 13:13:37 +08:00
qc = _src & 1;
2011-12-17 12:16:10 +08:00
break;
case 21:
case 22:
case 23:
2011-12-17 13:13:37 +08:00
qc = _src != 0;
2011-12-17 12:16:10 +08:00
break;
case 24:
2011-12-17 13:13:37 +08:00
qc = _src & 1;
2011-12-17 12:16:10 +08:00
break;
default:
2011-12-17 16:14:24 +08:00
throw "GET_CARRY: unsupported cc_op=" + _op;
2011-12-17 12:16:10 +08:00
}
return qc;
}
2011-12-18 20:40:30 +08:00
function check_overflow() {
2011-12-17 12:16:10 +08:00
var qc, Yb;
2011-12-17 16:14:24 +08:00
switch (_op) {
2011-12-17 12:16:10 +08:00
case 0:
2011-12-17 16:14:24 +08:00
Yb = (_dst - _src) >> 0;
qc = (((Yb ^ _src ^ -1) & (Yb ^ _dst)) >> 7) & 1;
2011-12-17 12:16:10 +08:00
break;
case 1:
2011-12-17 16:14:24 +08:00
Yb = (_dst - _src) >> 0;
qc = (((Yb ^ _src ^ -1) & (Yb ^ _dst)) >> 15) & 1;
2011-12-17 12:16:10 +08:00
break;
case 2:
2011-12-17 16:14:24 +08:00
Yb = (_dst - _src) >> 0;
qc = (((Yb ^ _src ^ -1) & (Yb ^ _dst)) >> 31) & 1;
2011-12-17 12:16:10 +08:00
break;
case 3:
2011-12-17 16:14:24 +08:00
Yb = (_dst - _src - 1) >> 0;
qc = (((Yb ^ _src ^ -1) & (Yb ^ _dst)) >> 7) & 1;
2011-12-17 12:16:10 +08:00
break;
case 4:
2011-12-17 16:14:24 +08:00
Yb = (_dst - _src - 1) >> 0;
qc = (((Yb ^ _src ^ -1) & (Yb ^ _dst)) >> 15) & 1;
2011-12-17 12:16:10 +08:00
break;
case 5:
2011-12-17 16:14:24 +08:00
Yb = (_dst - _src - 1) >> 0;
qc = (((Yb ^ _src ^ -1) & (Yb ^ _dst)) >> 31) & 1;
2011-12-17 12:16:10 +08:00
break;
case 6:
2011-12-17 16:14:24 +08:00
Yb = (_dst + _src) >> 0;
qc = (((Yb ^ _src) & (Yb ^ _dst)) >> 7) & 1;
2011-12-17 12:16:10 +08:00
break;
case 7:
2011-12-17 16:14:24 +08:00
Yb = (_dst + _src) >> 0;
qc = (((Yb ^ _src) & (Yb ^ _dst)) >> 15) & 1;
2011-12-17 12:16:10 +08:00
break;
case 8:
2011-12-17 16:14:24 +08:00
Yb = (_dst + _src) >> 0;
qc = (((Yb ^ _src) & (Yb ^ _dst)) >> 31) & 1;
2011-12-17 12:16:10 +08:00
break;
case 9:
2011-12-17 16:14:24 +08:00
Yb = (_dst + _src + 1) >> 0;
qc = (((Yb ^ _src) & (Yb ^ _dst)) >> 7) & 1;
2011-12-17 12:16:10 +08:00
break;
case 10:
2011-12-17 16:14:24 +08:00
Yb = (_dst + _src + 1) >> 0;
qc = (((Yb ^ _src) & (Yb ^ _dst)) >> 15) & 1;
2011-12-17 12:16:10 +08:00
break;
case 11:
2011-12-17 16:14:24 +08:00
Yb = (_dst + _src + 1) >> 0;
qc = (((Yb ^ _src) & (Yb ^ _dst)) >> 31) & 1;
2011-12-17 12:16:10 +08:00
break;
case 12:
case 13:
case 14:
qc = 0;
break;
case 15:
case 18:
2011-12-17 16:14:24 +08:00
qc = ((_src ^ _dst) >> 7) & 1;
2011-12-17 12:16:10 +08:00
break;
case 16:
case 19:
2011-12-17 16:14:24 +08:00
qc = ((_src ^ _dst) >> 15) & 1;
2011-12-17 12:16:10 +08:00
break;
case 17:
case 20:
2011-12-17 16:14:24 +08:00
qc = ((_src ^ _dst) >> 31) & 1;
2011-12-17 12:16:10 +08:00
break;
case 21:
case 22:
case 23:
2011-12-17 13:13:37 +08:00
qc = _src != 0;
2011-12-17 12:16:10 +08:00
break;
case 24:
2011-12-17 13:13:37 +08:00
qc = (_src >> 11) & 1;
2011-12-17 12:16:10 +08:00
break;
case 25:
2011-12-17 16:14:24 +08:00
qc = (_dst & 0xff) == 0x80;
2011-12-17 12:16:10 +08:00
break;
case 26:
2011-12-17 16:14:24 +08:00
qc = (_dst & 0xffff) == 0x8000;
2011-12-17 12:16:10 +08:00
break;
case 27:
2011-12-17 16:14:24 +08:00
qc = (_dst == -2147483648);
2011-12-17 12:16:10 +08:00
break;
case 28:
2011-12-17 16:14:24 +08:00
qc = (_dst & 0xff) == 0x7f;
2011-12-17 12:16:10 +08:00
break;
case 29:
2011-12-17 16:14:24 +08:00
qc = (_dst & 0xffff) == 0x7fff;
2011-12-17 12:16:10 +08:00
break;
case 30:
2011-12-17 16:14:24 +08:00
qc = _dst == 0x7fffffff;
2011-12-17 12:16:10 +08:00
break;
default:
2011-12-17 16:14:24 +08:00
throw "JO: unsupported cc_op=" + _op;
2011-12-17 12:16:10 +08:00
}
return qc;
}
2011-12-23 21:15:54 +08:00
function check_below_or_equal() {
2011-12-17 12:16:10 +08:00
var qc;
2011-12-17 16:14:24 +08:00
switch (_op) {
2011-12-17 12:16:10 +08:00
case 6:
2011-12-17 16:14:24 +08:00
qc = ((_dst + _src) & 0xff) <= (_src & 0xff);
2011-12-17 12:16:10 +08:00
break;
case 7:
2011-12-17 16:14:24 +08:00
qc = ((_dst + _src) & 0xffff) <= (_src & 0xffff);
2011-12-17 12:16:10 +08:00
break;
case 8:
2011-12-17 16:14:24 +08:00
qc = ((_dst + _src) >>> 0) <= (_src >>> 0);
2011-12-17 12:16:10 +08:00
break;
case 24:
2011-12-17 13:13:37 +08:00
qc = (_src & (0x0040 | 0x0001)) != 0;
2011-12-17 12:16:10 +08:00
break;
default:
2011-12-18 20:40:30 +08:00
qc = check_carry() | (_dst == 0);
2011-12-17 12:16:10 +08:00
break;
}
return qc;
}
2011-12-20 21:20:23 +08:00
function check_parity() {
2011-12-17 16:14:24 +08:00
if (_op == 24) {
2011-12-17 13:13:37 +08:00
return (_src >> 2) & 1;
2011-12-17 12:16:10 +08:00
} else {
return parity_LUT[_dst & 0xff];
2011-12-17 12:16:10 +08:00
}
}
2011-12-23 21:15:54 +08:00
function check_less_than() {
2011-12-17 12:16:10 +08:00
var qc;
2011-12-17 16:14:24 +08:00
switch (_op) {
2011-12-17 12:16:10 +08:00
case 6:
2011-12-17 16:14:24 +08:00
qc = ((_dst + _src) << 24) < (_src << 24);
2011-12-17 12:16:10 +08:00
break;
case 7:
2011-12-17 16:14:24 +08:00
qc = ((_dst + _src) << 16) < (_src << 16);
2011-12-17 12:16:10 +08:00
break;
case 8:
2011-12-17 16:14:24 +08:00
qc = ((_dst + _src) >> 0) < _src;
2011-12-17 12:16:10 +08:00
break;
case 12:
case 25:
case 28:
case 13:
case 26:
case 29:
case 14:
case 27:
case 30:
2011-12-17 16:14:24 +08:00
qc = _dst < 0;
2011-12-17 12:16:10 +08:00
break;
case 24:
2011-12-17 13:13:37 +08:00
qc = ((_src >> 7) ^ (_src >> 11)) & 1;
2011-12-17 12:16:10 +08:00
break;
default:
2011-12-18 20:40:30 +08:00
qc = (_op == 24 ? ((_src >> 7) & 1) : (_dst < 0)) ^ check_overflow();
2011-12-17 12:16:10 +08:00
break;
}
return qc;
}
2011-12-23 21:15:54 +08:00
function check_less_or_equal() {
2011-12-17 12:16:10 +08:00
var qc;
2011-12-17 16:14:24 +08:00
switch (_op) {
2011-12-17 12:16:10 +08:00
case 6:
2011-12-17 16:14:24 +08:00
qc = ((_dst + _src) << 24) <= (_src << 24);
2011-12-17 12:16:10 +08:00
break;
case 7:
2011-12-17 16:14:24 +08:00
qc = ((_dst + _src) << 16) <= (_src << 16);
2011-12-17 12:16:10 +08:00
break;
case 8:
2011-12-17 16:14:24 +08:00
qc = ((_dst + _src) >> 0) <= _src;
2011-12-17 12:16:10 +08:00
break;
case 12:
case 25:
case 28:
case 13:
case 26:
case 29:
case 14:
case 27:
case 30:
2011-12-17 16:14:24 +08:00
qc = _dst <= 0;
2011-12-17 12:16:10 +08:00
break;
case 24:
2011-12-17 13:13:37 +08:00
qc = (((_src >> 7) ^ (_src >> 11)) | (_src >> 6)) & 1;
2011-12-17 12:16:10 +08:00
break;
default:
2011-12-18 20:40:30 +08:00
qc = ((_op == 24 ? ((_src >> 7) & 1) : (_dst < 0)) ^ check_overflow()) | (_dst == 0);
2011-12-17 12:16:10 +08:00
break;
}
return qc;
}
2011-12-23 21:15:54 +08:00
function check_adjust_flag() {
2011-12-17 12:16:10 +08:00
var Yb, qc;
2011-12-17 16:14:24 +08:00
switch (_op) {
2011-12-17 12:16:10 +08:00
case 0:
case 1:
case 2:
2011-12-17 16:14:24 +08:00
Yb = (_dst - _src) >> 0;
qc = (_dst ^ Yb ^ _src) & 0x10;
2011-12-17 12:16:10 +08:00
break;
case 3:
case 4:
case 5:
2011-12-17 16:14:24 +08:00
Yb = (_dst - _src - 1) >> 0;
qc = (_dst ^ Yb ^ _src) & 0x10;
2011-12-17 12:16:10 +08:00
break;
case 6:
case 7:
case 8:
2011-12-17 16:14:24 +08:00
Yb = (_dst + _src) >> 0;
qc = (_dst ^ Yb ^ _src) & 0x10;
2011-12-17 12:16:10 +08:00
break;
case 9:
case 10:
case 11:
2011-12-17 16:14:24 +08:00
Yb = (_dst + _src + 1) >> 0;
qc = (_dst ^ Yb ^ _src) & 0x10;
2011-12-17 12:16:10 +08:00
break;
case 12:
case 13:
case 14:
qc = 0;
break;
case 15:
case 18:
case 16:
case 19:
case 17:
case 20:
case 21:
case 22:
case 23:
qc = 0;
break;
case 24:
2011-12-17 13:13:37 +08:00
qc = _src & 0x10;
2011-12-17 12:16:10 +08:00
break;
case 25:
case 26:
case 27:
2011-12-17 16:14:24 +08:00
qc = (_dst ^ (_dst - 1)) & 0x10;
2011-12-17 12:16:10 +08:00
break;
case 28:
case 29:
case 30:
2011-12-17 16:14:24 +08:00
qc = (_dst ^ (_dst + 1)) & 0x10;
2011-12-17 12:16:10 +08:00
break;
default:
2011-12-17 16:14:24 +08:00
throw "AF: unsupported cc_op=" + _op;
2011-12-17 12:16:10 +08:00
}
return qc;
}
2011-12-21 09:18:08 +08:00
function check_status_bits_for_jump(gd) {
2011-12-17 12:16:10 +08:00
var qc;
switch (gd >> 1) {
case 0:
2011-12-18 20:40:30 +08:00
qc = check_overflow();
2011-12-17 12:16:10 +08:00
break;
case 1:
2011-12-18 20:40:30 +08:00
qc = check_carry();
2011-12-17 12:16:10 +08:00
break;
case 2:
2011-12-17 16:14:24 +08:00
qc = (_dst == 0);
2011-12-17 12:16:10 +08:00
break;
case 3:
2011-12-23 21:15:54 +08:00
qc = check_below_or_equal();
2011-12-17 12:16:10 +08:00
break;
case 4:
2011-12-17 16:14:24 +08:00
qc = (_op == 24 ? ((_src >> 7) & 1) : (_dst < 0));
2011-12-17 12:16:10 +08:00
break;
case 5:
2011-12-20 21:20:23 +08:00
qc = check_parity();
2011-12-17 12:16:10 +08:00
break;
case 6:
2011-12-23 21:15:54 +08:00
qc = check_less_than();
2011-12-17 12:16:10 +08:00
break;
case 7:
2011-12-23 21:15:54 +08:00
qc = check_less_or_equal();
2011-12-17 12:16:10 +08:00
break;
default:
throw "unsupported cond: " + gd;
}
return qc ^ (gd & 1);
}
2011-12-23 21:15:54 +08:00
function conditional_flags_for_rot_shift_ops() {
return (check_parity() << 2) | ((_dst == 0) << 6) | ((_op == 24 ? ((_src >> 7) & 1) : (_dst < 0)) << 7) | check_adjust_flag();
2011-12-17 12:16:10 +08:00
}
2011-12-23 21:15:54 +08:00
function get_conditional_flags() {
return (check_carry() << 0) | (check_parity() << 2) | ((_dst == 0) << 6) | ((_op == 24 ? ((_src >> 7) & 1) : (_dst < 0)) << 7) | (check_overflow() << 11) | check_adjust_flag();
2011-12-17 12:16:10 +08:00
}
function id() {
var jd;
2011-12-23 21:15:54 +08:00
jd = get_conditional_flags();
2011-12-17 13:38:46 +08:00
jd |= cpu.df & 0x00000400;
jd |= cpu.eflags;
2011-12-17 12:16:10 +08:00
return jd;
}
function kd(jd, ld) {
2011-12-17 13:13:37 +08:00
_src = jd & (0x0800 | 0x0080 | 0x0040 | 0x0010 | 0x0004 | 0x0001);
2011-12-17 16:14:24 +08:00
_dst = ((_src >> 6) & 1) ^ 1;
_op = 24;
2011-12-17 13:38:46 +08:00
cpu.df = 1 - (2 * ((jd >> 10) & 1));
cpu.eflags = (cpu.eflags & ~ld) | (jd & ld);
2011-12-17 12:16:10 +08:00
}
2011-12-21 10:28:01 +08:00
function current_cycle_count() {
return cpu.cycle_count + (N_cycles - cycles_left);
2011-12-17 12:16:10 +08:00
}
function cpu_abort(str) {
throw "CPU abort: " + str;
2011-12-17 12:16:10 +08:00
}
2011-12-18 20:40:30 +08:00
function cpu_dump() {
2011-12-17 16:20:47 +08:00
cpu.eip = eip;
2011-12-17 13:38:46 +08:00
cpu.cc_src = _src;
2011-12-17 16:14:24 +08:00
cpu.cc_dst = _dst;
cpu.cc_op = _op;
2011-12-17 16:20:47 +08:00
cpu.cc_op2 = _op2;
cpu.cc_dst2 = _dst2;
2011-12-17 13:38:46 +08:00
cpu.dump();
2011-12-17 12:16:10 +08:00
}
2011-12-18 20:40:30 +08:00
function cpu_dump_short() {
2011-12-17 16:20:47 +08:00
cpu.eip = eip;
2011-12-17 13:38:46 +08:00
cpu.cc_src = _src;
2011-12-17 16:14:24 +08:00
cpu.cc_dst = _dst;
cpu.cc_op = _op;
2011-12-17 16:20:47 +08:00
cpu.cc_op2 = _op2;
cpu.cc_dst2 = _dst2;
2011-12-17 13:38:46 +08:00
cpu.dump_short();
2011-12-17 12:16:10 +08:00
}
/* Oh No You Didn't!
Identifier Description
0 Divide error
1 Debug exceptions
2 Nonmaskable interrupt
3 Breakpoint (one-byte INT 3 instruction)
4 Overflow (INTO instruction)
5 Bounds check (BOUND instruction)
6 Invalid opcode
7 Coprocessor not available
8 Double fault
9 (reserved)
10 Invalid TSS
11 Segment not present
12 Stack exception
13 General protection
14 Page fault
15 (reserved)
16 Coprecessor error
17-31 (reserved)
32-255 Available for external interrupts via INTR pin
The identifiers of the maskable interrupts are determined by external
interrupt controllers (such as Intel's 8259A Programmable Interrupt
Controller) and communicated to the processor during the processor's
interrupt-acknowledge sequence. The numbers assigned by an 8259A PIC
can be specified by software. Any numbers in the range 32 through 255
can be used. Table 9-1 shows the assignment of interrupt and exception
identifiers.
*/
function abort_with_error_code(intno, error_code) { //used only for errors 10,11,12,13,14
2011-12-21 10:28:01 +08:00
cpu.cycle_count += (N_cycles - cycles_left);
2011-12-17 16:20:47 +08:00
cpu.eip = eip;
2011-12-17 13:38:46 +08:00
cpu.cc_src = _src;
2011-12-17 16:14:24 +08:00
cpu.cc_dst = _dst;
cpu.cc_op = _op;
2011-12-17 16:20:47 +08:00
cpu.cc_op2 = _op2;
cpu.cc_dst2 = _dst2;
throw {intno: intno, error_code: error_code};
2011-12-17 12:16:10 +08:00
}
function abort(intno) { //used only for errors 0, 5, 6, 7, 13
abort_with_error_code(intno, 0);
2011-12-17 12:16:10 +08:00
}
2011-12-21 09:18:08 +08:00
function change_permission_level(sd) {
2011-12-17 13:38:46 +08:00
cpu.cpl = sd;
if (cpu.cpl == 3) {
2011-12-17 17:17:40 +08:00
_tlb_read_ = tlb_read_user;
_tlb_write_ = tlb_write_user;
2011-12-17 12:16:10 +08:00
} else {
2011-12-17 17:17:40 +08:00
_tlb_read_ = tlb_read_kernel;
_tlb_write_ = tlb_write_kernel;
2011-12-17 12:16:10 +08:00
}
}
function td(mem8_loc, ud) {
var tlb_lookup;
2011-12-17 12:16:10 +08:00
if (ud) {
tlb_lookup = _tlb_write_[mem8_loc >>> 12];
2011-12-17 12:16:10 +08:00
} else {
tlb_lookup = _tlb_read_[mem8_loc >>> 12];
2011-12-17 12:16:10 +08:00
}
if (tlb_lookup == -1) {
do_tlb_set_page(mem8_loc, ud, cpu.cpl == 3);
2011-12-17 12:16:10 +08:00
if (ud) {
tlb_lookup = _tlb_write_[mem8_loc >>> 12];
2011-12-17 12:16:10 +08:00
} else {
tlb_lookup = _tlb_read_[mem8_loc >>> 12];
2011-12-17 12:16:10 +08:00
}
}
return tlb_lookup ^ mem8_loc;
2011-12-17 12:16:10 +08:00
}
2011-12-21 10:43:53 +08:00
function vd(x) {
2011-12-17 12:16:10 +08:00
var wd;
2011-12-17 16:08:25 +08:00
wd = regs[4] - 2;
2011-12-21 10:28:01 +08:00
mem8_loc = ((wd & SS_mask) + SS_base) >> 0;
st16_mem8_write(x);
2011-12-21 10:28:01 +08:00
regs[4] = (regs[4] & ~SS_mask) | ((wd) & SS_mask);
2011-12-17 12:16:10 +08:00
}
2011-12-21 10:43:53 +08:00
function xd(x) {
2011-12-17 12:16:10 +08:00
var wd;
2011-12-17 16:08:25 +08:00
wd = regs[4] - 4;
2011-12-21 10:28:01 +08:00
mem8_loc = ((wd & SS_mask) + SS_base) >> 0;
st32_mem8_write(x);
2011-12-21 10:28:01 +08:00
regs[4] = (regs[4] & ~SS_mask) | ((wd) & SS_mask);
2011-12-17 12:16:10 +08:00
}
function yd() {
2011-12-21 10:28:01 +08:00
mem8_loc = ((regs[4] & SS_mask) + SS_base) >> 0;
return ld_16bits_mem8_read();
2011-12-17 12:16:10 +08:00
}
function zd() {
2011-12-21 10:28:01 +08:00
regs[4] = (regs[4] & ~SS_mask) | ((regs[4] + 2) & SS_mask);
2011-12-17 12:16:10 +08:00
}
function Ad() {
2011-12-21 10:28:01 +08:00
mem8_loc = ((regs[4] & SS_mask) + SS_base) >> 0;
return ld_32bits_mem8_read();
2011-12-17 12:16:10 +08:00
}
function Bd() {
2011-12-21 10:28:01 +08:00
regs[4] = (regs[4] & ~SS_mask) | ((regs[4] + 4) & SS_mask);
2011-12-17 12:16:10 +08:00
}
function Cd(Nb, OPbyte) {
var n, CS_flags, l, mem8, Dd, base, conditional_var, Ed;
2011-12-17 12:16:10 +08:00
n = 1;
2011-12-21 10:28:01 +08:00
CS_flags = init_CS_flags;
if (CS_flags & 0x0100)
2011-12-17 12:16:10 +08:00
Ed = 2;
else
Ed = 4;
2011-12-23 21:15:54 +08:00
EXEC_LOOP: for (; ; ) {
switch (OPbyte) {
2011-12-17 12:16:10 +08:00
case 0x66:
2011-12-21 10:28:01 +08:00
if (init_CS_flags & 0x0100) {
2011-12-17 12:16:10 +08:00
Ed = 4;
2011-12-21 10:28:01 +08:00
CS_flags &= ~0x0100;
2011-12-17 12:16:10 +08:00
} else {
Ed = 2;
2011-12-21 10:28:01 +08:00
CS_flags |= 0x0100;
2011-12-17 12:16:10 +08:00
}
case 0xf0:
case 0xf2:
case 0xf3:
case 0x26:
case 0x2e:
case 0x36:
case 0x3e:
case 0x64:
case 0x65:
{
if ((n + 1) > 15)
abort(6);
mem8_loc = (Nb + (n++)) >> 0;
2011-12-21 10:43:53 +08:00
OPbyte = (((last_tlb_val = _tlb_read_[mem8_loc >>> 12]) == -1) ? __ld_8bits_mem8_read() : phys_mem8[mem8_loc ^ last_tlb_val]);
2011-12-17 12:16:10 +08:00
}
break;
case 0x67:
2011-12-21 10:28:01 +08:00
if (init_CS_flags & 0x0080) {
CS_flags &= ~0x0080;
2011-12-17 12:16:10 +08:00
} else {
2011-12-21 10:28:01 +08:00
CS_flags |= 0x0080;
2011-12-17 12:16:10 +08:00
}
{
if ((n + 1) > 15)
abort(6);
mem8_loc = (Nb + (n++)) >> 0;
2011-12-21 10:43:53 +08:00
OPbyte = (((last_tlb_val = _tlb_read_[mem8_loc >>> 12]) == -1) ? __ld_8bits_mem8_read() : phys_mem8[mem8_loc ^ last_tlb_val]);
2011-12-17 12:16:10 +08:00
}
break;
case 0x91:
case 0x92:
case 0x93:
case 0x94:
case 0x95:
case 0x96:
case 0x97:
case 0x40:
case 0x41:
case 0x42:
case 0x43:
case 0x44:
case 0x45:
case 0x46:
case 0x47:
case 0x48:
case 0x49:
case 0x4a:
case 0x4b:
case 0x4c:
case 0x4d:
case 0x4e:
case 0x4f:
case 0x50:
case 0x51:
case 0x52:
case 0x53:
case 0x54:
case 0x55:
case 0x56:
case 0x57:
case 0x58:
case 0x59:
case 0x5a:
case 0x5b:
case 0x5c:
case 0x5d:
case 0x5e:
case 0x5f:
case 0x98:
case 0x99:
case 0xc9:
case 0x9c:
case 0x9d:
case 0x06:
case 0x0e:
case 0x16:
case 0x1e:
case 0x07:
case 0x17:
case 0x1f:
case 0xc3:
case 0xcb:
case 0x90:
case 0xcc:
case 0xce:
case 0xcf:
case 0xf5:
case 0xf8:
case 0xf9:
case 0xfc:
case 0xfd:
case 0xfa:
case 0xfb:
case 0x9e:
case 0x9f:
case 0xf4:
case 0xa4:
case 0xa5:
case 0xaa:
case 0xab:
case 0xa6:
case 0xa7:
case 0xac:
case 0xad:
case 0xae:
case 0xaf:
case 0x9b:
case 0xec:
case 0xed:
case 0xee:
case 0xef:
case 0xd7:
case 0x27:
case 0x2f:
case 0x37:
case 0x3f:
case 0x60:
case 0x61:
case 0x6c:
case 0x6d:
case 0x6e:
case 0x6f:
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
2011-12-17 12:16:10 +08:00
case 0xb0:
case 0xb1:
case 0xb2:
case 0xb3:
case 0xb4:
case 0xb5:
case 0xb6:
case 0xb7:
case 0x04:
case 0x0c:
case 0x14:
case 0x1c:
case 0x24:
case 0x2c:
case 0x34:
case 0x3c:
case 0xa8:
case 0x6a:
case 0xeb:
case 0x70:
case 0x71:
case 0x72:
case 0x73:
case 0x76:
case 0x77:
case 0x78:
case 0x79:
case 0x7a:
case 0x7b:
case 0x7c:
case 0x7d:
case 0x7e:
case 0x7f:
case 0x74:
case 0x75:
case 0xe0:
case 0xe1:
case 0xe2:
case 0xe3:
case 0xcd:
case 0xe4:
case 0xe5:
case 0xe6:
case 0xe7:
case 0xd4:
case 0xd5:
n++;
if (n > 15)
abort(6);
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
2011-12-17 12:16:10 +08:00
case 0xb8:
case 0xb9:
case 0xba:
case 0xbb:
case 0xbc:
case 0xbd:
case 0xbe:
case 0xbf:
case 0x05:
case 0x0d:
case 0x15:
case 0x1d:
case 0x25:
case 0x2d:
case 0x35:
case 0x3d:
case 0xa9:
case 0x68:
case 0xe9:
case 0xe8:
n += Ed;
if (n > 15)
abort(6);
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
2011-12-17 12:16:10 +08:00
case 0x88:
case 0x89:
case 0x8a:
case 0x8b:
case 0x86:
case 0x87:
case 0x8e:
case 0x8c:
case 0xc4:
case 0xc5:
case 0x00:
case 0x08:
case 0x10:
case 0x18:
case 0x20:
case 0x28:
case 0x30:
case 0x38:
case 0x01:
case 0x09:
case 0x11:
case 0x19:
case 0x21:
case 0x29:
case 0x31:
case 0x39:
case 0x02:
case 0x0a:
case 0x12:
case 0x1a:
case 0x22:
case 0x2a:
case 0x32:
case 0x3a:
case 0x03:
case 0x0b:
case 0x13:
case 0x1b:
case 0x23:
case 0x2b:
case 0x33:
case 0x3b:
case 0x84:
case 0x85:
case 0xd0:
case 0xd1:
case 0xd2:
case 0xd3:
case 0x8f:
case 0x8d:
case 0xfe:
case 0xff:
case 0xd8:
case 0xd9:
case 0xda:
case 0xdb:
case 0xdc:
case 0xdd:
case 0xde:
case 0xdf:
case 0x62:
case 0x63:
{
{
if ((n + 1) > 15)
abort(6);
mem8_loc = (Nb + (n++)) >> 0;
2011-12-21 10:43:53 +08:00
mem8 = (((last_tlb_val = _tlb_read_[mem8_loc >>> 12]) == -1) ? __ld_8bits_mem8_read() : phys_mem8[mem8_loc ^ last_tlb_val]);
2011-12-17 12:16:10 +08:00
}
2011-12-21 10:28:01 +08:00
if (CS_flags & 0x0080) {
2011-12-18 21:19:08 +08:00
switch (mem8 >> 6) {
2011-12-17 12:16:10 +08:00
case 0:
2011-12-18 21:19:08 +08:00
if ((mem8 & 7) == 6)
2011-12-17 12:16:10 +08:00
n += 2;
break;
case 1:
n++;
break;
default:
n += 2;
break;
}
} else {
2011-12-18 21:19:08 +08:00
switch ((mem8 & 7) | ((mem8 >> 3) & 0x18)) {
2011-12-17 12:16:10 +08:00
case 0x04:
{
if ((n + 1) > 15)
abort(6);
mem8_loc = (Nb + (n++)) >> 0;
2011-12-21 10:43:53 +08:00
Dd = (((last_tlb_val = _tlb_read_[mem8_loc >>> 12]) == -1) ? __ld_8bits_mem8_read() : phys_mem8[mem8_loc ^ last_tlb_val]);
2011-12-17 12:16:10 +08:00
}
if ((Dd & 7) == 5) {
n += 4;
}
break;
case 0x0c:
n += 2;
break;
case 0x14:
n += 5;
break;
case 0x05:
n += 4;
break;
case 0x00:
case 0x01:
case 0x02:
case 0x03:
case 0x06:
case 0x07:
break;
case 0x08:
case 0x09:
case 0x0a:
case 0x0b:
case 0x0d:
case 0x0e:
case 0x0f:
n++;
break;
case 0x10:
case 0x11:
case 0x12:
case 0x13:
case 0x15:
case 0x16:
case 0x17:
n += 4;
break;
}
}
if (n > 15)
abort(6);
2011-12-17 12:16:10 +08:00
}
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
2011-12-17 12:16:10 +08:00
case 0xa0:
case 0xa1:
case 0xa2:
case 0xa3:
2011-12-21 10:28:01 +08:00
if (CS_flags & 0x0100)
2011-12-17 12:16:10 +08:00
n += 2;
else
n += 4;
if (n > 15)
abort(6);
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
2011-12-17 12:16:10 +08:00
case 0xc6:
case 0x80:
case 0x82:
case 0x83:
case 0x6b:
case 0xc0:
case 0xc1:
{
{
if ((n + 1) > 15)
abort(6);
mem8_loc = (Nb + (n++)) >> 0;
2011-12-21 10:43:53 +08:00
mem8 = (((last_tlb_val = _tlb_read_[mem8_loc >>> 12]) == -1) ? __ld_8bits_mem8_read() : phys_mem8[mem8_loc ^ last_tlb_val]);
2011-12-17 12:16:10 +08:00
}
2011-12-21 10:28:01 +08:00
if (CS_flags & 0x0080) {
2011-12-18 21:19:08 +08:00
switch (mem8 >> 6) {
2011-12-17 12:16:10 +08:00
case 0:
2011-12-18 21:19:08 +08:00
if ((mem8 & 7) == 6)
2011-12-17 12:16:10 +08:00
n += 2;
break;
case 1:
n++;
break;
default:
n += 2;
break;
}
} else {
2011-12-18 21:19:08 +08:00
switch ((mem8 & 7) | ((mem8 >> 3) & 0x18)) {
2011-12-17 12:16:10 +08:00
case 0x04:
{
if ((n + 1) > 15)
abort(6);
mem8_loc = (Nb + (n++)) >> 0;
2011-12-21 10:43:53 +08:00
Dd = (((last_tlb_val = _tlb_read_[mem8_loc >>> 12]) == -1) ? __ld_8bits_mem8_read() : phys_mem8[mem8_loc ^ last_tlb_val]);
2011-12-17 12:16:10 +08:00
}
if ((Dd & 7) == 5) {
n += 4;
}
break;
case 0x0c:
n += 2;
break;
case 0x14:
n += 5;
break;
case 0x05:
n += 4;
break;
case 0x00:
case 0x01:
case 0x02:
case 0x03:
case 0x06:
case 0x07:
break;
case 0x08:
case 0x09:
case 0x0a:
case 0x0b:
case 0x0d:
case 0x0e:
case 0x0f:
n++;
break;
case 0x10:
case 0x11:
case 0x12:
case 0x13:
case 0x15:
case 0x16:
case 0x17:
n += 4;
break;
}
}
if (n > 15)
abort(6);
2011-12-17 12:16:10 +08:00
}
n++;
if (n > 15)
abort(6);
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
2011-12-17 12:16:10 +08:00
case 0xc7:
case 0x81:
case 0x69:
{
{
if ((n + 1) > 15)
abort(6);
mem8_loc = (Nb + (n++)) >> 0;
2011-12-21 10:43:53 +08:00
mem8 = (((last_tlb_val = _tlb_read_[mem8_loc >>> 12]) == -1) ? __ld_8bits_mem8_read() : phys_mem8[mem8_loc ^ last_tlb_val]);
2011-12-17 12:16:10 +08:00
}
2011-12-21 10:28:01 +08:00
if (CS_flags & 0x0080) {
2011-12-18 21:19:08 +08:00
switch (mem8 >> 6) {
2011-12-17 12:16:10 +08:00
case 0:
2011-12-18 21:19:08 +08:00
if ((mem8 & 7) == 6)
2011-12-17 12:16:10 +08:00
n += 2;
break;
case 1:
n++;
break;
default:
n += 2;
break;
}
} else {
2011-12-18 21:19:08 +08:00
switch ((mem8 & 7) | ((mem8 >> 3) & 0x18)) {
2011-12-17 12:16:10 +08:00
case 0x04:
{
if ((n + 1) > 15)
abort(6);
mem8_loc = (Nb + (n++)) >> 0;
2011-12-21 10:43:53 +08:00
Dd = (((last_tlb_val = _tlb_read_[mem8_loc >>> 12]) == -1) ? __ld_8bits_mem8_read() : phys_mem8[mem8_loc ^ last_tlb_val]);
2011-12-17 12:16:10 +08:00
}
if ((Dd & 7) == 5) {
n += 4;
}
break;
case 0x0c:
n += 2;
break;
case 0x14:
n += 5;
break;
case 0x05:
n += 4;
break;
case 0x00:
case 0x01:
case 0x02:
case 0x03:
case 0x06:
case 0x07:
break;
case 0x08:
case 0x09:
case 0x0a:
case 0x0b:
case 0x0d:
case 0x0e:
case 0x0f:
n++;
break;
case 0x10:
case 0x11:
case 0x12:
case 0x13:
case 0x15:
case 0x16:
case 0x17:
n += 4;
break;
}
}
if (n > 15)
abort(6);
2011-12-17 12:16:10 +08:00
}
n += Ed;
if (n > 15)
abort(6);
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
2011-12-17 12:16:10 +08:00
case 0xf6:
{
{
if ((n + 1) > 15)
abort(6);
mem8_loc = (Nb + (n++)) >> 0;
2011-12-21 10:43:53 +08:00
mem8 = (((last_tlb_val = _tlb_read_[mem8_loc >>> 12]) == -1) ? __ld_8bits_mem8_read() : phys_mem8[mem8_loc ^ last_tlb_val]);
2011-12-17 12:16:10 +08:00
}
2011-12-21 10:28:01 +08:00
if (CS_flags & 0x0080) {
2011-12-18 21:19:08 +08:00
switch (mem8 >> 6) {
2011-12-17 12:16:10 +08:00
case 0:
2011-12-18 21:19:08 +08:00
if ((mem8 & 7) == 6)
2011-12-17 12:16:10 +08:00
n += 2;
break;
case 1:
n++;
break;
default:
n += 2;
break;
}
} else {
2011-12-18 21:19:08 +08:00
switch ((mem8 & 7) | ((mem8 >> 3) & 0x18)) {
2011-12-17 12:16:10 +08:00
case 0x04:
{
if ((n + 1) > 15)
abort(6);
mem8_loc = (Nb + (n++)) >> 0;
2011-12-21 10:43:53 +08:00
Dd = (((last_tlb_val = _tlb_read_[mem8_loc >>> 12]) == -1) ? __ld_8bits_mem8_read() : phys_mem8[mem8_loc ^ last_tlb_val]);
2011-12-17 12:16:10 +08:00
}
if ((Dd & 7) == 5) {
n += 4;
}
break;
case 0x0c:
n += 2;
break;
case 0x14:
n += 5;
break;
case 0x05:
n += 4;
break;
case 0x00:
case 0x01:
case 0x02:
case 0x03:
case 0x06:
case 0x07:
break;
case 0x08:
case 0x09:
case 0x0a:
case 0x0b:
case 0x0d:
case 0x0e:
case 0x0f:
n++;
break;
case 0x10:
case 0x11:
case 0x12:
case 0x13:
case 0x15:
case 0x16:
case 0x17:
n += 4;
break;
}
}
if (n > 15)
abort(6);
2011-12-17 12:16:10 +08:00
}
conditional_var = (mem8 >> 3) & 7;
if (conditional_var == 0) {
2011-12-17 12:16:10 +08:00
n++;
if (n > 15)
abort(6);
2011-12-17 12:16:10 +08:00
}
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
2011-12-17 12:16:10 +08:00
case 0xf7:
{
{
if ((n + 1) > 15)
abort(6);
mem8_loc = (Nb + (n++)) >> 0;
2011-12-21 10:43:53 +08:00
mem8 = (((last_tlb_val = _tlb_read_[mem8_loc >>> 12]) == -1) ? __ld_8bits_mem8_read() : phys_mem8[mem8_loc ^ last_tlb_val]);
2011-12-17 12:16:10 +08:00
}
2011-12-21 10:28:01 +08:00
if (CS_flags & 0x0080) {
2011-12-18 21:19:08 +08:00
switch (mem8 >> 6) {
2011-12-17 12:16:10 +08:00
case 0:
2011-12-18 21:19:08 +08:00
if ((mem8 & 7) == 6)
2011-12-17 12:16:10 +08:00
n += 2;
break;
case 1:
n++;
break;
default:
n += 2;
break;
}
} else {
2011-12-18 21:19:08 +08:00
switch ((mem8 & 7) | ((mem8 >> 3) & 0x18)) {
2011-12-17 12:16:10 +08:00
case 0x04:
{
if ((n + 1) > 15)
abort(6);
mem8_loc = (Nb + (n++)) >> 0;
2011-12-21 10:43:53 +08:00
Dd = (((last_tlb_val = _tlb_read_[mem8_loc >>> 12]) == -1) ? __ld_8bits_mem8_read() : phys_mem8[mem8_loc ^ last_tlb_val]);
2011-12-17 12:16:10 +08:00
}
if ((Dd & 7) == 5) {
n += 4;
}
break;
case 0x0c:
n += 2;
break;
case 0x14:
n += 5;
break;
case 0x05:
n += 4;
break;
case 0x00:
case 0x01:
case 0x02:
case 0x03:
case 0x06:
case 0x07:
break;
case 0x08:
case 0x09:
case 0x0a:
case 0x0b:
case 0x0d:
case 0x0e:
case 0x0f:
n++;
break;
case 0x10:
case 0x11:
case 0x12:
case 0x13:
case 0x15:
case 0x16:
case 0x17:
n += 4;
break;
}
}
if (n > 15)
abort(6);
2011-12-17 12:16:10 +08:00
}
conditional_var = (mem8 >> 3) & 7;
if (conditional_var == 0) {
2011-12-17 12:16:10 +08:00
n += Ed;
if (n > 15)
abort(6);
2011-12-17 12:16:10 +08:00
}
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
2011-12-17 12:16:10 +08:00
case 0xea:
case 0x9a:
n += 2 + Ed;
if (n > 15)
abort(6);
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
2011-12-17 12:16:10 +08:00
case 0xc2:
case 0xca:
n += 2;
if (n > 15)
abort(6);
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
2011-12-17 12:16:10 +08:00
case 0xc8:
n += 3;
if (n > 15)
abort(6);
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
2011-12-17 12:16:10 +08:00
case 0xd6:
case 0xf1:
default:
abort(6);
2011-12-17 12:16:10 +08:00
case 0x0f:
{
if ((n + 1) > 15)
abort(6);
mem8_loc = (Nb + (n++)) >> 0;
2011-12-21 10:43:53 +08:00
OPbyte = (((last_tlb_val = _tlb_read_[mem8_loc >>> 12]) == -1) ? __ld_8bits_mem8_read() : phys_mem8[mem8_loc ^ last_tlb_val]);
2011-12-17 12:16:10 +08:00
}
switch (OPbyte) {
2011-12-17 12:16:10 +08:00
case 0x06:
case 0xa2:
case 0x31:
case 0xa0:
case 0xa8:
case 0xa1:
case 0xa9:
case 0xc8:
case 0xc9:
case 0xca:
case 0xcb:
case 0xcc:
case 0xcd:
case 0xce:
case 0xcf:
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
2011-12-17 12:16:10 +08:00
case 0x80:
case 0x81:
case 0x82:
case 0x83:
case 0x84:
case 0x85:
case 0x86:
case 0x87:
case 0x88:
case 0x89:
case 0x8a:
case 0x8b:
case 0x8c:
case 0x8d:
case 0x8e:
case 0x8f:
n += Ed;
if (n > 15)
abort(6);
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
2011-12-17 12:16:10 +08:00
case 0x90:
case 0x91:
case 0x92:
case 0x93:
case 0x94:
case 0x95:
case 0x96:
case 0x97:
case 0x98:
case 0x99:
case 0x9a:
case 0x9b:
case 0x9c:
case 0x9d:
case 0x9e:
case 0x9f:
case 0x40:
case 0x41:
case 0x42:
case 0x43:
case 0x44:
case 0x45:
case 0x46:
case 0x47:
case 0x48:
case 0x49:
case 0x4a:
case 0x4b:
case 0x4c:
case 0x4d:
case 0x4e:
case 0x4f:
case 0xb6:
case 0xb7:
case 0xbe:
case 0xbf:
case 0x00:
case 0x01:
case 0x02:
case 0x03:
case 0x20:
case 0x22:
case 0x23:
case 0xb2:
case 0xb4:
case 0xb5:
case 0xa5:
case 0xad:
case 0xa3:
case 0xab:
case 0xb3:
case 0xbb:
case 0xbc:
case 0xbd:
case 0xaf:
case 0xc0:
case 0xc1:
case 0xb0:
case 0xb1:
{
{
if ((n + 1) > 15)
abort(6);
mem8_loc = (Nb + (n++)) >> 0;
2011-12-21 10:43:53 +08:00
mem8 = (((last_tlb_val = _tlb_read_[mem8_loc >>> 12]) == -1) ? __ld_8bits_mem8_read() : phys_mem8[mem8_loc ^ last_tlb_val]);
2011-12-17 12:16:10 +08:00
}
2011-12-21 10:28:01 +08:00
if (CS_flags & 0x0080) {
2011-12-18 21:19:08 +08:00
switch (mem8 >> 6) {
2011-12-17 12:16:10 +08:00
case 0:
2011-12-18 21:19:08 +08:00
if ((mem8 & 7) == 6)
2011-12-17 12:16:10 +08:00
n += 2;
break;
case 1:
n++;
break;
default:
n += 2;
break;
}
} else {
2011-12-18 21:19:08 +08:00
switch ((mem8 & 7) | ((mem8 >> 3) & 0x18)) {
2011-12-17 12:16:10 +08:00
case 0x04:
{
if ((n + 1) > 15)
abort(6);
mem8_loc = (Nb + (n++)) >> 0;
2011-12-21 10:43:53 +08:00
Dd = (((last_tlb_val = _tlb_read_[mem8_loc >>> 12]) == -1) ? __ld_8bits_mem8_read() : phys_mem8[mem8_loc ^ last_tlb_val]);
2011-12-17 12:16:10 +08:00
}
if ((Dd & 7) == 5) {
n += 4;
}
break;
case 0x0c:
n += 2;
break;
case 0x14:
n += 5;
break;
case 0x05:
n += 4;
break;
case 0x00:
case 0x01:
case 0x02:
case 0x03:
case 0x06:
case 0x07:
break;
case 0x08:
case 0x09:
case 0x0a:
case 0x0b:
case 0x0d:
case 0x0e:
case 0x0f:
n++;
break;
case 0x10:
case 0x11:
case 0x12:
case 0x13:
case 0x15:
case 0x16:
case 0x17:
n += 4;
break;
}
}
if (n > 15)
abort(6);
2011-12-17 12:16:10 +08:00
}
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
2011-12-17 12:16:10 +08:00
case 0xa4:
case 0xac:
case 0xba:
{
{
if ((n + 1) > 15)
abort(6);
mem8_loc = (Nb + (n++)) >> 0;
2011-12-21 10:43:53 +08:00
mem8 = (((last_tlb_val = _tlb_read_[mem8_loc >>> 12]) == -1) ? __ld_8bits_mem8_read() : phys_mem8[mem8_loc ^ last_tlb_val]);
2011-12-17 12:16:10 +08:00
}
2011-12-21 10:28:01 +08:00
if (CS_flags & 0x0080) {
2011-12-18 21:19:08 +08:00
switch (mem8 >> 6) {
2011-12-17 12:16:10 +08:00
case 0:
2011-12-18 21:19:08 +08:00
if ((mem8 & 7) == 6)
2011-12-17 12:16:10 +08:00
n += 2;
break;
case 1:
n++;
break;
default:
n += 2;
break;
}
} else {
2011-12-18 21:19:08 +08:00
switch ((mem8 & 7) | ((mem8 >> 3) & 0x18)) {
2011-12-17 12:16:10 +08:00
case 0x04:
{
if ((n + 1) > 15)
abort(6);
mem8_loc = (Nb + (n++)) >> 0;
2011-12-21 10:43:53 +08:00
Dd = (((last_tlb_val = _tlb_read_[mem8_loc >>> 12]) == -1) ? __ld_8bits_mem8_read() : phys_mem8[mem8_loc ^ last_tlb_val]);
2011-12-17 12:16:10 +08:00
}
if ((Dd & 7) == 5) {
n += 4;
}
break;
case 0x0c:
n += 2;
break;
case 0x14:
n += 5;
break;
case 0x05:
n += 4;
break;
case 0x00:
case 0x01:
case 0x02:
case 0x03:
case 0x06:
case 0x07:
break;
case 0x08:
case 0x09:
case 0x0a:
case 0x0b:
case 0x0d:
case 0x0e:
case 0x0f:
n++;
break;
case 0x10:
case 0x11:
case 0x12:
case 0x13:
case 0x15:
case 0x16:
case 0x17:
n += 4;
break;
}
}
if (n > 15)
abort(6);
2011-12-17 12:16:10 +08:00
}
n++;
if (n > 15)
abort(6);
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
2011-12-17 12:16:10 +08:00
case 0x04:
case 0x05:
case 0x07:
case 0x08:
case 0x09:
case 0x0a:
case 0x0b:
case 0x0c:
case 0x0d:
case 0x0e:
case 0x0f:
case 0x10:
case 0x11:
case 0x12:
case 0x13:
case 0x14:
case 0x15:
case 0x16:
case 0x17:
case 0x18:
case 0x19:
case 0x1a:
case 0x1b:
case 0x1c:
case 0x1d:
case 0x1e:
case 0x1f:
case 0x21:
case 0x24:
case 0x25:
case 0x26:
case 0x27:
case 0x28:
case 0x29:
case 0x2a:
case 0x2b:
case 0x2c:
case 0x2d:
case 0x2e:
case 0x2f:
case 0x30:
case 0x32:
case 0x33:
case 0x34:
case 0x35:
case 0x36:
case 0x37:
case 0x38:
case 0x39:
case 0x3a:
case 0x3b:
case 0x3c:
case 0x3d:
case 0x3e:
case 0x3f:
case 0x50:
case 0x51:
case 0x52:
case 0x53:
case 0x54:
case 0x55:
case 0x56:
case 0x57:
case 0x58:
case 0x59:
case 0x5a:
case 0x5b:
case 0x5c:
case 0x5d:
case 0x5e:
case 0x5f:
case 0x60:
case 0x61:
case 0x62:
case 0x63:
case 0x64:
case 0x65:
case 0x66:
case 0x67:
case 0x68:
case 0x69:
case 0x6a:
case 0x6b:
case 0x6c:
case 0x6d:
case 0x6e:
case 0x6f:
case 0x70:
case 0x71:
case 0x72:
case 0x73:
case 0x74:
case 0x75:
case 0x76:
case 0x77:
case 0x78:
case 0x79:
case 0x7a:
case 0x7b:
case 0x7c:
case 0x7d:
case 0x7e:
case 0x7f:
case 0xa6:
case 0xa7:
case 0xaa:
case 0xae:
case 0xb8:
case 0xb9:
case 0xc2:
case 0xc3:
case 0xc4:
case 0xc5:
case 0xc6:
case 0xc7:
default:
abort(6);
2011-12-17 12:16:10 +08:00
}
break;
}
}
return n;
}
/* Typically, the upper 20 bits of CR3 become the page directory base register (PDBR),
which stores the physical address of the first page directory entry. */
function do_tlb_set_page(Gd, Hd, ja) {
2011-12-17 12:16:10 +08:00
var Id, Jd, error_code, Kd, Ld, Md, Nd, ud, Od;
if (!(cpu.cr0 & (1 << 31))) { //CR0: bit31 PG Paging If 1, enable paging and use the CR3 register, else disable paging
2011-12-17 13:38:46 +08:00
cpu.tlb_set_page(Gd & -4096, Gd & -4096, 1);
2011-12-17 12:16:10 +08:00
} else {
2011-12-17 13:38:46 +08:00
Id = (cpu.cr3 & -4096) + ((Gd >> 20) & 0xffc);
Jd = cpu.ld32_phys(Id);
2011-12-17 12:16:10 +08:00
if (!(Jd & 0x00000001)) {
error_code = 0;
} else {
if (!(Jd & 0x00000020)) {
Jd |= 0x00000020;
2011-12-17 13:38:46 +08:00
cpu.st32_phys(Id, Jd);
2011-12-17 12:16:10 +08:00
}
Kd = (Jd & -4096) + ((Gd >> 10) & 0xffc);
2011-12-17 13:38:46 +08:00
Ld = cpu.ld32_phys(Kd);
2011-12-17 12:16:10 +08:00
if (!(Ld & 0x00000001)) {
error_code = 0;
} else {
Md = Ld & Jd;
if (ja && !(Md & 0x00000004)) {
error_code = 0x01;
} else if (Hd && !(Md & 0x00000002)) {
error_code = 0x01;
} else {
Nd = (Hd && !(Ld & 0x00000040));
if (!(Ld & 0x00000020) || Nd) {
Ld |= 0x00000020;
if (Nd)
Ld |= 0x00000040;
2011-12-17 13:38:46 +08:00
cpu.st32_phys(Kd, Ld);
2011-12-17 12:16:10 +08:00
}
ud = 0;
if ((Ld & 0x00000040) && (Md & 0x00000002))
ud = 1;
Od = 0;
if (Md & 0x00000004)
Od = 1;
2011-12-17 13:38:46 +08:00
cpu.tlb_set_page(Gd & -4096, Ld & -4096, ud, Od);
2011-12-17 12:16:10 +08:00
return;
}
}
}
error_code |= Hd << 1;
if (ja)
error_code |= 0x04;
2011-12-17 13:38:46 +08:00
cpu.cr2 = Gd;
abort_with_error_code(14, error_code);
2011-12-17 12:16:10 +08:00
}
}
function set_CR0(Qd) {
if (!(Qd & (1 << 0))) //0th bit protected or real, only real supported!
2011-12-18 21:03:29 +08:00
cpu_abort("real mode not supported");
//if changing flags 31, 16, or 0 must flush tlb
2011-12-17 13:38:46 +08:00
if ((Qd & ((1 << 31) | (1 << 16) | (1 << 0))) != (cpu.cr0 & ((1 << 31) | (1 << 16) | (1 << 0)))) {
cpu.tlb_flush_all();
2011-12-17 12:16:10 +08:00
}
cpu.cr0 = Qd | (1 << 4); //keep bit 4 set to 1
2011-12-17 12:16:10 +08:00
}
function set_CR3(Sd) {
2011-12-17 13:38:46 +08:00
cpu.cr3 = Sd;
if (cpu.cr0 & (1 << 31)) {
cpu.tlb_flush_all();
2011-12-17 12:16:10 +08:00
}
}
function set_CR4(Ud) {
2011-12-17 13:38:46 +08:00
cpu.cr4 = Ud;
2011-12-17 12:16:10 +08:00
}
2011-12-21 10:28:01 +08:00
function SS_mask_from_flags(Wd) {
2011-12-17 12:16:10 +08:00
if (Wd & (1 << 22))
return -1;
else
return 0xffff;
}
function Xd(selector) {
var sa, Rb, Yd, Wd;
if (selector & 0x4)
2011-12-17 13:38:46 +08:00
sa = cpu.ldt;
2011-12-17 12:16:10 +08:00
else
2011-12-17 13:38:46 +08:00
sa = cpu.gdt;
2011-12-17 12:16:10 +08:00
Rb = selector & ~7;
if ((Rb + 7) > sa.limit)
return null;
mem8_loc = sa.base + Rb;
Yd = ld32_mem8_kernel_read();
mem8_loc += 4;
Wd = ld32_mem8_kernel_read();
2011-12-17 12:16:10 +08:00
return [Yd, Wd];
}
2011-12-18 21:19:08 +08:00
2011-12-21 10:28:01 +08:00
/*
Segment Handling Functions
------------------------------
*/
2011-12-23 21:15:54 +08:00
function calculate_descriptor_limit(Yd, Wd) {
2011-12-17 12:16:10 +08:00
var limit;
limit = (Yd & 0xffff) | (Wd & 0x000f0000);
if (Wd & (1 << 23))
limit = (limit << 12) | 0xfff;
return limit;
}
2011-12-23 21:15:54 +08:00
function calculate_descriptor_base(Yd, Wd) {
2011-12-17 12:16:10 +08:00
return (((Yd >>> 16) | ((Wd & 0xff) << 16) | (Wd & 0xff000000))) & -1;
}
2011-12-23 21:15:54 +08:00
/* Used to set TR and LDTR */
function set_descriptor_register(sa, Yd, Wd) {
sa.base = calculate_descriptor_base(Yd, Wd);
sa.limit = calculate_descriptor_limit(Yd, Wd);
2011-12-17 12:16:10 +08:00
sa.flags = Wd;
}
2011-12-21 10:28:01 +08:00
function init_segment_local_vars() {
CS_base = cpu.segs[1].base;//CS
SS_base = cpu.segs[2].base;//SS
2011-12-17 13:38:46 +08:00
if (cpu.segs[2].flags & (1 << 22))
2011-12-21 10:28:01 +08:00
SS_mask = -1;
2011-12-17 12:16:10 +08:00
else
2011-12-21 10:28:01 +08:00
SS_mask = 0xffff;
FS_usage_flag = (((CS_base | SS_base | cpu.segs[3].base | cpu.segs[0].base) == 0) && SS_mask == -1);
2011-12-17 13:38:46 +08:00
if (cpu.segs[1].flags & (1 << 22))
2011-12-21 10:28:01 +08:00
init_CS_flags = 0;
2011-12-17 12:16:10 +08:00
else
2011-12-21 10:28:01 +08:00
init_CS_flags = 0x0100 | 0x0080;
2011-12-17 12:16:10 +08:00
}
2011-12-18 21:19:08 +08:00
function set_segment_vars(ee, selector, base, limit, flags) {
2011-12-17 13:38:46 +08:00
cpu.segs[ee] = {selector: selector,base: base,limit: limit,flags: flags};
2011-12-21 10:28:01 +08:00
init_segment_local_vars();
2011-12-17 12:16:10 +08:00
}
2011-12-21 10:28:01 +08:00
function init_segment_vars_with_selector(Sb, selector) {
2011-12-18 21:19:08 +08:00
set_segment_vars(Sb, selector, (selector << 4), 0xffff, (1 << 15) | (3 << 13) | (1 << 12) | (1 << 8) | (1 << 12) | (1 << 9));
2011-12-17 12:16:10 +08:00
}
2011-12-21 10:28:01 +08:00
2011-12-17 12:16:10 +08:00
function ge(he) {
var ie, Rb, je, ke, le;
2011-12-17 13:38:46 +08:00
if (!(cpu.tr.flags & (1 << 15)))
cpu_abort("invalid tss"); //task state segment
2011-12-17 13:38:46 +08:00
ie = (cpu.tr.flags >> 8) & 0xf;
2011-12-17 12:16:10 +08:00
if ((ie & 7) != 1)
2011-12-18 21:03:29 +08:00
cpu_abort("invalid tss type");
2011-12-17 12:16:10 +08:00
je = ie >> 3;
Rb = (he * 4 + 2) << je;
2011-12-17 13:38:46 +08:00
if (Rb + (4 << je) - 1 > cpu.tr.limit)
abort_with_error_code(10, cpu.tr.selector & 0xfffc);
mem8_loc = (cpu.tr.base + Rb) & -1;
2011-12-17 12:16:10 +08:00
if (je == 0) {
le = ld16_mem8_kernel_read();
mem8_loc += 2;
2011-12-17 12:16:10 +08:00
} else {
le = ld32_mem8_kernel_read();
mem8_loc += 4;
2011-12-17 12:16:10 +08:00
}
ke = ld16_mem8_kernel_read();
2011-12-17 12:16:10 +08:00
return [ke, le];
}
2011-12-23 21:15:54 +08:00
function do_interrupt_paged_mode(intno, ne, error_code, oe, pe) {
2011-12-17 12:16:10 +08:00
var sa, qe, ie, he, selector, re, se;
var te, ue, je;
var e, Yd, Wd, ve, ke, le, we, xe;
2011-12-21 10:28:01 +08:00
var ye, SS_mask;
2011-12-17 12:16:10 +08:00
te = 0;
if (!ne && !pe) {
switch (intno) {
case 8:
case 10:
case 11:
case 12:
case 13:
case 14:
case 17:
te = 1;
break;
}
}
if (ne)
ye = oe;
else
2011-12-17 16:20:47 +08:00
ye = eip;
2011-12-17 13:38:46 +08:00
sa = cpu.idt;
2011-12-17 12:16:10 +08:00
if (intno * 8 + 7 > sa.limit)
abort_with_error_code(13, intno * 8 + 2);
mem8_loc = (sa.base + intno * 8) & -1;
Yd = ld32_mem8_kernel_read();
mem8_loc += 4;
Wd = ld32_mem8_kernel_read();
2011-12-17 12:16:10 +08:00
ie = (Wd >> 8) & 0x1f;
switch (ie) {
case 5:
case 7:
case 6:
throw "unsupported task gate";
case 14:
case 15:
break;
default:
abort_with_error_code(13, intno * 8 + 2);
2011-12-17 12:16:10 +08:00
break;
}
he = (Wd >> 13) & 3;
2011-12-17 13:38:46 +08:00
se = cpu.cpl;
2011-12-17 12:16:10 +08:00
if (ne && he < se)
abort_with_error_code(13, intno * 8 + 2);
2011-12-17 12:16:10 +08:00
if (!(Wd & (1 << 15)))
abort_with_error_code(11, intno * 8 + 2);
2011-12-17 12:16:10 +08:00
selector = Yd >> 16;
ve = (Wd & -65536) | (Yd & 0x0000ffff);
if ((selector & 0xfffc) == 0)
abort_with_error_code(13, 0);
2011-12-17 12:16:10 +08:00
e = Xd(selector);
if (!e)
abort_with_error_code(13, selector & 0xfffc);
2011-12-17 12:16:10 +08:00
Yd = e[0];
Wd = e[1];
if (!(Wd & (1 << 12)) || !(Wd & ((1 << 11))))
abort_with_error_code(13, selector & 0xfffc);
2011-12-17 12:16:10 +08:00
he = (Wd >> 13) & 3;
if (he > se)
abort_with_error_code(13, selector & 0xfffc);
2011-12-17 12:16:10 +08:00
if (!(Wd & (1 << 15)))
abort_with_error_code(11, selector & 0xfffc);
2011-12-17 12:16:10 +08:00
if (!(Wd & (1 << 10)) && he < se) {
e = ge(he);
ke = e[0];
le = e[1];
if ((ke & 0xfffc) == 0)
abort_with_error_code(10, ke & 0xfffc);
2011-12-17 12:16:10 +08:00
if ((ke & 3) != he)
abort_with_error_code(10, ke & 0xfffc);
2011-12-17 12:16:10 +08:00
e = Xd(ke);
if (!e)
abort_with_error_code(10, ke & 0xfffc);
2011-12-17 12:16:10 +08:00
we = e[0];
xe = e[1];
re = (xe >> 13) & 3;
if (re != he)
abort_with_error_code(10, ke & 0xfffc);
2011-12-17 12:16:10 +08:00
if (!(xe & (1 << 12)) || (xe & (1 << 11)) || !(xe & (1 << 9)))
abort_with_error_code(10, ke & 0xfffc);
2011-12-17 12:16:10 +08:00
if (!(xe & (1 << 15)))
abort_with_error_code(10, ke & 0xfffc);
2011-12-17 12:16:10 +08:00
ue = 1;
2011-12-21 10:28:01 +08:00
SS_mask = SS_mask_from_flags(xe);
2011-12-23 21:15:54 +08:00
qe = calculate_descriptor_base(we, xe);
2011-12-17 12:16:10 +08:00
} else if ((Wd & (1 << 10)) || he == se) {
2011-12-17 13:38:46 +08:00
if (cpu.eflags & 0x00020000)
abort_with_error_code(13, selector & 0xfffc);
2011-12-17 12:16:10 +08:00
ue = 0;
2011-12-21 10:28:01 +08:00
SS_mask = SS_mask_from_flags(cpu.segs[2].flags);
2011-12-17 13:38:46 +08:00
qe = cpu.segs[2].base;
2011-12-17 16:08:25 +08:00
le = regs[4];
2011-12-17 12:16:10 +08:00
he = se;
} else {
abort_with_error_code(13, selector & 0xfffc);
2011-12-17 12:16:10 +08:00
ue = 0;
2011-12-21 10:28:01 +08:00
SS_mask = 0;
2011-12-17 12:16:10 +08:00
qe = 0;
le = 0;
}
je = ie >> 3;
if (je == 1) {
if (ue) {
2011-12-17 13:38:46 +08:00
if (cpu.eflags & 0x00020000) {
2011-12-17 12:16:10 +08:00
{
le = (le - 4) & -1;
2011-12-21 10:28:01 +08:00
mem8_loc = (qe + (le & SS_mask)) & -1;
st32_mem8_kernel_write(cpu.segs[5].selector);
2011-12-17 12:16:10 +08:00
}
{
le = (le - 4) & -1;
2011-12-21 10:28:01 +08:00
mem8_loc = (qe + (le & SS_mask)) & -1;
st32_mem8_kernel_write(cpu.segs[4].selector);
2011-12-17 12:16:10 +08:00
}
{
le = (le - 4) & -1;
2011-12-21 10:28:01 +08:00
mem8_loc = (qe + (le & SS_mask)) & -1;
st32_mem8_kernel_write(cpu.segs[3].selector);
2011-12-17 12:16:10 +08:00
}
{
le = (le - 4) & -1;
2011-12-21 10:28:01 +08:00
mem8_loc = (qe + (le & SS_mask)) & -1;
st32_mem8_kernel_write(cpu.segs[0].selector);
2011-12-17 12:16:10 +08:00
}
}
{
le = (le - 4) & -1;
2011-12-21 10:28:01 +08:00
mem8_loc = (qe + (le & SS_mask)) & -1;
st32_mem8_kernel_write(cpu.segs[2].selector);
2011-12-17 12:16:10 +08:00
}
{
le = (le - 4) & -1;
2011-12-21 10:28:01 +08:00
mem8_loc = (qe + (le & SS_mask)) & -1;
st32_mem8_kernel_write(regs[4]);
2011-12-17 12:16:10 +08:00
}
}
{
le = (le - 4) & -1;
2011-12-21 10:28:01 +08:00
mem8_loc = (qe + (le & SS_mask)) & -1;
st32_mem8_kernel_write(id());
2011-12-17 12:16:10 +08:00
}
{
le = (le - 4) & -1;
2011-12-21 10:28:01 +08:00
mem8_loc = (qe + (le & SS_mask)) & -1;
st32_mem8_kernel_write(cpu.segs[1].selector);
2011-12-17 12:16:10 +08:00
}
{
le = (le - 4) & -1;
2011-12-21 10:28:01 +08:00
mem8_loc = (qe + (le & SS_mask)) & -1;
st32_mem8_kernel_write(ye);
2011-12-17 12:16:10 +08:00
}
if (te) {
{
le = (le - 4) & -1;
2011-12-21 10:28:01 +08:00
mem8_loc = (qe + (le & SS_mask)) & -1;
st32_mem8_kernel_write(error_code);
2011-12-17 12:16:10 +08:00
}
}
} else {
if (ue) {
2011-12-17 13:38:46 +08:00
if (cpu.eflags & 0x00020000) {
2011-12-17 12:16:10 +08:00
{
le = (le - 2) & -1;
2011-12-21 10:28:01 +08:00
mem8_loc = (qe + (le & SS_mask)) & -1;
st16_mem8_kernel_write(cpu.segs[5].selector);
2011-12-17 12:16:10 +08:00
}
{
le = (le - 2) & -1;
2011-12-21 10:28:01 +08:00
mem8_loc = (qe + (le & SS_mask)) & -1;
st16_mem8_kernel_write(cpu.segs[4].selector);
2011-12-17 12:16:10 +08:00
}
{
le = (le - 2) & -1;
2011-12-21 10:28:01 +08:00
mem8_loc = (qe + (le & SS_mask)) & -1;
st16_mem8_kernel_write(cpu.segs[3].selector);
2011-12-17 12:16:10 +08:00
}
{
le = (le - 2) & -1;
2011-12-21 10:28:01 +08:00
mem8_loc = (qe + (le & SS_mask)) & -1;
st16_mem8_kernel_write(cpu.segs[0].selector);
2011-12-17 12:16:10 +08:00
}
}
{
le = (le - 2) & -1;
2011-12-21 10:28:01 +08:00
mem8_loc = (qe + (le & SS_mask)) & -1;
st16_mem8_kernel_write(cpu.segs[2].selector);
2011-12-17 12:16:10 +08:00
}
{
le = (le - 2) & -1;
2011-12-21 10:28:01 +08:00
mem8_loc = (qe + (le & SS_mask)) & -1;
st16_mem8_kernel_write(regs[4]);
2011-12-17 12:16:10 +08:00
}
}
{
le = (le - 2) & -1;
2011-12-21 10:28:01 +08:00
mem8_loc = (qe + (le & SS_mask)) & -1;
st16_mem8_kernel_write(id());
2011-12-17 12:16:10 +08:00
}
{
le = (le - 2) & -1;
2011-12-21 10:28:01 +08:00
mem8_loc = (qe + (le & SS_mask)) & -1;
st16_mem8_kernel_write(cpu.segs[1].selector);
2011-12-17 12:16:10 +08:00
}
{
le = (le - 2) & -1;
2011-12-21 10:28:01 +08:00
mem8_loc = (qe + (le & SS_mask)) & -1;
st16_mem8_kernel_write(ye);
2011-12-17 12:16:10 +08:00
}
if (te) {
{
le = (le - 2) & -1;
2011-12-21 10:28:01 +08:00
mem8_loc = (qe + (le & SS_mask)) & -1;
st16_mem8_kernel_write(error_code);
2011-12-17 12:16:10 +08:00
}
}
}
if (ue) {
2011-12-17 13:38:46 +08:00
if (cpu.eflags & 0x00020000) {
2011-12-18 21:19:08 +08:00
set_segment_vars(0, 0, 0, 0, 0);
set_segment_vars(3, 0, 0, 0, 0);
set_segment_vars(4, 0, 0, 0, 0);
set_segment_vars(5, 0, 0, 0, 0);
2011-12-17 12:16:10 +08:00
}
ke = (ke & ~3) | he;
2011-12-23 21:15:54 +08:00
set_segment_vars(2, ke, qe, calculate_descriptor_limit(we, xe), xe);
2011-12-17 12:16:10 +08:00
}
2011-12-21 10:28:01 +08:00
regs[4] = (regs[4] & ~SS_mask) | ((le) & SS_mask);
2011-12-17 12:16:10 +08:00
selector = (selector & ~3) | he;
2011-12-23 21:15:54 +08:00
set_segment_vars(1, selector, calculate_descriptor_base(Yd, Wd), calculate_descriptor_limit(Yd, Wd), Wd);
2011-12-21 09:18:08 +08:00
change_permission_level(he);
2011-12-23 20:24:16 +08:00
eip = ve, physmem8_ptr = initial_mem_ptr = 0;
2011-12-17 12:16:10 +08:00
if ((ie & 1) == 0) {
2011-12-17 13:38:46 +08:00
cpu.eflags &= ~0x00000200;
2011-12-17 12:16:10 +08:00
}
2011-12-17 13:38:46 +08:00
cpu.eflags &= ~(0x00000100 | 0x00020000 | 0x00010000 | 0x00004000);
2011-12-17 12:16:10 +08:00
}
2011-12-23 21:15:54 +08:00
function do_interrupt_not_paged_mode(intno, ne, error_code, oe, pe) {
2011-12-17 12:16:10 +08:00
var sa, qe, selector, ve, le, ye;
2011-12-17 13:38:46 +08:00
sa = cpu.idt;
2011-12-17 12:16:10 +08:00
if (intno * 4 + 3 > sa.limit)
abort_with_error_code(13, intno * 8 + 2);
mem8_loc = (sa.base + (intno << 2)) >> 0;
ve = ld16_mem8_kernel_read();
mem8_loc = (mem8_loc + 2) >> 0;
selector = ld16_mem8_kernel_read();
2011-12-17 16:08:25 +08:00
le = regs[4];
2011-12-17 12:16:10 +08:00
if (ne)
ye = oe;
else
2011-12-17 16:20:47 +08:00
ye = eip;
2011-12-17 12:16:10 +08:00
{
le = (le - 2) >> 0;
2011-12-21 10:28:01 +08:00
mem8_loc = ((le & SS_mask) + SS_base) >> 0;
st16_mem8_write(id());
2011-12-17 12:16:10 +08:00
}
{
le = (le - 2) >> 0;
2011-12-21 10:28:01 +08:00
mem8_loc = ((le & SS_mask) + SS_base) >> 0;
st16_mem8_write(cpu.segs[1].selector);
2011-12-17 12:16:10 +08:00
}
{
le = (le - 2) >> 0;
2011-12-21 10:28:01 +08:00
mem8_loc = ((le & SS_mask) + SS_base) >> 0;
st16_mem8_write(ye);
2011-12-17 12:16:10 +08:00
}
2011-12-21 10:28:01 +08:00
regs[4] = (regs[4] & ~SS_mask) | ((le) & SS_mask);
2011-12-23 20:24:16 +08:00
eip = ve, physmem8_ptr = initial_mem_ptr = 0;
2011-12-17 13:38:46 +08:00
cpu.segs[1].selector = selector;
cpu.segs[1].base = (selector << 4);
cpu.eflags &= ~(0x00000200 | 0x00000100 | 0x00040000 | 0x00010000);
2011-12-17 12:16:10 +08:00
}
2011-12-23 21:15:54 +08:00
function do_interrupt(intno, ne, error_code, oe, pe) {
2011-12-17 12:16:10 +08:00
if (intno == 0x06) {
2011-12-17 16:20:47 +08:00
var Be = eip;
2011-12-17 12:16:10 +08:00
var Nb;
2011-12-23 21:15:54 +08:00
str = "do_interrupt: intno=" + _2_bytes_(intno) + " error_code=" + _4_bytes_(error_code)
+ " EIP=" + _4_bytes_(Be) + " ESP=" + _4_bytes_(regs[4]) + " EAX=" + _4_bytes_(regs[0])
+ " EBX=" + _4_bytes_(regs[3]) + " ECX=" + _4_bytes_(regs[1]);
2011-12-17 12:16:10 +08:00
if (intno == 0x0e) {
str += " CR2=" + _4_bytes_(cpu.cr2);
2011-12-17 12:16:10 +08:00
}
console.log(str);
2011-12-17 12:16:10 +08:00
if (intno == 0x06) {
var str, i, n;
str = "Code:";
2011-12-21 10:28:01 +08:00
Nb = (Be + CS_base) >> 0;
2011-12-17 12:16:10 +08:00
n = 4096 - (Nb & 0xfff);
if (n > 15)
n = 15;
for (i = 0; i < n; i++) {
mem8_loc = (Nb + i) & -1;
str += " " + _2_bytes_(ld_8bits_mem8_read());
2011-12-17 12:16:10 +08:00
}
console.log(str);
2011-12-17 12:16:10 +08:00
}
}
2011-12-17 13:38:46 +08:00
if (cpu.cr0 & (1 << 0)) {
2011-12-23 21:15:54 +08:00
do_interrupt_paged_mode(intno, ne, error_code, oe, pe);
2011-12-17 12:16:10 +08:00
} else {
2011-12-23 21:15:54 +08:00
do_interrupt_not_paged_mode(intno, ne, error_code, oe, pe);
2011-12-17 12:16:10 +08:00
}
}
function Ce(selector) {
var sa, Yd, Wd, Rb, De;
selector &= 0xffff;
if ((selector & 0xfffc) == 0) {
2011-12-17 13:38:46 +08:00
cpu.ldt.base = 0;
cpu.ldt.limit = 0;
2011-12-17 12:16:10 +08:00
} else {
if (selector & 0x4)
abort_with_error_code(13, selector & 0xfffc);
2011-12-17 13:38:46 +08:00
sa = cpu.gdt;
2011-12-17 12:16:10 +08:00
Rb = selector & ~7;
De = 7;
if ((Rb + De) > sa.limit)
abort_with_error_code(13, selector & 0xfffc);
mem8_loc = (sa.base + Rb) & -1;
Yd = ld32_mem8_kernel_read();
mem8_loc += 4;
Wd = ld32_mem8_kernel_read();
2011-12-17 12:16:10 +08:00
if ((Wd & (1 << 12)) || ((Wd >> 8) & 0xf) != 2)
abort_with_error_code(13, selector & 0xfffc);
2011-12-17 12:16:10 +08:00
if (!(Wd & (1 << 15)))
abort_with_error_code(11, selector & 0xfffc);
2011-12-23 21:15:54 +08:00
set_descriptor_register(cpu.ldt, Yd, Wd);
2011-12-17 12:16:10 +08:00
}
2011-12-17 13:38:46 +08:00
cpu.ldt.selector = selector;
2011-12-17 12:16:10 +08:00
}
function Ee(selector) {
var sa, Yd, Wd, Rb, ie, De;
selector &= 0xffff;
if ((selector & 0xfffc) == 0) {
2011-12-17 13:38:46 +08:00
cpu.tr.base = 0;
cpu.tr.limit = 0;
cpu.tr.flags = 0;
2011-12-17 12:16:10 +08:00
} else {
if (selector & 0x4)
abort_with_error_code(13, selector & 0xfffc);
2011-12-17 13:38:46 +08:00
sa = cpu.gdt;
2011-12-17 12:16:10 +08:00
Rb = selector & ~7;
De = 7;
if ((Rb + De) > sa.limit)
abort_with_error_code(13, selector & 0xfffc);
mem8_loc = (sa.base + Rb) & -1;
Yd = ld32_mem8_kernel_read();
mem8_loc += 4;
Wd = ld32_mem8_kernel_read();
2011-12-17 12:16:10 +08:00
ie = (Wd >> 8) & 0xf;
if ((Wd & (1 << 12)) || (ie != 1 && ie != 9))
abort_with_error_code(13, selector & 0xfffc);
2011-12-17 12:16:10 +08:00
if (!(Wd & (1 << 15)))
abort_with_error_code(11, selector & 0xfffc);
2011-12-23 21:15:54 +08:00
set_descriptor_register(cpu.tr, Yd, Wd);
2011-12-17 12:16:10 +08:00
Wd |= (1 << 9);
st32_mem8_kernel_write(Wd);
2011-12-17 12:16:10 +08:00
}
2011-12-17 13:38:46 +08:00
cpu.tr.selector = selector;
2011-12-17 12:16:10 +08:00
}
function Fe(Ge, selector) {
var Yd, Wd, se, he, He, sa, Rb;
2011-12-17 13:38:46 +08:00
se = cpu.cpl;
2011-12-17 12:16:10 +08:00
if ((selector & 0xfffc) == 0) {
if (Ge == 2)
abort_with_error_code(13, 0);
2011-12-18 21:19:08 +08:00
set_segment_vars(Ge, selector, 0, 0, 0);
2011-12-17 12:16:10 +08:00
} else {
if (selector & 0x4)
2011-12-17 13:38:46 +08:00
sa = cpu.ldt;
2011-12-17 12:16:10 +08:00
else
2011-12-17 13:38:46 +08:00
sa = cpu.gdt;
2011-12-17 12:16:10 +08:00
Rb = selector & ~7;
if ((Rb + 7) > sa.limit)
abort_with_error_code(13, selector & 0xfffc);
mem8_loc = (sa.base + Rb) & -1;
Yd = ld32_mem8_kernel_read();
mem8_loc += 4;
Wd = ld32_mem8_kernel_read();
2011-12-17 12:16:10 +08:00
if (!(Wd & (1 << 12)))
abort_with_error_code(13, selector & 0xfffc);
2011-12-17 12:16:10 +08:00
He = selector & 3;
he = (Wd >> 13) & 3;
if (Ge == 2) {
if ((Wd & (1 << 11)) || !(Wd & (1 << 9)))
abort_with_error_code(13, selector & 0xfffc);
2011-12-17 12:16:10 +08:00
if (He != se || he != se)
abort_with_error_code(13, selector & 0xfffc);
2011-12-17 12:16:10 +08:00
} else {
if ((Wd & ((1 << 11) | (1 << 9))) == (1 << 11))
abort_with_error_code(13, selector & 0xfffc);
2011-12-17 12:16:10 +08:00
if (!(Wd & (1 << 11)) || !(Wd & (1 << 10))) {
if (he < se || he < He)
abort_with_error_code(13, selector & 0xfffc);
2011-12-17 12:16:10 +08:00
}
}
if (!(Wd & (1 << 15))) {
if (Ge == 2)
abort_with_error_code(12, selector & 0xfffc);
2011-12-17 12:16:10 +08:00
else
abort_with_error_code(11, selector & 0xfffc);
2011-12-17 12:16:10 +08:00
}
if (!(Wd & (1 << 8))) {
Wd |= (1 << 8);
st32_mem8_kernel_write(Wd);
2011-12-17 12:16:10 +08:00
}
2011-12-23 21:15:54 +08:00
set_segment_vars(Ge, selector, calculate_descriptor_base(Yd, Wd), calculate_descriptor_limit(Yd, Wd), Wd);
2011-12-17 12:16:10 +08:00
}
}
function Ie(Ge, selector) {
var sa;
selector &= 0xffff;
2011-12-17 13:38:46 +08:00
if (!(cpu.cr0 & (1 << 0))) {
sa = cpu.segs[Ge];
2011-12-17 12:16:10 +08:00
sa.selector = selector;
sa.base = selector << 4;
2011-12-17 13:38:46 +08:00
} else if (cpu.eflags & 0x00020000) {
2011-12-21 10:28:01 +08:00
init_segment_vars_with_selector(Ge, selector);
2011-12-17 12:16:10 +08:00
} else {
Fe(Ge, selector);
}
}
function Je(Ke, Le) {
2011-12-23 20:24:16 +08:00
eip = Le, physmem8_ptr = initial_mem_ptr = 0;
2011-12-17 13:38:46 +08:00
cpu.segs[1].selector = Ke;
cpu.segs[1].base = (Ke << 4);
2011-12-21 10:28:01 +08:00
init_segment_local_vars();
2011-12-17 12:16:10 +08:00
}
function Me(Ke, Le) {
var Ne, ie, Yd, Wd, se, he, He, limit, e;
if ((Ke & 0xfffc) == 0)
abort_with_error_code(13, 0);
2011-12-17 12:16:10 +08:00
e = Xd(Ke);
if (!e)
abort_with_error_code(13, Ke & 0xfffc);
2011-12-17 12:16:10 +08:00
Yd = e[0];
Wd = e[1];
2011-12-17 13:38:46 +08:00
se = cpu.cpl;
2011-12-17 12:16:10 +08:00
if (Wd & (1 << 12)) {
if (!(Wd & (1 << 11)))
abort_with_error_code(13, Ke & 0xfffc);
2011-12-17 12:16:10 +08:00
he = (Wd >> 13) & 3;
if (Wd & (1 << 10)) {
if (he > se)
abort_with_error_code(13, Ke & 0xfffc);
2011-12-17 12:16:10 +08:00
} else {
He = Ke & 3;
if (He > se)
abort_with_error_code(13, Ke & 0xfffc);
2011-12-17 12:16:10 +08:00
if (he != se)
abort_with_error_code(13, Ke & 0xfffc);
2011-12-17 12:16:10 +08:00
}
if (!(Wd & (1 << 15)))
abort_with_error_code(11, Ke & 0xfffc);
2011-12-23 21:15:54 +08:00
limit = calculate_descriptor_limit(Yd, Wd);
2011-12-17 12:16:10 +08:00
if ((Le >>> 0) > (limit >>> 0))
abort_with_error_code(13, Ke & 0xfffc);
2011-12-23 21:15:54 +08:00
set_segment_vars(1, (Ke & 0xfffc) | se, calculate_descriptor_base(Yd, Wd), limit, Wd);
2011-12-23 20:24:16 +08:00
eip = Le, physmem8_ptr = initial_mem_ptr = 0;
2011-12-17 12:16:10 +08:00
} else {
2011-12-18 21:03:29 +08:00
cpu_abort("unsupported jump to call or task gate");
2011-12-17 12:16:10 +08:00
}
}
function Oe(Ke, Le) {
2011-12-17 13:38:46 +08:00
if (!(cpu.cr0 & (1 << 0)) || (cpu.eflags & 0x00020000)) {
2011-12-17 12:16:10 +08:00
Je(Ke, Le);
} else {
Me(Ke, Le);
}
}
function Pe(Ge, se) {
var he, Wd;
2011-12-17 13:38:46 +08:00
if ((Ge == 4 || Ge == 5) && (cpu.segs[Ge].selector & 0xfffc) == 0)
2011-12-17 12:16:10 +08:00
return;
2011-12-17 13:38:46 +08:00
Wd = cpu.segs[Ge].flags;
2011-12-17 12:16:10 +08:00
he = (Wd >> 13) & 3;
if (!(Wd & (1 << 11)) || !(Wd & (1 << 10))) {
if (he < se) {
2011-12-18 21:19:08 +08:00
set_segment_vars(Ge, 0, 0, 0, 0);
2011-12-17 12:16:10 +08:00
}
}
}
function Qe(je, Ke, Le, oe) {
var le;
2011-12-17 16:08:25 +08:00
le = regs[4];
2011-12-17 12:16:10 +08:00
if (je) {
{
le = (le - 4) >> 0;
2011-12-21 10:28:01 +08:00
mem8_loc = ((le & SS_mask) + SS_base) >> 0;
st32_mem8_write(cpu.segs[1].selector);
2011-12-17 12:16:10 +08:00
}
{
le = (le - 4) >> 0;
2011-12-21 10:28:01 +08:00
mem8_loc = ((le & SS_mask) + SS_base) >> 0;
st32_mem8_write(oe);
2011-12-17 12:16:10 +08:00
}
} else {
{
le = (le - 2) >> 0;
2011-12-21 10:28:01 +08:00
mem8_loc = ((le & SS_mask) + SS_base) >> 0;
st16_mem8_write(cpu.segs[1].selector);
2011-12-17 12:16:10 +08:00
}
{
le = (le - 2) >> 0;
2011-12-21 10:28:01 +08:00
mem8_loc = ((le & SS_mask) + SS_base) >> 0;
st16_mem8_write(oe);
2011-12-17 12:16:10 +08:00
}
}
2011-12-21 10:28:01 +08:00
regs[4] = (regs[4] & ~SS_mask) | ((le) & SS_mask);
2011-12-23 20:24:16 +08:00
eip = Le, physmem8_ptr = initial_mem_ptr = 0;
2011-12-17 13:38:46 +08:00
cpu.segs[1].selector = Ke;
cpu.segs[1].base = (Ke << 4);
2011-12-21 10:28:01 +08:00
init_segment_local_vars();
2011-12-17 12:16:10 +08:00
}
function Re(je, Ke, Le, oe) {
var ue, i, e;
var Yd, Wd, se, he, He, selector, ve, Se;
2011-12-21 10:28:01 +08:00
var ke, we, xe, Te, ie, re, SS_mask;
2011-12-21 10:43:53 +08:00
var x, limit, Ue;
2011-12-17 12:16:10 +08:00
var qe, Ve, We;
if ((Ke & 0xfffc) == 0)
abort_with_error_code(13, 0);
2011-12-17 12:16:10 +08:00
e = Xd(Ke);
if (!e)
abort_with_error_code(13, Ke & 0xfffc);
2011-12-17 12:16:10 +08:00
Yd = e[0];
Wd = e[1];
2011-12-17 13:38:46 +08:00
se = cpu.cpl;
2011-12-17 16:08:25 +08:00
We = regs[4];
2011-12-17 12:16:10 +08:00
if (Wd & (1 << 12)) {
if (!(Wd & (1 << 11)))
abort_with_error_code(13, Ke & 0xfffc);
2011-12-17 12:16:10 +08:00
he = (Wd >> 13) & 3;
if (Wd & (1 << 10)) {
if (he > se)
abort_with_error_code(13, Ke & 0xfffc);
2011-12-17 12:16:10 +08:00
} else {
He = Ke & 3;
if (He > se)
abort_with_error_code(13, Ke & 0xfffc);
2011-12-17 12:16:10 +08:00
if (he != se)
abort_with_error_code(13, Ke & 0xfffc);
2011-12-17 12:16:10 +08:00
}
if (!(Wd & (1 << 15)))
abort_with_error_code(11, Ke & 0xfffc);
2011-12-17 12:16:10 +08:00
{
Te = We;
2011-12-21 10:28:01 +08:00
SS_mask = SS_mask_from_flags(cpu.segs[2].flags);
2011-12-17 13:38:46 +08:00
qe = cpu.segs[2].base;
2011-12-17 12:16:10 +08:00
if (je) {
{
Te = (Te - 4) & -1;
2011-12-21 10:28:01 +08:00
mem8_loc = (qe + (Te & SS_mask)) & -1;
st32_mem8_kernel_write(cpu.segs[1].selector);
2011-12-17 12:16:10 +08:00
}
{
Te = (Te - 4) & -1;
2011-12-21 10:28:01 +08:00
mem8_loc = (qe + (Te & SS_mask)) & -1;
st32_mem8_kernel_write(oe);
2011-12-17 12:16:10 +08:00
}
} else {
{
Te = (Te - 2) & -1;
2011-12-21 10:28:01 +08:00
mem8_loc = (qe + (Te & SS_mask)) & -1;
st16_mem8_kernel_write(cpu.segs[1].selector);
2011-12-17 12:16:10 +08:00
}
{
Te = (Te - 2) & -1;
2011-12-21 10:28:01 +08:00
mem8_loc = (qe + (Te & SS_mask)) & -1;
st16_mem8_kernel_write(oe);
2011-12-17 12:16:10 +08:00
}
}
2011-12-23 21:15:54 +08:00
limit = calculate_descriptor_limit(Yd, Wd);
2011-12-17 12:16:10 +08:00
if (Le > limit)
abort_with_error_code(13, Ke & 0xfffc);
2011-12-21 10:28:01 +08:00
regs[4] = (regs[4] & ~SS_mask) | ((Te) & SS_mask);
2011-12-23 21:15:54 +08:00
set_segment_vars(1, (Ke & 0xfffc) | se, calculate_descriptor_base(Yd, Wd), limit, Wd);
2011-12-23 20:24:16 +08:00
eip = Le, physmem8_ptr = initial_mem_ptr = 0;
2011-12-17 12:16:10 +08:00
}
} else {
ie = (Wd >> 8) & 0x1f;
he = (Wd >> 13) & 3;
He = Ke & 3;
switch (ie) {
case 1:
case 9:
case 5:
throw "unsupported task gate";
return;
case 4:
case 12:
break;
default:
abort_with_error_code(13, Ke & 0xfffc);
2011-12-17 12:16:10 +08:00
break;
}
je = ie >> 3;
if (he < se || he < He)
abort_with_error_code(13, Ke & 0xfffc);
2011-12-17 12:16:10 +08:00
if (!(Wd & (1 << 15)))
abort_with_error_code(11, Ke & 0xfffc);
2011-12-17 12:16:10 +08:00
selector = Yd >> 16;
ve = (Wd & 0xffff0000) | (Yd & 0x0000ffff);
Se = Wd & 0x1f;
if ((selector & 0xfffc) == 0)
abort_with_error_code(13, 0);
2011-12-17 12:16:10 +08:00
e = Xd(selector);
if (!e)
abort_with_error_code(13, selector & 0xfffc);
2011-12-17 12:16:10 +08:00
Yd = e[0];
Wd = e[1];
if (!(Wd & (1 << 12)) || !(Wd & ((1 << 11))))
abort_with_error_code(13, selector & 0xfffc);
2011-12-17 12:16:10 +08:00
he = (Wd >> 13) & 3;
if (he > se)
abort_with_error_code(13, selector & 0xfffc);
2011-12-17 12:16:10 +08:00
if (!(Wd & (1 << 15)))
abort_with_error_code(11, selector & 0xfffc);
2011-12-17 12:16:10 +08:00
if (!(Wd & (1 << 10)) && he < se) {
e = ge(he);
ke = e[0];
Te = e[1];
if ((ke & 0xfffc) == 0)
abort_with_error_code(10, ke & 0xfffc);
2011-12-17 12:16:10 +08:00
if ((ke & 3) != he)
abort_with_error_code(10, ke & 0xfffc);
2011-12-17 12:16:10 +08:00
e = Xd(ke);
if (!e)
abort_with_error_code(10, ke & 0xfffc);
2011-12-17 12:16:10 +08:00
we = e[0];
xe = e[1];
re = (xe >> 13) & 3;
if (re != he)
abort_with_error_code(10, ke & 0xfffc);
2011-12-17 12:16:10 +08:00
if (!(xe & (1 << 12)) || (xe & (1 << 11)) || !(xe & (1 << 9)))
abort_with_error_code(10, ke & 0xfffc);
2011-12-17 12:16:10 +08:00
if (!(xe & (1 << 15)))
abort_with_error_code(10, ke & 0xfffc);
2011-12-21 10:28:01 +08:00
Ue = SS_mask_from_flags(cpu.segs[2].flags);
2011-12-17 13:38:46 +08:00
Ve = cpu.segs[2].base;
2011-12-21 10:28:01 +08:00
SS_mask = SS_mask_from_flags(xe);
2011-12-23 21:15:54 +08:00
qe = calculate_descriptor_base(we, xe);
2011-12-17 12:16:10 +08:00
if (je) {
{
Te = (Te - 4) & -1;
2011-12-21 10:28:01 +08:00
mem8_loc = (qe + (Te & SS_mask)) & -1;
st32_mem8_kernel_write(cpu.segs[2].selector);
2011-12-17 12:16:10 +08:00
}
{
Te = (Te - 4) & -1;
2011-12-21 10:28:01 +08:00
mem8_loc = (qe + (Te & SS_mask)) & -1;
st32_mem8_kernel_write(We);
2011-12-17 12:16:10 +08:00
}
for (i = Se - 1; i >= 0; i--) {
2011-12-21 10:43:53 +08:00
x = Xe(Ve + ((We + i * 4) & Ue));
2011-12-17 12:16:10 +08:00
{
Te = (Te - 4) & -1;
2011-12-21 10:28:01 +08:00
mem8_loc = (qe + (Te & SS_mask)) & -1;
st32_mem8_kernel_write(x);
2011-12-17 12:16:10 +08:00
}
}
} else {
{
Te = (Te - 2) & -1;
2011-12-21 10:28:01 +08:00
mem8_loc = (qe + (Te & SS_mask)) & -1;
st16_mem8_kernel_write(cpu.segs[2].selector);
2011-12-17 12:16:10 +08:00
}
{
Te = (Te - 2) & -1;
2011-12-21 10:28:01 +08:00
mem8_loc = (qe + (Te & SS_mask)) & -1;
st16_mem8_kernel_write(We);
2011-12-17 12:16:10 +08:00
}
for (i = Se - 1; i >= 0; i--) {
2011-12-21 10:43:53 +08:00
x = Ye(Ve + ((We + i * 2) & Ue));
2011-12-17 12:16:10 +08:00
{
Te = (Te - 2) & -1;
2011-12-21 10:28:01 +08:00
mem8_loc = (qe + (Te & SS_mask)) & -1;
st16_mem8_kernel_write(x);
2011-12-17 12:16:10 +08:00
}
}
}
ue = 1;
} else {
Te = We;
2011-12-21 10:28:01 +08:00
SS_mask = SS_mask_from_flags(cpu.segs[2].flags);
2011-12-17 13:38:46 +08:00
qe = cpu.segs[2].base;
2011-12-17 12:16:10 +08:00
ue = 0;
}
if (je) {
{
Te = (Te - 4) & -1;
2011-12-21 10:28:01 +08:00
mem8_loc = (qe + (Te & SS_mask)) & -1;
st32_mem8_kernel_write(cpu.segs[1].selector);
2011-12-17 12:16:10 +08:00
}
{
Te = (Te - 4) & -1;
2011-12-21 10:28:01 +08:00
mem8_loc = (qe + (Te & SS_mask)) & -1;
st32_mem8_kernel_write(oe);
2011-12-17 12:16:10 +08:00
}
} else {
{
Te = (Te - 2) & -1;
2011-12-21 10:28:01 +08:00
mem8_loc = (qe + (Te & SS_mask)) & -1;
st16_mem8_kernel_write(cpu.segs[1].selector);
2011-12-17 12:16:10 +08:00
}
{
Te = (Te - 2) & -1;
2011-12-21 10:28:01 +08:00
mem8_loc = (qe + (Te & SS_mask)) & -1;
st16_mem8_kernel_write(oe);
2011-12-17 12:16:10 +08:00
}
}
if (ue) {
ke = (ke & ~3) | he;
2011-12-23 21:15:54 +08:00
set_segment_vars(2, ke, qe, calculate_descriptor_limit(we, xe), xe);
2011-12-17 12:16:10 +08:00
}
selector = (selector & ~3) | he;
2011-12-23 21:15:54 +08:00
set_segment_vars(1, selector, calculate_descriptor_base(Yd, Wd), calculate_descriptor_limit(Yd, Wd), Wd);
2011-12-21 09:18:08 +08:00
change_permission_level(he);
2011-12-21 10:28:01 +08:00
regs[4] = (regs[4] & ~SS_mask) | ((Te) & SS_mask);
2011-12-23 20:24:16 +08:00
eip = ve, physmem8_ptr = initial_mem_ptr = 0;
2011-12-17 12:16:10 +08:00
}
}
function Ze(je, Ke, Le, oe) {
2011-12-17 13:38:46 +08:00
if (!(cpu.cr0 & (1 << 0)) || (cpu.eflags & 0x00020000)) {
2011-12-17 12:16:10 +08:00
Qe(je, Ke, Le, oe);
} else {
Re(je, Ke, Le, oe);
}
}
function af(je, bf, cf) {
2011-12-21 10:28:01 +08:00
var Te, Ke, Le, df, SS_mask, qe, ef;
SS_mask = 0xffff;
2011-12-17 16:08:25 +08:00
Te = regs[4];
2011-12-17 13:38:46 +08:00
qe = cpu.segs[2].base;
2011-12-17 12:16:10 +08:00
if (je == 1) {
{
2011-12-21 10:28:01 +08:00
mem8_loc = (qe + (Te & SS_mask)) & -1;
Le = ld32_mem8_kernel_read();
2011-12-17 12:16:10 +08:00
Te = (Te + 4) & -1;
}
{
2011-12-21 10:28:01 +08:00
mem8_loc = (qe + (Te & SS_mask)) & -1;
Ke = ld32_mem8_kernel_read();
2011-12-17 12:16:10 +08:00
Te = (Te + 4) & -1;
}
Ke &= 0xffff;
if (bf) {
2011-12-21 10:28:01 +08:00
mem8_loc = (qe + (Te & SS_mask)) & -1;
df = ld32_mem8_kernel_read();
2011-12-17 12:16:10 +08:00
Te = (Te + 4) & -1;
}
} else {
{
2011-12-21 10:28:01 +08:00
mem8_loc = (qe + (Te & SS_mask)) & -1;
Le = ld16_mem8_kernel_read();
2011-12-17 12:16:10 +08:00
Te = (Te + 2) & -1;
}
{
2011-12-21 10:28:01 +08:00
mem8_loc = (qe + (Te & SS_mask)) & -1;
Ke = ld16_mem8_kernel_read();
2011-12-17 12:16:10 +08:00
Te = (Te + 2) & -1;
}
if (bf) {
2011-12-21 10:28:01 +08:00
mem8_loc = (qe + (Te & SS_mask)) & -1;
df = ld16_mem8_kernel_read();
2011-12-17 12:16:10 +08:00
Te = (Te + 2) & -1;
}
}
2011-12-21 10:28:01 +08:00
regs[4] = (regs[4] & ~SS_mask) | ((Te + cf) & SS_mask);
2011-12-17 13:38:46 +08:00
cpu.segs[1].selector = Ke;
cpu.segs[1].base = (Ke << 4);
2011-12-23 20:24:16 +08:00
eip = Le, physmem8_ptr = initial_mem_ptr = 0;
2011-12-17 12:16:10 +08:00
if (bf) {
2011-12-17 13:38:46 +08:00
if (cpu.eflags & 0x00020000)
2011-12-17 12:16:10 +08:00
ef = 0x00000100 | 0x00040000 | 0x00200000 | 0x00000200 | 0x00010000 | 0x00004000;
else
ef = 0x00000100 | 0x00040000 | 0x00200000 | 0x00000200 | 0x00003000 | 0x00010000 | 0x00004000;
if (je == 0)
ef &= 0xffff;
kd(df, ef);
}
2011-12-21 10:28:01 +08:00
init_segment_local_vars();
2011-12-17 12:16:10 +08:00
}
function ff(je, bf, cf) {
var Ke, df, gf;
var hf, jf, kf, lf;
var e, Yd, Wd, we, xe;
var se, he, He, ef, iopl;
2011-12-21 10:28:01 +08:00
var qe, Te, Le, wd, SS_mask;
SS_mask = SS_mask_from_flags(cpu.segs[2].flags);
2011-12-17 16:08:25 +08:00
Te = regs[4];
2011-12-17 13:38:46 +08:00
qe = cpu.segs[2].base;
2011-12-17 12:16:10 +08:00
df = 0;
if (je == 1) {
{
2011-12-21 10:28:01 +08:00
mem8_loc = (qe + (Te & SS_mask)) & -1;
Le = ld32_mem8_kernel_read();
2011-12-17 12:16:10 +08:00
Te = (Te + 4) & -1;
}
{
2011-12-21 10:28:01 +08:00
mem8_loc = (qe + (Te & SS_mask)) & -1;
Ke = ld32_mem8_kernel_read();
2011-12-17 12:16:10 +08:00
Te = (Te + 4) & -1;
}
Ke &= 0xffff;
if (bf) {
{
2011-12-21 10:28:01 +08:00
mem8_loc = (qe + (Te & SS_mask)) & -1;
df = ld32_mem8_kernel_read();
2011-12-17 12:16:10 +08:00
Te = (Te + 4) & -1;
}
if (df & 0x00020000) {
{
2011-12-21 10:28:01 +08:00
mem8_loc = (qe + (Te & SS_mask)) & -1;
wd = ld32_mem8_kernel_read();
2011-12-17 12:16:10 +08:00
Te = (Te + 4) & -1;
}
{
2011-12-21 10:28:01 +08:00
mem8_loc = (qe + (Te & SS_mask)) & -1;
gf = ld32_mem8_kernel_read();
2011-12-17 12:16:10 +08:00
Te = (Te + 4) & -1;
}
{
2011-12-21 10:28:01 +08:00
mem8_loc = (qe + (Te & SS_mask)) & -1;
hf = ld32_mem8_kernel_read();
2011-12-17 12:16:10 +08:00
Te = (Te + 4) & -1;
}
{
2011-12-21 10:28:01 +08:00
mem8_loc = (qe + (Te & SS_mask)) & -1;
jf = ld32_mem8_kernel_read();
2011-12-17 12:16:10 +08:00
Te = (Te + 4) & -1;
}
{
2011-12-21 10:28:01 +08:00
mem8_loc = (qe + (Te & SS_mask)) & -1;
kf = ld32_mem8_kernel_read();
2011-12-17 12:16:10 +08:00
Te = (Te + 4) & -1;
}
{
2011-12-21 10:28:01 +08:00
mem8_loc = (qe + (Te & SS_mask)) & -1;
lf = ld32_mem8_kernel_read();
2011-12-17 12:16:10 +08:00
Te = (Te + 4) & -1;
}
kd(df, 0x00000100 | 0x00040000 | 0x00200000 | 0x00000200 | 0x00003000 | 0x00020000 | 0x00004000 | 0x00080000 | 0x00100000);
2011-12-21 10:28:01 +08:00
init_segment_vars_with_selector(1, Ke & 0xffff);
2011-12-21 09:18:08 +08:00
change_permission_level(3);
2011-12-21 10:28:01 +08:00
init_segment_vars_with_selector(2, gf & 0xffff);
init_segment_vars_with_selector(0, hf & 0xffff);
init_segment_vars_with_selector(3, jf & 0xffff);
init_segment_vars_with_selector(4, kf & 0xffff);
init_segment_vars_with_selector(5, lf & 0xffff);
2011-12-23 20:24:16 +08:00
eip = Le & 0xffff, physmem8_ptr = initial_mem_ptr = 0;
2011-12-21 10:28:01 +08:00
regs[4] = (regs[4] & ~SS_mask) | ((wd) & SS_mask);
2011-12-17 12:16:10 +08:00
return;
}
}
} else {
{
2011-12-21 10:28:01 +08:00
mem8_loc = (qe + (Te & SS_mask)) & -1;
Le = ld16_mem8_kernel_read();
2011-12-17 12:16:10 +08:00
Te = (Te + 2) & -1;
}
{
2011-12-21 10:28:01 +08:00
mem8_loc = (qe + (Te & SS_mask)) & -1;
Ke = ld16_mem8_kernel_read();
2011-12-17 12:16:10 +08:00
Te = (Te + 2) & -1;
}
if (bf) {
2011-12-21 10:28:01 +08:00
mem8_loc = (qe + (Te & SS_mask)) & -1;
df = ld16_mem8_kernel_read();
2011-12-17 12:16:10 +08:00
Te = (Te + 2) & -1;
}
}
if ((Ke & 0xfffc) == 0)
abort_with_error_code(13, Ke & 0xfffc);
2011-12-17 12:16:10 +08:00
e = Xd(Ke);
if (!e)
abort_with_error_code(13, Ke & 0xfffc);
2011-12-17 12:16:10 +08:00
Yd = e[0];
Wd = e[1];
if (!(Wd & (1 << 12)) || !(Wd & (1 << 11)))
abort_with_error_code(13, Ke & 0xfffc);
2011-12-17 13:38:46 +08:00
se = cpu.cpl;
2011-12-17 12:16:10 +08:00
He = Ke & 3;
if (He < se)
abort_with_error_code(13, Ke & 0xfffc);
2011-12-17 12:16:10 +08:00
he = (Wd >> 13) & 3;
if (Wd & (1 << 10)) {
if (he > He)
abort_with_error_code(13, Ke & 0xfffc);
2011-12-17 12:16:10 +08:00
} else {
if (he != He)
abort_with_error_code(13, Ke & 0xfffc);
2011-12-17 12:16:10 +08:00
}
if (!(Wd & (1 << 15)))
abort_with_error_code(11, Ke & 0xfffc);
2011-12-17 12:16:10 +08:00
Te = (Te + cf) & -1;
if (He == se) {
2011-12-23 21:15:54 +08:00
set_segment_vars(1, Ke, calculate_descriptor_base(Yd, Wd), calculate_descriptor_limit(Yd, Wd), Wd);
2011-12-17 12:16:10 +08:00
} else {
if (je == 1) {
{
2011-12-21 10:28:01 +08:00
mem8_loc = (qe + (Te & SS_mask)) & -1;
wd = ld32_mem8_kernel_read();
2011-12-17 12:16:10 +08:00
Te = (Te + 4) & -1;
}
{
2011-12-21 10:28:01 +08:00
mem8_loc = (qe + (Te & SS_mask)) & -1;
gf = ld32_mem8_kernel_read();
2011-12-17 12:16:10 +08:00
Te = (Te + 4) & -1;
}
gf &= 0xffff;
} else {
{
2011-12-21 10:28:01 +08:00
mem8_loc = (qe + (Te & SS_mask)) & -1;
wd = ld16_mem8_kernel_read();
2011-12-17 12:16:10 +08:00
Te = (Te + 2) & -1;
}
{
2011-12-21 10:28:01 +08:00
mem8_loc = (qe + (Te & SS_mask)) & -1;
gf = ld16_mem8_kernel_read();
2011-12-17 12:16:10 +08:00
Te = (Te + 2) & -1;
}
}
if ((gf & 0xfffc) == 0) {
abort_with_error_code(13, 0);
2011-12-17 12:16:10 +08:00
} else {
if ((gf & 3) != He)
abort_with_error_code(13, gf & 0xfffc);
2011-12-17 12:16:10 +08:00
e = Xd(gf);
if (!e)
abort_with_error_code(13, gf & 0xfffc);
2011-12-17 12:16:10 +08:00
we = e[0];
xe = e[1];
if (!(xe & (1 << 12)) || (xe & (1 << 11)) || !(xe & (1 << 9)))
abort_with_error_code(13, gf & 0xfffc);
2011-12-17 12:16:10 +08:00
he = (xe >> 13) & 3;
if (he != He)
abort_with_error_code(13, gf & 0xfffc);
2011-12-17 12:16:10 +08:00
if (!(xe & (1 << 15)))
abort_with_error_code(11, gf & 0xfffc);
2011-12-23 21:15:54 +08:00
set_segment_vars(2, gf, calculate_descriptor_base(we, xe), calculate_descriptor_limit(we, xe), xe);
2011-12-17 12:16:10 +08:00
}
2011-12-23 21:15:54 +08:00
set_segment_vars(1, Ke, calculate_descriptor_base(Yd, Wd), calculate_descriptor_limit(Yd, Wd), Wd);
2011-12-21 09:18:08 +08:00
change_permission_level(He);
2011-12-17 12:16:10 +08:00
Te = wd;
2011-12-21 10:28:01 +08:00
SS_mask = SS_mask_from_flags(xe);
2011-12-17 12:16:10 +08:00
Pe(0, He);
Pe(3, He);
Pe(4, He);
Pe(5, He);
Te = (Te + cf) & -1;
}
2011-12-21 10:28:01 +08:00
regs[4] = (regs[4] & ~SS_mask) | ((Te) & SS_mask);
2011-12-23 20:24:16 +08:00
eip = Le, physmem8_ptr = initial_mem_ptr = 0;
2011-12-17 12:16:10 +08:00
if (bf) {
ef = 0x00000100 | 0x00040000 | 0x00200000 | 0x00010000 | 0x00004000;
if (se == 0)
ef |= 0x00003000;
iopl = (cpu.eflags >> 12) & 3;
if (se <= iopl)
2011-12-17 12:16:10 +08:00
ef |= 0x00000200;
if (je == 0)
ef &= 0xffff;
kd(df, ef);
}
}
function mf(je) {
var iopl;
2011-12-17 13:38:46 +08:00
if (!(cpu.cr0 & (1 << 0)) || (cpu.eflags & 0x00020000)) {
if (cpu.eflags & 0x00020000) {
iopl = (cpu.eflags >> 12) & 3;
if (iopl != 3)
abort(13);
2011-12-17 12:16:10 +08:00
}
af(je, 1, 0);
} else {
2011-12-17 13:38:46 +08:00
if (cpu.eflags & 0x00004000) {
2011-12-17 12:16:10 +08:00
throw "unsupported task gate";
} else {
ff(je, 1, 0);
}
}
}
function nf(je, cf) {
2011-12-17 13:38:46 +08:00
if (!(cpu.cr0 & (1 << 0)) || (cpu.eflags & 0x00020000)) {
2011-12-17 12:16:10 +08:00
af(je, 0, cf);
} else {
ff(je, 0, cf);
}
}
function of(selector, pf) {
var e, Yd, Wd, He, he, se, ie;
if ((selector & 0xfffc) == 0)
return null;
e = Xd(selector);
if (!e)
return null;
Yd = e[0];
Wd = e[1];
He = selector & 3;
he = (Wd >> 13) & 3;
2011-12-17 13:38:46 +08:00
se = cpu.cpl;
2011-12-17 12:16:10 +08:00
if (Wd & (1 << 12)) {
if ((Wd & (1 << 11)) && (Wd & (1 << 10))) {
} else {
if (he < se || he < He)
return null;
}
} else {
ie = (Wd >> 8) & 0xf;
switch (ie) {
case 1:
case 2:
case 3:
case 9:
case 11:
break;
case 4:
case 5:
case 12:
if (pf)
return null;
break;
default:
return null;
}
if (he < se || he < He)
return null;
}
if (pf) {
2011-12-23 21:15:54 +08:00
return calculate_descriptor_limit(Yd, Wd);
2011-12-17 12:16:10 +08:00
} else {
return Wd & 0x00f0ff00;
}
}
function qf(je, pf) {
2011-12-23 20:24:16 +08:00
var x, mem8, reg_idx1, selector;
2011-12-17 13:38:46 +08:00
if (!(cpu.cr0 & (1 << 0)) || (cpu.eflags & 0x00020000))
abort(6);
2011-12-23 20:24:16 +08:00
mem8 = phys_mem8[physmem8_ptr++];
reg_idx1 = (mem8 >> 3) & 7;
2011-12-18 21:19:08 +08:00
if ((mem8 >> 6) == 3) {
selector = regs[mem8 & 7] & 0xffff;
2011-12-17 12:16:10 +08:00
} else {
2011-12-23 20:24:16 +08:00
mem8_loc = segment_translation(mem8);
selector = ld_16bits_mem8_read();
2011-12-17 12:16:10 +08:00
}
2011-12-21 10:43:53 +08:00
x = of(selector, pf);
2011-12-23 21:15:54 +08:00
_src = get_conditional_flags();
2011-12-21 10:43:53 +08:00
if (x === null) {
2011-12-17 13:13:37 +08:00
_src &= ~0x0040;
2011-12-17 12:16:10 +08:00
} else {
2011-12-17 13:13:37 +08:00
_src |= 0x0040;
2011-12-17 12:16:10 +08:00
if (je)
2011-12-23 20:24:16 +08:00
regs[reg_idx1] = x;
2011-12-17 12:16:10 +08:00
else
2011-12-23 20:24:16 +08:00
set_lower_word_in_register(reg_idx1, x);
2011-12-17 12:16:10 +08:00
}
2011-12-17 16:14:24 +08:00
_dst = ((_src >> 6) & 1) ^ 1;
_op = 24;
2011-12-17 12:16:10 +08:00
}
function rf(selector, ud) {
var e, Yd, Wd, He, he, se;
if ((selector & 0xfffc) == 0)
return 0;
e = Xd(selector);
if (!e)
return 0;
Yd = e[0];
Wd = e[1];
if (!(Wd & (1 << 12)))
return 0;
He = selector & 3;
he = (Wd >> 13) & 3;
2011-12-17 13:38:46 +08:00
se = cpu.cpl;
2011-12-17 12:16:10 +08:00
if (Wd & (1 << 11)) {
if (ud) {
return 0;
} else {
if (!(Wd & (1 << 9)))
return 1;
if (!(Wd & (1 << 10))) {
if (he < se || he < He)
return 0;
}
}
} else {
if (he < se || he < He)
return 0;
if (ud && !(Wd & (1 << 9)))
return 0;
}
return 1;
}
function sf(selector, ud) {
var z;
z = rf(selector, ud);
2011-12-23 21:15:54 +08:00
_src = get_conditional_flags();
2011-12-17 12:16:10 +08:00
if (z)
2011-12-17 13:13:37 +08:00
_src |= 0x0040;
2011-12-17 12:16:10 +08:00
else
2011-12-17 13:13:37 +08:00
_src &= ~0x0040;
2011-12-17 16:14:24 +08:00
_dst = ((_src >> 6) & 1) ^ 1;
_op = 24;
2011-12-17 12:16:10 +08:00
}
function tf() {
2011-12-23 20:24:16 +08:00
var mem8, x, y, reg_idx0;
2011-12-17 13:38:46 +08:00
if (!(cpu.cr0 & (1 << 0)) || (cpu.eflags & 0x00020000))
abort(6);
2011-12-23 20:24:16 +08:00
mem8 = phys_mem8[physmem8_ptr++];
2011-12-18 21:19:08 +08:00
if ((mem8 >> 6) == 3) {
2011-12-23 20:24:16 +08:00
reg_idx0 = mem8 & 7;
x = regs[reg_idx0] & 0xffff;
2011-12-17 12:16:10 +08:00
} else {
2011-12-23 20:24:16 +08:00
mem8_loc = segment_translation(mem8);
2011-12-21 10:43:53 +08:00
x = ld_16bits_mem8_write();
2011-12-17 12:16:10 +08:00
}
y = regs[(mem8 >> 3) & 7];
2011-12-23 21:15:54 +08:00
_src = get_conditional_flags();
if ((x & 3) < (y & 3)) {
x = (x & ~3) | (y & 3);
2011-12-18 21:19:08 +08:00
if ((mem8 >> 6) == 3) {
2011-12-23 20:24:16 +08:00
set_lower_word_in_register(reg_idx0, x);
2011-12-17 12:16:10 +08:00
} else {
st16_mem8_write(x);
2011-12-17 12:16:10 +08:00
}
2011-12-17 13:13:37 +08:00
_src |= 0x0040;
2011-12-17 12:16:10 +08:00
} else {
2011-12-17 13:13:37 +08:00
_src &= ~0x0040;
2011-12-17 12:16:10 +08:00
}
2011-12-17 16:14:24 +08:00
_dst = ((_src >> 6) & 1) ^ 1;
_op = 24;
2011-12-17 12:16:10 +08:00
}
function uf() {
var Rb;
2011-12-17 16:08:25 +08:00
Rb = regs[0];
2011-12-17 12:16:10 +08:00
switch (Rb) {
case 0:
2011-12-17 16:08:25 +08:00
regs[0] = 1;
regs[3] = 0x756e6547 & -1;
regs[2] = 0x49656e69 & -1;
regs[1] = 0x6c65746e & -1;
2011-12-17 12:16:10 +08:00
break;
case 1:
default:
2011-12-17 16:08:25 +08:00
regs[0] = (5 << 8) | (4 << 4) | 3;
regs[3] = 8 << 8;
regs[1] = 0;
regs[2] = (1 << 4);
2011-12-17 12:16:10 +08:00
break;
}
}
function vf(base) {
var wf, xf;
if (base == 0)
abort(0);
2011-12-17 16:08:25 +08:00
wf = regs[0] & 0xff;
2011-12-17 12:16:10 +08:00
xf = (wf / base) & -1;
wf = (wf % base);
2011-12-17 16:08:25 +08:00
regs[0] = (regs[0] & ~0xffff) | wf | (xf << 8);
2011-12-17 16:14:24 +08:00
_dst = (((wf) << 24) >> 24);
_op = 12;
2011-12-17 12:16:10 +08:00
}
function yf(base) {
var wf, xf;
2011-12-17 16:08:25 +08:00
wf = regs[0] & 0xff;
xf = (regs[0] >> 8) & 0xff;
2011-12-17 12:16:10 +08:00
wf = (xf * base + wf) & 0xff;
2011-12-17 16:08:25 +08:00
regs[0] = (regs[0] & ~0xffff) | wf;
2011-12-17 16:14:24 +08:00
_dst = (((wf) << 24) >> 24);
_op = 12;
2011-12-17 12:16:10 +08:00
}
function zf() {
var Af, wf, xf, Bf, jd;
2011-12-23 21:15:54 +08:00
jd = get_conditional_flags();
2011-12-17 12:16:10 +08:00
Bf = jd & 0x0010;
2011-12-17 16:08:25 +08:00
wf = regs[0] & 0xff;
xf = (regs[0] >> 8) & 0xff;
2011-12-17 12:16:10 +08:00
Af = (wf > 0xf9);
if (((wf & 0x0f) > 9) || Bf) {
wf = (wf + 6) & 0x0f;
xf = (xf + 1 + Af) & 0xff;
jd |= 0x0001 | 0x0010;
} else {
jd &= ~(0x0001 | 0x0010);
wf &= 0x0f;
}
2011-12-17 16:08:25 +08:00
regs[0] = (regs[0] & ~0xffff) | wf | (xf << 8);
2011-12-17 13:13:37 +08:00
_src = jd;
2011-12-17 16:14:24 +08:00
_dst = ((_src >> 6) & 1) ^ 1;
_op = 24;
2011-12-17 12:16:10 +08:00
}
function Cf() {
var Af, wf, xf, Bf, jd;
2011-12-23 21:15:54 +08:00
jd = get_conditional_flags();
2011-12-17 12:16:10 +08:00
Bf = jd & 0x0010;
2011-12-17 16:08:25 +08:00
wf = regs[0] & 0xff;
xf = (regs[0] >> 8) & 0xff;
2011-12-17 12:16:10 +08:00
Af = (wf < 6);
if (((wf & 0x0f) > 9) || Bf) {
wf = (wf - 6) & 0x0f;
xf = (xf - 1 - Af) & 0xff;
jd |= 0x0001 | 0x0010;
} else {
jd &= ~(0x0001 | 0x0010);
wf &= 0x0f;
}
2011-12-17 16:08:25 +08:00
regs[0] = (regs[0] & ~0xffff) | wf | (xf << 8);
2011-12-17 13:13:37 +08:00
_src = jd;
2011-12-17 16:14:24 +08:00
_dst = ((_src >> 6) & 1) ^ 1;
_op = 24;
2011-12-17 12:16:10 +08:00
}
function Df() {
var wf, Bf, Ef, jd;
2011-12-23 21:15:54 +08:00
jd = get_conditional_flags();
2011-12-17 12:16:10 +08:00
Ef = jd & 0x0001;
Bf = jd & 0x0010;
2011-12-17 16:08:25 +08:00
wf = regs[0] & 0xff;
2011-12-17 12:16:10 +08:00
jd = 0;
if (((wf & 0x0f) > 9) || Bf) {
wf = (wf + 6) & 0xff;
jd |= 0x0010;
}
if ((wf > 0x9f) || Ef) {
wf = (wf + 0x60) & 0xff;
jd |= 0x0001;
}
2011-12-17 16:08:25 +08:00
regs[0] = (regs[0] & ~0xff) | wf;
2011-12-17 12:16:10 +08:00
jd |= (wf == 0) << 6;
jd |= parity_LUT[wf] << 2;
2011-12-17 12:16:10 +08:00
jd |= (wf & 0x80);
2011-12-17 13:13:37 +08:00
_src = jd;
2011-12-17 16:14:24 +08:00
_dst = ((_src >> 6) & 1) ^ 1;
_op = 24;
2011-12-17 12:16:10 +08:00
}
function Ff() {
var wf, Gf, Bf, Ef, jd;
2011-12-23 21:15:54 +08:00
jd = get_conditional_flags();
2011-12-17 12:16:10 +08:00
Ef = jd & 0x0001;
Bf = jd & 0x0010;
2011-12-17 16:08:25 +08:00
wf = regs[0] & 0xff;
2011-12-17 12:16:10 +08:00
jd = 0;
Gf = wf;
if (((wf & 0x0f) > 9) || Bf) {
jd |= 0x0010;
if (wf < 6 || Ef)
jd |= 0x0001;
wf = (wf - 6) & 0xff;
}
if ((Gf > 0x99) || Ef) {
wf = (wf - 0x60) & 0xff;
jd |= 0x0001;
}
2011-12-17 16:08:25 +08:00
regs[0] = (regs[0] & ~0xff) | wf;
2011-12-17 12:16:10 +08:00
jd |= (wf == 0) << 6;
jd |= parity_LUT[wf] << 2;
2011-12-17 12:16:10 +08:00
jd |= (wf & 0x80);
2011-12-17 13:13:37 +08:00
_src = jd;
2011-12-17 16:14:24 +08:00
_dst = ((_src >> 6) & 1) ^ 1;
_op = 24;
2011-12-17 12:16:10 +08:00
}
2011-12-23 01:49:18 +08:00
function checkOp_BOUND() {
var mem8, x, y, z;
2011-12-23 20:24:16 +08:00
mem8 = phys_mem8[physmem8_ptr++];
2011-12-18 21:19:08 +08:00
if ((mem8 >> 3) == 3)
abort(6);
2011-12-23 20:24:16 +08:00
mem8_loc = segment_translation(mem8);
2011-12-21 10:43:53 +08:00
x = ld_32bits_mem8_read();
mem8_loc = (mem8_loc + 4) & -1;
y = ld_32bits_mem8_read();
2011-12-23 20:24:16 +08:00
reg_idx1 = (mem8 >> 3) & 7;
z = regs[reg_idx1];
if (z < x || z > y)
abort(5);
2011-12-17 12:16:10 +08:00
}
function If() {
var mem8, x, y, z;
2011-12-23 20:24:16 +08:00
mem8 = phys_mem8[physmem8_ptr++];
2011-12-18 21:19:08 +08:00
if ((mem8 >> 3) == 3)
abort(6);
2011-12-23 20:24:16 +08:00
mem8_loc = segment_translation(mem8);
2011-12-21 10:43:53 +08:00
x = (ld_16bits_mem8_read() << 16) >> 16;
mem8_loc = (mem8_loc + 2) & -1;
y = (ld_16bits_mem8_read() << 16) >> 16;
2011-12-23 20:24:16 +08:00
reg_idx1 = (mem8 >> 3) & 7;
z = (regs[reg_idx1] << 16) >> 16;
if (z < x || z > y)
abort(5);
2011-12-17 12:16:10 +08:00
}
function Jf() {
2011-12-23 20:24:16 +08:00
var x, y, reg_idx1;
y = (regs[4] - 16) >> 0;
mem8_loc = ((y & SS_mask) + SS_base) >> 0;
2011-12-23 20:24:16 +08:00
for (reg_idx1 = 7; reg_idx1 >= 0; reg_idx1--) {
x = regs[reg_idx1];
st16_mem8_write(x);
mem8_loc = (mem8_loc + 2) >> 0;
2011-12-17 12:16:10 +08:00
}
regs[4] = (regs[4] & ~SS_mask) | ((y) & SS_mask);
2011-12-17 12:16:10 +08:00
}
function Kf() {
2011-12-23 20:24:16 +08:00
var x, y, reg_idx1;
y = (regs[4] - 32) >> 0;
mem8_loc = ((y & SS_mask) + SS_base) >> 0;
2011-12-23 20:24:16 +08:00
for (reg_idx1 = 7; reg_idx1 >= 0; reg_idx1--) {
x = regs[reg_idx1];
st32_mem8_write(x);
mem8_loc = (mem8_loc + 4) >> 0;
2011-12-17 12:16:10 +08:00
}
regs[4] = (regs[4] & ~SS_mask) | ((y) & SS_mask);
2011-12-17 12:16:10 +08:00
}
function Lf() {
2011-12-23 20:24:16 +08:00
var reg_idx1;
2011-12-21 10:28:01 +08:00
mem8_loc = ((regs[4] & SS_mask) + SS_base) >> 0;
2011-12-23 20:24:16 +08:00
for (reg_idx1 = 7; reg_idx1 >= 0; reg_idx1--) {
if (reg_idx1 != 4) {
set_lower_word_in_register(reg_idx1, ld_16bits_mem8_read());
2011-12-17 12:16:10 +08:00
}
mem8_loc = (mem8_loc + 2) >> 0;
2011-12-17 12:16:10 +08:00
}
2011-12-21 10:28:01 +08:00
regs[4] = (regs[4] & ~SS_mask) | ((regs[4] + 16) & SS_mask);
2011-12-17 12:16:10 +08:00
}
function Mf() {
2011-12-23 20:24:16 +08:00
var reg_idx1;
2011-12-21 10:28:01 +08:00
mem8_loc = ((regs[4] & SS_mask) + SS_base) >> 0;
2011-12-23 20:24:16 +08:00
for (reg_idx1 = 7; reg_idx1 >= 0; reg_idx1--) {
if (reg_idx1 != 4) {
regs[reg_idx1] = ld_32bits_mem8_read();
2011-12-17 12:16:10 +08:00
}
mem8_loc = (mem8_loc + 4) >> 0;
2011-12-17 12:16:10 +08:00
}
2011-12-21 10:28:01 +08:00
regs[4] = (regs[4] & ~SS_mask) | ((regs[4] + 32) & SS_mask);
2011-12-17 12:16:10 +08:00
}
function Nf() {
var x, y;
y = regs[5];
mem8_loc = ((y & SS_mask) + SS_base) >> 0;
2011-12-21 10:43:53 +08:00
x = ld_16bits_mem8_read();
2011-12-23 20:24:16 +08:00
set_lower_word_in_register(5, x);
regs[4] = (regs[4] & ~SS_mask) | ((y + 2) & SS_mask);
2011-12-17 12:16:10 +08:00
}
function Of() {
var x, y;
y = regs[5];
mem8_loc = ((y & SS_mask) + SS_base) >> 0;
2011-12-21 10:43:53 +08:00
x = ld_32bits_mem8_read();
regs[5] = x;
regs[4] = (regs[4] & ~SS_mask) | ((y + 4) & SS_mask);
2011-12-17 12:16:10 +08:00
}
function Pf() {
2011-12-21 10:43:53 +08:00
var cf, Qf, le, Rf, x, Sf;
2011-12-23 01:49:18 +08:00
cf = ld16_mem8_direct();
2011-12-23 20:24:16 +08:00
Qf = phys_mem8[physmem8_ptr++];
2011-12-17 12:16:10 +08:00
Qf &= 0x1f;
2011-12-17 16:08:25 +08:00
le = regs[4];
Rf = regs[5];
2011-12-17 12:16:10 +08:00
{
le = (le - 2) >> 0;
2011-12-21 10:28:01 +08:00
mem8_loc = ((le & SS_mask) + SS_base) >> 0;
st16_mem8_write(Rf);
2011-12-17 12:16:10 +08:00
}
Sf = le;
if (Qf != 0) {
while (Qf > 1) {
Rf = (Rf - 2) >> 0;
2011-12-21 10:28:01 +08:00
mem8_loc = ((Rf & SS_mask) + SS_base) >> 0;
2011-12-21 10:43:53 +08:00
x = ld_16bits_mem8_read();
2011-12-17 12:16:10 +08:00
{
le = (le - 2) >> 0;
2011-12-21 10:28:01 +08:00
mem8_loc = ((le & SS_mask) + SS_base) >> 0;
st16_mem8_write(x);
2011-12-17 12:16:10 +08:00
}
Qf--;
}
{
le = (le - 2) >> 0;
2011-12-21 10:28:01 +08:00
mem8_loc = ((le & SS_mask) + SS_base) >> 0;
st16_mem8_write(Sf);
2011-12-17 12:16:10 +08:00
}
}
le = (le - cf) >> 0;
2011-12-21 10:28:01 +08:00
mem8_loc = ((le & SS_mask) + SS_base) >> 0;
ld_16bits_mem8_write();
2011-12-21 10:28:01 +08:00
regs[5] = (regs[5] & ~SS_mask) | (Sf & SS_mask);
2011-12-17 16:08:25 +08:00
regs[4] = le;
2011-12-17 12:16:10 +08:00
}
function Tf() {
2011-12-21 10:43:53 +08:00
var cf, Qf, le, Rf, x, Sf;
2011-12-23 01:49:18 +08:00
cf = ld16_mem8_direct();
2011-12-23 20:24:16 +08:00
Qf = phys_mem8[physmem8_ptr++];
2011-12-17 12:16:10 +08:00
Qf &= 0x1f;
2011-12-17 16:08:25 +08:00
le = regs[4];
Rf = regs[5];
2011-12-17 12:16:10 +08:00
{
le = (le - 4) >> 0;
2011-12-21 10:28:01 +08:00
mem8_loc = ((le & SS_mask) + SS_base) >> 0;
st32_mem8_write(Rf);
2011-12-17 12:16:10 +08:00
}
Sf = le;
if (Qf != 0) {
while (Qf > 1) {
Rf = (Rf - 4) >> 0;
2011-12-21 10:28:01 +08:00
mem8_loc = ((Rf & SS_mask) + SS_base) >> 0;
2011-12-21 10:43:53 +08:00
x = ld_32bits_mem8_read();
2011-12-17 12:16:10 +08:00
{
le = (le - 4) >> 0;
2011-12-21 10:28:01 +08:00
mem8_loc = ((le & SS_mask) + SS_base) >> 0;
st32_mem8_write(x);
2011-12-17 12:16:10 +08:00
}
Qf--;
}
{
le = (le - 4) >> 0;
2011-12-21 10:28:01 +08:00
mem8_loc = ((le & SS_mask) + SS_base) >> 0;
st32_mem8_write(Sf);
2011-12-17 12:16:10 +08:00
}
}
le = (le - cf) >> 0;
2011-12-21 10:28:01 +08:00
mem8_loc = ((le & SS_mask) + SS_base) >> 0;
ld_32bits_mem8_write();
2011-12-21 10:28:01 +08:00
regs[5] = (regs[5] & ~SS_mask) | (Sf & SS_mask);
regs[4] = (regs[4] & ~SS_mask) | ((le) & SS_mask);
2011-12-17 12:16:10 +08:00
}
function Uf(Sb) {
var x, y, mem8;
2011-12-23 20:24:16 +08:00
mem8 = phys_mem8[physmem8_ptr++];
2011-12-18 21:19:08 +08:00
if ((mem8 >> 3) == 3)
abort(6);
2011-12-23 20:24:16 +08:00
mem8_loc = segment_translation(mem8);
2011-12-21 10:43:53 +08:00
x = ld_32bits_mem8_read();
mem8_loc += 4;
y = ld_16bits_mem8_read();
Ie(Sb, y);
2011-12-21 10:43:53 +08:00
regs[(mem8 >> 3) & 7] = x;
2011-12-17 12:16:10 +08:00
}
function Vf(Sb) {
var x, y, mem8;
2011-12-23 20:24:16 +08:00
mem8 = phys_mem8[physmem8_ptr++];
2011-12-18 21:19:08 +08:00
if ((mem8 >> 3) == 3)
abort(6);
2011-12-23 20:24:16 +08:00
mem8_loc = segment_translation(mem8);
2011-12-21 10:43:53 +08:00
x = ld_16bits_mem8_read();
mem8_loc += 2;
y = ld_16bits_mem8_read();
Ie(Sb, y);
2011-12-23 20:24:16 +08:00
set_lower_word_in_register((mem8 >> 3) & 7, x);
2011-12-17 12:16:10 +08:00
}
function stringOp_INSB() {
var Xf, Yf, Zf, ag, iopl, x;
iopl = (cpu.eflags >> 12) & 3;
if (cpu.cpl > iopl)
abort(13);
2011-12-21 10:28:01 +08:00
if (CS_flags & 0x0080)
2011-12-17 12:16:10 +08:00
Xf = 0xffff;
else
Xf = -1;
2011-12-17 16:08:25 +08:00
Yf = regs[7];
Zf = regs[2] & 0xffff;
2011-12-21 10:28:01 +08:00
if (CS_flags & (0x0010 | 0x0020)) {
2011-12-17 16:08:25 +08:00
ag = regs[1];
2011-12-17 12:16:10 +08:00
if ((ag & Xf) == 0)
return;
2011-12-21 10:43:53 +08:00
x = cpu.ld8_port(Zf);
mem8_loc = ((Yf & Xf) + cpu.segs[0].base) >> 0;
st8_mem8_write(x);
2011-12-17 16:08:25 +08:00
regs[7] = (Yf & ~Xf) | ((Yf + (cpu.df << 0)) & Xf);
regs[1] = ag = (ag & ~Xf) | ((ag - 1) & Xf);
2011-12-17 12:16:10 +08:00
if (ag & Xf)
2011-12-23 20:24:16 +08:00
physmem8_ptr = initial_mem_ptr;
2011-12-17 12:16:10 +08:00
} else {
2011-12-21 10:43:53 +08:00
x = cpu.ld8_port(Zf);
mem8_loc = ((Yf & Xf) + cpu.segs[0].base) >> 0;
st8_mem8_write(x);
2011-12-17 16:08:25 +08:00
regs[7] = (Yf & ~Xf) | ((Yf + (cpu.df << 0)) & Xf);
2011-12-17 12:16:10 +08:00
}
}
function stringOp_OUTSB() {
var Xf, cg, Sb, ag, Zf, iopl, x;
iopl = (cpu.eflags >> 12) & 3;
if (cpu.cpl > iopl)
abort(13);
2011-12-21 10:28:01 +08:00
if (CS_flags & 0x0080)
2011-12-17 12:16:10 +08:00
Xf = 0xffff;
else
Xf = -1;
2011-12-21 10:28:01 +08:00
Sb = CS_flags & 0x000f;
2011-12-17 12:16:10 +08:00
if (Sb == 0)
Sb = 3;
else
Sb--;
2011-12-17 16:08:25 +08:00
cg = regs[6];
Zf = regs[2] & 0xffff;
2011-12-21 10:28:01 +08:00
if (CS_flags & (0x0010 | 0x0020)) {
2011-12-17 16:08:25 +08:00
ag = regs[1];
2011-12-17 12:16:10 +08:00
if ((ag & Xf) == 0)
return;
mem8_loc = ((cg & Xf) + cpu.segs[Sb].base) >> 0;
2011-12-21 10:43:53 +08:00
x = ld_8bits_mem8_read();
cpu.st8_port(Zf, x);
2011-12-17 16:08:25 +08:00
regs[6] = (cg & ~Xf) | ((cg + (cpu.df << 0)) & Xf);
regs[1] = ag = (ag & ~Xf) | ((ag - 1) & Xf);
2011-12-17 12:16:10 +08:00
if (ag & Xf)
2011-12-23 20:24:16 +08:00
physmem8_ptr = initial_mem_ptr;
2011-12-17 12:16:10 +08:00
} else {
mem8_loc = ((cg & Xf) + cpu.segs[Sb].base) >> 0;
2011-12-21 10:43:53 +08:00
x = ld_8bits_mem8_read();
cpu.st8_port(Zf, x);
2011-12-17 16:08:25 +08:00
regs[6] = (cg & ~Xf) | ((cg + (cpu.df << 0)) & Xf);
2011-12-17 12:16:10 +08:00
}
}
function stringOp_MOVSB() {
2011-12-17 12:16:10 +08:00
var Xf, Yf, cg, ag, Sb, eg;
2011-12-21 10:28:01 +08:00
if (CS_flags & 0x0080)
2011-12-17 12:16:10 +08:00
Xf = 0xffff;
else
Xf = -1;
2011-12-21 10:28:01 +08:00
Sb = CS_flags & 0x000f;
2011-12-17 12:16:10 +08:00
if (Sb == 0)
Sb = 3;
else
Sb--;
2011-12-17 16:08:25 +08:00
cg = regs[6];
Yf = regs[7];
mem8_loc = ((cg & Xf) + cpu.segs[Sb].base) >> 0;
2011-12-17 13:38:46 +08:00
eg = ((Yf & Xf) + cpu.segs[0].base) >> 0;
2011-12-21 10:28:01 +08:00
if (CS_flags & (0x0010 | 0x0020)) {
2011-12-17 16:08:25 +08:00
ag = regs[1];
2011-12-17 12:16:10 +08:00
if ((ag & Xf) == 0)
return;
{
2011-12-21 10:43:53 +08:00
x = ld_8bits_mem8_read();
mem8_loc = eg;
st8_mem8_write(x);
2011-12-17 16:08:25 +08:00
regs[6] = (cg & ~Xf) | ((cg + (cpu.df << 0)) & Xf);
regs[7] = (Yf & ~Xf) | ((Yf + (cpu.df << 0)) & Xf);
regs[1] = ag = (ag & ~Xf) | ((ag - 1) & Xf);
2011-12-17 12:16:10 +08:00
if (ag & Xf)
2011-12-23 20:24:16 +08:00
physmem8_ptr = initial_mem_ptr;
2011-12-17 12:16:10 +08:00
}
} else {
2011-12-21 10:43:53 +08:00
x = ld_8bits_mem8_read();
mem8_loc = eg;
st8_mem8_write(x);
2011-12-17 16:08:25 +08:00
regs[6] = (cg & ~Xf) | ((cg + (cpu.df << 0)) & Xf);
regs[7] = (Yf & ~Xf) | ((Yf + (cpu.df << 0)) & Xf);
2011-12-17 12:16:10 +08:00
}
}
function stringOp_STOSB() {
2011-12-17 12:16:10 +08:00
var Xf, Yf, ag;
2011-12-21 10:28:01 +08:00
if (CS_flags & 0x0080)
2011-12-17 12:16:10 +08:00
Xf = 0xffff;
else
Xf = -1;
2011-12-17 16:08:25 +08:00
Yf = regs[7];
mem8_loc = ((Yf & Xf) + cpu.segs[0].base) >> 0;
2011-12-21 10:28:01 +08:00
if (CS_flags & (0x0010 | 0x0020)) {
2011-12-17 16:08:25 +08:00
ag = regs[1];
2011-12-17 12:16:10 +08:00
if ((ag & Xf) == 0)
return;
{
st8_mem8_write(regs[0]);
2011-12-17 16:08:25 +08:00
regs[7] = (Yf & ~Xf) | ((Yf + (cpu.df << 0)) & Xf);
regs[1] = ag = (ag & ~Xf) | ((ag - 1) & Xf);
2011-12-17 12:16:10 +08:00
if (ag & Xf)
2011-12-23 20:24:16 +08:00
physmem8_ptr = initial_mem_ptr;
2011-12-17 12:16:10 +08:00
}
} else {
st8_mem8_write(regs[0]);
2011-12-17 16:08:25 +08:00
regs[7] = (Yf & ~Xf) | ((Yf + (cpu.df << 0)) & Xf);
2011-12-17 12:16:10 +08:00
}
}
function stringOp_CMPSB() {
2011-12-17 12:16:10 +08:00
var Xf, Yf, cg, ag, Sb, eg;
2011-12-21 10:28:01 +08:00
if (CS_flags & 0x0080)
2011-12-17 12:16:10 +08:00
Xf = 0xffff;
else
Xf = -1;
2011-12-21 10:28:01 +08:00
Sb = CS_flags & 0x000f;
2011-12-17 12:16:10 +08:00
if (Sb == 0)
Sb = 3;
else
Sb--;
2011-12-17 16:08:25 +08:00
cg = regs[6];
Yf = regs[7];
mem8_loc = ((cg & Xf) + cpu.segs[Sb].base) >> 0;
2011-12-17 13:38:46 +08:00
eg = ((Yf & Xf) + cpu.segs[0].base) >> 0;
2011-12-21 10:28:01 +08:00
if (CS_flags & (0x0010 | 0x0020)) {
2011-12-17 16:08:25 +08:00
ag = regs[1];
2011-12-17 12:16:10 +08:00
if ((ag & Xf) == 0)
return;
2011-12-21 10:43:53 +08:00
x = ld_8bits_mem8_read();
mem8_loc = eg;
y = ld_8bits_mem8_read();
do_8bit_math(7, x, y);
2011-12-17 16:08:25 +08:00
regs[6] = (cg & ~Xf) | ((cg + (cpu.df << 0)) & Xf);
regs[7] = (Yf & ~Xf) | ((Yf + (cpu.df << 0)) & Xf);
regs[1] = ag = (ag & ~Xf) | ((ag - 1) & Xf);
2011-12-21 10:28:01 +08:00
if (CS_flags & 0x0010) {
2011-12-17 16:14:24 +08:00
if (!(_dst == 0))
2011-12-17 12:16:10 +08:00
return;
} else {
2011-12-17 16:14:24 +08:00
if ((_dst == 0))
2011-12-17 12:16:10 +08:00
return;
}
if (ag & Xf)
2011-12-23 20:24:16 +08:00
physmem8_ptr = initial_mem_ptr;
2011-12-17 12:16:10 +08:00
} else {
2011-12-21 10:43:53 +08:00
x = ld_8bits_mem8_read();
mem8_loc = eg;
y = ld_8bits_mem8_read();
do_8bit_math(7, x, y);
2011-12-17 16:08:25 +08:00
regs[6] = (cg & ~Xf) | ((cg + (cpu.df << 0)) & Xf);
regs[7] = (Yf & ~Xf) | ((Yf + (cpu.df << 0)) & Xf);
2011-12-17 12:16:10 +08:00
}
}
function stringOp_LODSB() {
2011-12-21 10:43:53 +08:00
var Xf, cg, Sb, ag, x;
2011-12-21 10:28:01 +08:00
if (CS_flags & 0x0080)
2011-12-17 12:16:10 +08:00
Xf = 0xffff;
else
Xf = -1;
2011-12-21 10:28:01 +08:00
Sb = CS_flags & 0x000f;
2011-12-17 12:16:10 +08:00
if (Sb == 0)
Sb = 3;
else
Sb--;
2011-12-17 16:08:25 +08:00
cg = regs[6];
mem8_loc = ((cg & Xf) + cpu.segs[Sb].base) >> 0;
2011-12-21 10:28:01 +08:00
if (CS_flags & (0x0010 | 0x0020)) {
2011-12-17 16:08:25 +08:00
ag = regs[1];
2011-12-17 12:16:10 +08:00
if ((ag & Xf) == 0)
return;
2011-12-21 10:43:53 +08:00
x = ld_8bits_mem8_read();
regs[0] = (regs[0] & -256) | x;
2011-12-17 16:08:25 +08:00
regs[6] = (cg & ~Xf) | ((cg + (cpu.df << 0)) & Xf);
regs[1] = ag = (ag & ~Xf) | ((ag - 1) & Xf);
2011-12-17 12:16:10 +08:00
if (ag & Xf)
2011-12-23 20:24:16 +08:00
physmem8_ptr = initial_mem_ptr;
2011-12-17 12:16:10 +08:00
} else {
2011-12-21 10:43:53 +08:00
x = ld_8bits_mem8_read();
regs[0] = (regs[0] & -256) | x;
2011-12-17 16:08:25 +08:00
regs[6] = (cg & ~Xf) | ((cg + (cpu.df << 0)) & Xf);
2011-12-17 12:16:10 +08:00
}
}
function stringOp_SCASB() {
2011-12-21 10:43:53 +08:00
var Xf, Yf, ag, x;
2011-12-21 10:28:01 +08:00
if (CS_flags & 0x0080)
2011-12-17 12:16:10 +08:00
Xf = 0xffff;
else
Xf = -1;
2011-12-17 16:08:25 +08:00
Yf = regs[7];
mem8_loc = ((Yf & Xf) + cpu.segs[0].base) >> 0;
2011-12-21 10:28:01 +08:00
if (CS_flags & (0x0010 | 0x0020)) {
2011-12-17 16:08:25 +08:00
ag = regs[1];
2011-12-17 12:16:10 +08:00
if ((ag & Xf) == 0)
return;
2011-12-21 10:43:53 +08:00
x = ld_8bits_mem8_read();
do_8bit_math(7, regs[0], x);
2011-12-17 16:08:25 +08:00
regs[7] = (Yf & ~Xf) | ((Yf + (cpu.df << 0)) & Xf);
regs[1] = ag = (ag & ~Xf) | ((ag - 1) & Xf);
2011-12-21 10:28:01 +08:00
if (CS_flags & 0x0010) {
2011-12-17 16:14:24 +08:00
if (!(_dst == 0))
2011-12-17 12:16:10 +08:00
return;
} else {
2011-12-17 16:14:24 +08:00
if ((_dst == 0))
2011-12-17 12:16:10 +08:00
return;
}
if (ag & Xf)
2011-12-23 20:24:16 +08:00
physmem8_ptr = initial_mem_ptr;
2011-12-17 12:16:10 +08:00
} else {
2011-12-21 10:43:53 +08:00
x = ld_8bits_mem8_read();
do_8bit_math(7, regs[0], x);
2011-12-17 16:08:25 +08:00
regs[7] = (Yf & ~Xf) | ((Yf + (cpu.df << 0)) & Xf);
2011-12-17 12:16:10 +08:00
}
}
function jg() {
var Xf, Yf, Zf, ag, iopl, x;
iopl = (cpu.eflags >> 12) & 3;
if (cpu.cpl > iopl)
abort(13);
2011-12-21 10:28:01 +08:00
if (CS_flags & 0x0080)
2011-12-17 12:16:10 +08:00
Xf = 0xffff;
else
Xf = -1;
2011-12-17 16:08:25 +08:00
Yf = regs[7];
Zf = regs[2] & 0xffff;
2011-12-21 10:28:01 +08:00
if (CS_flags & (0x0010 | 0x0020)) {
2011-12-17 16:08:25 +08:00
ag = regs[1];
2011-12-17 12:16:10 +08:00
if ((ag & Xf) == 0)
return;
2011-12-21 10:43:53 +08:00
x = cpu.ld16_port(Zf);
mem8_loc = ((Yf & Xf) + cpu.segs[0].base) >> 0;
st16_mem8_write(x);
2011-12-17 16:08:25 +08:00
regs[7] = (Yf & ~Xf) | ((Yf + (cpu.df << 1)) & Xf);
regs[1] = ag = (ag & ~Xf) | ((ag - 1) & Xf);
2011-12-17 12:16:10 +08:00
if (ag & Xf)
2011-12-23 20:24:16 +08:00
physmem8_ptr = initial_mem_ptr;
2011-12-17 12:16:10 +08:00
} else {
2011-12-21 10:43:53 +08:00
x = cpu.ld16_port(Zf);
mem8_loc = ((Yf & Xf) + cpu.segs[0].base) >> 0;
st16_mem8_write(x);
2011-12-17 16:08:25 +08:00
regs[7] = (Yf & ~Xf) | ((Yf + (cpu.df << 1)) & Xf);
2011-12-17 12:16:10 +08:00
}
}
function kg() {
var Xf, cg, Sb, ag, Zf, iopl, x;
iopl = (cpu.eflags >> 12) & 3;
if (cpu.cpl > iopl)
abort(13);
2011-12-21 10:28:01 +08:00
if (CS_flags & 0x0080)
2011-12-17 12:16:10 +08:00
Xf = 0xffff;
else
Xf = -1;
2011-12-21 10:28:01 +08:00
Sb = CS_flags & 0x000f;
2011-12-17 12:16:10 +08:00
if (Sb == 0)
Sb = 3;
else
Sb--;
2011-12-17 16:08:25 +08:00
cg = regs[6];
Zf = regs[2] & 0xffff;
2011-12-21 10:28:01 +08:00
if (CS_flags & (0x0010 | 0x0020)) {
2011-12-17 16:08:25 +08:00
ag = regs[1];
2011-12-17 12:16:10 +08:00
if ((ag & Xf) == 0)
return;
mem8_loc = ((cg & Xf) + cpu.segs[Sb].base) >> 0;
2011-12-21 10:43:53 +08:00
x = ld_16bits_mem8_read();
cpu.st16_port(Zf, x);
2011-12-17 16:08:25 +08:00
regs[6] = (cg & ~Xf) | ((cg + (cpu.df << 1)) & Xf);
regs[1] = ag = (ag & ~Xf) | ((ag - 1) & Xf);
2011-12-17 12:16:10 +08:00
if (ag & Xf)
2011-12-23 20:24:16 +08:00
physmem8_ptr = initial_mem_ptr;
2011-12-17 12:16:10 +08:00
} else {
mem8_loc = ((cg & Xf) + cpu.segs[Sb].base) >> 0;
2011-12-21 10:43:53 +08:00
x = ld_16bits_mem8_read();
cpu.st16_port(Zf, x);
2011-12-17 16:08:25 +08:00
regs[6] = (cg & ~Xf) | ((cg + (cpu.df << 1)) & Xf);
2011-12-17 12:16:10 +08:00
}
}
function lg() {
var Xf, Yf, cg, ag, Sb, eg;
2011-12-21 10:28:01 +08:00
if (CS_flags & 0x0080)
2011-12-17 12:16:10 +08:00
Xf = 0xffff;
else
Xf = -1;
2011-12-21 10:28:01 +08:00
Sb = CS_flags & 0x000f;
2011-12-17 12:16:10 +08:00
if (Sb == 0)
Sb = 3;
else
Sb--;
2011-12-17 16:08:25 +08:00
cg = regs[6];
Yf = regs[7];
mem8_loc = ((cg & Xf) + cpu.segs[Sb].base) >> 0;
2011-12-17 13:38:46 +08:00
eg = ((Yf & Xf) + cpu.segs[0].base) >> 0;
2011-12-21 10:28:01 +08:00
if (CS_flags & (0x0010 | 0x0020)) {
2011-12-17 16:08:25 +08:00
ag = regs[1];
2011-12-17 12:16:10 +08:00
if ((ag & Xf) == 0)
return;
{
2011-12-21 10:43:53 +08:00
x = ld_16bits_mem8_read();
mem8_loc = eg;
st16_mem8_write(x);
2011-12-17 16:08:25 +08:00
regs[6] = (cg & ~Xf) | ((cg + (cpu.df << 1)) & Xf);
regs[7] = (Yf & ~Xf) | ((Yf + (cpu.df << 1)) & Xf);
regs[1] = ag = (ag & ~Xf) | ((ag - 1) & Xf);
2011-12-17 12:16:10 +08:00
if (ag & Xf)
2011-12-23 20:24:16 +08:00
physmem8_ptr = initial_mem_ptr;
2011-12-17 12:16:10 +08:00
}
} else {
2011-12-21 10:43:53 +08:00
x = ld_16bits_mem8_read();
mem8_loc = eg;
st16_mem8_write(x);
2011-12-17 16:08:25 +08:00
regs[6] = (cg & ~Xf) | ((cg + (cpu.df << 1)) & Xf);
regs[7] = (Yf & ~Xf) | ((Yf + (cpu.df << 1)) & Xf);
2011-12-17 12:16:10 +08:00
}
}
function mg() {
var Xf, Yf, ag;
2011-12-21 10:28:01 +08:00
if (CS_flags & 0x0080)
2011-12-17 12:16:10 +08:00
Xf = 0xffff;
else
Xf = -1;
2011-12-17 16:08:25 +08:00
Yf = regs[7];
mem8_loc = ((Yf & Xf) + cpu.segs[0].base) >> 0;
2011-12-21 10:28:01 +08:00
if (CS_flags & (0x0010 | 0x0020)) {
2011-12-17 16:08:25 +08:00
ag = regs[1];
2011-12-17 12:16:10 +08:00
if ((ag & Xf) == 0)
return;
{
st16_mem8_write(regs[0]);
2011-12-17 16:08:25 +08:00
regs[7] = (Yf & ~Xf) | ((Yf + (cpu.df << 1)) & Xf);
regs[1] = ag = (ag & ~Xf) | ((ag - 1) & Xf);
2011-12-17 12:16:10 +08:00
if (ag & Xf)
2011-12-23 20:24:16 +08:00
physmem8_ptr = initial_mem_ptr;
2011-12-17 12:16:10 +08:00
}
} else {
st16_mem8_write(regs[0]);
2011-12-17 16:08:25 +08:00
regs[7] = (Yf & ~Xf) | ((Yf + (cpu.df << 1)) & Xf);
2011-12-17 12:16:10 +08:00
}
}
function ng() {
var Xf, Yf, cg, ag, Sb, eg;
2011-12-21 10:28:01 +08:00
if (CS_flags & 0x0080)
2011-12-17 12:16:10 +08:00
Xf = 0xffff;
else
Xf = -1;
2011-12-21 10:28:01 +08:00
Sb = CS_flags & 0x000f;
2011-12-17 12:16:10 +08:00
if (Sb == 0)
Sb = 3;
else
Sb--;
2011-12-17 16:08:25 +08:00
cg = regs[6];
Yf = regs[7];
mem8_loc = ((cg & Xf) + cpu.segs[Sb].base) >> 0;
2011-12-17 13:38:46 +08:00
eg = ((Yf & Xf) + cpu.segs[0].base) >> 0;
2011-12-21 10:28:01 +08:00
if (CS_flags & (0x0010 | 0x0020)) {
2011-12-17 16:08:25 +08:00
ag = regs[1];
2011-12-17 12:16:10 +08:00
if ((ag & Xf) == 0)
return;
2011-12-21 10:43:53 +08:00
x = ld_16bits_mem8_read();
mem8_loc = eg;
y = ld_16bits_mem8_read();
do_16bit_math(7, x, y);
2011-12-17 16:08:25 +08:00
regs[6] = (cg & ~Xf) | ((cg + (cpu.df << 1)) & Xf);
regs[7] = (Yf & ~Xf) | ((Yf + (cpu.df << 1)) & Xf);
regs[1] = ag = (ag & ~Xf) | ((ag - 1) & Xf);
2011-12-21 10:28:01 +08:00
if (CS_flags & 0x0010) {
2011-12-17 16:14:24 +08:00
if (!(_dst == 0))
2011-12-17 12:16:10 +08:00
return;
} else {
2011-12-17 16:14:24 +08:00
if ((_dst == 0))
2011-12-17 12:16:10 +08:00
return;
}
if (ag & Xf)
2011-12-23 20:24:16 +08:00
physmem8_ptr = initial_mem_ptr;
2011-12-17 12:16:10 +08:00
} else {
2011-12-21 10:43:53 +08:00
x = ld_16bits_mem8_read();
mem8_loc = eg;
y = ld_16bits_mem8_read();
do_16bit_math(7, x, y);
2011-12-17 16:08:25 +08:00
regs[6] = (cg & ~Xf) | ((cg + (cpu.df << 1)) & Xf);
regs[7] = (Yf & ~Xf) | ((Yf + (cpu.df << 1)) & Xf);
2011-12-17 12:16:10 +08:00
}
}
function og() {
2011-12-21 10:43:53 +08:00
var Xf, cg, Sb, ag, x;
2011-12-21 10:28:01 +08:00
if (CS_flags & 0x0080)
2011-12-17 12:16:10 +08:00
Xf = 0xffff;
else
Xf = -1;
2011-12-21 10:28:01 +08:00
Sb = CS_flags & 0x000f;
2011-12-17 12:16:10 +08:00
if (Sb == 0)
Sb = 3;
else
Sb--;
2011-12-17 16:08:25 +08:00
cg = regs[6];
mem8_loc = ((cg & Xf) + cpu.segs[Sb].base) >> 0;
2011-12-21 10:28:01 +08:00
if (CS_flags & (0x0010 | 0x0020)) {
2011-12-17 16:08:25 +08:00
ag = regs[1];
2011-12-17 12:16:10 +08:00
if ((ag & Xf) == 0)
return;
2011-12-21 10:43:53 +08:00
x = ld_16bits_mem8_read();
regs[0] = (regs[0] & -65536) | x;
2011-12-17 16:08:25 +08:00
regs[6] = (cg & ~Xf) | ((cg + (cpu.df << 1)) & Xf);
regs[1] = ag = (ag & ~Xf) | ((ag - 1) & Xf);
2011-12-17 12:16:10 +08:00
if (ag & Xf)
2011-12-23 20:24:16 +08:00
physmem8_ptr = initial_mem_ptr;
2011-12-17 12:16:10 +08:00
} else {
2011-12-21 10:43:53 +08:00
x = ld_16bits_mem8_read();
regs[0] = (regs[0] & -65536) | x;
2011-12-17 16:08:25 +08:00
regs[6] = (cg & ~Xf) | ((cg + (cpu.df << 1)) & Xf);
2011-12-17 12:16:10 +08:00
}
}
function pg() {
2011-12-21 10:43:53 +08:00
var Xf, Yf, ag, x;
2011-12-21 10:28:01 +08:00
if (CS_flags & 0x0080)
2011-12-17 12:16:10 +08:00
Xf = 0xffff;
else
Xf = -1;
2011-12-17 16:08:25 +08:00
Yf = regs[7];
mem8_loc = ((Yf & Xf) + cpu.segs[0].base) >> 0;
2011-12-21 10:28:01 +08:00
if (CS_flags & (0x0010 | 0x0020)) {
2011-12-17 16:08:25 +08:00
ag = regs[1];
2011-12-17 12:16:10 +08:00
if ((ag & Xf) == 0)
return;
2011-12-21 10:43:53 +08:00
x = ld_16bits_mem8_read();
do_16bit_math(7, regs[0], x);
2011-12-17 16:08:25 +08:00
regs[7] = (Yf & ~Xf) | ((Yf + (cpu.df << 1)) & Xf);
regs[1] = ag = (ag & ~Xf) | ((ag - 1) & Xf);
2011-12-21 10:28:01 +08:00
if (CS_flags & 0x0010) {
2011-12-17 16:14:24 +08:00
if (!(_dst == 0))
2011-12-17 12:16:10 +08:00
return;
} else {
2011-12-17 16:14:24 +08:00
if ((_dst == 0))
2011-12-17 12:16:10 +08:00
return;
}
if (ag & Xf)
2011-12-23 20:24:16 +08:00
physmem8_ptr = initial_mem_ptr;
2011-12-17 12:16:10 +08:00
} else {
2011-12-21 10:43:53 +08:00
x = ld_16bits_mem8_read();
do_16bit_math(7, regs[0], x);
2011-12-17 16:08:25 +08:00
regs[7] = (Yf & ~Xf) | ((Yf + (cpu.df << 1)) & Xf);
2011-12-17 12:16:10 +08:00
}
}
function stringOp_INSD() {
var Xf, Yf, Zf, ag, iopl, x;
iopl = (cpu.eflags >> 12) & 3;
if (cpu.cpl > iopl)
abort(13);
2011-12-21 10:28:01 +08:00
if (CS_flags & 0x0080)
2011-12-17 12:16:10 +08:00
Xf = 0xffff;
else
Xf = -1;
2011-12-17 16:08:25 +08:00
Yf = regs[7];
Zf = regs[2] & 0xffff;
2011-12-21 10:28:01 +08:00
if (CS_flags & (0x0010 | 0x0020)) {
2011-12-17 16:08:25 +08:00
ag = regs[1];
2011-12-17 12:16:10 +08:00
if ((ag & Xf) == 0)
return;
2011-12-21 10:43:53 +08:00
x = cpu.ld32_port(Zf);
mem8_loc = ((Yf & Xf) + cpu.segs[0].base) >> 0;
st32_mem8_write(x);
2011-12-17 16:08:25 +08:00
regs[7] = (Yf & ~Xf) | ((Yf + (cpu.df << 2)) & Xf);
regs[1] = ag = (ag & ~Xf) | ((ag - 1) & Xf);
2011-12-17 12:16:10 +08:00
if (ag & Xf)
2011-12-23 20:24:16 +08:00
physmem8_ptr = initial_mem_ptr;
2011-12-17 12:16:10 +08:00
} else {
2011-12-21 10:43:53 +08:00
x = cpu.ld32_port(Zf);
mem8_loc = ((Yf & Xf) + cpu.segs[0].base) >> 0;
st32_mem8_write(x);
2011-12-17 16:08:25 +08:00
regs[7] = (Yf & ~Xf) | ((Yf + (cpu.df << 2)) & Xf);
2011-12-17 12:16:10 +08:00
}
}
function stringOp_OUTSD() {
var Xf, cg, Sb, ag, Zf, iopl, x;
iopl = (cpu.eflags >> 12) & 3;
if (cpu.cpl > iopl)
abort(13);
2011-12-21 10:28:01 +08:00
if (CS_flags & 0x0080)
2011-12-17 12:16:10 +08:00
Xf = 0xffff;
else
Xf = -1;
2011-12-21 10:28:01 +08:00
Sb = CS_flags & 0x000f;
2011-12-17 12:16:10 +08:00
if (Sb == 0)
Sb = 3;
else
Sb--;
2011-12-17 16:08:25 +08:00
cg = regs[6];
Zf = regs[2] & 0xffff;
2011-12-21 10:28:01 +08:00
if (CS_flags & (0x0010 | 0x0020)) {
2011-12-17 16:08:25 +08:00
ag = regs[1];
2011-12-17 12:16:10 +08:00
if ((ag & Xf) == 0)
return;
mem8_loc = ((cg & Xf) + cpu.segs[Sb].base) >> 0;
2011-12-21 10:43:53 +08:00
x = ld_32bits_mem8_read();
cpu.st32_port(Zf, x);
2011-12-17 16:08:25 +08:00
regs[6] = (cg & ~Xf) | ((cg + (cpu.df << 2)) & Xf);
regs[1] = ag = (ag & ~Xf) | ((ag - 1) & Xf);
2011-12-17 12:16:10 +08:00
if (ag & Xf)
2011-12-23 20:24:16 +08:00
physmem8_ptr = initial_mem_ptr;
2011-12-17 12:16:10 +08:00
} else {
mem8_loc = ((cg & Xf) + cpu.segs[Sb].base) >> 0;
2011-12-21 10:43:53 +08:00
x = ld_32bits_mem8_read();
cpu.st32_port(Zf, x);
2011-12-17 16:08:25 +08:00
regs[6] = (cg & ~Xf) | ((cg + (cpu.df << 2)) & Xf);
2011-12-17 12:16:10 +08:00
}
}
function stringOp_MOVSD() {
2011-12-17 12:16:10 +08:00
var Xf, Yf, cg, ag, Sb, eg;
2011-12-21 10:28:01 +08:00
if (CS_flags & 0x0080)
2011-12-17 12:16:10 +08:00
Xf = 0xffff;
else
Xf = -1;
2011-12-21 10:28:01 +08:00
Sb = CS_flags & 0x000f;
2011-12-17 12:16:10 +08:00
if (Sb == 0)
Sb = 3;
else
Sb--;
2011-12-17 16:08:25 +08:00
cg = regs[6];
Yf = regs[7];
mem8_loc = ((cg & Xf) + cpu.segs[Sb].base) >> 0;
2011-12-17 13:38:46 +08:00
eg = ((Yf & Xf) + cpu.segs[0].base) >> 0;
2011-12-21 10:28:01 +08:00
if (CS_flags & (0x0010 | 0x0020)) {
2011-12-17 16:08:25 +08:00
ag = regs[1];
2011-12-17 12:16:10 +08:00
if ((ag & Xf) == 0)
return;
if (Xf == -1 && cpu.df == 1 && ((mem8_loc | eg) & 3) == 0) {
2011-12-17 12:16:10 +08:00
var tg, l, ug, vg, i, wg;
tg = ag >>> 0;
l = (4096 - (mem8_loc & 0xfff)) >> 2;
2011-12-17 12:16:10 +08:00
if (tg > l)
tg = l;
l = (4096 - (eg & 0xfff)) >> 2;
if (tg > l)
tg = l;
ug = td(mem8_loc, 0);
2011-12-17 12:16:10 +08:00
vg = td(eg, 1);
wg = tg << 2;
vg >>= 2;
ug >>= 2;
for (i = 0; i < tg; i++)
2011-12-17 15:55:29 +08:00
phys_mem32[vg + i] = phys_mem32[ug + i];
2011-12-17 16:08:25 +08:00
regs[6] = (cg + wg) >> 0;
regs[7] = (Yf + wg) >> 0;
regs[1] = ag = (ag - tg) >> 0;
2011-12-17 12:16:10 +08:00
if (ag)
2011-12-23 20:24:16 +08:00
physmem8_ptr = initial_mem_ptr;
2011-12-17 12:16:10 +08:00
} else {
2011-12-21 10:43:53 +08:00
x = ld_32bits_mem8_read();
mem8_loc = eg;
st32_mem8_write(x);
2011-12-17 16:08:25 +08:00
regs[6] = (cg & ~Xf) | ((cg + (cpu.df << 2)) & Xf);
regs[7] = (Yf & ~Xf) | ((Yf + (cpu.df << 2)) & Xf);
regs[1] = ag = (ag & ~Xf) | ((ag - 1) & Xf);
2011-12-17 12:16:10 +08:00
if (ag & Xf)
2011-12-23 20:24:16 +08:00
physmem8_ptr = initial_mem_ptr;
2011-12-17 12:16:10 +08:00
}
} else {
2011-12-21 10:43:53 +08:00
x = ld_32bits_mem8_read();
mem8_loc = eg;
st32_mem8_write(x);
2011-12-17 16:08:25 +08:00
regs[6] = (cg & ~Xf) | ((cg + (cpu.df << 2)) & Xf);
regs[7] = (Yf & ~Xf) | ((Yf + (cpu.df << 2)) & Xf);
2011-12-17 12:16:10 +08:00
}
}
function stringOp_STOSD() {
2011-12-17 12:16:10 +08:00
var Xf, Yf, ag;
2011-12-21 10:28:01 +08:00
if (CS_flags & 0x0080)
2011-12-17 12:16:10 +08:00
Xf = 0xffff;
else
Xf = -1;
2011-12-17 16:08:25 +08:00
Yf = regs[7];
mem8_loc = ((Yf & Xf) + cpu.segs[0].base) >> 0;
2011-12-21 10:28:01 +08:00
if (CS_flags & (0x0010 | 0x0020)) {
2011-12-17 16:08:25 +08:00
ag = regs[1];
2011-12-17 12:16:10 +08:00
if ((ag & Xf) == 0)
return;
if (Xf == -1 && cpu.df == 1 && (mem8_loc & 3) == 0) {
2011-12-21 10:43:53 +08:00
var tg, l, vg, i, wg, x;
2011-12-17 12:16:10 +08:00
tg = ag >>> 0;
l = (4096 - (mem8_loc & 0xfff)) >> 2;
2011-12-17 12:16:10 +08:00
if (tg > l)
tg = l;
2011-12-17 16:08:25 +08:00
vg = td(regs[7], 1);
2011-12-21 10:43:53 +08:00
x = regs[0];
2011-12-17 12:16:10 +08:00
vg >>= 2;
for (i = 0; i < tg; i++)
2011-12-21 10:43:53 +08:00
phys_mem32[vg + i] = x;
2011-12-17 12:16:10 +08:00
wg = tg << 2;
2011-12-17 16:08:25 +08:00
regs[7] = (Yf + wg) >> 0;
regs[1] = ag = (ag - tg) >> 0;
2011-12-17 12:16:10 +08:00
if (ag)
2011-12-23 20:24:16 +08:00
physmem8_ptr = initial_mem_ptr;
2011-12-17 12:16:10 +08:00
} else {
st32_mem8_write(regs[0]);
2011-12-17 16:08:25 +08:00
regs[7] = (Yf & ~Xf) | ((Yf + (cpu.df << 2)) & Xf);
regs[1] = ag = (ag & ~Xf) | ((ag - 1) & Xf);
2011-12-17 12:16:10 +08:00
if (ag & Xf)
2011-12-23 20:24:16 +08:00
physmem8_ptr = initial_mem_ptr;
2011-12-17 12:16:10 +08:00
}
} else {
st32_mem8_write(regs[0]);
2011-12-17 16:08:25 +08:00
regs[7] = (Yf & ~Xf) | ((Yf + (cpu.df << 2)) & Xf);
2011-12-17 12:16:10 +08:00
}
}
function stringOp_CMPSD() {
2011-12-17 12:16:10 +08:00
var Xf, Yf, cg, ag, Sb, eg;
2011-12-21 10:28:01 +08:00
if (CS_flags & 0x0080)
2011-12-17 12:16:10 +08:00
Xf = 0xffff;
else
Xf = -1;
2011-12-21 10:28:01 +08:00
Sb = CS_flags & 0x000f;
2011-12-17 12:16:10 +08:00
if (Sb == 0)
Sb = 3;
else
Sb--;
2011-12-17 16:08:25 +08:00
cg = regs[6];
Yf = regs[7];
mem8_loc = ((cg & Xf) + cpu.segs[Sb].base) >> 0;
2011-12-17 13:38:46 +08:00
eg = ((Yf & Xf) + cpu.segs[0].base) >> 0;
2011-12-21 10:28:01 +08:00
if (CS_flags & (0x0010 | 0x0020)) {
2011-12-17 16:08:25 +08:00
ag = regs[1];
2011-12-17 12:16:10 +08:00
if ((ag & Xf) == 0)
return;
2011-12-21 10:43:53 +08:00
x = ld_32bits_mem8_read();
mem8_loc = eg;
y = ld_32bits_mem8_read();
do_32bit_math(7, x, y);
2011-12-17 16:08:25 +08:00
regs[6] = (cg & ~Xf) | ((cg + (cpu.df << 2)) & Xf);
regs[7] = (Yf & ~Xf) | ((Yf + (cpu.df << 2)) & Xf);
regs[1] = ag = (ag & ~Xf) | ((ag - 1) & Xf);
2011-12-21 10:28:01 +08:00
if (CS_flags & 0x0010) {
2011-12-17 16:14:24 +08:00
if (!(_dst == 0))
2011-12-17 12:16:10 +08:00
return;
} else {
2011-12-17 16:14:24 +08:00
if ((_dst == 0))
2011-12-17 12:16:10 +08:00
return;
}
if (ag & Xf)
2011-12-23 20:24:16 +08:00
physmem8_ptr = initial_mem_ptr;
2011-12-17 12:16:10 +08:00
} else {
2011-12-21 10:43:53 +08:00
x = ld_32bits_mem8_read();
mem8_loc = eg;
y = ld_32bits_mem8_read();
do_32bit_math(7, x, y);
2011-12-17 16:08:25 +08:00
regs[6] = (cg & ~Xf) | ((cg + (cpu.df << 2)) & Xf);
regs[7] = (Yf & ~Xf) | ((Yf + (cpu.df << 2)) & Xf);
2011-12-17 12:16:10 +08:00
}
}
function stringOp_LODSD() {
2011-12-21 10:43:53 +08:00
var Xf, cg, Sb, ag, x;
2011-12-21 10:28:01 +08:00
if (CS_flags & 0x0080)
2011-12-17 12:16:10 +08:00
Xf = 0xffff;
else
Xf = -1;
2011-12-21 10:28:01 +08:00
Sb = CS_flags & 0x000f;
2011-12-17 12:16:10 +08:00
if (Sb == 0)
Sb = 3;
else
Sb--;
2011-12-17 16:08:25 +08:00
cg = regs[6];
mem8_loc = ((cg & Xf) + cpu.segs[Sb].base) >> 0;
2011-12-21 10:28:01 +08:00
if (CS_flags & (0x0010 | 0x0020)) {
2011-12-17 16:08:25 +08:00
ag = regs[1];
2011-12-17 12:16:10 +08:00
if ((ag & Xf) == 0)
return;
2011-12-21 10:43:53 +08:00
x = ld_32bits_mem8_read();
regs[0] = x;
2011-12-17 16:08:25 +08:00
regs[6] = (cg & ~Xf) | ((cg + (cpu.df << 2)) & Xf);
regs[1] = ag = (ag & ~Xf) | ((ag - 1) & Xf);
2011-12-17 12:16:10 +08:00
if (ag & Xf)
2011-12-23 20:24:16 +08:00
physmem8_ptr = initial_mem_ptr;
2011-12-17 12:16:10 +08:00
} else {
2011-12-21 10:43:53 +08:00
x = ld_32bits_mem8_read();
regs[0] = x;
2011-12-17 16:08:25 +08:00
regs[6] = (cg & ~Xf) | ((cg + (cpu.df << 2)) & Xf);
2011-12-17 12:16:10 +08:00
}
}
function stringOp_SCASD() {
2011-12-21 10:43:53 +08:00
var Xf, Yf, ag, x;
2011-12-21 10:28:01 +08:00
if (CS_flags & 0x0080)
2011-12-17 12:16:10 +08:00
Xf = 0xffff;
else
Xf = -1;
2011-12-17 16:08:25 +08:00
Yf = regs[7];
mem8_loc = ((Yf & Xf) + cpu.segs[0].base) >> 0;
2011-12-21 10:28:01 +08:00
if (CS_flags & (0x0010 | 0x0020)) {
2011-12-17 16:08:25 +08:00
ag = regs[1];
2011-12-17 12:16:10 +08:00
if ((ag & Xf) == 0)
return;
2011-12-21 10:43:53 +08:00
x = ld_32bits_mem8_read();
do_32bit_math(7, regs[0], x);
2011-12-17 16:08:25 +08:00
regs[7] = (Yf & ~Xf) | ((Yf + (cpu.df << 2)) & Xf);
regs[1] = ag = (ag & ~Xf) | ((ag - 1) & Xf);
2011-12-21 10:28:01 +08:00
if (CS_flags & 0x0010) {
2011-12-17 16:14:24 +08:00
if (!(_dst == 0))
2011-12-17 12:16:10 +08:00
return;
} else {
2011-12-17 16:14:24 +08:00
if ((_dst == 0))
2011-12-17 12:16:10 +08:00
return;
}
if (ag & Xf)
2011-12-23 20:24:16 +08:00
physmem8_ptr = initial_mem_ptr;
2011-12-17 12:16:10 +08:00
} else {
2011-12-21 10:43:53 +08:00
x = ld_32bits_mem8_read();
do_32bit_math(7, regs[0], x);
2011-12-17 16:08:25 +08:00
regs[7] = (Yf & ~Xf) | ((Yf + (cpu.df << 2)) & Xf);
2011-12-17 12:16:10 +08:00
}
}
2011-12-17 17:17:40 +08:00
2011-12-17 13:38:46 +08:00
cpu = this;
2011-12-23 21:15:54 +08:00
phys_mem8 = this.phys_mem8;
phys_mem16 = this.phys_mem16;
phys_mem32 = this.phys_mem32;
tlb_read_user = this.tlb_read_user;
tlb_write_user = this.tlb_write_user;
tlb_read_kernel = this.tlb_read_kernel;
2011-12-17 16:08:25 +08:00
tlb_write_kernel = this.tlb_write_kernel;
2011-12-23 21:15:54 +08:00
2011-12-17 17:17:40 +08:00
if (cpu.cpl == 3) { //current privilege level
_tlb_read_ = tlb_read_user;
_tlb_write_ = tlb_write_user;
2011-12-17 12:16:10 +08:00
} else {
2011-12-17 17:17:40 +08:00
_tlb_read_ = tlb_read_kernel;
_tlb_write_ = tlb_write_kernel;
2011-12-17 12:16:10 +08:00
}
2011-12-23 21:15:54 +08:00
2011-12-17 13:38:46 +08:00
if (cpu.halted) {
if (cpu.hard_irq != 0 && (cpu.eflags & 0x00000200)) {
cpu.halted = 0;
2011-12-17 12:16:10 +08:00
} else {
return 257;
}
}
2011-12-23 21:15:54 +08:00
2011-12-17 16:08:25 +08:00
regs = this.regs;
2011-12-17 13:13:37 +08:00
_src = this.cc_src;
2011-12-17 16:14:24 +08:00
_dst = this.cc_dst;
_op = this.cc_op;
2011-12-17 16:20:47 +08:00
_op2 = this.cc_op2;
_dst2 = this.cc_dst2;
2011-12-23 21:15:54 +08:00
2011-12-17 16:20:47 +08:00
eip = this.eip;
2011-12-21 10:28:01 +08:00
init_segment_local_vars();
exit_code = 256;
2011-12-21 10:28:01 +08:00
cycles_left = N_cycles;
2011-12-23 21:15:54 +08:00
if (interrupt) {
do_interrupt(interrupt.intno, 0, interrupt.error_code, 0, 0);
2011-12-17 12:16:10 +08:00
}
2011-12-17 13:38:46 +08:00
if (cpu.hard_intno >= 0) {
2011-12-23 21:15:54 +08:00
do_interrupt(cpu.hard_intno, 0, 0, 0, 1);
2011-12-17 13:38:46 +08:00
cpu.hard_intno = -1;
2011-12-17 12:16:10 +08:00
}
2011-12-17 13:38:46 +08:00
if (cpu.hard_irq != 0 && (cpu.eflags & 0x00000200)) {
cpu.hard_intno = cpu.get_hard_intno();
2011-12-23 21:15:54 +08:00
do_interrupt(cpu.hard_intno, 0, 0, 0, 1);
2011-12-17 13:38:46 +08:00
cpu.hard_intno = -1;
2011-12-17 12:16:10 +08:00
}
2011-12-23 21:15:54 +08:00
2011-12-23 20:24:16 +08:00
physmem8_ptr = 0;
2011-12-21 10:28:01 +08:00
initial_mem_ptr = 0;
2011-12-17 17:17:40 +08:00
2011-12-23 21:44:05 +08:00
OUTER_LOOP: do {
2011-12-23 20:24:16 +08:00
eip = (eip + physmem8_ptr - initial_mem_ptr) >> 0;
2011-12-21 10:28:01 +08:00
Nb = (eip + CS_base) >> 0;
2011-12-17 17:17:40 +08:00
Lb = _tlb_read_[Nb >>> 12];
2011-12-17 12:16:10 +08:00
if (((Lb | Nb) & 0xfff) >= (4096 - 15 + 1)) {
var Cg;
if (Lb == -1)
do_tlb_set_page(Nb, 0, cpu.cpl == 3);
2011-12-17 17:17:40 +08:00
Lb = _tlb_read_[Nb >>> 12];
2011-12-23 20:24:16 +08:00
initial_mem_ptr = physmem8_ptr = Nb ^ Lb;
OPbyte = phys_mem8[physmem8_ptr++];
2011-12-17 12:16:10 +08:00
Cg = Nb & 0xfff;
if (Cg >= (4096 - 15 + 1)) {
2011-12-21 10:43:53 +08:00
x = Cd(Nb, OPbyte);
if ((Cg + x) > 4096) {
2011-12-23 20:24:16 +08:00
initial_mem_ptr = physmem8_ptr = this.mem_size;
for (y = 0; y < x; y++) {
mem8_loc = (Nb + y) >> 0;
2011-12-23 20:24:16 +08:00
phys_mem8[physmem8_ptr + y] = (((last_tlb_val = _tlb_read_[mem8_loc >>> 12]) == -1) ? __ld_8bits_mem8_read() : phys_mem8[mem8_loc ^ last_tlb_val]);
2011-12-17 12:16:10 +08:00
}
2011-12-23 20:24:16 +08:00
physmem8_ptr++;
2011-12-17 12:16:10 +08:00
}
}
} else {
2011-12-23 20:24:16 +08:00
initial_mem_ptr = physmem8_ptr = Nb ^ Lb;
OPbyte = phys_mem8[physmem8_ptr++];
2011-12-17 12:16:10 +08:00
}
2011-12-21 10:28:01 +08:00
OPbyte |= (CS_flags = init_CS_flags) & 0x0100;
2011-12-23 21:15:54 +08:00
EXEC_LOOP: for (; ; ) {
switch (OPbyte) {
2011-12-22 13:04:09 +08:00
case 0x66:// Operand-size override prefix
2011-12-21 10:28:01 +08:00
if (CS_flags == init_CS_flags)
Cd(Nb, OPbyte);
2011-12-21 10:28:01 +08:00
if (init_CS_flags & 0x0100)
CS_flags &= ~0x0100;
2011-12-17 12:16:10 +08:00
else
2011-12-21 10:28:01 +08:00
CS_flags |= 0x0100;
2011-12-23 20:24:16 +08:00
OPbyte = phys_mem8[physmem8_ptr++];
2011-12-21 10:28:01 +08:00
OPbyte |= (CS_flags & 0x0100);
2011-12-17 12:16:10 +08:00
break;
2011-12-22 13:04:09 +08:00
case 0x67:// Address-size override prefix
2011-12-21 10:28:01 +08:00
if (CS_flags == init_CS_flags)
Cd(Nb, OPbyte);
2011-12-21 10:28:01 +08:00
if (init_CS_flags & 0x0080)
CS_flags &= ~0x0080;
2011-12-17 12:16:10 +08:00
else
2011-12-21 10:28:01 +08:00
CS_flags |= 0x0080;
2011-12-23 20:24:16 +08:00
OPbyte = phys_mem8[physmem8_ptr++];
2011-12-21 10:28:01 +08:00
OPbyte |= (CS_flags & 0x0100);
2011-12-17 12:16:10 +08:00
break;
case 0xf0://LOCK Assert LOCK# Signal Prefix
2011-12-21 10:28:01 +08:00
if (CS_flags == init_CS_flags)
Cd(Nb, OPbyte);
2011-12-21 10:28:01 +08:00
CS_flags |= 0x0040;
2011-12-23 20:24:16 +08:00
OPbyte = phys_mem8[physmem8_ptr++];
2011-12-21 10:28:01 +08:00
OPbyte |= (CS_flags & 0x0100);
2011-12-17 12:16:10 +08:00
break;
case 0xf2://REPNZ eCX Repeat String Operation Prefix
2011-12-21 10:28:01 +08:00
if (CS_flags == init_CS_flags)
Cd(Nb, OPbyte);
2011-12-21 10:28:01 +08:00
CS_flags |= 0x0020;
2011-12-23 20:24:16 +08:00
OPbyte = phys_mem8[physmem8_ptr++];
2011-12-21 10:28:01 +08:00
OPbyte |= (CS_flags & 0x0100);
2011-12-17 12:16:10 +08:00
break;
case 0xf3://REPZ eCX Repeat String Operation Prefix
2011-12-21 10:28:01 +08:00
if (CS_flags == init_CS_flags)
Cd(Nb, OPbyte);
2011-12-21 10:28:01 +08:00
CS_flags |= 0x0010;
2011-12-23 20:24:16 +08:00
OPbyte = phys_mem8[physmem8_ptr++];
2011-12-21 10:28:01 +08:00
OPbyte |= (CS_flags & 0x0100);
2011-12-17 12:16:10 +08:00
break;
2011-12-22 13:04:09 +08:00
case 0x26://ES ES ES segment override prefix
case 0x2e://CS CS CS segment override prefix
2011-12-22 13:04:09 +08:00
case 0x36://SS SS SS segment override prefix
case 0x3e://DS DS DS segment override prefix
2011-12-21 10:28:01 +08:00
if (CS_flags == init_CS_flags)
Cd(Nb, OPbyte);
2011-12-21 10:28:01 +08:00
CS_flags = (CS_flags & ~0x000f) | (((OPbyte >> 3) & 3) + 1);
2011-12-23 20:24:16 +08:00
OPbyte = phys_mem8[physmem8_ptr++];
2011-12-21 10:28:01 +08:00
OPbyte |= (CS_flags & 0x0100);
2011-12-17 12:16:10 +08:00
break;
2011-12-22 13:04:09 +08:00
case 0x64://FS FS FS segment override prefix
case 0x65://GS GS GS segment override prefix
2011-12-21 10:28:01 +08:00
if (CS_flags == init_CS_flags)
Cd(Nb, OPbyte);
2011-12-21 10:28:01 +08:00
CS_flags = (CS_flags & ~0x000f) | ((OPbyte & 7) + 1);
2011-12-23 20:24:16 +08:00
OPbyte = phys_mem8[physmem8_ptr++];
2011-12-21 10:28:01 +08:00
OPbyte |= (CS_flags & 0x0100);
2011-12-17 12:16:10 +08:00
break;
case 0xb0://MOV Ib Zb Move
2011-12-17 12:16:10 +08:00
case 0xb1:
case 0xb2:
case 0xb3:
case 0xb4:
case 0xb5:
case 0xb6:
case 0xb7:
2011-12-23 20:24:16 +08:00
x = phys_mem8[physmem8_ptr++]; //r8
OPbyte &= 7; //last bits
2011-12-21 10:43:53 +08:00
last_tlb_val = (OPbyte & 4) << 1;
regs[OPbyte & 3] = (regs[OPbyte & 3] & ~(0xff << last_tlb_val)) | (((x) & 0xff) << last_tlb_val);
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
case 0xb8://MOV Ivqp Zvqp Move
2011-12-17 12:16:10 +08:00
case 0xb9:
case 0xba:
case 0xbb:
case 0xbc:
case 0xbd:
case 0xbe:
case 0xbf:
{
2011-12-23 20:24:16 +08:00
x = phys_mem8[physmem8_ptr] | (phys_mem8[physmem8_ptr + 1] << 8) | (phys_mem8[physmem8_ptr + 2] << 16) | (phys_mem8[physmem8_ptr + 3] << 24);
physmem8_ptr += 4;
2011-12-17 12:16:10 +08:00
}
2011-12-21 10:43:53 +08:00
regs[OPbyte & 7] = x;
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
2011-12-22 13:04:09 +08:00
case 0x88://MOV Gb Eb Move
2011-12-23 20:24:16 +08:00
mem8 = phys_mem8[physmem8_ptr++];
reg_idx1 = (mem8 >> 3) & 7;
x = (regs[reg_idx1 & 3] >> ((reg_idx1 & 4) << 1));
2011-12-18 21:19:08 +08:00
if ((mem8 >> 6) == 3) {
2011-12-23 20:24:16 +08:00
reg_idx0 = mem8 & 7;
last_tlb_val = (reg_idx0 & 4) << 1;
regs[reg_idx0 & 3] = (regs[reg_idx0 & 3] & ~(0xff << last_tlb_val)) | (((x) & 0xff) << last_tlb_val);
2011-12-17 12:16:10 +08:00
} else {
2011-12-23 20:24:16 +08:00
mem8_loc = segment_translation(mem8);
2011-12-17 12:16:10 +08:00
{
2011-12-21 10:43:53 +08:00
last_tlb_val = _tlb_write_[mem8_loc >>> 12];
if (last_tlb_val == -1) {
__st8_mem8_write(x);
2011-12-17 12:16:10 +08:00
} else {
2011-12-21 10:43:53 +08:00
phys_mem8[mem8_loc ^ last_tlb_val] = x;
2011-12-17 12:16:10 +08:00
}
}
}
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
2011-12-22 13:04:09 +08:00
case 0x89://MOV Gvqp Evqp Move
2011-12-23 20:24:16 +08:00
mem8 = phys_mem8[physmem8_ptr++];
2011-12-21 10:43:53 +08:00
x = regs[(mem8 >> 3) & 7];
2011-12-18 21:19:08 +08:00
if ((mem8 >> 6) == 3) {
2011-12-21 10:43:53 +08:00
regs[mem8 & 7] = x;
2011-12-17 12:16:10 +08:00
} else {
2011-12-23 20:24:16 +08:00
mem8_loc = segment_translation(mem8);
2011-12-17 12:16:10 +08:00
{
2011-12-21 10:43:53 +08:00
last_tlb_val = _tlb_write_[mem8_loc >>> 12];
if ((last_tlb_val | mem8_loc) & 3) {
__st32_mem8_write(x);
2011-12-17 12:16:10 +08:00
} else {
2011-12-21 10:43:53 +08:00
phys_mem32[(mem8_loc ^ last_tlb_val) >> 2] = x;
2011-12-17 12:16:10 +08:00
}
}
}
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
case 0x8a://MOV Eb Gb Move
2011-12-23 20:24:16 +08:00
mem8 = phys_mem8[physmem8_ptr++];
2011-12-18 21:19:08 +08:00
if ((mem8 >> 6) == 3) {
2011-12-23 20:24:16 +08:00
reg_idx0 = mem8 & 7;
x = (regs[reg_idx0 & 3] >> ((reg_idx0 & 4) << 1));
2011-12-17 12:16:10 +08:00
} else {
2011-12-23 20:24:16 +08:00
mem8_loc = segment_translation(mem8);
2011-12-21 10:43:53 +08:00
x = (((last_tlb_val = _tlb_read_[mem8_loc >>> 12]) == -1) ? __ld_8bits_mem8_read() : phys_mem8[mem8_loc ^ last_tlb_val]);
2011-12-17 12:16:10 +08:00
}
2011-12-23 20:24:16 +08:00
reg_idx1 = (mem8 >> 3) & 7;
last_tlb_val = (reg_idx1 & 4) << 1;
regs[reg_idx1 & 3] = (regs[reg_idx1 & 3] & ~(0xff << last_tlb_val)) | (((x) & 0xff) << last_tlb_val);
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
case 0x8b://MOV Evqp Gvqp Move
2011-12-23 20:24:16 +08:00
mem8 = phys_mem8[physmem8_ptr++];
2011-12-18 21:19:08 +08:00
if ((mem8 >> 6) == 3) {
2011-12-21 10:43:53 +08:00
x = regs[mem8 & 7];
2011-12-17 12:16:10 +08:00
} else {
2011-12-23 20:24:16 +08:00
mem8_loc = segment_translation(mem8);
2011-12-21 10:43:53 +08:00
x = (((last_tlb_val = _tlb_read_[mem8_loc >>> 12]) | mem8_loc) & 3 ? __ld_32bits_mem8_read() : phys_mem32[(mem8_loc ^ last_tlb_val) >> 2]);
2011-12-17 12:16:10 +08:00
}
2011-12-21 10:43:53 +08:00
regs[(mem8 >> 3) & 7] = x;
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
2011-12-23 20:24:16 +08:00
case 0xa0://MOV Ob AL Move byte at (seg:offset) to AL
mem8_loc = segmented_mem8_loc_for_MOV();
2011-12-21 10:43:53 +08:00
x = ld_8bits_mem8_read();
regs[0] = (regs[0] & -256) | x;
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
2011-12-23 20:24:16 +08:00
case 0xa1://MOV Ovqp rAX Move dword at (seg:offset) to EAX
mem8_loc = segmented_mem8_loc_for_MOV();
2011-12-21 10:43:53 +08:00
x = ld_32bits_mem8_read();
regs[0] = x;
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
2011-12-23 20:24:16 +08:00
case 0xa2://MOV AL Ob Move AL to (seg:offset)
mem8_loc = segmented_mem8_loc_for_MOV();
st8_mem8_write(regs[0]);
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
2011-12-23 20:24:16 +08:00
case 0xa3://MOV rAX Ovqp Move EAX to (seg:offset)
mem8_loc = segmented_mem8_loc_for_MOV();
st32_mem8_write(regs[0]);
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
case 0xd7://XLAT (DS:)[rBX+AL] AL Table Look-up Translation
mem8_loc = (regs[3] + (regs[0] & 0xff)) >> 0;
2011-12-21 10:28:01 +08:00
if (CS_flags & 0x0080)
mem8_loc &= 0xffff;
2011-12-23 20:24:16 +08:00
reg_idx1 = CS_flags & 0x000f;
if (reg_idx1 == 0)
reg_idx1 = 3;
2011-12-17 12:16:10 +08:00
else
2011-12-23 20:24:16 +08:00
reg_idx1--;
mem8_loc = (mem8_loc + cpu.segs[reg_idx1].base) >> 0;
2011-12-21 10:43:53 +08:00
x = ld_8bits_mem8_read();
2011-12-23 20:24:16 +08:00
set_word_in_register(0, x);
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
case 0xc6://MOV Ib Eb Move
2011-12-23 20:24:16 +08:00
mem8 = phys_mem8[physmem8_ptr++];
2011-12-18 21:19:08 +08:00
if ((mem8 >> 6) == 3) {
2011-12-23 20:24:16 +08:00
x = phys_mem8[physmem8_ptr++];
set_word_in_register(mem8 & 7, x);
2011-12-17 12:16:10 +08:00
} else {
2011-12-23 20:24:16 +08:00
mem8_loc = segment_translation(mem8);
x = phys_mem8[physmem8_ptr++];
st8_mem8_write(x);
2011-12-17 12:16:10 +08:00
}
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
case 0xc7://MOV Ivds Evqp Move
2011-12-23 20:24:16 +08:00
mem8 = phys_mem8[physmem8_ptr++];
2011-12-18 21:19:08 +08:00
if ((mem8 >> 6) == 3) {
2011-12-17 12:16:10 +08:00
{
2011-12-23 20:24:16 +08:00
x = phys_mem8[physmem8_ptr] | (phys_mem8[physmem8_ptr + 1] << 8) | (phys_mem8[physmem8_ptr + 2] << 16) | (phys_mem8[physmem8_ptr + 3] << 24);
physmem8_ptr += 4;
2011-12-17 12:16:10 +08:00
}
2011-12-21 10:43:53 +08:00
regs[mem8 & 7] = x;
2011-12-17 12:16:10 +08:00
} else {
2011-12-23 20:24:16 +08:00
mem8_loc = segment_translation(mem8);
2011-12-17 12:16:10 +08:00
{
2011-12-23 20:24:16 +08:00
x = phys_mem8[physmem8_ptr] | (phys_mem8[physmem8_ptr + 1] << 8) | (phys_mem8[physmem8_ptr + 2] << 16) | (phys_mem8[physmem8_ptr + 3] << 24);
physmem8_ptr += 4;
2011-12-17 12:16:10 +08:00
}
st32_mem8_write(x);
2011-12-17 12:16:10 +08:00
}
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
case 0x91://(90+r) XCHG r16/32 eAX Exchange Register/Memory with Register
2011-12-17 12:16:10 +08:00
case 0x92:
case 0x93:
case 0x94:
case 0x95:
case 0x96:
case 0x97:
2011-12-23 20:24:16 +08:00
reg_idx1 = OPbyte & 7;
2011-12-21 10:43:53 +08:00
x = regs[0];
2011-12-23 20:24:16 +08:00
regs[0] = regs[reg_idx1];
regs[reg_idx1] = x;
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
2011-12-22 13:04:09 +08:00
case 0x86://XCHG Gb Exchange Register/Memory with Register
2011-12-23 20:24:16 +08:00
mem8 = phys_mem8[physmem8_ptr++];
reg_idx1 = (mem8 >> 3) & 7;
2011-12-18 21:19:08 +08:00
if ((mem8 >> 6) == 3) {
2011-12-23 20:24:16 +08:00
reg_idx0 = mem8 & 7;
x = (regs[reg_idx0 & 3] >> ((reg_idx0 & 4) << 1));
set_word_in_register(reg_idx0, (regs[reg_idx1 & 3] >> ((reg_idx1 & 4) << 1)));
2011-12-17 12:16:10 +08:00
} else {
2011-12-23 20:24:16 +08:00
mem8_loc = segment_translation(mem8);
2011-12-21 10:43:53 +08:00
x = ld_8bits_mem8_write();
2011-12-23 20:24:16 +08:00
st8_mem8_write((regs[reg_idx1 & 3] >> ((reg_idx1 & 4) << 1)));
2011-12-17 12:16:10 +08:00
}
2011-12-23 20:24:16 +08:00
set_word_in_register(reg_idx1, x);
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
2011-12-22 13:04:09 +08:00
case 0x87://XCHG Gvqp Exchange Register/Memory with Register
2011-12-23 20:24:16 +08:00
mem8 = phys_mem8[physmem8_ptr++];
reg_idx1 = (mem8 >> 3) & 7;
2011-12-18 21:19:08 +08:00
if ((mem8 >> 6) == 3) {
2011-12-23 20:24:16 +08:00
reg_idx0 = mem8 & 7;
x = regs[reg_idx0];
regs[reg_idx0] = regs[reg_idx1];
2011-12-17 12:16:10 +08:00
} else {
2011-12-23 20:24:16 +08:00
mem8_loc = segment_translation(mem8);
2011-12-21 10:43:53 +08:00
x = ld_32bits_mem8_write();
2011-12-23 20:24:16 +08:00
st32_mem8_write(regs[reg_idx1]);
2011-12-17 12:16:10 +08:00
}
2011-12-23 20:24:16 +08:00
regs[reg_idx1] = x;
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
case 0x8e://MOV Ew Sw Move
2011-12-23 20:24:16 +08:00
mem8 = phys_mem8[physmem8_ptr++];
reg_idx1 = (mem8 >> 3) & 7;
if (reg_idx1 >= 6 || reg_idx1 == 1)
abort(6);
2011-12-18 21:19:08 +08:00
if ((mem8 >> 6) == 3) {
2011-12-21 10:43:53 +08:00
x = regs[mem8 & 7] & 0xffff;
2011-12-17 12:16:10 +08:00
} else {
2011-12-23 20:24:16 +08:00
mem8_loc = segment_translation(mem8);
2011-12-21 10:43:53 +08:00
x = ld_16bits_mem8_read();
2011-12-17 12:16:10 +08:00
}
2011-12-23 20:24:16 +08:00
Ie(reg_idx1, x);
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
case 0x8c://MOV Sw Mw Move
2011-12-23 20:24:16 +08:00
mem8 = phys_mem8[physmem8_ptr++];
reg_idx1 = (mem8 >> 3) & 7;
if (reg_idx1 >= 6)
abort(6);
2011-12-23 20:24:16 +08:00
x = cpu.segs[reg_idx1].selector;
2011-12-18 21:19:08 +08:00
if ((mem8 >> 6) == 3) {
2011-12-21 10:28:01 +08:00
if ((((CS_flags >> 8) & 1) ^ 1)) {
2011-12-21 10:43:53 +08:00
regs[mem8 & 7] = x;
2011-12-17 12:16:10 +08:00
} else {
2011-12-23 20:24:16 +08:00
set_lower_word_in_register(mem8 & 7, x);
2011-12-17 12:16:10 +08:00
}
} else {
2011-12-23 20:24:16 +08:00
mem8_loc = segment_translation(mem8);
st16_mem8_write(x);
2011-12-17 12:16:10 +08:00
}
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
case 0xc4://LES Mp ES Load Far Pointer
2011-12-17 12:16:10 +08:00
Uf(0);
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
case 0xc5://LDS Mp DS Load Far Pointer
2011-12-17 12:16:10 +08:00
Uf(3);
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
2011-12-22 13:04:09 +08:00
case 0x00://ADD Gb Eb Add
case 0x08://OR Gb Eb Logical Inclusive OR
case 0x10://ADC Gb Eb Add with Carry
case 0x18://SBB Gb Eb Integer Subtraction with Borrow
case 0x20://AND Gb Eb Logical AND
case 0x28://SUB Gb Eb Subtract
case 0x30://XOR Gb Eb Logical Exclusive OR
case 0x38://CMP Eb Compare Two Operands
2011-12-23 20:24:16 +08:00
mem8 = phys_mem8[physmem8_ptr++];
conditional_var = OPbyte >> 3;
2011-12-23 20:24:16 +08:00
reg_idx1 = (mem8 >> 3) & 7;
y = (regs[reg_idx1 & 3] >> ((reg_idx1 & 4) << 1));
2011-12-18 21:19:08 +08:00
if ((mem8 >> 6) == 3) {
2011-12-23 20:24:16 +08:00
reg_idx0 = mem8 & 7;
set_word_in_register(reg_idx0, do_8bit_math(conditional_var, (regs[reg_idx0 & 3] >> ((reg_idx0 & 4) << 1)), y));
2011-12-17 12:16:10 +08:00
} else {
2011-12-23 20:24:16 +08:00
mem8_loc = segment_translation(mem8);
if (conditional_var != 7) {
2011-12-21 10:43:53 +08:00
x = ld_8bits_mem8_write();
x = do_8bit_math(conditional_var, x, y);
st8_mem8_write(x);
2011-12-17 12:16:10 +08:00
} else {
2011-12-21 10:43:53 +08:00
x = ld_8bits_mem8_read();
do_8bit_math(7, x, y);
2011-12-17 12:16:10 +08:00
}
}
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
2011-12-22 13:04:09 +08:00
case 0x01://ADD Gvqp Evqp Add
2011-12-23 20:24:16 +08:00
mem8 = phys_mem8[physmem8_ptr++];
y = regs[(mem8 >> 3) & 7];
2011-12-18 21:19:08 +08:00
if ((mem8 >> 6) == 3) {
2011-12-23 20:24:16 +08:00
reg_idx0 = mem8 & 7;
2011-12-17 12:16:10 +08:00
{
_src = y;
2011-12-23 20:24:16 +08:00
_dst = regs[reg_idx0] = (regs[reg_idx0] + _src) >> 0;
2011-12-17 16:14:24 +08:00
_op = 2;
2011-12-17 12:16:10 +08:00
}
} else {
2011-12-23 20:24:16 +08:00
mem8_loc = segment_translation(mem8);
2011-12-21 10:43:53 +08:00
x = ld_32bits_mem8_write();
2011-12-17 12:16:10 +08:00
{
_src = y;
2011-12-21 10:43:53 +08:00
_dst = x = (x + _src) >> 0;
2011-12-17 16:14:24 +08:00
_op = 2;
2011-12-17 12:16:10 +08:00
}
st32_mem8_write(x);
2011-12-17 12:16:10 +08:00
}
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
2011-12-22 13:04:09 +08:00
case 0x09://OR Gvqp Evqp Logical Inclusive OR
case 0x11://ADC Gvqp Evqp Add with Carry
case 0x19://SBB Gvqp Evqp Integer Subtraction with Borrow
case 0x21://AND Gvqp Evqp Logical AND
case 0x29://SUB Gvqp Evqp Subtract
case 0x31://XOR Gvqp Evqp Logical Exclusive OR
2011-12-23 20:24:16 +08:00
mem8 = phys_mem8[physmem8_ptr++];
conditional_var = OPbyte >> 3;
y = regs[(mem8 >> 3) & 7];
2011-12-18 21:19:08 +08:00
if ((mem8 >> 6) == 3) {
2011-12-23 20:24:16 +08:00
reg_idx0 = mem8 & 7;
regs[reg_idx0] = do_32bit_math(conditional_var, regs[reg_idx0], y);
2011-12-17 12:16:10 +08:00
} else {
2011-12-23 20:24:16 +08:00
mem8_loc = segment_translation(mem8);
2011-12-21 10:43:53 +08:00
x = ld_32bits_mem8_write();
x = do_32bit_math(conditional_var, x, y);
st32_mem8_write(x);
2011-12-17 12:16:10 +08:00
}
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
2011-12-22 13:04:09 +08:00
case 0x39://CMP Evqp Compare Two Operands
2011-12-23 20:24:16 +08:00
mem8 = phys_mem8[physmem8_ptr++];
conditional_var = OPbyte >> 3;
y = regs[(mem8 >> 3) & 7];
2011-12-18 21:19:08 +08:00
if ((mem8 >> 6) == 3) {
2011-12-23 20:24:16 +08:00
reg_idx0 = mem8 & 7;
2011-12-17 12:16:10 +08:00
{
_src = y;
2011-12-23 20:24:16 +08:00
_dst = (regs[reg_idx0] - _src) >> 0;
2011-12-17 16:14:24 +08:00
_op = 8;
2011-12-17 12:16:10 +08:00
}
} else {
2011-12-23 20:24:16 +08:00
mem8_loc = segment_translation(mem8);
2011-12-21 10:43:53 +08:00
x = ld_32bits_mem8_read();
2011-12-17 12:16:10 +08:00
{
_src = y;
2011-12-21 10:43:53 +08:00
_dst = (x - _src) >> 0;
2011-12-17 16:14:24 +08:00
_op = 8;
2011-12-17 12:16:10 +08:00
}
}
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
2011-12-22 13:04:09 +08:00
case 0x02://ADD Eb Gb Add
case 0x0a://OR Eb Gb Logical Inclusive OR
2011-12-22 13:04:09 +08:00
case 0x12://ADC Eb Gb Add with Carry
case 0x1a://SBB Eb Gb Integer Subtraction with Borrow
2011-12-22 13:04:09 +08:00
case 0x22://AND Eb Gb Logical AND
case 0x2a://SUB Eb Gb Subtract
2011-12-22 13:04:09 +08:00
case 0x32://XOR Eb Gb Logical Exclusive OR
case 0x3a://CMP Gb Compare Two Operands
2011-12-23 20:24:16 +08:00
mem8 = phys_mem8[physmem8_ptr++];
conditional_var = OPbyte >> 3;
2011-12-23 20:24:16 +08:00
reg_idx1 = (mem8 >> 3) & 7;
2011-12-18 21:19:08 +08:00
if ((mem8 >> 6) == 3) {
2011-12-23 20:24:16 +08:00
reg_idx0 = mem8 & 7;
y = (regs[reg_idx0 & 3] >> ((reg_idx0 & 4) << 1));
2011-12-17 12:16:10 +08:00
} else {
2011-12-23 20:24:16 +08:00
mem8_loc = segment_translation(mem8);
y = ld_8bits_mem8_read();
2011-12-17 12:16:10 +08:00
}
2011-12-23 20:24:16 +08:00
set_word_in_register(reg_idx1, do_8bit_math(conditional_var, (regs[reg_idx1 & 3] >> ((reg_idx1 & 4) << 1)), y));
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
2011-12-22 13:04:09 +08:00
case 0x03://ADD Evqp Gvqp Add
2011-12-23 20:24:16 +08:00
mem8 = phys_mem8[physmem8_ptr++];
reg_idx1 = (mem8 >> 3) & 7;
2011-12-18 21:19:08 +08:00
if ((mem8 >> 6) == 3) {
y = regs[mem8 & 7];
2011-12-17 12:16:10 +08:00
} else {
2011-12-23 20:24:16 +08:00
mem8_loc = segment_translation(mem8);
y = ld_32bits_mem8_read();
2011-12-17 12:16:10 +08:00
}
{
_src = y;
2011-12-23 20:24:16 +08:00
_dst = regs[reg_idx1] = (regs[reg_idx1] + _src) >> 0;
2011-12-17 16:14:24 +08:00
_op = 2;
2011-12-17 12:16:10 +08:00
}
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
case 0x0b://OR Evqp Gvqp Logical Inclusive OR
2011-12-22 13:04:09 +08:00
case 0x13://ADC Evqp Gvqp Add with Carry
case 0x1b://SBB Evqp Gvqp Integer Subtraction with Borrow
2011-12-22 13:04:09 +08:00
case 0x23://AND Evqp Gvqp Logical AND
case 0x2b://SUB Evqp Gvqp Subtract
2011-12-22 13:04:09 +08:00
case 0x33://XOR Evqp Gvqp Logical Exclusive OR
2011-12-23 20:24:16 +08:00
mem8 = phys_mem8[physmem8_ptr++];
conditional_var = OPbyte >> 3;
2011-12-23 20:24:16 +08:00
reg_idx1 = (mem8 >> 3) & 7;
2011-12-18 21:19:08 +08:00
if ((mem8 >> 6) == 3) {
y = regs[mem8 & 7];
2011-12-17 12:16:10 +08:00
} else {
2011-12-23 20:24:16 +08:00
mem8_loc = segment_translation(mem8);
y = ld_32bits_mem8_read();
2011-12-17 12:16:10 +08:00
}
2011-12-23 20:24:16 +08:00
regs[reg_idx1] = do_32bit_math(conditional_var, regs[reg_idx1], y);
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
case 0x3b://CMP Gvqp Compare Two Operands
2011-12-23 20:24:16 +08:00
mem8 = phys_mem8[physmem8_ptr++];
conditional_var = OPbyte >> 3;
2011-12-23 20:24:16 +08:00
reg_idx1 = (mem8 >> 3) & 7;
2011-12-18 21:19:08 +08:00
if ((mem8 >> 6) == 3) {
y = regs[mem8 & 7];
2011-12-17 12:16:10 +08:00
} else {
2011-12-23 20:24:16 +08:00
mem8_loc = segment_translation(mem8);
y = ld_32bits_mem8_read();
2011-12-17 12:16:10 +08:00
}
{
_src = y;
2011-12-23 20:24:16 +08:00
_dst = (regs[reg_idx1] - _src) >> 0;
2011-12-17 16:14:24 +08:00
_op = 8;
2011-12-17 12:16:10 +08:00
}
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
2011-12-22 13:04:09 +08:00
case 0x04://ADD Ib AL Add
case 0x0c://OR Ib AL Logical Inclusive OR
2011-12-22 13:04:09 +08:00
case 0x14://ADC Ib AL Add with Carry
case 0x1c://SBB Ib AL Integer Subtraction with Borrow
2011-12-22 13:04:09 +08:00
case 0x24://AND Ib AL Logical AND
case 0x2c://SUB Ib AL Subtract
2011-12-22 13:04:09 +08:00
case 0x34://XOR Ib AL Logical Exclusive OR
case 0x3c://CMP AL Compare Two Operands
2011-12-23 20:24:16 +08:00
y = phys_mem8[physmem8_ptr++];
conditional_var = OPbyte >> 3;
2011-12-23 20:24:16 +08:00
set_word_in_register(0, do_8bit_math(conditional_var, regs[0] & 0xff, y));
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
2011-12-22 13:04:09 +08:00
case 0x05://ADD Ivds rAX Add
2011-12-17 12:16:10 +08:00
{
2011-12-23 20:24:16 +08:00
y = phys_mem8[physmem8_ptr] | (phys_mem8[physmem8_ptr + 1] << 8) | (phys_mem8[physmem8_ptr + 2] << 16) | (phys_mem8[physmem8_ptr + 3] << 24);
physmem8_ptr += 4;
2011-12-17 12:16:10 +08:00
}
{
_src = y;
2011-12-17 16:14:24 +08:00
_dst = regs[0] = (regs[0] + _src) >> 0;
_op = 2;
2011-12-17 12:16:10 +08:00
}
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
case 0x0d://OR Ivds rAX Logical Inclusive OR
2011-12-22 13:04:09 +08:00
case 0x15://ADC Ivds rAX Add with Carry
case 0x1d://SBB Ivds rAX Integer Subtraction with Borrow
2011-12-22 13:04:09 +08:00
case 0x25://AND Ivds rAX Logical AND
case 0x2d://SUB Ivds rAX Subtract
2011-12-17 12:16:10 +08:00
{
2011-12-23 20:24:16 +08:00
y = phys_mem8[physmem8_ptr] | (phys_mem8[physmem8_ptr + 1] << 8) | (phys_mem8[physmem8_ptr + 2] << 16) | (phys_mem8[physmem8_ptr + 3] << 24);
physmem8_ptr += 4;
2011-12-17 12:16:10 +08:00
}
conditional_var = OPbyte >> 3;
regs[0] = do_32bit_math(conditional_var, regs[0], y);
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
2011-12-22 13:04:09 +08:00
case 0x35://XOR Ivds rAX Logical Exclusive OR
2011-12-17 12:16:10 +08:00
{
2011-12-23 20:24:16 +08:00
y = phys_mem8[physmem8_ptr] | (phys_mem8[physmem8_ptr + 1] << 8) | (phys_mem8[physmem8_ptr + 2] << 16) | (phys_mem8[physmem8_ptr + 3] << 24);
physmem8_ptr += 4;
2011-12-17 12:16:10 +08:00
}
{
_dst = regs[0] = regs[0] ^ y;
2011-12-17 16:14:24 +08:00
_op = 14;
2011-12-17 12:16:10 +08:00
}
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
case 0x3d://CMP rAX Compare Two Operands
2011-12-17 12:16:10 +08:00
{
2011-12-23 20:24:16 +08:00
y = phys_mem8[physmem8_ptr] | (phys_mem8[physmem8_ptr + 1] << 8) | (phys_mem8[physmem8_ptr + 2] << 16) | (phys_mem8[physmem8_ptr + 3] << 24);
physmem8_ptr += 4;
2011-12-17 12:16:10 +08:00
}
{
_src = y;
2011-12-17 16:14:24 +08:00
_dst = (regs[0] - _src) >> 0;
_op = 8;
2011-12-17 12:16:10 +08:00
}
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
2011-12-22 13:04:09 +08:00
case 0x80://ADD Ib Eb Add
case 0x82://ADD Ib Eb Add
2011-12-23 20:24:16 +08:00
mem8 = phys_mem8[physmem8_ptr++];
conditional_var = (mem8 >> 3) & 7;
2011-12-18 21:19:08 +08:00
if ((mem8 >> 6) == 3) {
2011-12-23 20:24:16 +08:00
reg_idx0 = mem8 & 7;
y = phys_mem8[physmem8_ptr++];
set_word_in_register(reg_idx0, do_8bit_math(conditional_var, (regs[reg_idx0 & 3] >> ((reg_idx0 & 4) << 1)), y));
2011-12-17 12:16:10 +08:00
} else {
2011-12-23 20:24:16 +08:00
mem8_loc = segment_translation(mem8);
y = phys_mem8[physmem8_ptr++];
if (conditional_var != 7) {
2011-12-21 10:43:53 +08:00
x = ld_8bits_mem8_write();
x = do_8bit_math(conditional_var, x, y);
st8_mem8_write(x);
2011-12-17 12:16:10 +08:00
} else {
2011-12-21 10:43:53 +08:00
x = ld_8bits_mem8_read();
do_8bit_math(7, x, y);
2011-12-17 12:16:10 +08:00
}
}
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
2011-12-22 13:04:09 +08:00
case 0x81://ADD Ivds Evqp Add
2011-12-23 20:24:16 +08:00
mem8 = phys_mem8[physmem8_ptr++];
conditional_var = (mem8 >> 3) & 7;
if (conditional_var == 7) {
2011-12-18 21:19:08 +08:00
if ((mem8 >> 6) == 3) {
2011-12-21 10:43:53 +08:00
x = regs[mem8 & 7];
2011-12-17 12:16:10 +08:00
} else {
2011-12-23 20:24:16 +08:00
mem8_loc = segment_translation(mem8);
2011-12-21 10:43:53 +08:00
x = ld_32bits_mem8_read();
2011-12-17 12:16:10 +08:00
}
{
2011-12-23 20:24:16 +08:00
y = phys_mem8[physmem8_ptr] | (phys_mem8[physmem8_ptr + 1] << 8) | (phys_mem8[physmem8_ptr + 2] << 16) | (phys_mem8[physmem8_ptr + 3] << 24);
physmem8_ptr += 4;
2011-12-17 12:16:10 +08:00
}
{
_src = y;
2011-12-21 10:43:53 +08:00
_dst = (x - _src) >> 0;
2011-12-17 16:14:24 +08:00
_op = 8;
2011-12-17 12:16:10 +08:00
}
} else {
2011-12-18 21:19:08 +08:00
if ((mem8 >> 6) == 3) {
2011-12-23 20:24:16 +08:00
reg_idx0 = mem8 & 7;
2011-12-17 12:16:10 +08:00
{
2011-12-23 20:24:16 +08:00
y = phys_mem8[physmem8_ptr] | (phys_mem8[physmem8_ptr + 1] << 8) | (phys_mem8[physmem8_ptr + 2] << 16) | (phys_mem8[physmem8_ptr + 3] << 24);
physmem8_ptr += 4;
2011-12-17 12:16:10 +08:00
}
2011-12-23 20:24:16 +08:00
regs[reg_idx0] = do_32bit_math(conditional_var, regs[reg_idx0], y);
2011-12-17 12:16:10 +08:00
} else {
2011-12-23 20:24:16 +08:00
mem8_loc = segment_translation(mem8);
2011-12-17 12:16:10 +08:00
{
2011-12-23 20:24:16 +08:00
y = phys_mem8[physmem8_ptr] | (phys_mem8[physmem8_ptr + 1] << 8) | (phys_mem8[physmem8_ptr + 2] << 16) | (phys_mem8[physmem8_ptr + 3] << 24);
physmem8_ptr += 4;
2011-12-17 12:16:10 +08:00
}
2011-12-21 10:43:53 +08:00
x = ld_32bits_mem8_write();
x = do_32bit_math(conditional_var, x, y);
st32_mem8_write(x);
2011-12-17 12:16:10 +08:00
}
}
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
2011-12-22 13:04:09 +08:00
case 0x83://ADD Ibs Evqp Add
2011-12-23 20:24:16 +08:00
mem8 = phys_mem8[physmem8_ptr++];
conditional_var = (mem8 >> 3) & 7;
if (conditional_var == 7) {
2011-12-18 21:19:08 +08:00
if ((mem8 >> 6) == 3) {
2011-12-21 10:43:53 +08:00
x = regs[mem8 & 7];
2011-12-17 12:16:10 +08:00
} else {
2011-12-23 20:24:16 +08:00
mem8_loc = segment_translation(mem8);
2011-12-21 10:43:53 +08:00
x = ld_32bits_mem8_read();
2011-12-17 12:16:10 +08:00
}
2011-12-23 20:24:16 +08:00
y = ((phys_mem8[physmem8_ptr++] << 24) >> 24);
2011-12-17 12:16:10 +08:00
{
_src = y;
2011-12-21 10:43:53 +08:00
_dst = (x - _src) >> 0;
2011-12-17 16:14:24 +08:00
_op = 8;
2011-12-17 12:16:10 +08:00
}
} else {
2011-12-18 21:19:08 +08:00
if ((mem8 >> 6) == 3) {
2011-12-23 20:24:16 +08:00
reg_idx0 = mem8 & 7;
y = ((phys_mem8[physmem8_ptr++] << 24) >> 24);
regs[reg_idx0] = do_32bit_math(conditional_var, regs[reg_idx0], y);
2011-12-17 12:16:10 +08:00
} else {
2011-12-23 20:24:16 +08:00
mem8_loc = segment_translation(mem8);
y = ((phys_mem8[physmem8_ptr++] << 24) >> 24);
2011-12-21 10:43:53 +08:00
x = ld_32bits_mem8_write();
x = do_32bit_math(conditional_var, x, y);
st32_mem8_write(x);
2011-12-17 12:16:10 +08:00
}
}
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
2011-12-22 13:04:09 +08:00
case 0x40://INC Zv Increment by 1
case 0x41://REX.B Extension of r/m field, base field, or opcode reg field
case 0x42://REX.X Extension of SIB index field
case 0x43://REX.XB REX.X and REX.B combination
case 0x44://REX.R Extension of ModR/M reg field
case 0x45://REX.RB REX.R and REX.B combination
case 0x46://REX.RX REX.R and REX.X combination
case 0x47://REX.RXB REX.R, REX.X and REX.B combination
2011-12-23 20:24:16 +08:00
reg_idx1 = OPbyte & 7;
2011-12-17 12:16:10 +08:00
{
2011-12-17 16:14:24 +08:00
if (_op < 25) {
2011-12-17 16:20:47 +08:00
_op2 = _op;
_dst2 = _dst;
2011-12-17 12:16:10 +08:00
}
2011-12-23 20:24:16 +08:00
regs[reg_idx1] = _dst = (regs[reg_idx1] + 1) >> 0;
2011-12-17 16:14:24 +08:00
_op = 27;
2011-12-17 12:16:10 +08:00
}
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
2011-12-22 13:04:09 +08:00
case 0x48://DEC Zv Decrement by 1
case 0x49://REX.WB REX.W and REX.B combination
case 0x4a://REX.WX REX.W and REX.X combination
case 0x4b://REX.WXB REX.W, REX.X and REX.B combination
case 0x4c://REX.WR REX.W and REX.R combination
case 0x4d://REX.WRB REX.W, REX.R and REX.B combination
case 0x4e://REX.WRX REX.W, REX.R and REX.X combination
case 0x4f://REX.WRXB REX.W, REX.R, REX.X and REX.B combination
2011-12-23 20:24:16 +08:00
reg_idx1 = OPbyte & 7;
2011-12-17 12:16:10 +08:00
{
2011-12-17 16:14:24 +08:00
if (_op < 25) {
2011-12-17 16:20:47 +08:00
_op2 = _op;
_dst2 = _dst;
2011-12-17 12:16:10 +08:00
}
2011-12-23 20:24:16 +08:00
regs[reg_idx1] = _dst = (regs[reg_idx1] - 1) >> 0;
2011-12-17 16:14:24 +08:00
_op = 30;
2011-12-17 12:16:10 +08:00
}
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
case 0x6b://IMUL Evqp Gvqp Signed Multiply
2011-12-23 20:24:16 +08:00
mem8 = phys_mem8[physmem8_ptr++];
reg_idx1 = (mem8 >> 3) & 7;
2011-12-18 21:19:08 +08:00
if ((mem8 >> 6) == 3) {
y = regs[mem8 & 7];
2011-12-17 12:16:10 +08:00
} else {
2011-12-23 20:24:16 +08:00
mem8_loc = segment_translation(mem8);
y = ld_32bits_mem8_read();
2011-12-17 12:16:10 +08:00
}
2011-12-23 20:24:16 +08:00
z = ((phys_mem8[physmem8_ptr++] << 24) >> 24);
regs[reg_idx1] = Wc(y, z);
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
2011-12-22 13:04:09 +08:00
case 0x69://IMUL Evqp Gvqp Signed Multiply
2011-12-23 20:24:16 +08:00
mem8 = phys_mem8[physmem8_ptr++];
reg_idx1 = (mem8 >> 3) & 7;
2011-12-18 21:19:08 +08:00
if ((mem8 >> 6) == 3) {
y = regs[mem8 & 7];
2011-12-17 12:16:10 +08:00
} else {
2011-12-23 20:24:16 +08:00
mem8_loc = segment_translation(mem8);
y = ld_32bits_mem8_read();
2011-12-17 12:16:10 +08:00
}
{
2011-12-23 20:24:16 +08:00
z = phys_mem8[physmem8_ptr] | (phys_mem8[physmem8_ptr + 1] << 8) | (phys_mem8[physmem8_ptr + 2] << 16) | (phys_mem8[physmem8_ptr + 3] << 24);
physmem8_ptr += 4;
2011-12-17 12:16:10 +08:00
}
2011-12-23 20:24:16 +08:00
regs[reg_idx1] = Wc(y, z);
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
2011-12-22 13:04:09 +08:00
case 0x84://TEST Eb Logical Compare
2011-12-23 20:24:16 +08:00
mem8 = phys_mem8[physmem8_ptr++];
2011-12-18 21:19:08 +08:00
if ((mem8 >> 6) == 3) {
2011-12-23 20:24:16 +08:00
reg_idx0 = mem8 & 7;
x = (regs[reg_idx0 & 3] >> ((reg_idx0 & 4) << 1));
2011-12-17 12:16:10 +08:00
} else {
2011-12-23 20:24:16 +08:00
mem8_loc = segment_translation(mem8);
2011-12-21 10:43:53 +08:00
x = ld_8bits_mem8_read();
2011-12-17 12:16:10 +08:00
}
2011-12-23 20:24:16 +08:00
reg_idx1 = (mem8 >> 3) & 7;
y = (regs[reg_idx1 & 3] >> ((reg_idx1 & 4) << 1));
2011-12-17 12:16:10 +08:00
{
_dst = (((x & y) << 24) >> 24);
2011-12-17 16:14:24 +08:00
_op = 12;
2011-12-17 12:16:10 +08:00
}
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
2011-12-22 13:04:09 +08:00
case 0x85://TEST Evqp Logical Compare
2011-12-23 20:24:16 +08:00
mem8 = phys_mem8[physmem8_ptr++];
2011-12-18 21:19:08 +08:00
if ((mem8 >> 6) == 3) {
2011-12-21 10:43:53 +08:00
x = regs[mem8 & 7];
2011-12-17 12:16:10 +08:00
} else {
2011-12-23 20:24:16 +08:00
mem8_loc = segment_translation(mem8);
2011-12-21 10:43:53 +08:00
x = ld_32bits_mem8_read();
2011-12-17 12:16:10 +08:00
}
y = regs[(mem8 >> 3) & 7];
2011-12-17 12:16:10 +08:00
{
_dst = x & y;
2011-12-17 16:14:24 +08:00
_op = 14;
2011-12-17 12:16:10 +08:00
}
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
case 0xa8://TEST AL Logical Compare
2011-12-23 20:24:16 +08:00
y = phys_mem8[physmem8_ptr++];
2011-12-17 12:16:10 +08:00
{
_dst = (((regs[0] & y) << 24) >> 24);
2011-12-17 16:14:24 +08:00
_op = 12;
2011-12-17 12:16:10 +08:00
}
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
case 0xa9://TEST rAX Logical Compare
2011-12-17 12:16:10 +08:00
{
2011-12-23 20:24:16 +08:00
y = phys_mem8[physmem8_ptr] | (phys_mem8[physmem8_ptr + 1] << 8) | (phys_mem8[physmem8_ptr + 2] << 16) | (phys_mem8[physmem8_ptr + 3] << 24);
physmem8_ptr += 4;
2011-12-17 12:16:10 +08:00
}
{
_dst = regs[0] & y;
2011-12-17 16:14:24 +08:00
_op = 14;
2011-12-17 12:16:10 +08:00
}
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
case 0xf6://TEST Eb Logical Compare
2011-12-23 20:24:16 +08:00
mem8 = phys_mem8[physmem8_ptr++];
conditional_var = (mem8 >> 3) & 7;
switch (conditional_var) {
2011-12-17 12:16:10 +08:00
case 0:
2011-12-18 21:19:08 +08:00
if ((mem8 >> 6) == 3) {
2011-12-23 20:24:16 +08:00
reg_idx0 = mem8 & 7;
x = (regs[reg_idx0 & 3] >> ((reg_idx0 & 4) << 1));
2011-12-17 12:16:10 +08:00
} else {
2011-12-23 20:24:16 +08:00
mem8_loc = segment_translation(mem8);
2011-12-21 10:43:53 +08:00
x = ld_8bits_mem8_read();
2011-12-17 12:16:10 +08:00
}
2011-12-23 20:24:16 +08:00
y = phys_mem8[physmem8_ptr++];
2011-12-17 12:16:10 +08:00
{
_dst = (((x & y) << 24) >> 24);
2011-12-17 16:14:24 +08:00
_op = 12;
2011-12-17 12:16:10 +08:00
}
break;
case 2:
2011-12-18 21:19:08 +08:00
if ((mem8 >> 6) == 3) {
2011-12-23 20:24:16 +08:00
reg_idx0 = mem8 & 7;
set_word_in_register(reg_idx0, ~(regs[reg_idx0 & 3] >> ((reg_idx0 & 4) << 1)));
2011-12-17 12:16:10 +08:00
} else {
2011-12-23 20:24:16 +08:00
mem8_loc = segment_translation(mem8);
2011-12-21 10:43:53 +08:00
x = ld_8bits_mem8_write();
x = ~x;
st8_mem8_write(x);
2011-12-17 12:16:10 +08:00
}
break;
case 3:
2011-12-18 21:19:08 +08:00
if ((mem8 >> 6) == 3) {
2011-12-23 20:24:16 +08:00
reg_idx0 = mem8 & 7;
set_word_in_register(reg_idx0, do_8bit_math(5, 0, (regs[reg_idx0 & 3] >> ((reg_idx0 & 4) << 1))));
2011-12-17 12:16:10 +08:00
} else {
2011-12-23 20:24:16 +08:00
mem8_loc = segment_translation(mem8);
2011-12-21 10:43:53 +08:00
x = ld_8bits_mem8_write();
x = do_8bit_math(5, 0, x);
st8_mem8_write(x);
2011-12-17 12:16:10 +08:00
}
break;
case 4:
2011-12-18 21:19:08 +08:00
if ((mem8 >> 6) == 3) {
2011-12-23 20:24:16 +08:00
reg_idx0 = mem8 & 7;
x = (regs[reg_idx0 & 3] >> ((reg_idx0 & 4) << 1));
2011-12-17 12:16:10 +08:00
} else {
2011-12-23 20:24:16 +08:00
mem8_loc = segment_translation(mem8);
2011-12-21 10:43:53 +08:00
x = ld_8bits_mem8_read();
2011-12-17 12:16:10 +08:00
}
2011-12-23 20:24:16 +08:00
set_lower_word_in_register(0, Oc(regs[0], x));
2011-12-17 12:16:10 +08:00
break;
case 5:
2011-12-18 21:19:08 +08:00
if ((mem8 >> 6) == 3) {
2011-12-23 20:24:16 +08:00
reg_idx0 = mem8 & 7;
x = (regs[reg_idx0 & 3] >> ((reg_idx0 & 4) << 1));
2011-12-17 12:16:10 +08:00
} else {
2011-12-23 20:24:16 +08:00
mem8_loc = segment_translation(mem8);
2011-12-21 10:43:53 +08:00
x = ld_8bits_mem8_read();
2011-12-17 12:16:10 +08:00
}
2011-12-23 20:24:16 +08:00
set_lower_word_in_register(0, Pc(regs[0], x));
2011-12-17 12:16:10 +08:00
break;
case 6:
2011-12-18 21:19:08 +08:00
if ((mem8 >> 6) == 3) {
2011-12-23 20:24:16 +08:00
reg_idx0 = mem8 & 7;
x = (regs[reg_idx0 & 3] >> ((reg_idx0 & 4) << 1));
2011-12-17 12:16:10 +08:00
} else {
2011-12-23 20:24:16 +08:00
mem8_loc = segment_translation(mem8);
2011-12-21 10:43:53 +08:00
x = ld_8bits_mem8_read();
2011-12-17 12:16:10 +08:00
}
2011-12-21 10:43:53 +08:00
Cc(x);
2011-12-17 12:16:10 +08:00
break;
case 7:
2011-12-18 21:19:08 +08:00
if ((mem8 >> 6) == 3) {
2011-12-23 20:24:16 +08:00
reg_idx0 = mem8 & 7;
x = (regs[reg_idx0 & 3] >> ((reg_idx0 & 4) << 1));
2011-12-17 12:16:10 +08:00
} else {
2011-12-23 20:24:16 +08:00
mem8_loc = segment_translation(mem8);
2011-12-21 10:43:53 +08:00
x = ld_8bits_mem8_read();
2011-12-17 12:16:10 +08:00
}
2011-12-21 10:43:53 +08:00
Ec(x);
2011-12-17 12:16:10 +08:00
break;
default:
abort(6);
2011-12-17 12:16:10 +08:00
}
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
case 0xf7://TEST Evqp Logical Compare
2011-12-23 20:24:16 +08:00
mem8 = phys_mem8[physmem8_ptr++];
conditional_var = (mem8 >> 3) & 7;
switch (conditional_var) {
2011-12-17 12:16:10 +08:00
case 0:
2011-12-18 21:19:08 +08:00
if ((mem8 >> 6) == 3) {
2011-12-21 10:43:53 +08:00
x = regs[mem8 & 7];
2011-12-17 12:16:10 +08:00
} else {
2011-12-23 20:24:16 +08:00
mem8_loc = segment_translation(mem8);
2011-12-21 10:43:53 +08:00
x = ld_32bits_mem8_read();
2011-12-17 12:16:10 +08:00
}
{
2011-12-23 20:24:16 +08:00
y = phys_mem8[physmem8_ptr] | (phys_mem8[physmem8_ptr + 1] << 8) | (phys_mem8[physmem8_ptr + 2] << 16) | (phys_mem8[physmem8_ptr + 3] << 24);
physmem8_ptr += 4;
2011-12-17 12:16:10 +08:00
}
{
_dst = x & y;
2011-12-17 16:14:24 +08:00
_op = 14;
2011-12-17 12:16:10 +08:00
}
break;
case 2:
2011-12-18 21:19:08 +08:00
if ((mem8 >> 6) == 3) {
2011-12-23 20:24:16 +08:00
reg_idx0 = mem8 & 7;
regs[reg_idx0] = ~regs[reg_idx0];
2011-12-17 12:16:10 +08:00
} else {
2011-12-23 20:24:16 +08:00
mem8_loc = segment_translation(mem8);
2011-12-21 10:43:53 +08:00
x = ld_32bits_mem8_write();
x = ~x;
st32_mem8_write(x);
2011-12-17 12:16:10 +08:00
}
break;
case 3:
2011-12-18 21:19:08 +08:00
if ((mem8 >> 6) == 3) {
2011-12-23 20:24:16 +08:00
reg_idx0 = mem8 & 7;
regs[reg_idx0] = do_32bit_math(5, 0, regs[reg_idx0]);
2011-12-17 12:16:10 +08:00
} else {
2011-12-23 20:24:16 +08:00
mem8_loc = segment_translation(mem8);
2011-12-21 10:43:53 +08:00
x = ld_32bits_mem8_write();
x = do_32bit_math(5, 0, x);
st32_mem8_write(x);
2011-12-17 12:16:10 +08:00
}
break;
case 4:
2011-12-18 21:19:08 +08:00
if ((mem8 >> 6) == 3) {
2011-12-21 10:43:53 +08:00
x = regs[mem8 & 7];
2011-12-17 12:16:10 +08:00
} else {
2011-12-23 20:24:16 +08:00
mem8_loc = segment_translation(mem8);
2011-12-21 10:43:53 +08:00
x = ld_32bits_mem8_read();
2011-12-17 12:16:10 +08:00
}
2011-12-21 10:43:53 +08:00
regs[0] = Vc(regs[0], x);
regs[2] = v;
2011-12-17 12:16:10 +08:00
break;
case 5:
2011-12-18 21:19:08 +08:00
if ((mem8 >> 6) == 3) {
2011-12-21 10:43:53 +08:00
x = regs[mem8 & 7];
2011-12-17 12:16:10 +08:00
} else {
2011-12-23 20:24:16 +08:00
mem8_loc = segment_translation(mem8);
2011-12-21 10:43:53 +08:00
x = ld_32bits_mem8_read();
2011-12-17 12:16:10 +08:00
}
2011-12-21 10:43:53 +08:00
regs[0] = Wc(regs[0], x);
regs[2] = v;
2011-12-17 12:16:10 +08:00
break;
case 6:
2011-12-18 21:19:08 +08:00
if ((mem8 >> 6) == 3) {
2011-12-21 10:43:53 +08:00
x = regs[mem8 & 7];
2011-12-17 12:16:10 +08:00
} else {
2011-12-23 20:24:16 +08:00
mem8_loc = segment_translation(mem8);
2011-12-21 10:43:53 +08:00
x = ld_32bits_mem8_read();
2011-12-17 12:16:10 +08:00
}
2011-12-21 10:43:53 +08:00
regs[0] = Hc(regs[2], regs[0], x);
regs[2] = v;
2011-12-17 12:16:10 +08:00
break;
case 7:
2011-12-18 21:19:08 +08:00
if ((mem8 >> 6) == 3) {
2011-12-21 10:43:53 +08:00
x = regs[mem8 & 7];
2011-12-17 12:16:10 +08:00
} else {
2011-12-23 20:24:16 +08:00
mem8_loc = segment_translation(mem8);
2011-12-21 10:43:53 +08:00
x = ld_32bits_mem8_read();
2011-12-17 12:16:10 +08:00
}
2011-12-21 10:43:53 +08:00
regs[0] = Lc(regs[2], regs[0], x);
regs[2] = v;
2011-12-17 12:16:10 +08:00
break;
default:
abort(6);
2011-12-17 12:16:10 +08:00
}
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
2011-12-22 13:34:05 +08:00
//Rotate and Shift ops ---------------------------------------------------------------
case 0xc0://ROL Ib Eb Rotate
2011-12-23 20:24:16 +08:00
mem8 = phys_mem8[physmem8_ptr++];
conditional_var = (mem8 >> 3) & 7;
2011-12-18 21:19:08 +08:00
if ((mem8 >> 6) == 3) {
2011-12-23 20:24:16 +08:00
y = phys_mem8[physmem8_ptr++];
reg_idx0 = mem8 & 7;
set_word_in_register(reg_idx0, shift8(conditional_var, (regs[reg_idx0 & 3] >> ((reg_idx0 & 4) << 1)), y));
2011-12-17 12:16:10 +08:00
} else {
2011-12-23 20:24:16 +08:00
mem8_loc = segment_translation(mem8);
y = phys_mem8[physmem8_ptr++];
2011-12-21 10:43:53 +08:00
x = ld_8bits_mem8_write();
x = shift8(conditional_var, x, y);
st8_mem8_write(x);
2011-12-17 12:16:10 +08:00
}
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
case 0xc1://ROL Ib Evqp Rotate
2011-12-23 20:24:16 +08:00
mem8 = phys_mem8[physmem8_ptr++];
conditional_var = (mem8 >> 3) & 7;
2011-12-18 21:19:08 +08:00
if ((mem8 >> 6) == 3) {
2011-12-23 20:24:16 +08:00
y = phys_mem8[physmem8_ptr++];
reg_idx0 = mem8 & 7;
regs[reg_idx0] = shift32(conditional_var, regs[reg_idx0], y);
2011-12-17 12:16:10 +08:00
} else {
2011-12-23 20:24:16 +08:00
mem8_loc = segment_translation(mem8);
y = phys_mem8[physmem8_ptr++];
2011-12-21 10:43:53 +08:00
x = ld_32bits_mem8_write();
2011-12-23 01:49:18 +08:00
x = shift32(conditional_var, x, y);
st32_mem8_write(x);
2011-12-17 12:16:10 +08:00
}
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
case 0xd0://ROL 1 Eb Rotate
2011-12-23 20:24:16 +08:00
mem8 = phys_mem8[physmem8_ptr++];
conditional_var = (mem8 >> 3) & 7;
2011-12-18 21:19:08 +08:00
if ((mem8 >> 6) == 3) {
2011-12-23 20:24:16 +08:00
reg_idx0 = mem8 & 7;
set_word_in_register(reg_idx0, shift8(conditional_var, (regs[reg_idx0 & 3] >> ((reg_idx0 & 4) << 1)), 1));
2011-12-17 12:16:10 +08:00
} else {
2011-12-23 20:24:16 +08:00
mem8_loc = segment_translation(mem8);
2011-12-21 10:43:53 +08:00
x = ld_8bits_mem8_write();
x = shift8(conditional_var, x, 1);
st8_mem8_write(x);
2011-12-17 12:16:10 +08:00
}
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
case 0xd1://ROL 1 Evqp Rotate
2011-12-23 20:24:16 +08:00
mem8 = phys_mem8[physmem8_ptr++];
conditional_var = (mem8 >> 3) & 7;
2011-12-18 21:19:08 +08:00
if ((mem8 >> 6) == 3) {
2011-12-23 20:24:16 +08:00
reg_idx0 = mem8 & 7;
regs[reg_idx0] = shift32(conditional_var, regs[reg_idx0], 1);
2011-12-17 12:16:10 +08:00
} else {
2011-12-23 20:24:16 +08:00
mem8_loc = segment_translation(mem8);
2011-12-21 10:43:53 +08:00
x = ld_32bits_mem8_write();
2011-12-23 01:49:18 +08:00
x = shift32(conditional_var, x, 1);
st32_mem8_write(x);
2011-12-17 12:16:10 +08:00
}
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
case 0xd2://ROL CL Eb Rotate
2011-12-23 20:24:16 +08:00
mem8 = phys_mem8[physmem8_ptr++];
conditional_var = (mem8 >> 3) & 7;
y = regs[1] & 0xff;
2011-12-18 21:19:08 +08:00
if ((mem8 >> 6) == 3) {
2011-12-23 20:24:16 +08:00
reg_idx0 = mem8 & 7;
set_word_in_register(reg_idx0, shift8(conditional_var, (regs[reg_idx0 & 3] >> ((reg_idx0 & 4) << 1)), y));
2011-12-17 12:16:10 +08:00
} else {
2011-12-23 20:24:16 +08:00
mem8_loc = segment_translation(mem8);
2011-12-21 10:43:53 +08:00
x = ld_8bits_mem8_write();
x = shift8(conditional_var, x, y);
st8_mem8_write(x);
2011-12-17 12:16:10 +08:00
}
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
case 0xd3://ROL CL Evqp Rotate
2011-12-23 20:24:16 +08:00
mem8 = phys_mem8[physmem8_ptr++];
conditional_var = (mem8 >> 3) & 7;
y = regs[1] & 0xff;
2011-12-18 21:19:08 +08:00
if ((mem8 >> 6) == 3) {
2011-12-23 20:24:16 +08:00
reg_idx0 = mem8 & 7;
regs[reg_idx0] = shift32(conditional_var, regs[reg_idx0], y);
2011-12-17 12:16:10 +08:00
} else {
2011-12-23 20:24:16 +08:00
mem8_loc = segment_translation(mem8);
2011-12-21 10:43:53 +08:00
x = ld_32bits_mem8_write();
2011-12-23 01:49:18 +08:00
x = shift32(conditional_var, x, y);
st32_mem8_write(x);
2011-12-17 12:16:10 +08:00
}
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
2011-12-22 13:04:09 +08:00
case 0x98://CBW AL AX Convert Byte to Word
2011-12-17 16:08:25 +08:00
regs[0] = (regs[0] << 16) >> 16;
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
2011-12-22 13:04:09 +08:00
case 0x99://CWD AX DX Convert Word to Doubleword
2011-12-17 16:08:25 +08:00
regs[2] = regs[0] >> 31;
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
2011-12-22 13:04:09 +08:00
case 0x50://PUSH Zv SS:[rSP] Push Word, Doubleword or Quadword Onto the Stack
2011-12-17 12:16:10 +08:00
case 0x51:
case 0x52:
case 0x53:
case 0x54:
case 0x55:
case 0x56:
case 0x57:
2011-12-21 10:43:53 +08:00
x = regs[OPbyte & 7];
2011-12-21 10:28:01 +08:00
if (FS_usage_flag) {
mem8_loc = (regs[4] - 4) >> 0;
2011-12-17 12:16:10 +08:00
{
2011-12-21 10:43:53 +08:00
last_tlb_val = _tlb_write_[mem8_loc >>> 12];
if ((last_tlb_val | mem8_loc) & 3) {
__st32_mem8_write(x);
2011-12-17 12:16:10 +08:00
} else {
2011-12-21 10:43:53 +08:00
phys_mem32[(mem8_loc ^ last_tlb_val) >> 2] = x;
2011-12-17 12:16:10 +08:00
}
}
regs[4] = mem8_loc;
2011-12-17 12:16:10 +08:00
} else {
2011-12-21 10:43:53 +08:00
xd(x);
2011-12-17 12:16:10 +08:00
}
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
2011-12-22 13:04:09 +08:00
case 0x58://POP SS:[rSP] Zv Pop a Value from the Stack
2011-12-17 12:16:10 +08:00
case 0x59:
case 0x5a:
case 0x5b:
case 0x5c:
case 0x5d:
case 0x5e:
case 0x5f:
2011-12-21 10:28:01 +08:00
if (FS_usage_flag) {
mem8_loc = regs[4];
2011-12-21 10:43:53 +08:00
x = (((last_tlb_val = _tlb_read_[mem8_loc >>> 12]) | mem8_loc) & 3 ? __ld_32bits_mem8_read() : phys_mem32[(mem8_loc ^ last_tlb_val) >> 2]);
regs[4] = (mem8_loc + 4) >> 0;
2011-12-17 12:16:10 +08:00
} else {
2011-12-21 10:43:53 +08:00
x = Ad();
2011-12-17 12:16:10 +08:00
Bd();
}
2011-12-21 10:43:53 +08:00
regs[OPbyte & 7] = x;
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
2011-12-22 13:34:05 +08:00
2011-12-22 13:04:09 +08:00
case 0x60://PUSHA AX SS:[rSP] Push All General-Purpose Registers
2011-12-17 12:16:10 +08:00
Kf();
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
2011-12-22 13:04:09 +08:00
case 0x61://POPA SS:[rSP] DI Pop All General-Purpose Registers
2011-12-17 12:16:10 +08:00
Mf();
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
case 0x8f://POP SS:[rSP] Ev Pop a Value from the Stack
2011-12-23 20:24:16 +08:00
mem8 = phys_mem8[physmem8_ptr++];
2011-12-18 21:19:08 +08:00
if ((mem8 >> 6) == 3) {
2011-12-21 10:43:53 +08:00
x = Ad();
2011-12-17 12:16:10 +08:00
Bd();
2011-12-21 10:43:53 +08:00
regs[mem8 & 7] = x;
2011-12-17 12:16:10 +08:00
} else {
2011-12-21 10:43:53 +08:00
x = Ad();
y = regs[4];
2011-12-17 12:16:10 +08:00
Bd();
z = regs[4];
2011-12-23 20:24:16 +08:00
mem8_loc = segment_translation(mem8);
regs[4] = y;
st32_mem8_write(x);
regs[4] = z;
2011-12-17 12:16:10 +08:00
}
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
2011-12-22 13:04:09 +08:00
case 0x68://PUSH Ivs SS:[rSP] Push Word, Doubleword or Quadword Onto the Stack
2011-12-17 12:16:10 +08:00
{
2011-12-23 20:24:16 +08:00
x = phys_mem8[physmem8_ptr] | (phys_mem8[physmem8_ptr + 1] << 8) | (phys_mem8[physmem8_ptr + 2] << 16) | (phys_mem8[physmem8_ptr + 3] << 24);
physmem8_ptr += 4;
2011-12-17 12:16:10 +08:00
}
2011-12-21 10:28:01 +08:00
if (FS_usage_flag) {
mem8_loc = (regs[4] - 4) >> 0;
st32_mem8_write(x);
regs[4] = mem8_loc;
2011-12-17 12:16:10 +08:00
} else {
2011-12-21 10:43:53 +08:00
xd(x);
2011-12-17 12:16:10 +08:00
}
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
case 0x6a://PUSH Ibss SS:[rSP] Push Word, Doubleword or Quadword Onto the Stack
2011-12-23 20:24:16 +08:00
x = ((phys_mem8[physmem8_ptr++] << 24) >> 24);
2011-12-21 10:28:01 +08:00
if (FS_usage_flag) {
mem8_loc = (regs[4] - 4) >> 0;
st32_mem8_write(x);
regs[4] = mem8_loc;
2011-12-17 12:16:10 +08:00
} else {
2011-12-21 10:43:53 +08:00
xd(x);
2011-12-17 12:16:10 +08:00
}
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
case 0xc8://ENTER Iw SS:[rSP] Make Stack Frame for Procedure Parameters
2011-12-17 12:16:10 +08:00
Tf();
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
case 0xc9://LEAVE SS:[rSP] eBP High Level Procedure Exit
2011-12-21 10:28:01 +08:00
if (FS_usage_flag) {
mem8_loc = regs[5];
2011-12-21 10:43:53 +08:00
x = ld_32bits_mem8_read();
regs[5] = x;
regs[4] = (mem8_loc + 4) >> 0;
2011-12-17 12:16:10 +08:00
} else {
Of();
}
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
case 0x9c://PUSHF Flags SS:[rSP] Push FLAGS Register onto the Stack
iopl = (cpu.eflags >> 12) & 3;
if ((cpu.eflags & 0x00020000) && iopl != 3)
abort(13);
2011-12-21 10:43:53 +08:00
x = id() & ~(0x00020000 | 0x00010000);
2011-12-21 10:28:01 +08:00
if ((((CS_flags >> 8) & 1) ^ 1)) {
2011-12-21 10:43:53 +08:00
xd(x);
2011-12-17 12:16:10 +08:00
} else {
2011-12-21 10:43:53 +08:00
vd(x);
2011-12-17 12:16:10 +08:00
}
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
case 0x9d://POPF SS:[rSP] Flags Pop Stack into FLAGS Register
iopl = (cpu.eflags >> 12) & 3;
if ((cpu.eflags & 0x00020000) && iopl != 3)
abort(13);
2011-12-21 10:28:01 +08:00
if ((((CS_flags >> 8) & 1) ^ 1)) {
2011-12-21 10:43:53 +08:00
x = Ad();
2011-12-17 12:16:10 +08:00
Bd();
y = -1;
2011-12-17 12:16:10 +08:00
} else {
2011-12-21 10:43:53 +08:00
x = yd();
2011-12-17 12:16:10 +08:00
zd();
y = 0xffff;
2011-12-17 12:16:10 +08:00
}
z = (0x00000100 | 0x00040000 | 0x00200000 | 0x00004000);
2011-12-17 13:38:46 +08:00
if (cpu.cpl == 0) {
z |= 0x00000200 | 0x00003000;
2011-12-17 12:16:10 +08:00
} else {
if (cpu.cpl <= iopl)
z |= 0x00000200;
2011-12-17 12:16:10 +08:00
}
kd(x, z & y);
2011-12-17 12:16:10 +08:00
{
2011-12-17 13:38:46 +08:00
if (cpu.hard_irq != 0 && (cpu.eflags & 0x00000200))
2011-12-23 21:44:05 +08:00
break OUTER_LOOP;
2011-12-17 12:16:10 +08:00
}
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
2011-12-22 13:04:09 +08:00
case 0x06://PUSH ES SS:[rSP] Push Word, Doubleword or Quadword Onto the Stack
case 0x0e://PUSH CS SS:[rSP] Push Word, Doubleword or Quadword Onto the Stack
2011-12-22 13:04:09 +08:00
case 0x16://PUSH SS SS:[rSP] Push Word, Doubleword or Quadword Onto the Stack
case 0x1e://PUSH DS SS:[rSP] Push Word, Doubleword or Quadword Onto the Stack
xd(cpu.segs[OPbyte >> 3].selector);
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
2011-12-22 13:04:09 +08:00
case 0x07://POP SS:[rSP] ES Pop a Value from the Stack
case 0x17://POP SS:[rSP] SS Pop a Value from the Stack
case 0x1f://POP SS:[rSP] DS Pop a Value from the Stack
Ie(OPbyte >> 3, Ad() & 0xffff);
2011-12-17 12:16:10 +08:00
Bd();
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
case 0x8d://LEA M Gvqp Load Effective Address
2011-12-23 20:24:16 +08:00
mem8 = phys_mem8[physmem8_ptr++];
2011-12-18 21:19:08 +08:00
if ((mem8 >> 6) == 3)
abort(6);
2011-12-21 10:28:01 +08:00
CS_flags = (CS_flags & ~0x000f) | (6 + 1);
2011-12-23 20:24:16 +08:00
regs[(mem8 >> 3) & 7] = segment_translation(mem8);
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
case 0xfe://INC Eb Increment by 1
2011-12-23 20:24:16 +08:00
mem8 = phys_mem8[physmem8_ptr++];
conditional_var = (mem8 >> 3) & 7;
switch (conditional_var) {
2011-12-17 12:16:10 +08:00
case 0:
2011-12-18 21:19:08 +08:00
if ((mem8 >> 6) == 3) {
2011-12-23 20:24:16 +08:00
reg_idx0 = mem8 & 7;
set_word_in_register(reg_idx0, increment_8bit((regs[reg_idx0 & 3] >> ((reg_idx0 & 4) << 1))));
2011-12-17 12:16:10 +08:00
} else {
2011-12-23 20:24:16 +08:00
mem8_loc = segment_translation(mem8);
2011-12-21 10:43:53 +08:00
x = ld_8bits_mem8_write();
2011-12-23 01:49:18 +08:00
x = increment_8bit(x);
st8_mem8_write(x);
2011-12-17 12:16:10 +08:00
}
break;
case 1:
2011-12-18 21:19:08 +08:00
if ((mem8 >> 6) == 3) {
2011-12-23 20:24:16 +08:00
reg_idx0 = mem8 & 7;
set_word_in_register(reg_idx0, decrement_8bit((regs[reg_idx0 & 3] >> ((reg_idx0 & 4) << 1))));
2011-12-17 12:16:10 +08:00
} else {
2011-12-23 20:24:16 +08:00
mem8_loc = segment_translation(mem8);
2011-12-21 10:43:53 +08:00
x = ld_8bits_mem8_write();
2011-12-23 01:49:18 +08:00
x = decrement_8bit(x);
st8_mem8_write(x);
2011-12-17 12:16:10 +08:00
}
break;
default:
abort(6);
2011-12-17 12:16:10 +08:00
}
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
case 0xff://INC Evqp Increment by 1
2011-12-23 20:24:16 +08:00
mem8 = phys_mem8[physmem8_ptr++];
conditional_var = (mem8 >> 3) & 7;
switch (conditional_var) {
2011-12-17 12:16:10 +08:00
case 0:
2011-12-18 21:19:08 +08:00
if ((mem8 >> 6) == 3) {
2011-12-23 20:24:16 +08:00
reg_idx0 = mem8 & 7;
2011-12-17 12:16:10 +08:00
{
2011-12-17 16:14:24 +08:00
if (_op < 25) {
2011-12-17 16:20:47 +08:00
_op2 = _op;
_dst2 = _dst;
2011-12-17 12:16:10 +08:00
}
2011-12-23 20:24:16 +08:00
regs[reg_idx0] = _dst = (regs[reg_idx0] + 1) >> 0;
2011-12-17 16:14:24 +08:00
_op = 27;
2011-12-17 12:16:10 +08:00
}
} else {
2011-12-23 20:24:16 +08:00
mem8_loc = segment_translation(mem8);
2011-12-21 10:43:53 +08:00
x = ld_32bits_mem8_write();
2011-12-17 12:16:10 +08:00
{
2011-12-17 16:14:24 +08:00
if (_op < 25) {
2011-12-17 16:20:47 +08:00
_op2 = _op;
_dst2 = _dst;
2011-12-17 12:16:10 +08:00
}
2011-12-21 10:43:53 +08:00
x = _dst = (x + 1) >> 0;
2011-12-17 16:14:24 +08:00
_op = 27;
2011-12-17 12:16:10 +08:00
}
st32_mem8_write(x);
2011-12-17 12:16:10 +08:00
}
break;
case 1:
2011-12-18 21:19:08 +08:00
if ((mem8 >> 6) == 3) {
2011-12-23 20:24:16 +08:00
reg_idx0 = mem8 & 7;
2011-12-17 12:16:10 +08:00
{
2011-12-17 16:14:24 +08:00
if (_op < 25) {
2011-12-17 16:20:47 +08:00
_op2 = _op;
_dst2 = _dst;
2011-12-17 12:16:10 +08:00
}
2011-12-23 20:24:16 +08:00
regs[reg_idx0] = _dst = (regs[reg_idx0] - 1) >> 0;
2011-12-17 16:14:24 +08:00
_op = 30;
2011-12-17 12:16:10 +08:00
}
} else {
2011-12-23 20:24:16 +08:00
mem8_loc = segment_translation(mem8);
2011-12-21 10:43:53 +08:00
x = ld_32bits_mem8_write();
2011-12-17 12:16:10 +08:00
{
2011-12-17 16:14:24 +08:00
if (_op < 25) {
2011-12-17 16:20:47 +08:00
_op2 = _op;
_dst2 = _dst;
2011-12-17 12:16:10 +08:00
}
2011-12-21 10:43:53 +08:00
x = _dst = (x - 1) >> 0;
2011-12-17 16:14:24 +08:00
_op = 30;
2011-12-17 12:16:10 +08:00
}
st32_mem8_write(x);
2011-12-17 12:16:10 +08:00
}
break;
case 2:
2011-12-18 21:19:08 +08:00
if ((mem8 >> 6) == 3) {
2011-12-21 10:43:53 +08:00
x = regs[mem8 & 7];
2011-12-17 12:16:10 +08:00
} else {
2011-12-23 20:24:16 +08:00
mem8_loc = segment_translation(mem8);
2011-12-21 10:43:53 +08:00
x = ld_32bits_mem8_read();
2011-12-17 12:16:10 +08:00
}
2011-12-23 20:24:16 +08:00
y = (eip + physmem8_ptr - initial_mem_ptr);
2011-12-21 10:28:01 +08:00
if (FS_usage_flag) {
mem8_loc = (regs[4] - 4) >> 0;
st32_mem8_write(y);
regs[4] = mem8_loc;
2011-12-17 12:16:10 +08:00
} else {
xd(y);
2011-12-17 12:16:10 +08:00
}
2011-12-23 20:24:16 +08:00
eip = x, physmem8_ptr = initial_mem_ptr = 0;
2011-12-17 12:16:10 +08:00
break;
case 4:
2011-12-18 21:19:08 +08:00
if ((mem8 >> 6) == 3) {
2011-12-21 10:43:53 +08:00
x = regs[mem8 & 7];
2011-12-17 12:16:10 +08:00
} else {
2011-12-23 20:24:16 +08:00
mem8_loc = segment_translation(mem8);
2011-12-21 10:43:53 +08:00
x = ld_32bits_mem8_read();
2011-12-17 12:16:10 +08:00
}
2011-12-23 20:24:16 +08:00
eip = x, physmem8_ptr = initial_mem_ptr = 0;
2011-12-17 12:16:10 +08:00
break;
case 6:
2011-12-18 21:19:08 +08:00
if ((mem8 >> 6) == 3) {
2011-12-21 10:43:53 +08:00
x = regs[mem8 & 7];
2011-12-17 12:16:10 +08:00
} else {
2011-12-23 20:24:16 +08:00
mem8_loc = segment_translation(mem8);
2011-12-21 10:43:53 +08:00
x = ld_32bits_mem8_read();
2011-12-17 12:16:10 +08:00
}
2011-12-21 10:28:01 +08:00
if (FS_usage_flag) {
mem8_loc = (regs[4] - 4) >> 0;
st32_mem8_write(x);
regs[4] = mem8_loc;
2011-12-17 12:16:10 +08:00
} else {
2011-12-21 10:43:53 +08:00
xd(x);
2011-12-17 12:16:10 +08:00
}
break;
case 3:
case 5:
2011-12-18 21:19:08 +08:00
if ((mem8 >> 6) == 3)
abort(6);
2011-12-23 20:24:16 +08:00
mem8_loc = segment_translation(mem8);
2011-12-21 10:43:53 +08:00
x = ld_32bits_mem8_read();
mem8_loc = (mem8_loc + 4) >> 0;
y = ld_16bits_mem8_read();
if (conditional_var == 3)
2011-12-23 20:24:16 +08:00
Ze(1, y, x, (eip + physmem8_ptr - initial_mem_ptr));
2011-12-17 12:16:10 +08:00
else
Oe(y, x);
2011-12-17 12:16:10 +08:00
break;
default:
abort(6);
2011-12-17 12:16:10 +08:00
}
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
case 0xeb://JMP Jbs Jump
2011-12-23 20:24:16 +08:00
x = ((phys_mem8[physmem8_ptr++] << 24) >> 24);
physmem8_ptr = (physmem8_ptr + x) >> 0;
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
case 0xe9://JMP Jvds Jump
2011-12-17 12:16:10 +08:00
{
2011-12-23 20:24:16 +08:00
x = phys_mem8[physmem8_ptr] | (phys_mem8[physmem8_ptr + 1] << 8) | (phys_mem8[physmem8_ptr + 2] << 16) | (phys_mem8[physmem8_ptr + 3] << 24);
physmem8_ptr += 4;
2011-12-17 12:16:10 +08:00
}
2011-12-23 20:24:16 +08:00
physmem8_ptr = (physmem8_ptr + x) >> 0;
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
case 0xea://JMPF Ap Jump
2011-12-21 10:28:01 +08:00
if ((((CS_flags >> 8) & 1) ^ 1)) {
2011-12-17 12:16:10 +08:00
{
2011-12-23 20:24:16 +08:00
x = phys_mem8[physmem8_ptr] | (phys_mem8[physmem8_ptr + 1] << 8) | (phys_mem8[physmem8_ptr + 2] << 16) | (phys_mem8[physmem8_ptr + 3] << 24);
physmem8_ptr += 4;
2011-12-17 12:16:10 +08:00
}
} else {
2011-12-23 01:49:18 +08:00
x = ld16_mem8_direct();
2011-12-17 12:16:10 +08:00
}
2011-12-23 01:49:18 +08:00
y = ld16_mem8_direct();
Oe(y, x);
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
2011-12-22 13:04:09 +08:00
case 0x70://JO Jbs Jump short if overflow (OF=1)
2011-12-18 20:40:30 +08:00
if (check_overflow()) {
2011-12-23 20:24:16 +08:00
x = ((phys_mem8[physmem8_ptr++] << 24) >> 24);
physmem8_ptr = (physmem8_ptr + x) >> 0;
2011-12-17 12:16:10 +08:00
} else {
2011-12-23 20:24:16 +08:00
physmem8_ptr = (physmem8_ptr + 1) >> 0;
2011-12-17 12:16:10 +08:00
}
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
2011-12-22 13:04:09 +08:00
case 0x71://JNO Jbs Jump short if not overflow (OF=0)
2011-12-18 20:40:30 +08:00
if (!check_overflow()) {
2011-12-23 20:24:16 +08:00
x = ((phys_mem8[physmem8_ptr++] << 24) >> 24);
physmem8_ptr = (physmem8_ptr + x) >> 0;
2011-12-17 12:16:10 +08:00
} else {
2011-12-23 20:24:16 +08:00
physmem8_ptr = (physmem8_ptr + 1) >> 0;
2011-12-17 12:16:10 +08:00
}
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
2011-12-22 13:04:09 +08:00
case 0x72://JB Jbs Jump short if below/not above or equal/carry (CF=1)
2011-12-18 20:40:30 +08:00
if (check_carry()) {
2011-12-23 20:24:16 +08:00
x = ((phys_mem8[physmem8_ptr++] << 24) >> 24);
physmem8_ptr = (physmem8_ptr + x) >> 0;
2011-12-17 12:16:10 +08:00
} else {
2011-12-23 20:24:16 +08:00
physmem8_ptr = (physmem8_ptr + 1) >> 0;
2011-12-17 12:16:10 +08:00
}
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
2011-12-22 13:04:09 +08:00
case 0x73://JNB Jbs Jump short if not below/above or equal/not carry (CF=0)
2011-12-18 20:40:30 +08:00
if (!check_carry()) {
2011-12-23 20:24:16 +08:00
x = ((phys_mem8[physmem8_ptr++] << 24) >> 24);
physmem8_ptr = (physmem8_ptr + x) >> 0;
2011-12-17 12:16:10 +08:00
} else {
2011-12-23 20:24:16 +08:00
physmem8_ptr = (physmem8_ptr + 1) >> 0;
2011-12-17 12:16:10 +08:00
}
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
2011-12-22 13:04:09 +08:00
case 0x74://JZ Jbs Jump short if zero/equal (ZF=0)
2011-12-17 16:14:24 +08:00
if ((_dst == 0)) {
2011-12-23 20:24:16 +08:00
x = ((phys_mem8[physmem8_ptr++] << 24) >> 24);
physmem8_ptr = (physmem8_ptr + x) >> 0;
2011-12-17 12:16:10 +08:00
} else {
2011-12-23 20:24:16 +08:00
physmem8_ptr = (physmem8_ptr + 1) >> 0;
2011-12-17 12:16:10 +08:00
}
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
2011-12-22 13:04:09 +08:00
case 0x75://JNZ Jbs Jump short if not zero/not equal (ZF=1)
2011-12-17 16:14:24 +08:00
if (!(_dst == 0)) {
2011-12-23 20:24:16 +08:00
x = ((phys_mem8[physmem8_ptr++] << 24) >> 24);
physmem8_ptr = (physmem8_ptr + x) >> 0;
2011-12-17 12:16:10 +08:00
} else {
2011-12-23 20:24:16 +08:00
physmem8_ptr = (physmem8_ptr + 1) >> 0;
2011-12-17 12:16:10 +08:00
}
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
2011-12-22 13:04:09 +08:00
case 0x76://JBE Jbs Jump short if below or equal/not above (CF=1 AND ZF=1)
2011-12-23 21:15:54 +08:00
if (check_below_or_equal()) {
2011-12-23 20:24:16 +08:00
x = ((phys_mem8[physmem8_ptr++] << 24) >> 24);
physmem8_ptr = (physmem8_ptr + x) >> 0;
2011-12-17 12:16:10 +08:00
} else {
2011-12-23 20:24:16 +08:00
physmem8_ptr = (physmem8_ptr + 1) >> 0;
2011-12-17 12:16:10 +08:00
}
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
2011-12-22 13:04:09 +08:00
case 0x77://JNBE Jbs Jump short if not below or equal/above (CF=0 AND ZF=0)
2011-12-23 21:15:54 +08:00
if (!check_below_or_equal()) {
2011-12-23 20:24:16 +08:00
x = ((phys_mem8[physmem8_ptr++] << 24) >> 24);
physmem8_ptr = (physmem8_ptr + x) >> 0;
2011-12-17 12:16:10 +08:00
} else {
2011-12-23 20:24:16 +08:00
physmem8_ptr = (physmem8_ptr + 1) >> 0;
2011-12-17 12:16:10 +08:00
}
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
2011-12-22 13:04:09 +08:00
case 0x78://JS Jbs Jump short if sign (SF=1)
2011-12-17 16:14:24 +08:00
if ((_op == 24 ? ((_src >> 7) & 1) : (_dst < 0))) {
2011-12-23 20:24:16 +08:00
x = ((phys_mem8[physmem8_ptr++] << 24) >> 24);
physmem8_ptr = (physmem8_ptr + x) >> 0;
2011-12-17 12:16:10 +08:00
} else {
2011-12-23 20:24:16 +08:00
physmem8_ptr = (physmem8_ptr + 1) >> 0;
2011-12-17 12:16:10 +08:00
}
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
2011-12-22 13:04:09 +08:00
case 0x79://JNS Jbs Jump short if not sign (SF=0)
2011-12-17 16:14:24 +08:00
if (!(_op == 24 ? ((_src >> 7) & 1) : (_dst < 0))) {
2011-12-23 20:24:16 +08:00
x = ((phys_mem8[physmem8_ptr++] << 24) >> 24);
physmem8_ptr = (physmem8_ptr + x) >> 0;
2011-12-17 12:16:10 +08:00
} else {
2011-12-23 20:24:16 +08:00
physmem8_ptr = (physmem8_ptr + 1) >> 0;
2011-12-17 12:16:10 +08:00
}
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
case 0x7a://JP Jbs Jump short if parity/parity even (PF=1)
2011-12-20 21:20:23 +08:00
if (check_parity()) {
2011-12-23 20:24:16 +08:00
x = ((phys_mem8[physmem8_ptr++] << 24) >> 24);
physmem8_ptr = (physmem8_ptr + x) >> 0;
2011-12-17 12:16:10 +08:00
} else {
2011-12-23 20:24:16 +08:00
physmem8_ptr = (physmem8_ptr + 1) >> 0;
2011-12-17 12:16:10 +08:00
}
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
case 0x7b://JNP Jbs Jump short if not parity/parity odd
2011-12-20 21:20:23 +08:00
if (!check_parity()) {
2011-12-23 20:24:16 +08:00
x = ((phys_mem8[physmem8_ptr++] << 24) >> 24);
physmem8_ptr = (physmem8_ptr + x) >> 0;
2011-12-17 12:16:10 +08:00
} else {
2011-12-23 20:24:16 +08:00
physmem8_ptr = (physmem8_ptr + 1) >> 0;
2011-12-17 12:16:10 +08:00
}
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
case 0x7c://JL Jbs Jump short if less/not greater (SF!=OF)
2011-12-23 21:15:54 +08:00
if (check_less_than()) {
2011-12-23 20:24:16 +08:00
x = ((phys_mem8[physmem8_ptr++] << 24) >> 24);
physmem8_ptr = (physmem8_ptr + x) >> 0;
2011-12-17 12:16:10 +08:00
} else {
2011-12-23 20:24:16 +08:00
physmem8_ptr = (physmem8_ptr + 1) >> 0;
2011-12-17 12:16:10 +08:00
}
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
case 0x7d://JNL Jbs Jump short if not less/greater or equal (SF=OF)
2011-12-23 21:15:54 +08:00
if (!check_less_than()) {
2011-12-23 20:24:16 +08:00
x = ((phys_mem8[physmem8_ptr++] << 24) >> 24);
physmem8_ptr = (physmem8_ptr + x) >> 0;
2011-12-17 12:16:10 +08:00
} else {
2011-12-23 20:24:16 +08:00
physmem8_ptr = (physmem8_ptr + 1) >> 0;
2011-12-17 12:16:10 +08:00
}
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
case 0x7e://JLE Jbs Jump short if less or equal/not greater ((ZF=1) OR (SF!=OF))
2011-12-23 21:15:54 +08:00
if (check_less_or_equal()) {
2011-12-23 20:24:16 +08:00
x = ((phys_mem8[physmem8_ptr++] << 24) >> 24);
physmem8_ptr = (physmem8_ptr + x) >> 0;
2011-12-17 12:16:10 +08:00
} else {
2011-12-23 20:24:16 +08:00
physmem8_ptr = (physmem8_ptr + 1) >> 0;
2011-12-17 12:16:10 +08:00
}
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
case 0x7f://JNLE Jbs Jump short if not less nor equal/greater ((ZF=0) AND (SF=OF))
2011-12-23 21:15:54 +08:00
if (!check_less_or_equal()) {
2011-12-23 20:24:16 +08:00
x = ((phys_mem8[physmem8_ptr++] << 24) >> 24);
physmem8_ptr = (physmem8_ptr + x) >> 0;
2011-12-17 12:16:10 +08:00
} else {
2011-12-23 20:24:16 +08:00
physmem8_ptr = (physmem8_ptr + 1) >> 0;
2011-12-17 12:16:10 +08:00
}
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
case 0xe0://LOOPNZ Jbs eCX Decrement count; Jump short if count!=0 and ZF=0
case 0xe1://LOOPZ Jbs eCX Decrement count; Jump short if count!=0 and ZF=1
case 0xe2://LOOP Jbs eCX Decrement count; Jump short if count!=0
2011-12-23 20:24:16 +08:00
x = ((phys_mem8[physmem8_ptr++] << 24) >> 24);
2011-12-21 10:28:01 +08:00
if (CS_flags & 0x0080)
conditional_var = 0xffff;
2011-12-17 12:16:10 +08:00
else
conditional_var = -1;
y = (regs[1] - 1) & conditional_var;
regs[1] = (regs[1] & ~conditional_var) | y;
OPbyte &= 3;
if (OPbyte == 0)
z = !(_dst == 0);
else if (OPbyte == 1)
z = (_dst == 0);
2011-12-17 12:16:10 +08:00
else
z = 1;
if (y && z) {
2011-12-21 10:28:01 +08:00
if (CS_flags & 0x0100) {
2011-12-23 20:24:16 +08:00
eip = (eip + physmem8_ptr - initial_mem_ptr + x) & 0xffff, physmem8_ptr = initial_mem_ptr = 0;
2011-12-17 12:16:10 +08:00
} else {
2011-12-23 20:24:16 +08:00
physmem8_ptr = (physmem8_ptr + x) >> 0;
2011-12-17 12:16:10 +08:00
}
}
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
case 0xe3://JCXZ Jbs Jump short if eCX register is 0
2011-12-23 20:24:16 +08:00
x = ((phys_mem8[physmem8_ptr++] << 24) >> 24);
2011-12-21 10:28:01 +08:00
if (CS_flags & 0x0080)
conditional_var = 0xffff;
2011-12-17 12:16:10 +08:00
else
conditional_var = -1;
if ((regs[1] & conditional_var) == 0) {
2011-12-21 10:28:01 +08:00
if (CS_flags & 0x0100) {
2011-12-23 20:24:16 +08:00
eip = (eip + physmem8_ptr - initial_mem_ptr + x) & 0xffff, physmem8_ptr = initial_mem_ptr = 0;
2011-12-17 12:16:10 +08:00
} else {
2011-12-23 20:24:16 +08:00
physmem8_ptr = (physmem8_ptr + x) >> 0;
2011-12-17 12:16:10 +08:00
}
}
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
case 0xc2://RETN SS:[rSP] Return from procedure
2011-12-23 01:49:18 +08:00
y = (ld16_mem8_direct() << 16) >> 16;
2011-12-21 10:43:53 +08:00
x = Ad();
regs[4] = (regs[4] & ~SS_mask) | ((regs[4] + 4 + y) & SS_mask);
2011-12-23 20:24:16 +08:00
eip = x, physmem8_ptr = initial_mem_ptr = 0;
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
case 0xc3://RETN SS:[rSP] Return from procedure
2011-12-21 10:28:01 +08:00
if (FS_usage_flag) {
mem8_loc = regs[4];
2011-12-21 10:43:53 +08:00
x = ld_32bits_mem8_read();
2011-12-17 16:08:25 +08:00
regs[4] = (regs[4] + 4) >> 0;
2011-12-17 12:16:10 +08:00
} else {
2011-12-21 10:43:53 +08:00
x = Ad();
2011-12-17 12:16:10 +08:00
Bd();
}
2011-12-23 20:24:16 +08:00
eip = x, physmem8_ptr = initial_mem_ptr = 0;
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
case 0xe8://CALL Jvds SS:[rSP] Call Procedure
2011-12-17 12:16:10 +08:00
{
2011-12-23 20:24:16 +08:00
x = phys_mem8[physmem8_ptr] | (phys_mem8[physmem8_ptr + 1] << 8) | (phys_mem8[physmem8_ptr + 2] << 16) | (phys_mem8[physmem8_ptr + 3] << 24);
physmem8_ptr += 4;
2011-12-17 12:16:10 +08:00
}
2011-12-23 20:24:16 +08:00
y = (eip + physmem8_ptr - initial_mem_ptr);
2011-12-21 10:28:01 +08:00
if (FS_usage_flag) {
mem8_loc = (regs[4] - 4) >> 0;
st32_mem8_write(y);
regs[4] = mem8_loc;
2011-12-17 12:16:10 +08:00
} else {
xd(y);
2011-12-17 12:16:10 +08:00
}
2011-12-23 20:24:16 +08:00
physmem8_ptr = (physmem8_ptr + x) >> 0;
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
case 0x9a://CALLF Ap SS:[rSP] Call Procedure
z = (((CS_flags >> 8) & 1) ^ 1);
if (z) {
2011-12-17 12:16:10 +08:00
{
2011-12-23 20:24:16 +08:00
x = phys_mem8[physmem8_ptr] | (phys_mem8[physmem8_ptr + 1] << 8) | (phys_mem8[physmem8_ptr + 2] << 16) | (phys_mem8[physmem8_ptr + 3] << 24);
physmem8_ptr += 4;
2011-12-17 12:16:10 +08:00
}
} else {
2011-12-23 01:49:18 +08:00
x = ld16_mem8_direct();
2011-12-17 12:16:10 +08:00
}
2011-12-23 01:49:18 +08:00
y = ld16_mem8_direct();
2011-12-23 20:24:16 +08:00
Ze(z, y, x, (eip + physmem8_ptr - initial_mem_ptr));
2011-12-17 12:16:10 +08:00
{
2011-12-17 13:38:46 +08:00
if (cpu.hard_irq != 0 && (cpu.eflags & 0x00000200))
2011-12-23 21:44:05 +08:00
break OUTER_LOOP;
2011-12-17 12:16:10 +08:00
}
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
case 0xca://RETF Iw Return from procedure
2011-12-23 01:49:18 +08:00
y = (ld16_mem8_direct() << 16) >> 16;
nf((((CS_flags >> 8) & 1) ^ 1), y);
2011-12-17 12:16:10 +08:00
{
2011-12-17 13:38:46 +08:00
if (cpu.hard_irq != 0 && (cpu.eflags & 0x00000200))
2011-12-23 21:44:05 +08:00
break OUTER_LOOP;
2011-12-17 12:16:10 +08:00
}
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
case 0xcb://RETF SS:[rSP] Return from procedure
2011-12-21 10:28:01 +08:00
nf((((CS_flags >> 8) & 1) ^ 1), 0);
2011-12-17 12:16:10 +08:00
{
2011-12-17 13:38:46 +08:00
if (cpu.hard_irq != 0 && (cpu.eflags & 0x00000200))
2011-12-23 21:44:05 +08:00
break OUTER_LOOP;
2011-12-17 12:16:10 +08:00
}
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
case 0xcf://IRET SS:[rSP] Flags Interrupt Return
2011-12-21 10:28:01 +08:00
mf((((CS_flags >> 8) & 1) ^ 1));
2011-12-17 12:16:10 +08:00
{
2011-12-17 13:38:46 +08:00
if (cpu.hard_irq != 0 && (cpu.eflags & 0x00000200))
2011-12-23 21:44:05 +08:00
break OUTER_LOOP;
2011-12-17 12:16:10 +08:00
}
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
2011-12-22 13:04:09 +08:00
case 0x90://XCHG Zvqp Exchange Register/Memory with Register
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
case 0xcc://INT 3 SS:[rSP] Call to Interrupt Procedure
2011-12-23 20:24:16 +08:00
y = (eip + physmem8_ptr - initial_mem_ptr);
2011-12-23 21:15:54 +08:00
do_interrupt(3, 1, 0, y, 0);
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
case 0xcd://INT Ib SS:[rSP] Call to Interrupt Procedure
2011-12-23 20:24:16 +08:00
x = phys_mem8[physmem8_ptr++];
2011-12-17 13:38:46 +08:00
if ((cpu.eflags & 0x00020000) && ((cpu.eflags >> 12) & 3) != 3)
abort(13);
2011-12-23 20:24:16 +08:00
y = (eip + physmem8_ptr - initial_mem_ptr);
2011-12-23 21:15:54 +08:00
do_interrupt(x, 1, 0, y, 0);
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
case 0xce://INTO eFlags SS:[rSP] Call to Interrupt Procedure
2011-12-18 20:40:30 +08:00
if (check_overflow()) {
2011-12-23 20:24:16 +08:00
y = (eip + physmem8_ptr - initial_mem_ptr);
2011-12-23 21:15:54 +08:00
do_interrupt(4, 1, 0, y, 0);
2011-12-17 12:16:10 +08:00
}
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
2011-12-22 13:04:09 +08:00
case 0x62://BOUND Gv SS:[rSP] Check Array Index Against Bounds
2011-12-23 01:49:18 +08:00
checkOp_BOUND();
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
case 0xf5://CMC Complement Carry Flag
2011-12-23 21:15:54 +08:00
_src = get_conditional_flags() ^ 0x0001;
2011-12-17 16:14:24 +08:00
_dst = ((_src >> 6) & 1) ^ 1;
_op = 24;
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
case 0xf8://CLC Clear Carry Flag
2011-12-23 21:15:54 +08:00
_src = get_conditional_flags() & ~0x0001;
2011-12-17 16:14:24 +08:00
_dst = ((_src >> 6) & 1) ^ 1;
_op = 24;
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
case 0xf9://STC Set Carry Flag
2011-12-23 21:15:54 +08:00
_src = get_conditional_flags() | 0x0001;
2011-12-17 16:14:24 +08:00
_dst = ((_src >> 6) & 1) ^ 1;
_op = 24;
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
case 0xfc://CLD Clear Direction Flag
2011-12-17 13:38:46 +08:00
cpu.df = 1;
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
case 0xfd://STD Set Direction Flag
2011-12-17 13:38:46 +08:00
cpu.df = -1;
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
case 0xfa://CLI Clear Interrupt Flag
iopl = (cpu.eflags >> 12) & 3;
if (cpu.cpl > iopl)
abort(13);
2011-12-17 13:38:46 +08:00
cpu.eflags &= ~0x00000200;
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
case 0xfb://STI Set Interrupt Flag
iopl = (cpu.eflags >> 12) & 3;
if (cpu.cpl > iopl)
abort(13);
2011-12-17 13:38:46 +08:00
cpu.eflags |= 0x00000200;
2011-12-17 12:16:10 +08:00
{
2011-12-17 13:38:46 +08:00
if (cpu.hard_irq != 0 && (cpu.eflags & 0x00000200))
2011-12-23 21:44:05 +08:00
break OUTER_LOOP;
2011-12-17 12:16:10 +08:00
}
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
case 0x9e://SAHF AH Store AH into Flags
2011-12-18 20:40:30 +08:00
_src = ((regs[0] >> 8) & (0x0080 | 0x0040 | 0x0010 | 0x0004 | 0x0001)) | (check_overflow() << 11);
2011-12-17 16:14:24 +08:00
_dst = ((_src >> 6) & 1) ^ 1;
_op = 24;
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
case 0x9f://LAHF AH Load Status Flags into AH Register
2011-12-21 10:43:53 +08:00
x = id();
2011-12-23 20:24:16 +08:00
set_word_in_register(4, x);
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
case 0xf4://HLT Halt
2011-12-17 13:38:46 +08:00
if (cpu.cpl != 0)
abort(13);
2011-12-17 13:38:46 +08:00
cpu.halted = 1;
exit_code = 257;
2011-12-23 21:44:05 +08:00
break OUTER_LOOP;
case 0xa4://MOVS (DS:)[rSI] (ES:)[rDI] Move Data from String to String
stringOp_MOVSB();
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
case 0xa5://MOVS DS:[SI] ES:[DI] Move Data from String to String
stringOp_MOVSD();
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
case 0xaa://STOS AL (ES:)[rDI] Store String
stringOp_STOSB();
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
case 0xab://STOS AX ES:[DI] Store String
stringOp_STOSD();
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
case 0xa6://CMPS (ES:)[rDI] Compare String Operands
stringOp_CMPSB();
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
case 0xa7://CMPS ES:[DI] Compare String Operands
stringOp_CMPSD();
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
case 0xac://LODS (DS:)[rSI] AL Load String
stringOp_LODSB();
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
case 0xad://LODS DS:[SI] AX Load String
stringOp_LODSD();
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
case 0xae://SCAS (ES:)[rDI] Scan String
stringOp_SCASB();
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
case 0xaf://SCAS ES:[DI] Scan String
stringOp_SCASD();
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
case 0x6c://INS DX (ES:)[rDI] Input from Port to String
stringOp_INSB();
2011-12-17 12:16:10 +08:00
{
2011-12-17 13:38:46 +08:00
if (cpu.hard_irq != 0 && (cpu.eflags & 0x00000200))
2011-12-23 21:44:05 +08:00
break OUTER_LOOP;
2011-12-17 12:16:10 +08:00
}
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
case 0x6d://INS DX ES:[DI] Input from Port to String
stringOp_INSD();
2011-12-17 12:16:10 +08:00
{
2011-12-17 13:38:46 +08:00
if (cpu.hard_irq != 0 && (cpu.eflags & 0x00000200))
2011-12-23 21:44:05 +08:00
break OUTER_LOOP;
2011-12-17 12:16:10 +08:00
}
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
case 0x6e://OUTS (DS):[rSI] DX Output String to Port
stringOp_OUTSB();
2011-12-17 12:16:10 +08:00
{
2011-12-17 13:38:46 +08:00
if (cpu.hard_irq != 0 && (cpu.eflags & 0x00000200))
2011-12-23 21:44:05 +08:00
break OUTER_LOOP;
2011-12-17 12:16:10 +08:00
}
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
case 0x6f://OUTS DS:[SI] DX Output String to Port
stringOp_OUTSD();
2011-12-17 12:16:10 +08:00
{
2011-12-17 13:38:46 +08:00
if (cpu.hard_irq != 0 && (cpu.eflags & 0x00000200))
2011-12-23 21:44:05 +08:00
break OUTER_LOOP;
2011-12-17 12:16:10 +08:00
}
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
case 0xd8://FADD Msr ST Add
case 0xd9://FLD ESsr ST Load Floating Point Value
case 0xda://FIADD Mdi ST Add
case 0xdb://FILD Mdi ST Load Integer
case 0xdc://FADD Mdr ST Add
case 0xdd://FLD Mdr ST Load Floating Point Value
case 0xde://FIADD Mwi ST Add
case 0xdf://FILD Mwi ST Load Integer
2011-12-17 13:38:46 +08:00
if (cpu.cr0 & ((1 << 2) | (1 << 3))) {
abort(7);
2011-12-17 12:16:10 +08:00
}
2011-12-23 20:24:16 +08:00
mem8 = phys_mem8[physmem8_ptr++];
reg_idx1 = (mem8 >> 3) & 7;
reg_idx0 = mem8 & 7;
conditional_var = ((OPbyte & 7) << 3) | ((mem8 >> 3) & 7);
2011-12-23 20:24:16 +08:00
set_lower_word_in_register(0, 0xffff);
2011-12-18 21:19:08 +08:00
if ((mem8 >> 6) == 3) {
2011-12-17 12:16:10 +08:00
} else {
2011-12-23 20:24:16 +08:00
mem8_loc = segment_translation(mem8);
2011-12-17 12:16:10 +08:00
}
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
case 0x9b://FWAIT Check pending unmasked floating-point exceptions
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
case 0xe4://IN Ib AL Input from Port
iopl = (cpu.eflags >> 12) & 3;
if (cpu.cpl > iopl)
abort(13);
2011-12-23 20:24:16 +08:00
x = phys_mem8[physmem8_ptr++];
set_word_in_register(0, cpu.ld8_port(x));
2011-12-17 12:16:10 +08:00
{
2011-12-17 13:38:46 +08:00
if (cpu.hard_irq != 0 && (cpu.eflags & 0x00000200))
2011-12-23 21:44:05 +08:00
break OUTER_LOOP;
2011-12-17 12:16:10 +08:00
}
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
case 0xe5://IN Ib eAX Input from Port
iopl = (cpu.eflags >> 12) & 3;
if (cpu.cpl > iopl)
abort(13);
2011-12-23 20:24:16 +08:00
x = phys_mem8[physmem8_ptr++];
2011-12-21 10:43:53 +08:00
regs[0] = cpu.ld32_port(x);
2011-12-17 12:16:10 +08:00
{
2011-12-17 13:38:46 +08:00
if (cpu.hard_irq != 0 && (cpu.eflags & 0x00000200))
2011-12-23 21:44:05 +08:00
break OUTER_LOOP;
2011-12-17 12:16:10 +08:00
}
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
case 0xe6://OUT AL Ib Output to Port
iopl = (cpu.eflags >> 12) & 3;
if (cpu.cpl > iopl)
abort(13);
2011-12-23 20:24:16 +08:00
x = phys_mem8[physmem8_ptr++];
2011-12-21 10:43:53 +08:00
cpu.st8_port(x, regs[0] & 0xff);
2011-12-17 12:16:10 +08:00
{
2011-12-17 13:38:46 +08:00
if (cpu.hard_irq != 0 && (cpu.eflags & 0x00000200))
2011-12-23 21:44:05 +08:00
break OUTER_LOOP;
2011-12-17 12:16:10 +08:00
}
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
case 0xe7://OUT eAX Ib Output to Port
iopl = (cpu.eflags >> 12) & 3;
if (cpu.cpl > iopl)
abort(13);
2011-12-23 20:24:16 +08:00
x = phys_mem8[physmem8_ptr++];
2011-12-21 10:43:53 +08:00
cpu.st32_port(x, regs[0]);
2011-12-17 12:16:10 +08:00
{
2011-12-17 13:38:46 +08:00
if (cpu.hard_irq != 0 && (cpu.eflags & 0x00000200))
2011-12-23 21:44:05 +08:00
break OUTER_LOOP;
2011-12-17 12:16:10 +08:00
}
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
case 0xec://IN DX AL Input from Port
iopl = (cpu.eflags >> 12) & 3;
if (cpu.cpl > iopl)
abort(13);
2011-12-23 20:24:16 +08:00
set_word_in_register(0, cpu.ld8_port(regs[2] & 0xffff));
2011-12-17 12:16:10 +08:00
{
2011-12-17 13:38:46 +08:00
if (cpu.hard_irq != 0 && (cpu.eflags & 0x00000200))
2011-12-23 21:44:05 +08:00
break OUTER_LOOP;
2011-12-17 12:16:10 +08:00
}
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
case 0xed://IN DX eAX Input from Port
iopl = (cpu.eflags >> 12) & 3;
if (cpu.cpl > iopl)
abort(13);
2011-12-17 16:08:25 +08:00
regs[0] = cpu.ld32_port(regs[2] & 0xffff);
2011-12-17 12:16:10 +08:00
{
2011-12-17 13:38:46 +08:00
if (cpu.hard_irq != 0 && (cpu.eflags & 0x00000200))
2011-12-23 21:44:05 +08:00
break OUTER_LOOP;
2011-12-17 12:16:10 +08:00
}
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
case 0xee://OUT AL DX Output to Port
iopl = (cpu.eflags >> 12) & 3;
if (cpu.cpl > iopl)
abort(13);
2011-12-17 16:08:25 +08:00
cpu.st8_port(regs[2] & 0xffff, regs[0] & 0xff);
2011-12-17 12:16:10 +08:00
{
2011-12-17 13:38:46 +08:00
if (cpu.hard_irq != 0 && (cpu.eflags & 0x00000200))
2011-12-23 21:44:05 +08:00
break OUTER_LOOP;
2011-12-17 12:16:10 +08:00
}
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
case 0xef://OUT eAX DX Output to Port
iopl = (cpu.eflags >> 12) & 3;
if (cpu.cpl > iopl)
abort(13);
2011-12-17 16:08:25 +08:00
cpu.st32_port(regs[2] & 0xffff, regs[0]);
2011-12-17 12:16:10 +08:00
{
2011-12-17 13:38:46 +08:00
if (cpu.hard_irq != 0 && (cpu.eflags & 0x00000200))
2011-12-23 21:44:05 +08:00
break OUTER_LOOP;
2011-12-17 12:16:10 +08:00
}
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
2011-12-22 13:04:09 +08:00
case 0x27://DAA AL Decimal Adjust AL after Addition
2011-12-17 12:16:10 +08:00
Df();
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
case 0x2f://DAS AL Decimal Adjust AL after Subtraction
2011-12-17 12:16:10 +08:00
Ff();
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
2011-12-22 13:04:09 +08:00
case 0x37://AAA AL ASCII Adjust After Addition
2011-12-17 12:16:10 +08:00
zf();
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
case 0x3f://AAS AL ASCII Adjust AL After Subtraction
2011-12-17 12:16:10 +08:00
Cf();
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
case 0xd4://AAM AL ASCII Adjust AX After Multiply
2011-12-23 20:24:16 +08:00
x = phys_mem8[physmem8_ptr++];
2011-12-21 10:43:53 +08:00
vf(x);
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
case 0xd5://AAD AL ASCII Adjust AX Before Division
2011-12-23 20:24:16 +08:00
x = phys_mem8[physmem8_ptr++];
2011-12-21 10:43:53 +08:00
yf(x);
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
2011-12-22 13:04:09 +08:00
case 0x63://ARPL Ew Adjust RPL Field of Segment Selector
2011-12-17 12:16:10 +08:00
tf();
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
case 0xd6://SALC Undefined and Reserved; Does not Generate #UD
case 0xf1://INT1 Undefined and Reserved; Does not Generate #UD
abort(6);
2011-12-17 12:16:10 +08:00
break;
2011-12-17 20:22:50 +08:00
/*
TWO BYTE CODE INSTRUCTIONS BEGIN WITH 0F : 0F xx
=====================================================================================================
*/
2011-12-17 12:16:10 +08:00
case 0x0f:
2011-12-23 20:24:16 +08:00
OPbyte = phys_mem8[physmem8_ptr++];
switch (OPbyte) {
2011-12-22 13:04:09 +08:00
case 0x80://JO Jvds Jump short if overflow (OF=1)
case 0x81://JNO Jvds Jump short if not overflow (OF=0)
case 0x82://JB Jvds Jump short if below/not above or equal/carry (CF=1)
case 0x83://JNB Jvds Jump short if not below/above or equal/not carry (CF=0)
case 0x84://JZ Jvds Jump short if zero/equal (ZF=0)
case 0x85://JNZ Jvds Jump short if not zero/not equal (ZF=1)
case 0x86://JBE Jvds Jump short if below or equal/not above (CF=1 AND ZF=1)
case 0x87://JNBE Jvds Jump short if not below or equal/above (CF=0 AND ZF=0)
case 0x88://JS Jvds Jump short if sign (SF=1)
case 0x89://JNS Jvds Jump short if not sign (SF=0)
case 0x8a://JP Jvds Jump short if parity/parity even (PF=1)
case 0x8b://JNP Jvds Jump short if not parity/parity odd
case 0x8c://JL Jvds Jump short if less/not greater (SF!=OF)
case 0x8d://JNL Jvds Jump short if not less/greater or equal (SF=OF)
case 0x8e://JLE Jvds Jump short if less or equal/not greater ((ZF=1) OR (SF!=OF))
case 0x8f://JNLE Jvds Jump short if not less nor equal/greater ((ZF=0) AND (SF=OF))
2011-12-17 12:16:10 +08:00
{
2011-12-23 20:24:16 +08:00
x = phys_mem8[physmem8_ptr] | (phys_mem8[physmem8_ptr + 1] << 8) | (phys_mem8[physmem8_ptr + 2] << 16) | (phys_mem8[physmem8_ptr + 3] << 24);
physmem8_ptr += 4;
2011-12-17 12:16:10 +08:00
}
2011-12-21 09:18:08 +08:00
if (check_status_bits_for_jump(OPbyte & 0xf))
2011-12-23 20:24:16 +08:00
physmem8_ptr = (physmem8_ptr + x) >> 0;
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
2011-12-22 13:04:09 +08:00
case 0x90://SETO Eb Set Byte on Condition - overflow (OF=1)
case 0x91://SETNO Eb Set Byte on Condition - not overflow (OF=0)
case 0x92://SETB Eb Set Byte on Condition - below/not above or equal/carry (CF=1)
case 0x93://SETNB Eb Set Byte on Condition - not below/above or equal/not carry (CF=0)
case 0x94://SETZ Eb Set Byte on Condition - zero/equal (ZF=0)
case 0x95://SETNZ Eb Set Byte on Condition - not zero/not equal (ZF=1)
case 0x96://SETBE Eb Set Byte on Condition - below or equal/not above (CF=1 AND ZF=1)
case 0x97://SETNBE Eb Set Byte on Condition - not below or equal/above (CF=0 AND ZF=0)
case 0x98://SETS Eb Set Byte on Condition - sign (SF=1)
case 0x99://SETNS Eb Set Byte on Condition - not sign (SF=0)
case 0x9a://SETP Eb Set Byte on Condition - parity/parity even (PF=1)
case 0x9b://SETNP Eb Set Byte on Condition - not parity/parity odd
case 0x9c://SETL Eb Set Byte on Condition - less/not greater (SF!=OF)
case 0x9d://SETNL Eb Set Byte on Condition - not less/greater or equal (SF=OF)
case 0x9e://SETLE Eb Set Byte on Condition - less or equal/not greater ((ZF=1) OR (SF!=OF))
case 0x9f://SETNLE Eb Set Byte on Condition - not less nor equal/greater ((ZF=0) AND (SF=OF))
2011-12-23 20:24:16 +08:00
mem8 = phys_mem8[physmem8_ptr++];
2011-12-21 10:43:53 +08:00
x = check_status_bits_for_jump(OPbyte & 0xf);
2011-12-18 21:19:08 +08:00
if ((mem8 >> 6) == 3) {
2011-12-23 20:24:16 +08:00
set_word_in_register(mem8 & 7, x);
2011-12-17 12:16:10 +08:00
} else {
2011-12-23 20:24:16 +08:00
mem8_loc = segment_translation(mem8);
st8_mem8_write(x);
2011-12-17 12:16:10 +08:00
}
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
2011-12-22 13:04:09 +08:00
case 0x40://CMOVO Evqp Gvqp Conditional Move - overflow (OF=1)
case 0x41://CMOVNO Evqp Gvqp Conditional Move - not overflow (OF=0)
case 0x42://CMOVB Evqp Gvqp Conditional Move - below/not above or equal/carry (CF=1)
case 0x43://CMOVNB Evqp Gvqp Conditional Move - not below/above or equal/not carry (CF=0)
case 0x44://CMOVZ Evqp Gvqp Conditional Move - zero/equal (ZF=0)
case 0x45://CMOVNZ Evqp Gvqp Conditional Move - not zero/not equal (ZF=1)
case 0x46://CMOVBE Evqp Gvqp Conditional Move - below or equal/not above (CF=1 AND ZF=1)
case 0x47://CMOVNBE Evqp Gvqp Conditional Move - not below or equal/above (CF=0 AND ZF=0)
case 0x48://CMOVS Evqp Gvqp Conditional Move - sign (SF=1)
case 0x49://CMOVNS Evqp Gvqp Conditional Move - not sign (SF=0)
case 0x4a://CMOVP Evqp Gvqp Conditional Move - parity/parity even (PF=1)
case 0x4b://CMOVNP Evqp Gvqp Conditional Move - not parity/parity odd
case 0x4c://CMOVL Evqp Gvqp Conditional Move - less/not greater (SF!=OF)
case 0x4d://CMOVNL Evqp Gvqp Conditional Move - not less/greater or equal (SF=OF)
case 0x4e://CMOVLE Evqp Gvqp Conditional Move - less or equal/not greater ((ZF=1) OR (SF!=OF))
case 0x4f://CMOVNLE Evqp Gvqp Conditional Move - not less nor equal/greater ((ZF=0) AND (SF=OF))
2011-12-23 20:24:16 +08:00
mem8 = phys_mem8[physmem8_ptr++];
2011-12-18 21:19:08 +08:00
if ((mem8 >> 6) == 3) {
2011-12-21 10:43:53 +08:00
x = regs[mem8 & 7];
2011-12-17 12:16:10 +08:00
} else {
2011-12-23 20:24:16 +08:00
mem8_loc = segment_translation(mem8);
2011-12-21 10:43:53 +08:00
x = ld_32bits_mem8_read();
2011-12-17 12:16:10 +08:00
}
2011-12-21 09:18:08 +08:00
if (check_status_bits_for_jump(OPbyte & 0xf))
2011-12-21 10:43:53 +08:00
regs[(mem8 >> 3) & 7] = x;
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
case 0xb6://MOVZX Eb Gvqp Move with Zero-Extend
2011-12-23 20:24:16 +08:00
mem8 = phys_mem8[physmem8_ptr++];
reg_idx1 = (mem8 >> 3) & 7;
2011-12-18 21:19:08 +08:00
if ((mem8 >> 6) == 3) {
2011-12-23 20:24:16 +08:00
reg_idx0 = mem8 & 7;
x = (regs[reg_idx0 & 3] >> ((reg_idx0 & 4) << 1)) & 0xff;
2011-12-17 12:16:10 +08:00
} else {
2011-12-23 20:24:16 +08:00
mem8_loc = segment_translation(mem8);
2011-12-21 10:43:53 +08:00
x = (((last_tlb_val = _tlb_read_[mem8_loc >>> 12]) == -1) ? __ld_8bits_mem8_read() : phys_mem8[mem8_loc ^ last_tlb_val]);
2011-12-17 12:16:10 +08:00
}
2011-12-23 20:24:16 +08:00
regs[reg_idx1] = x;
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
case 0xb7://MOVZX Ew Gvqp Move with Zero-Extend
2011-12-23 20:24:16 +08:00
mem8 = phys_mem8[physmem8_ptr++];
reg_idx1 = (mem8 >> 3) & 7;
2011-12-18 21:19:08 +08:00
if ((mem8 >> 6) == 3) {
2011-12-21 10:43:53 +08:00
x = regs[mem8 & 7] & 0xffff;
2011-12-17 12:16:10 +08:00
} else {
2011-12-23 20:24:16 +08:00
mem8_loc = segment_translation(mem8);
2011-12-21 10:43:53 +08:00
x = ld_16bits_mem8_read();
2011-12-17 12:16:10 +08:00
}
2011-12-23 20:24:16 +08:00
regs[reg_idx1] = x;
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
case 0xbe://MOVSX Eb Gvqp Move with Sign-Extension
2011-12-23 20:24:16 +08:00
mem8 = phys_mem8[physmem8_ptr++];
reg_idx1 = (mem8 >> 3) & 7;
2011-12-18 21:19:08 +08:00
if ((mem8 >> 6) == 3) {
2011-12-23 20:24:16 +08:00
reg_idx0 = mem8 & 7;
x = (regs[reg_idx0 & 3] >> ((reg_idx0 & 4) << 1));
2011-12-17 12:16:10 +08:00
} else {
2011-12-23 20:24:16 +08:00
mem8_loc = segment_translation(mem8);
2011-12-21 10:43:53 +08:00
x = (((last_tlb_val = _tlb_read_[mem8_loc >>> 12]) == -1) ? __ld_8bits_mem8_read() : phys_mem8[mem8_loc ^ last_tlb_val]);
2011-12-17 12:16:10 +08:00
}
2011-12-23 20:24:16 +08:00
regs[reg_idx1] = (((x) << 24) >> 24);
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
case 0xbf://MOVSX Ew Gvqp Move with Sign-Extension
2011-12-23 20:24:16 +08:00
mem8 = phys_mem8[physmem8_ptr++];
reg_idx1 = (mem8 >> 3) & 7;
2011-12-18 21:19:08 +08:00
if ((mem8 >> 6) == 3) {
2011-12-21 10:43:53 +08:00
x = regs[mem8 & 7];
2011-12-17 12:16:10 +08:00
} else {
2011-12-23 20:24:16 +08:00
mem8_loc = segment_translation(mem8);
2011-12-21 10:43:53 +08:00
x = ld_16bits_mem8_read();
2011-12-17 12:16:10 +08:00
}
2011-12-23 20:24:16 +08:00
regs[reg_idx1] = (((x) << 16) >> 16);
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
2011-12-22 13:04:09 +08:00
case 0x00://SLDT LDTR Mw Store Local Descriptor Table Register
2011-12-17 13:38:46 +08:00
if (!(cpu.cr0 & (1 << 0)) || (cpu.eflags & 0x00020000))
abort(6);
2011-12-23 20:24:16 +08:00
mem8 = phys_mem8[physmem8_ptr++];
conditional_var = (mem8 >> 3) & 7;
switch (conditional_var) {
2011-12-17 12:16:10 +08:00
case 0:
case 1:
if (conditional_var == 0)
2011-12-21 10:43:53 +08:00
x = cpu.ldt.selector;
2011-12-17 12:16:10 +08:00
else
2011-12-21 10:43:53 +08:00
x = cpu.tr.selector;
2011-12-18 21:19:08 +08:00
if ((mem8 >> 6) == 3) {
2011-12-23 20:24:16 +08:00
set_lower_word_in_register(mem8 & 7, x);
2011-12-17 12:16:10 +08:00
} else {
2011-12-23 20:24:16 +08:00
mem8_loc = segment_translation(mem8);
st16_mem8_write(x);
2011-12-17 12:16:10 +08:00
}
break;
case 2:
case 3:
2011-12-17 13:38:46 +08:00
if (cpu.cpl != 0)
abort(13);
2011-12-18 21:19:08 +08:00
if ((mem8 >> 6) == 3) {
2011-12-21 10:43:53 +08:00
x = regs[mem8 & 7] & 0xffff;
2011-12-17 12:16:10 +08:00
} else {
2011-12-23 20:24:16 +08:00
mem8_loc = segment_translation(mem8);
2011-12-21 10:43:53 +08:00
x = ld_16bits_mem8_read();
2011-12-17 12:16:10 +08:00
}
if (conditional_var == 2)
2011-12-21 10:43:53 +08:00
Ce(x);
2011-12-17 12:16:10 +08:00
else
2011-12-21 10:43:53 +08:00
Ee(x);
2011-12-17 12:16:10 +08:00
break;
case 4:
case 5:
2011-12-18 21:19:08 +08:00
if ((mem8 >> 6) == 3) {
2011-12-21 10:43:53 +08:00
x = regs[mem8 & 7] & 0xffff;
2011-12-17 12:16:10 +08:00
} else {
2011-12-23 20:24:16 +08:00
mem8_loc = segment_translation(mem8);
2011-12-21 10:43:53 +08:00
x = ld_16bits_mem8_read();
2011-12-17 12:16:10 +08:00
}
sf(x, conditional_var & 1);
2011-12-17 12:16:10 +08:00
break;
default:
abort(6);
2011-12-17 12:16:10 +08:00
}
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
2011-12-22 13:04:09 +08:00
case 0x01://SGDT GDTR Ms Store Global Descriptor Table Register
2011-12-23 20:24:16 +08:00
mem8 = phys_mem8[physmem8_ptr++];
conditional_var = (mem8 >> 3) & 7;
switch (conditional_var) {
2011-12-17 12:16:10 +08:00
case 2:
case 3:
2011-12-18 21:19:08 +08:00
if ((mem8 >> 6) == 3)
abort(6);
2011-12-17 12:16:10 +08:00
if (this.cpl != 0)
abort(13);
2011-12-23 20:24:16 +08:00
mem8_loc = segment_translation(mem8);
2011-12-21 10:43:53 +08:00
x = ld_16bits_mem8_read();
mem8_loc += 2;
y = ld_32bits_mem8_read();
if (conditional_var == 2) {
this.gdt.base = y;
2011-12-21 10:43:53 +08:00
this.gdt.limit = x;
2011-12-17 12:16:10 +08:00
} else {
this.idt.base = y;
2011-12-21 10:43:53 +08:00
this.idt.limit = x;
2011-12-17 12:16:10 +08:00
}
break;
case 7:
if (this.cpl != 0)
abort(13);
2011-12-18 21:19:08 +08:00
if ((mem8 >> 6) == 3)
abort(6);
2011-12-23 20:24:16 +08:00
mem8_loc = segment_translation(mem8);
cpu.tlb_flush_page(mem8_loc & -4096);
2011-12-17 12:16:10 +08:00
break;
default:
abort(6);
2011-12-17 12:16:10 +08:00
}
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
2011-12-22 13:04:09 +08:00
case 0x02://LAR Mw Gvqp Load Access Rights Byte
case 0x03://LSL Mw Gvqp Load Segment Limit
2011-12-21 10:28:01 +08:00
qf((((CS_flags >> 8) & 1) ^ 1), OPbyte & 1);
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
2011-12-22 13:04:09 +08:00
case 0x20://MOV Cd Rd Move to/from Control Registers
2011-12-17 13:38:46 +08:00
if (cpu.cpl != 0)
abort(13);
2011-12-23 20:24:16 +08:00
mem8 = phys_mem8[physmem8_ptr++];
2011-12-18 21:19:08 +08:00
if ((mem8 >> 6) != 3)
abort(6);
2011-12-23 20:24:16 +08:00
reg_idx1 = (mem8 >> 3) & 7;
switch (reg_idx1) {
2011-12-17 12:16:10 +08:00
case 0:
2011-12-21 10:43:53 +08:00
x = cpu.cr0;
2011-12-17 12:16:10 +08:00
break;
case 2:
2011-12-21 10:43:53 +08:00
x = cpu.cr2;
2011-12-17 12:16:10 +08:00
break;
case 3:
2011-12-21 10:43:53 +08:00
x = cpu.cr3;
2011-12-17 12:16:10 +08:00
break;
case 4:
2011-12-21 10:43:53 +08:00
x = cpu.cr4;
2011-12-17 12:16:10 +08:00
break;
default:
abort(6);
2011-12-17 12:16:10 +08:00
}
2011-12-21 10:43:53 +08:00
regs[mem8 & 7] = x;
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
2011-12-22 13:04:09 +08:00
case 0x22://MOV Rd Cd Move to/from Control Registers
2011-12-17 13:38:46 +08:00
if (cpu.cpl != 0)
abort(13);
2011-12-23 20:24:16 +08:00
mem8 = phys_mem8[physmem8_ptr++];
2011-12-18 21:19:08 +08:00
if ((mem8 >> 6) != 3)
abort(6);
2011-12-23 20:24:16 +08:00
reg_idx1 = (mem8 >> 3) & 7;
2011-12-21 10:43:53 +08:00
x = regs[mem8 & 7];
2011-12-23 20:24:16 +08:00
switch (reg_idx1) {
2011-12-17 12:16:10 +08:00
case 0:
2011-12-21 10:43:53 +08:00
set_CR0(x);
2011-12-17 12:16:10 +08:00
break;
case 2:
2011-12-21 10:43:53 +08:00
cpu.cr2 = x;
2011-12-17 12:16:10 +08:00
break;
case 3:
2011-12-21 10:43:53 +08:00
set_CR3(x);
2011-12-17 12:16:10 +08:00
break;
case 4:
2011-12-21 10:43:53 +08:00
set_CR4(x);
2011-12-17 12:16:10 +08:00
break;
default:
abort(6);
2011-12-17 12:16:10 +08:00
}
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
2011-12-22 13:04:09 +08:00
case 0x06://CLTS CR0 Clear Task-Switched Flag in CR0
2011-12-17 13:38:46 +08:00
if (cpu.cpl != 0)
abort(13);
set_CR0(cpu.cr0 & ~(1 << 3)); //Clear Task-Switched Flag in CR0
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
2011-12-22 13:04:09 +08:00
case 0x23://MOV Rd Dd Move to/from Debug Registers
2011-12-17 13:38:46 +08:00
if (cpu.cpl != 0)
abort(13);
2011-12-23 20:24:16 +08:00
mem8 = phys_mem8[physmem8_ptr++];
2011-12-18 21:19:08 +08:00
if ((mem8 >> 6) != 3)
abort(6);
2011-12-23 20:24:16 +08:00
reg_idx1 = (mem8 >> 3) & 7;
2011-12-21 10:43:53 +08:00
x = regs[mem8 & 7];
2011-12-23 20:24:16 +08:00
if (reg_idx1 == 4 || reg_idx1 == 5)
abort(6);
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
case 0xb2://LSS Mptp SS Load Far Pointer
case 0xb4://LFS Mptp FS Load Far Pointer
case 0xb5://LGS Mptp GS Load Far Pointer
Uf(OPbyte & 7);
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
case 0xa2://CPUID IA32_BIOS_SIGN_ID CPU Identification
2011-12-17 12:16:10 +08:00
uf();
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
case 0xa4://SHLD Gvqp Evqp Double Precision Shift Left
2011-12-23 20:24:16 +08:00
mem8 = phys_mem8[physmem8_ptr++];
y = regs[(mem8 >> 3) & 7];
2011-12-18 21:19:08 +08:00
if ((mem8 >> 6) == 3) {
2011-12-23 20:24:16 +08:00
z = phys_mem8[physmem8_ptr++];
reg_idx0 = mem8 & 7;
regs[reg_idx0] = rc(regs[reg_idx0], y, z);
2011-12-17 12:16:10 +08:00
} else {
2011-12-23 20:24:16 +08:00
mem8_loc = segment_translation(mem8);
z = phys_mem8[physmem8_ptr++];
2011-12-21 10:43:53 +08:00
x = ld_32bits_mem8_write();
x = rc(x, y, z);
st32_mem8_write(x);
2011-12-17 12:16:10 +08:00
}
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
case 0xa5://SHLD Gvqp Evqp Double Precision Shift Left
2011-12-23 20:24:16 +08:00
mem8 = phys_mem8[physmem8_ptr++];
y = regs[(mem8 >> 3) & 7];
z = regs[1];
2011-12-18 21:19:08 +08:00
if ((mem8 >> 6) == 3) {
2011-12-23 20:24:16 +08:00
reg_idx0 = mem8 & 7;
regs[reg_idx0] = rc(regs[reg_idx0], y, z);
2011-12-17 12:16:10 +08:00
} else {
2011-12-23 20:24:16 +08:00
mem8_loc = segment_translation(mem8);
2011-12-21 10:43:53 +08:00
x = ld_32bits_mem8_write();
x = rc(x, y, z);
st32_mem8_write(x);
2011-12-17 12:16:10 +08:00
}
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
case 0xac://SHRD Gvqp Evqp Double Precision Shift Right
2011-12-23 20:24:16 +08:00
mem8 = phys_mem8[physmem8_ptr++];
y = regs[(mem8 >> 3) & 7];
2011-12-18 21:19:08 +08:00
if ((mem8 >> 6) == 3) {
2011-12-23 20:24:16 +08:00
z = phys_mem8[physmem8_ptr++];
reg_idx0 = mem8 & 7;
regs[reg_idx0] = sc(regs[reg_idx0], y, z);
2011-12-17 12:16:10 +08:00
} else {
2011-12-23 20:24:16 +08:00
mem8_loc = segment_translation(mem8);
z = phys_mem8[physmem8_ptr++];
2011-12-21 10:43:53 +08:00
x = ld_32bits_mem8_write();
x = sc(x, y, z);
st32_mem8_write(x);
2011-12-17 12:16:10 +08:00
}
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
case 0xad://SHRD Gvqp Evqp Double Precision Shift Right
2011-12-23 20:24:16 +08:00
mem8 = phys_mem8[physmem8_ptr++];
y = regs[(mem8 >> 3) & 7];
z = regs[1];
2011-12-18 21:19:08 +08:00
if ((mem8 >> 6) == 3) {
2011-12-23 20:24:16 +08:00
reg_idx0 = mem8 & 7;
regs[reg_idx0] = sc(regs[reg_idx0], y, z);
2011-12-17 12:16:10 +08:00
} else {
2011-12-23 20:24:16 +08:00
mem8_loc = segment_translation(mem8);
2011-12-21 10:43:53 +08:00
x = ld_32bits_mem8_write();
x = sc(x, y, z);
st32_mem8_write(x);
2011-12-17 12:16:10 +08:00
}
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
case 0xba://BT Evqp Bit Test
2011-12-23 20:24:16 +08:00
mem8 = phys_mem8[physmem8_ptr++];
conditional_var = (mem8 >> 3) & 7;
switch (conditional_var) {
2011-12-17 12:16:10 +08:00
case 4:
2011-12-18 21:19:08 +08:00
if ((mem8 >> 6) == 3) {
2011-12-21 10:43:53 +08:00
x = regs[mem8 & 7];
2011-12-23 20:24:16 +08:00
y = phys_mem8[physmem8_ptr++];
2011-12-17 12:16:10 +08:00
} else {
2011-12-23 20:24:16 +08:00
mem8_loc = segment_translation(mem8);
y = phys_mem8[physmem8_ptr++];
2011-12-21 10:43:53 +08:00
x = ld_32bits_mem8_read();
2011-12-17 12:16:10 +08:00
}
uc(x, y);
2011-12-17 12:16:10 +08:00
break;
case 5:
case 6:
case 7:
2011-12-18 21:19:08 +08:00
if ((mem8 >> 6) == 3) {
2011-12-23 20:24:16 +08:00
reg_idx0 = mem8 & 7;
y = phys_mem8[physmem8_ptr++];
regs[reg_idx0] = xc(conditional_var & 3, regs[reg_idx0], y);
2011-12-17 12:16:10 +08:00
} else {
2011-12-23 20:24:16 +08:00
mem8_loc = segment_translation(mem8);
y = phys_mem8[physmem8_ptr++];
2011-12-21 10:43:53 +08:00
x = ld_32bits_mem8_write();
x = xc(conditional_var & 3, x, y);
st32_mem8_write(x);
2011-12-17 12:16:10 +08:00
}
break;
default:
abort(6);
2011-12-17 12:16:10 +08:00
}
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
case 0xa3://BT Evqp Bit Test
2011-12-23 20:24:16 +08:00
mem8 = phys_mem8[physmem8_ptr++];
y = regs[(mem8 >> 3) & 7];
2011-12-18 21:19:08 +08:00
if ((mem8 >> 6) == 3) {
2011-12-21 10:43:53 +08:00
x = regs[mem8 & 7];
2011-12-17 12:16:10 +08:00
} else {
2011-12-23 20:24:16 +08:00
mem8_loc = segment_translation(mem8);
mem8_loc = (mem8_loc + ((y >> 5) << 2)) >> 0;
2011-12-21 10:43:53 +08:00
x = ld_32bits_mem8_read();
2011-12-17 12:16:10 +08:00
}
uc(x, y);
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
case 0xab://BTS Gvqp Evqp Bit Test and Set
case 0xb3://BTR Gvqp Evqp Bit Test and Reset
case 0xbb://BTC Gvqp Evqp Bit Test and Complement
2011-12-23 20:24:16 +08:00
mem8 = phys_mem8[physmem8_ptr++];
y = regs[(mem8 >> 3) & 7];
conditional_var = (OPbyte >> 3) & 3;
2011-12-18 21:19:08 +08:00
if ((mem8 >> 6) == 3) {
2011-12-23 20:24:16 +08:00
reg_idx0 = mem8 & 7;
regs[reg_idx0] = xc(conditional_var, regs[reg_idx0], y);
2011-12-17 12:16:10 +08:00
} else {
2011-12-23 20:24:16 +08:00
mem8_loc = segment_translation(mem8);
mem8_loc = (mem8_loc + ((y >> 5) << 2)) >> 0;
2011-12-21 10:43:53 +08:00
x = ld_32bits_mem8_write();
x = xc(conditional_var, x, y);
st32_mem8_write(x);
2011-12-17 12:16:10 +08:00
}
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
case 0xbc://BSF Evqp Gvqp Bit Scan Forward
case 0xbd://BSR Evqp Gvqp Bit Scan Reverse
2011-12-23 20:24:16 +08:00
mem8 = phys_mem8[physmem8_ptr++];
reg_idx1 = (mem8 >> 3) & 7;
2011-12-18 21:19:08 +08:00
if ((mem8 >> 6) == 3) {
y = regs[mem8 & 7];
2011-12-17 12:16:10 +08:00
} else {
2011-12-23 20:24:16 +08:00
mem8_loc = segment_translation(mem8);
y = ld_32bits_mem8_read();
2011-12-17 12:16:10 +08:00
}
if (OPbyte & 1)
2011-12-23 20:24:16 +08:00
regs[reg_idx1] = Bc(regs[reg_idx1], y);
2011-12-17 12:16:10 +08:00
else
2011-12-23 20:24:16 +08:00
regs[reg_idx1] = zc(regs[reg_idx1], y);
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
case 0xaf://IMUL Evqp Gvqp Signed Multiply
2011-12-23 20:24:16 +08:00
mem8 = phys_mem8[physmem8_ptr++];
reg_idx1 = (mem8 >> 3) & 7;
2011-12-18 21:19:08 +08:00
if ((mem8 >> 6) == 3) {
y = regs[mem8 & 7];
2011-12-17 12:16:10 +08:00
} else {
2011-12-23 20:24:16 +08:00
mem8_loc = segment_translation(mem8);
y = ld_32bits_mem8_read();
2011-12-17 12:16:10 +08:00
}
2011-12-23 20:24:16 +08:00
regs[reg_idx1] = Wc(regs[reg_idx1], y);
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
2011-12-22 13:04:09 +08:00
case 0x31://RDTSC IA32_TIME_STAMP_COUNTER EAX Read Time-Stamp Counter
2011-12-17 13:38:46 +08:00
if ((cpu.cr4 & (1 << 2)) && cpu.cpl != 0)
abort(13);
2011-12-21 10:43:53 +08:00
x = current_cycle_count();
regs[0] = x >>> 0;
regs[2] = (x / 0x100000000) >>> 0;
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
case 0xc0://XADD Eb Exchange and Add
2011-12-23 20:24:16 +08:00
mem8 = phys_mem8[physmem8_ptr++];
reg_idx1 = (mem8 >> 3) & 7;
2011-12-18 21:19:08 +08:00
if ((mem8 >> 6) == 3) {
2011-12-23 20:24:16 +08:00
reg_idx0 = mem8 & 7;
x = (regs[reg_idx0 & 3] >> ((reg_idx0 & 4) << 1));
y = do_8bit_math(0, x, (regs[reg_idx1 & 3] >> ((reg_idx1 & 4) << 1)));
set_word_in_register(reg_idx1, x);
set_word_in_register(reg_idx0, y);
2011-12-17 12:16:10 +08:00
} else {
2011-12-23 20:24:16 +08:00
mem8_loc = segment_translation(mem8);
2011-12-21 10:43:53 +08:00
x = ld_8bits_mem8_write();
2011-12-23 20:24:16 +08:00
y = do_8bit_math(0, x, (regs[reg_idx1 & 3] >> ((reg_idx1 & 4) << 1)));
st8_mem8_write(y);
2011-12-23 20:24:16 +08:00
set_word_in_register(reg_idx1, x);
2011-12-17 12:16:10 +08:00
}
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
case 0xc1://XADD Evqp Exchange and Add
2011-12-23 20:24:16 +08:00
mem8 = phys_mem8[physmem8_ptr++];
reg_idx1 = (mem8 >> 3) & 7;
2011-12-18 21:19:08 +08:00
if ((mem8 >> 6) == 3) {
2011-12-23 20:24:16 +08:00
reg_idx0 = mem8 & 7;
x = regs[reg_idx0];
y = do_32bit_math(0, x, regs[reg_idx1]);
regs[reg_idx1] = x;
regs[reg_idx0] = y;
2011-12-17 12:16:10 +08:00
} else {
2011-12-23 20:24:16 +08:00
mem8_loc = segment_translation(mem8);
2011-12-21 10:43:53 +08:00
x = ld_32bits_mem8_write();
2011-12-23 20:24:16 +08:00
y = do_32bit_math(0, x, regs[reg_idx1]);
st32_mem8_write(y);
2011-12-23 20:24:16 +08:00
regs[reg_idx1] = x;
2011-12-17 12:16:10 +08:00
}
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
case 0xb0://CMPXCHG Gb Eb Compare and Exchange
2011-12-23 20:24:16 +08:00
mem8 = phys_mem8[physmem8_ptr++];
reg_idx1 = (mem8 >> 3) & 7;
2011-12-18 21:19:08 +08:00
if ((mem8 >> 6) == 3) {
2011-12-23 20:24:16 +08:00
reg_idx0 = mem8 & 7;
x = (regs[reg_idx0 & 3] >> ((reg_idx0 & 4) << 1));
y = do_8bit_math(5, regs[0], x);
if (y == 0) {
2011-12-23 20:24:16 +08:00
set_word_in_register(reg_idx0, (regs[reg_idx1 & 3] >> ((reg_idx1 & 4) << 1)));
2011-12-17 12:16:10 +08:00
} else {
2011-12-23 20:24:16 +08:00
set_word_in_register(0, x);
2011-12-17 12:16:10 +08:00
}
} else {
2011-12-23 20:24:16 +08:00
mem8_loc = segment_translation(mem8);
2011-12-21 10:43:53 +08:00
x = ld_8bits_mem8_write();
y = do_8bit_math(5, regs[0], x);
if (y == 0) {
2011-12-23 20:24:16 +08:00
st8_mem8_write((regs[reg_idx1 & 3] >> ((reg_idx1 & 4) << 1)));
2011-12-17 12:16:10 +08:00
} else {
2011-12-23 20:24:16 +08:00
set_word_in_register(0, x);
2011-12-17 12:16:10 +08:00
}
}
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
case 0xb1://CMPXCHG Gvqp Evqp Compare and Exchange
2011-12-23 20:24:16 +08:00
mem8 = phys_mem8[physmem8_ptr++];
reg_idx1 = (mem8 >> 3) & 7;
2011-12-18 21:19:08 +08:00
if ((mem8 >> 6) == 3) {
2011-12-23 20:24:16 +08:00
reg_idx0 = mem8 & 7;
x = regs[reg_idx0];
y = do_32bit_math(5, regs[0], x);
if (y == 0) {
2011-12-23 20:24:16 +08:00
regs[reg_idx0] = regs[reg_idx1];
2011-12-17 12:16:10 +08:00
} else {
2011-12-21 10:43:53 +08:00
regs[0] = x;
2011-12-17 12:16:10 +08:00
}
} else {
2011-12-23 20:24:16 +08:00
mem8_loc = segment_translation(mem8);
2011-12-21 10:43:53 +08:00
x = ld_32bits_mem8_write();
y = do_32bit_math(5, regs[0], x);
if (y == 0) {
2011-12-23 20:24:16 +08:00
st32_mem8_write(regs[reg_idx1]);
2011-12-17 12:16:10 +08:00
} else {
2011-12-21 10:43:53 +08:00
regs[0] = x;
2011-12-17 12:16:10 +08:00
}
}
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
case 0xa0://PUSH FS SS:[rSP] Push Word, Doubleword or Quadword Onto the Stack
case 0xa8://PUSH GS SS:[rSP] Push Word, Doubleword or Quadword Onto the Stack
xd(cpu.segs[(OPbyte >> 3) & 7].selector);
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
case 0xa1://POP SS:[rSP] FS Pop a Value from the Stack
case 0xa9://POP SS:[rSP] GS Pop a Value from the Stack
Ie((OPbyte >> 3) & 7, Ad() & 0xffff);
2011-12-17 12:16:10 +08:00
Bd();
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
case 0xc8://BSWAP Zvqp Byte Swap
2011-12-17 12:16:10 +08:00
case 0xc9:
case 0xca:
case 0xcb:
case 0xcc:
case 0xcd:
case 0xce:
case 0xcf:
2011-12-23 20:24:16 +08:00
reg_idx1 = OPbyte & 7;
x = regs[reg_idx1];
2011-12-21 10:43:53 +08:00
x = (x >>> 24) | ((x >> 8) & 0x0000ff00) | ((x << 8) & 0x00ff0000) | (x << 24);
2011-12-23 20:24:16 +08:00
regs[reg_idx1] = x;
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
2011-12-17 12:16:10 +08:00
case 0x04:
2011-12-22 13:04:09 +08:00
case 0x05://LOADALL AX Load All of the CPU Registers
case 0x07://LOADALL EAX Load All of the CPU Registers
case 0x08://INVD Invalidate Internal Caches
case 0x09://WBINVD Write Back and Invalidate Cache
2011-12-17 12:16:10 +08:00
case 0x0a:
case 0x0b://UD2 Undefined Instruction
2011-12-17 12:16:10 +08:00
case 0x0c:
case 0x0d://NOP Ev No Operation
2011-12-17 12:16:10 +08:00
case 0x0e:
case 0x0f:
2011-12-22 13:04:09 +08:00
case 0x10://MOVUPS Wps Vps Move Unaligned Packed Single-FP Values
case 0x11://MOVUPS Vps Wps Move Unaligned Packed Single-FP Values
case 0x12://MOVHLPS Uq Vq Move Packed Single-FP Values High to Low
case 0x13://MOVLPS Vq Mq Move Low Packed Single-FP Values
case 0x14://UNPCKLPS Wq Vps Unpack and Interleave Low Packed Single-FP Values
case 0x15://UNPCKHPS Wq Vps Unpack and Interleave High Packed Single-FP Values
case 0x16://MOVLHPS Uq Vq Move Packed Single-FP Values Low to High
case 0x17://MOVHPS Vq Mq Move High Packed Single-FP Values
case 0x18://HINT_NOP Ev Hintable NOP
case 0x19://HINT_NOP Ev Hintable NOP
case 0x1a://HINT_NOP Ev Hintable NOP
case 0x1b://HINT_NOP Ev Hintable NOP
case 0x1c://HINT_NOP Ev Hintable NOP
case 0x1d://HINT_NOP Ev Hintable NOP
case 0x1e://HINT_NOP Ev Hintable NOP
case 0x1f://HINT_NOP Ev Hintable NOP
2011-12-22 13:04:09 +08:00
case 0x21://MOV Dd Rd Move to/from Debug Registers
case 0x24://MOV Td Rd Move to/from Test Registers
2011-12-17 12:16:10 +08:00
case 0x25:
2011-12-22 13:04:09 +08:00
case 0x26://MOV Rd Td Move to/from Test Registers
2011-12-17 12:16:10 +08:00
case 0x27:
2011-12-22 13:04:09 +08:00
case 0x28://MOVAPS Wps Vps Move Aligned Packed Single-FP Values
case 0x29://MOVAPS Vps Wps Move Aligned Packed Single-FP Values
case 0x2a://CVTPI2PS Qpi Vps Convert Packed DW Integers to1.11 PackedSingle-FP Values
case 0x2b://MOVNTPS Vps Mps Store Packed Single-FP Values Using Non-Temporal Hint
case 0x2c://CVTTPS2PI Wpsq Ppi Convert with Trunc. Packed Single-FP Values to1.11 PackedDW Integers
case 0x2d://CVTPS2PI Wpsq Ppi Convert Packed Single-FP Values to1.11 PackedDW Integers
case 0x2e://UCOMISS Vss Unordered Compare Scalar Single-FP Values and Set EFLAGS
case 0x2f://COMISS Vss Compare Scalar Ordered Single-FP Values and Set EFLAGS
2011-12-22 13:04:09 +08:00
case 0x30://WRMSR rCX MSR Write to Model Specific Register
case 0x32://RDMSR rCX rAX Read from Model Specific Register
case 0x33://RDPMC PMC EAX Read Performance-Monitoring Counters
case 0x34://SYSENTER IA32_SYSENTER_CS SS Fast System Call
case 0x35://SYSEXIT IA32_SYSENTER_CS SS Fast Return from Fast System Call
2011-12-17 12:16:10 +08:00
case 0x36:
2011-12-22 13:04:09 +08:00
case 0x37://GETSEC EAX GETSEC Leaf Functions
case 0x38://PSHUFB Qq Pq Packed Shuffle Bytes
2011-12-17 12:16:10 +08:00
case 0x39:
case 0x3a://ROUNDPS Wps Vps Round Packed Single-FP Values
2011-12-17 12:16:10 +08:00
case 0x3b:
case 0x3c:
case 0x3d:
case 0x3e:
case 0x3f:
2011-12-22 13:04:09 +08:00
case 0x50://MOVMSKPS Ups Gdqp Extract Packed Single-FP Sign Mask
case 0x51://SQRTPS Wps Vps Compute Square Roots of Packed Single-FP Values
case 0x52://RSQRTPS Wps Vps Compute Recipr. of Square Roots of Packed Single-FP Values
case 0x53://RCPPS Wps Vps Compute Reciprocals of Packed Single-FP Values
case 0x54://ANDPS Wps Vps Bitwise Logical AND of Packed Single-FP Values
case 0x55://ANDNPS Wps Vps Bitwise Logical AND NOT of Packed Single-FP Values
case 0x56://ORPS Wps Vps Bitwise Logical OR of Single-FP Values
case 0x57://XORPS Wps Vps Bitwise Logical XOR for Single-FP Values
case 0x58://ADDPS Wps Vps Add Packed Single-FP Values
case 0x59://MULPS Wps Vps Multiply Packed Single-FP Values
case 0x5a://CVTPS2PD Wps Vpd Convert Packed Single-FP Values to1.11 PackedDouble-FP Values
case 0x5b://CVTDQ2PS Wdq Vps Convert Packed DW Integers to1.11 PackedSingle-FP Values
case 0x5c://SUBPS Wps Vps Subtract Packed Single-FP Values
case 0x5d://MINPS Wps Vps Return Minimum Packed Single-FP Values
case 0x5e://DIVPS Wps Vps Divide Packed Single-FP Values
case 0x5f://MAXPS Wps Vps Return Maximum Packed Single-FP Values
2011-12-22 13:04:09 +08:00
case 0x60://PUNPCKLBW Qd Pq Unpack Low Data
case 0x61://PUNPCKLWD Qd Pq Unpack Low Data
case 0x62://PUNPCKLDQ Qd Pq Unpack Low Data
case 0x63://PACKSSWB Qd Pq Pack with Signed Saturation
case 0x64://PCMPGTB Qd Pq Compare Packed Signed Integers for Greater Than
case 0x65://PCMPGTW Qd Pq Compare Packed Signed Integers for Greater Than
case 0x66://PCMPGTD Qd Pq Compare Packed Signed Integers for Greater Than
case 0x67://PACKUSWB Qq Pq Pack with Unsigned Saturation
case 0x68://PUNPCKHBW Qq Pq Unpack High Data
case 0x69://PUNPCKHWD Qq Pq Unpack High Data
case 0x6a://PUNPCKHDQ Qq Pq Unpack High Data
case 0x6b://PACKSSDW Qq Pq Pack with Signed Saturation
case 0x6c://PUNPCKLQDQ Wdq Vdq Unpack Low Data
case 0x6d://PUNPCKHQDQ Wdq Vdq Unpack High Data
case 0x6e://MOVD Ed Pq Move Doubleword
case 0x6f://MOVQ Qq Pq Move Quadword
2011-12-22 13:04:09 +08:00
case 0x70://PSHUFW Qq Pq Shuffle Packed Words
case 0x71://PSRLW Ib Nq Shift Packed Data Right Logical
case 0x72://PSRLD Ib Nq Shift Double Quadword Right Logical
case 0x73://PSRLQ Ib Nq Shift Packed Data Right Logical
case 0x74://PCMPEQB Qq Pq Compare Packed Data for Equal
case 0x75://PCMPEQW Qq Pq Compare Packed Data for Equal
case 0x76://PCMPEQD Qq Pq Compare Packed Data for Equal
case 0x77://EMMS Empty MMX Technology State
case 0x78://VMREAD Gd Ed Read Field from Virtual-Machine Control Structure
case 0x79://VMWRITE Gd Write Field to Virtual-Machine Control Structure
2011-12-17 12:16:10 +08:00
case 0x7a:
case 0x7b:
case 0x7c://HADDPD Wpd Vpd Packed Double-FP Horizontal Add
case 0x7d://HSUBPD Wpd Vpd Packed Double-FP Horizontal Subtract
case 0x7e://MOVD Pq Ed Move Doubleword
case 0x7f://MOVQ Pq Qq Move Quadword
2011-12-17 12:16:10 +08:00
case 0xa6:
case 0xa7:
case 0xaa://RSM Flags Resume from System Management Mode
case 0xae://FXSAVE ST Mstx Save x87 FPU, MMX, XMM, and MXCSR State
case 0xb8://JMPE Jump to IA-64 Instruction Set
case 0xb9://UD G Undefined Instruction
case 0xc2://CMPPS Wps Vps Compare Packed Single-FP Values
case 0xc3://MOVNTI Gdqp Mdqp Store Doubleword Using Non-Temporal Hint
case 0xc4://PINSRW Rdqp Pq Insert Word
case 0xc5://PEXTRW Nq Gdqp Extract Word
case 0xc6://SHUFPS Wps Vps Shuffle Packed Single-FP Values
case 0xc7://CMPXCHG8B EBX Mq Compare and Exchange Bytes
case 0xd0://ADDSUBPD Wpd Vpd Packed Double-FP Add/Subtract
case 0xd1://PSRLW Qq Pq Shift Packed Data Right Logical
case 0xd2://PSRLD Qq Pq Shift Packed Data Right Logical
case 0xd3://PSRLQ Qq Pq Shift Packed Data Right Logical
case 0xd4://PADDQ Qq Pq Add Packed Quadword Integers
case 0xd5://PMULLW Qq Pq Multiply Packed Signed Integers and Store Low Result
case 0xd6://MOVQ Vq Wq Move Quadword
case 0xd7://PMOVMSKB Nq Gdqp Move Byte Mask
case 0xd8://PSUBUSB Qq Pq Subtract Packed Unsigned Integers with Unsigned Saturation
case 0xd9://PSUBUSW Qq Pq Subtract Packed Unsigned Integers with Unsigned Saturation
case 0xda://PMINUB Qq Pq Minimum of Packed Unsigned Byte Integers
case 0xdb://PAND Qd Pq Logical AND
case 0xdc://PADDUSB Qq Pq Add Packed Unsigned Integers with Unsigned Saturation
case 0xdd://PADDUSW Qq Pq Add Packed Unsigned Integers with Unsigned Saturation
case 0xde://PMAXUB Qq Pq Maximum of Packed Unsigned Byte Integers
case 0xdf://PANDN Qq Pq Logical AND NOT
case 0xe0://PAVGB Qq Pq Average Packed Integers
case 0xe1://PSRAW Qq Pq Shift Packed Data Right Arithmetic
case 0xe2://PSRAD Qq Pq Shift Packed Data Right Arithmetic
case 0xe3://PAVGW Qq Pq Average Packed Integers
case 0xe4://PMULHUW Qq Pq Multiply Packed Unsigned Integers and Store High Result
case 0xe5://PMULHW Qq Pq Multiply Packed Signed Integers and Store High Result
case 0xe6://CVTPD2DQ Wpd Vdq Convert Packed Double-FP Values to1.11 PackedDW Integers
case 0xe7://MOVNTQ Pq Mq Store of Quadword Using Non-Temporal Hint
case 0xe8://PSUBSB Qq Pq Subtract Packed Signed Integers with Signed Saturation
case 0xe9://PSUBSW Qq Pq Subtract Packed Signed Integers with Signed Saturation
case 0xea://PMINSW Qq Pq Minimum of Packed Signed Word Integers
case 0xeb://POR Qq Pq Bitwise Logical OR
case 0xec://PADDSB Qq Pq Add Packed Signed Integers with Signed Saturation
case 0xed://PADDSW Qq Pq Add Packed Signed Integers with Signed Saturation
case 0xee://PMAXSW Qq Pq Maximum of Packed Signed Word Integers
case 0xef://PXOR Qq Pq Logical Exclusive OR
case 0xf0://LDDQU Mdq Vdq Load Unaligned Integer 128 Bits
case 0xf1://PSLLW Qq Pq Shift Packed Data Left Logical
case 0xf2://PSLLD Qq Pq Shift Packed Data Left Logical
case 0xf3://PSLLQ Qq Pq Shift Packed Data Left Logical
case 0xf4://PMULUDQ Qq Pq Multiply Packed Unsigned DW Integers
case 0xf5://PMADDWD Qd Pq Multiply and Add Packed Integers
case 0xf6://PSADBW Qq Pq Compute Sum of Absolute Differences
case 0xf7://MASKMOVQ Nq (DS:)[rDI] Store Selected Bytes of Quadword
case 0xf8://PSUBB Qq Pq Subtract Packed Integers
case 0xf9://PSUBW Qq Pq Subtract Packed Integers
case 0xfa://PSUBD Qq Pq Subtract Packed Integers
case 0xfb://PSUBQ Qq Pq Subtract Packed Quadword Integers
case 0xfc://PADDB Qq Pq Add Packed Integers
case 0xfd://PADDW Qq Pq Add Packed Integers
case 0xfe://PADDD Qq Pq Add Packed Integers
2011-12-17 12:16:10 +08:00
case 0xff:
default:
abort(6);
2011-12-17 12:16:10 +08:00
}
break;
default:
switch (OPbyte) {
2011-12-17 12:16:10 +08:00
case 0x189:
2011-12-23 20:24:16 +08:00
mem8 = phys_mem8[physmem8_ptr++];
2011-12-21 10:43:53 +08:00
x = regs[(mem8 >> 3) & 7];
2011-12-18 21:19:08 +08:00
if ((mem8 >> 6) == 3) {
2011-12-23 20:24:16 +08:00
set_lower_word_in_register(mem8 & 7, x);
2011-12-17 12:16:10 +08:00
} else {
2011-12-23 20:24:16 +08:00
mem8_loc = segment_translation(mem8);
st16_mem8_write(x);
2011-12-17 12:16:10 +08:00
}
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
2011-12-17 12:16:10 +08:00
case 0x18b:
2011-12-23 20:24:16 +08:00
mem8 = phys_mem8[physmem8_ptr++];
2011-12-18 21:19:08 +08:00
if ((mem8 >> 6) == 3) {
2011-12-21 10:43:53 +08:00
x = regs[mem8 & 7];
2011-12-17 12:16:10 +08:00
} else {
2011-12-23 20:24:16 +08:00
mem8_loc = segment_translation(mem8);
2011-12-21 10:43:53 +08:00
x = ld_16bits_mem8_read();
2011-12-17 12:16:10 +08:00
}
2011-12-23 20:24:16 +08:00
set_lower_word_in_register((mem8 >> 3) & 7, x);
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
2011-12-17 12:16:10 +08:00
case 0x1b8:
case 0x1b9:
case 0x1ba:
case 0x1bb:
case 0x1bc:
case 0x1bd:
case 0x1be:
case 0x1bf:
2011-12-23 20:24:16 +08:00
set_lower_word_in_register(OPbyte & 7, ld16_mem8_direct());
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
2011-12-23 20:24:16 +08:00
case 0x1a1://MOV EAX,moffs32 Move dword at (seg:offset) to EAX
mem8_loc = segmented_mem8_loc_for_MOV();
2011-12-21 10:43:53 +08:00
x = ld_16bits_mem8_read();
2011-12-23 20:24:16 +08:00
set_lower_word_in_register(0, x);
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
2011-12-23 20:24:16 +08:00
case 0x1a3://MOV moffs16,AX Move AX to (seg:offset)
mem8_loc = segmented_mem8_loc_for_MOV();
st16_mem8_write(regs[0]);
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
2011-12-17 12:16:10 +08:00
case 0x1c7:
2011-12-23 20:24:16 +08:00
mem8 = phys_mem8[physmem8_ptr++];
2011-12-18 21:19:08 +08:00
if ((mem8 >> 6) == 3) {
2011-12-23 01:49:18 +08:00
x = ld16_mem8_direct();
2011-12-23 20:24:16 +08:00
set_lower_word_in_register(mem8 & 7, x);
2011-12-17 12:16:10 +08:00
} else {
2011-12-23 20:24:16 +08:00
mem8_loc = segment_translation(mem8);
2011-12-23 01:49:18 +08:00
x = ld16_mem8_direct();
st16_mem8_write(x);
2011-12-17 12:16:10 +08:00
}
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
2011-12-17 12:16:10 +08:00
case 0x191:
case 0x192:
case 0x193:
case 0x194:
case 0x195:
case 0x196:
case 0x197:
2011-12-23 20:24:16 +08:00
reg_idx1 = OPbyte & 7;
2011-12-21 10:43:53 +08:00
x = regs[0];
2011-12-23 20:24:16 +08:00
set_lower_word_in_register(0, regs[reg_idx1]);
set_lower_word_in_register(reg_idx1, x);
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
2011-12-17 12:16:10 +08:00
case 0x187:
2011-12-23 20:24:16 +08:00
mem8 = phys_mem8[physmem8_ptr++];
reg_idx1 = (mem8 >> 3) & 7;
2011-12-18 21:19:08 +08:00
if ((mem8 >> 6) == 3) {
2011-12-23 20:24:16 +08:00
reg_idx0 = mem8 & 7;
x = regs[reg_idx0];
set_lower_word_in_register(reg_idx0, regs[reg_idx1]);
2011-12-17 12:16:10 +08:00
} else {
2011-12-23 20:24:16 +08:00
mem8_loc = segment_translation(mem8);
2011-12-21 10:43:53 +08:00
x = ld_16bits_mem8_write();
2011-12-23 20:24:16 +08:00
st16_mem8_write(regs[reg_idx1]);
2011-12-17 12:16:10 +08:00
}
2011-12-23 20:24:16 +08:00
set_lower_word_in_register(reg_idx1, x);
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
2011-12-17 12:16:10 +08:00
case 0x1c4:
Vf(0);
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
2011-12-17 12:16:10 +08:00
case 0x1c5:
Vf(3);
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
2011-12-17 12:16:10 +08:00
case 0x101:
case 0x109:
case 0x111:
case 0x119:
case 0x121:
case 0x129:
case 0x131:
case 0x139:
2011-12-23 20:24:16 +08:00
mem8 = phys_mem8[physmem8_ptr++];
conditional_var = (OPbyte >> 3) & 7;
y = regs[(mem8 >> 3) & 7];
2011-12-18 21:19:08 +08:00
if ((mem8 >> 6) == 3) {
2011-12-23 20:24:16 +08:00
reg_idx0 = mem8 & 7;
set_lower_word_in_register(reg_idx0, do_16bit_math(conditional_var, regs[reg_idx0], y));
2011-12-17 12:16:10 +08:00
} else {
2011-12-23 20:24:16 +08:00
mem8_loc = segment_translation(mem8);
if (conditional_var != 7) {
2011-12-21 10:43:53 +08:00
x = ld_16bits_mem8_write();
x = do_16bit_math(conditional_var, x, y);
st16_mem8_write(x);
2011-12-17 12:16:10 +08:00
} else {
2011-12-21 10:43:53 +08:00
x = ld_16bits_mem8_read();
do_16bit_math(7, x, y);
2011-12-17 12:16:10 +08:00
}
}
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
2011-12-17 12:16:10 +08:00
case 0x103:
case 0x10b:
case 0x113:
case 0x11b:
case 0x123:
case 0x12b:
case 0x133:
case 0x13b:
2011-12-23 20:24:16 +08:00
mem8 = phys_mem8[physmem8_ptr++];
conditional_var = (OPbyte >> 3) & 7;
2011-12-23 20:24:16 +08:00
reg_idx1 = (mem8 >> 3) & 7;
2011-12-18 21:19:08 +08:00
if ((mem8 >> 6) == 3) {
y = regs[mem8 & 7];
2011-12-17 12:16:10 +08:00
} else {
2011-12-23 20:24:16 +08:00
mem8_loc = segment_translation(mem8);
y = ld_16bits_mem8_read();
2011-12-17 12:16:10 +08:00
}
2011-12-23 20:24:16 +08:00
set_lower_word_in_register(reg_idx1, do_16bit_math(conditional_var, regs[reg_idx1], y));
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
2011-12-17 12:16:10 +08:00
case 0x105:
case 0x10d:
case 0x115:
case 0x11d:
case 0x125:
case 0x12d:
case 0x135:
case 0x13d:
2011-12-23 01:49:18 +08:00
y = ld16_mem8_direct();
conditional_var = (OPbyte >> 3) & 7;
2011-12-23 20:24:16 +08:00
set_lower_word_in_register(0, do_16bit_math(conditional_var, regs[0], y));
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
2011-12-17 12:16:10 +08:00
case 0x181:
2011-12-23 20:24:16 +08:00
mem8 = phys_mem8[physmem8_ptr++];
conditional_var = (mem8 >> 3) & 7;
2011-12-18 21:19:08 +08:00
if ((mem8 >> 6) == 3) {
2011-12-23 20:24:16 +08:00
reg_idx0 = mem8 & 7;
2011-12-23 01:49:18 +08:00
y = ld16_mem8_direct();
2011-12-23 20:24:16 +08:00
regs[reg_idx0] = do_16bit_math(conditional_var, regs[reg_idx0], y);
2011-12-17 12:16:10 +08:00
} else {
2011-12-23 20:24:16 +08:00
mem8_loc = segment_translation(mem8);
2011-12-23 01:49:18 +08:00
y = ld16_mem8_direct();
if (conditional_var != 7) {
2011-12-21 10:43:53 +08:00
x = ld_16bits_mem8_write();
x = do_16bit_math(conditional_var, x, y);
st16_mem8_write(x);
2011-12-17 12:16:10 +08:00
} else {
2011-12-21 10:43:53 +08:00
x = ld_16bits_mem8_read();
do_16bit_math(7, x, y);
2011-12-17 12:16:10 +08:00
}
}
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
2011-12-17 12:16:10 +08:00
case 0x183:
2011-12-23 20:24:16 +08:00
mem8 = phys_mem8[physmem8_ptr++];
conditional_var = (mem8 >> 3) & 7;
2011-12-18 21:19:08 +08:00
if ((mem8 >> 6) == 3) {
2011-12-23 20:24:16 +08:00
reg_idx0 = mem8 & 7;
y = ((phys_mem8[physmem8_ptr++] << 24) >> 24);
set_lower_word_in_register(reg_idx0, do_16bit_math(conditional_var, regs[reg_idx0], y));
2011-12-17 12:16:10 +08:00
} else {
2011-12-23 20:24:16 +08:00
mem8_loc = segment_translation(mem8);
y = ((phys_mem8[physmem8_ptr++] << 24) >> 24);
if (conditional_var != 7) {
2011-12-21 10:43:53 +08:00
x = ld_16bits_mem8_write();
x = do_16bit_math(conditional_var, x, y);
st16_mem8_write(x);
2011-12-17 12:16:10 +08:00
} else {
2011-12-21 10:43:53 +08:00
x = ld_16bits_mem8_read();
do_16bit_math(7, x, y);
2011-12-17 12:16:10 +08:00
}
}
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
2011-12-17 12:16:10 +08:00
case 0x140:
case 0x141:
case 0x142:
case 0x143:
case 0x144:
case 0x145:
case 0x146:
case 0x147:
2011-12-23 20:24:16 +08:00
reg_idx1 = OPbyte & 7;
set_lower_word_in_register(reg_idx1, increment_16bit(regs[reg_idx1]));
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
2011-12-17 12:16:10 +08:00
case 0x148:
case 0x149:
case 0x14a:
case 0x14b:
case 0x14c:
case 0x14d:
case 0x14e:
case 0x14f:
2011-12-23 20:24:16 +08:00
reg_idx1 = OPbyte & 7;
set_lower_word_in_register(reg_idx1, decrement_16bit(regs[reg_idx1]));
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
2011-12-17 12:16:10 +08:00
case 0x16b:
2011-12-23 20:24:16 +08:00
mem8 = phys_mem8[physmem8_ptr++];
reg_idx1 = (mem8 >> 3) & 7;
2011-12-18 21:19:08 +08:00
if ((mem8 >> 6) == 3) {
y = regs[mem8 & 7];
2011-12-17 12:16:10 +08:00
} else {
2011-12-23 20:24:16 +08:00
mem8_loc = segment_translation(mem8);
y = ld_16bits_mem8_read();
2011-12-17 12:16:10 +08:00
}
2011-12-23 20:24:16 +08:00
z = ((phys_mem8[physmem8_ptr++] << 24) >> 24);
set_lower_word_in_register(reg_idx1, Rc(y, z));
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
2011-12-17 12:16:10 +08:00
case 0x169:
2011-12-23 20:24:16 +08:00
mem8 = phys_mem8[physmem8_ptr++];
reg_idx1 = (mem8 >> 3) & 7;
2011-12-18 21:19:08 +08:00
if ((mem8 >> 6) == 3) {
y = regs[mem8 & 7];
2011-12-17 12:16:10 +08:00
} else {
2011-12-23 20:24:16 +08:00
mem8_loc = segment_translation(mem8);
y = ld_16bits_mem8_read();
2011-12-17 12:16:10 +08:00
}
2011-12-23 01:49:18 +08:00
z = ld16_mem8_direct();
2011-12-23 20:24:16 +08:00
set_lower_word_in_register(reg_idx1, Rc(y, z));
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
2011-12-17 12:16:10 +08:00
case 0x185:
2011-12-23 20:24:16 +08:00
mem8 = phys_mem8[physmem8_ptr++];
2011-12-18 21:19:08 +08:00
if ((mem8 >> 6) == 3) {
2011-12-21 10:43:53 +08:00
x = regs[mem8 & 7];
2011-12-17 12:16:10 +08:00
} else {
2011-12-23 20:24:16 +08:00
mem8_loc = segment_translation(mem8);
2011-12-21 10:43:53 +08:00
x = ld_16bits_mem8_read();
2011-12-17 12:16:10 +08:00
}
y = regs[(mem8 >> 3) & 7];
2011-12-17 12:16:10 +08:00
{
_dst = (((x & y) << 16) >> 16);
2011-12-17 16:14:24 +08:00
_op = 13;
2011-12-17 12:16:10 +08:00
}
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
2011-12-17 12:16:10 +08:00
case 0x1a9:
2011-12-23 01:49:18 +08:00
y = ld16_mem8_direct();
2011-12-17 12:16:10 +08:00
{
_dst = (((regs[0] & y) << 16) >> 16);
2011-12-17 16:14:24 +08:00
_op = 13;
2011-12-17 12:16:10 +08:00
}
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
2011-12-17 12:16:10 +08:00
case 0x1f7:
2011-12-23 20:24:16 +08:00
mem8 = phys_mem8[physmem8_ptr++];
conditional_var = (mem8 >> 3) & 7;
switch (conditional_var) {
2011-12-17 12:16:10 +08:00
case 0:
2011-12-18 21:19:08 +08:00
if ((mem8 >> 6) == 3) {
2011-12-21 10:43:53 +08:00
x = regs[mem8 & 7];
2011-12-17 12:16:10 +08:00
} else {
2011-12-23 20:24:16 +08:00
mem8_loc = segment_translation(mem8);
2011-12-21 10:43:53 +08:00
x = ld_16bits_mem8_read();
2011-12-17 12:16:10 +08:00
}
2011-12-23 01:49:18 +08:00
y = ld16_mem8_direct();
2011-12-17 12:16:10 +08:00
{
_dst = (((x & y) << 16) >> 16);
2011-12-17 16:14:24 +08:00
_op = 13;
2011-12-17 12:16:10 +08:00
}
break;
case 2:
2011-12-18 21:19:08 +08:00
if ((mem8 >> 6) == 3) {
2011-12-23 20:24:16 +08:00
reg_idx0 = mem8 & 7;
set_lower_word_in_register(reg_idx0, ~regs[reg_idx0]);
2011-12-17 12:16:10 +08:00
} else {
2011-12-23 20:24:16 +08:00
mem8_loc = segment_translation(mem8);
2011-12-21 10:43:53 +08:00
x = ld_16bits_mem8_write();
x = ~x;
st16_mem8_write(x);
2011-12-17 12:16:10 +08:00
}
break;
case 3:
2011-12-18 21:19:08 +08:00
if ((mem8 >> 6) == 3) {
2011-12-23 20:24:16 +08:00
reg_idx0 = mem8 & 7;
set_lower_word_in_register(reg_idx0, do_16bit_math(5, 0, regs[reg_idx0]));
2011-12-17 12:16:10 +08:00
} else {
2011-12-23 20:24:16 +08:00
mem8_loc = segment_translation(mem8);
2011-12-21 10:43:53 +08:00
x = ld_16bits_mem8_write();
x = do_16bit_math(5, 0, x);
st16_mem8_write(x);
2011-12-17 12:16:10 +08:00
}
break;
case 4:
2011-12-18 21:19:08 +08:00
if ((mem8 >> 6) == 3) {
2011-12-21 10:43:53 +08:00
x = regs[mem8 & 7];
2011-12-17 12:16:10 +08:00
} else {
2011-12-23 20:24:16 +08:00
mem8_loc = segment_translation(mem8);
2011-12-21 10:43:53 +08:00
x = ld_16bits_mem8_read();
2011-12-17 12:16:10 +08:00
}
2011-12-21 10:43:53 +08:00
x = Qc(regs[0], x);
2011-12-23 20:24:16 +08:00
set_lower_word_in_register(0, x);
set_lower_word_in_register(2, x >> 16);
2011-12-17 12:16:10 +08:00
break;
case 5:
2011-12-18 21:19:08 +08:00
if ((mem8 >> 6) == 3) {
2011-12-21 10:43:53 +08:00
x = regs[mem8 & 7];
2011-12-17 12:16:10 +08:00
} else {
2011-12-23 20:24:16 +08:00
mem8_loc = segment_translation(mem8);
2011-12-21 10:43:53 +08:00
x = ld_16bits_mem8_read();
2011-12-17 12:16:10 +08:00
}
2011-12-21 10:43:53 +08:00
x = Rc(regs[0], x);
2011-12-23 20:24:16 +08:00
set_lower_word_in_register(0, x);
set_lower_word_in_register(2, x >> 16);
2011-12-17 12:16:10 +08:00
break;
case 6:
2011-12-18 21:19:08 +08:00
if ((mem8 >> 6) == 3) {
2011-12-21 10:43:53 +08:00
x = regs[mem8 & 7];
2011-12-17 12:16:10 +08:00
} else {
2011-12-23 20:24:16 +08:00
mem8_loc = segment_translation(mem8);
2011-12-21 10:43:53 +08:00
x = ld_16bits_mem8_read();
2011-12-17 12:16:10 +08:00
}
2011-12-21 10:43:53 +08:00
Fc(x);
2011-12-17 12:16:10 +08:00
break;
case 7:
2011-12-18 21:19:08 +08:00
if ((mem8 >> 6) == 3) {
2011-12-21 10:43:53 +08:00
x = regs[mem8 & 7];
2011-12-17 12:16:10 +08:00
} else {
2011-12-23 20:24:16 +08:00
mem8_loc = segment_translation(mem8);
2011-12-21 10:43:53 +08:00
x = ld_16bits_mem8_read();
2011-12-17 12:16:10 +08:00
}
2011-12-21 10:43:53 +08:00
Gc(x);
2011-12-17 12:16:10 +08:00
break;
default:
abort(6);
2011-12-17 12:16:10 +08:00
}
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
2011-12-17 12:16:10 +08:00
case 0x1c1:
2011-12-23 20:24:16 +08:00
mem8 = phys_mem8[physmem8_ptr++];
conditional_var = (mem8 >> 3) & 7;
2011-12-18 21:19:08 +08:00
if ((mem8 >> 6) == 3) {
2011-12-23 20:24:16 +08:00
y = phys_mem8[physmem8_ptr++];
reg_idx0 = mem8 & 7;
set_lower_word_in_register(reg_idx0, shift16(conditional_var, regs[reg_idx0], y));
2011-12-17 12:16:10 +08:00
} else {
2011-12-23 20:24:16 +08:00
mem8_loc = segment_translation(mem8);
y = phys_mem8[physmem8_ptr++];
2011-12-21 10:43:53 +08:00
x = ld_16bits_mem8_write();
x = shift16(conditional_var, x, y);
st16_mem8_write(x);
2011-12-17 12:16:10 +08:00
}
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
2011-12-17 12:16:10 +08:00
case 0x1d1:
2011-12-23 20:24:16 +08:00
mem8 = phys_mem8[physmem8_ptr++];
conditional_var = (mem8 >> 3) & 7;
2011-12-18 21:19:08 +08:00
if ((mem8 >> 6) == 3) {
2011-12-23 20:24:16 +08:00
reg_idx0 = mem8 & 7;
set_lower_word_in_register(reg_idx0, shift16(conditional_var, regs[reg_idx0], 1));
2011-12-17 12:16:10 +08:00
} else {
2011-12-23 20:24:16 +08:00
mem8_loc = segment_translation(mem8);
2011-12-21 10:43:53 +08:00
x = ld_16bits_mem8_write();
x = shift16(conditional_var, x, 1);
st16_mem8_write(x);
2011-12-17 12:16:10 +08:00
}
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
2011-12-17 12:16:10 +08:00
case 0x1d3:
2011-12-23 20:24:16 +08:00
mem8 = phys_mem8[physmem8_ptr++];
conditional_var = (mem8 >> 3) & 7;
y = regs[1] & 0xff;
2011-12-18 21:19:08 +08:00
if ((mem8 >> 6) == 3) {
2011-12-23 20:24:16 +08:00
reg_idx0 = mem8 & 7;
set_lower_word_in_register(reg_idx0, shift16(conditional_var, regs[reg_idx0], y));
2011-12-17 12:16:10 +08:00
} else {
2011-12-23 20:24:16 +08:00
mem8_loc = segment_translation(mem8);
2011-12-21 10:43:53 +08:00
x = ld_16bits_mem8_write();
x = shift16(conditional_var, x, y);
st16_mem8_write(x);
2011-12-17 12:16:10 +08:00
}
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
2011-12-17 12:16:10 +08:00
case 0x198:
2011-12-23 20:24:16 +08:00
set_lower_word_in_register(0, (regs[0] << 24) >> 24);
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
2011-12-17 12:16:10 +08:00
case 0x199:
2011-12-23 20:24:16 +08:00
set_lower_word_in_register(2, (regs[0] << 16) >> 31);
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
2011-12-17 12:16:10 +08:00
case 0x190:
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
2011-12-17 12:16:10 +08:00
case 0x150:
case 0x151:
case 0x152:
case 0x153:
case 0x154:
case 0x155:
case 0x156:
case 0x157:
vd(regs[OPbyte & 7]);
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
2011-12-17 12:16:10 +08:00
case 0x158:
case 0x159:
case 0x15a:
case 0x15b:
case 0x15c:
case 0x15d:
case 0x15e:
case 0x15f:
2011-12-21 10:43:53 +08:00
x = yd();
2011-12-17 12:16:10 +08:00
zd();
2011-12-23 20:24:16 +08:00
set_lower_word_in_register(OPbyte & 7, x);
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
2011-12-17 12:16:10 +08:00
case 0x160:
Jf();
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
2011-12-17 12:16:10 +08:00
case 0x161:
Lf();
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
2011-12-17 12:16:10 +08:00
case 0x18f:
2011-12-23 20:24:16 +08:00
mem8 = phys_mem8[physmem8_ptr++];
2011-12-18 21:19:08 +08:00
if ((mem8 >> 6) == 3) {
2011-12-21 10:43:53 +08:00
x = yd();
2011-12-17 12:16:10 +08:00
zd();
2011-12-23 20:24:16 +08:00
set_lower_word_in_register(mem8 & 7, x);
2011-12-17 12:16:10 +08:00
} else {
2011-12-21 10:43:53 +08:00
x = yd();
y = regs[4];
2011-12-17 12:16:10 +08:00
zd();
z = regs[4];
2011-12-23 20:24:16 +08:00
mem8_loc = segment_translation(mem8);
regs[4] = y;
st16_mem8_write(x);
regs[4] = z;
2011-12-17 12:16:10 +08:00
}
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
2011-12-17 12:16:10 +08:00
case 0x168:
2011-12-23 01:49:18 +08:00
x = ld16_mem8_direct();
2011-12-21 10:43:53 +08:00
vd(x);
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
2011-12-17 12:16:10 +08:00
case 0x16a:
2011-12-23 20:24:16 +08:00
x = ((phys_mem8[physmem8_ptr++] << 24) >> 24);
2011-12-21 10:43:53 +08:00
vd(x);
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
2011-12-17 12:16:10 +08:00
case 0x1c8:
Pf();
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
2011-12-17 12:16:10 +08:00
case 0x1c9:
Nf();
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
2011-12-17 12:16:10 +08:00
case 0x106:
case 0x10e:
case 0x116:
case 0x11e:
vd(cpu.segs[(OPbyte >> 3) & 3].selector);
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
2011-12-17 12:16:10 +08:00
case 0x107:
case 0x117:
case 0x11f:
Ie((OPbyte >> 3) & 3, yd());
2011-12-17 12:16:10 +08:00
zd();
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
2011-12-17 12:16:10 +08:00
case 0x18d:
2011-12-23 20:24:16 +08:00
mem8 = phys_mem8[physmem8_ptr++];
2011-12-18 21:19:08 +08:00
if ((mem8 >> 6) == 3)
abort(6);
2011-12-21 10:28:01 +08:00
CS_flags = (CS_flags & ~0x000f) | (6 + 1);
2011-12-23 20:24:16 +08:00
set_lower_word_in_register((mem8 >> 3) & 7, segment_translation(mem8));
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
2011-12-17 12:16:10 +08:00
case 0x1ff:
2011-12-23 20:24:16 +08:00
mem8 = phys_mem8[physmem8_ptr++];
conditional_var = (mem8 >> 3) & 7;
switch (conditional_var) {
2011-12-17 12:16:10 +08:00
case 0:
2011-12-18 21:19:08 +08:00
if ((mem8 >> 6) == 3) {
2011-12-23 20:24:16 +08:00
reg_idx0 = mem8 & 7;
set_lower_word_in_register(reg_idx0, increment_16bit(regs[reg_idx0]));
2011-12-17 12:16:10 +08:00
} else {
2011-12-23 20:24:16 +08:00
mem8_loc = segment_translation(mem8);
2011-12-21 10:43:53 +08:00
x = ld_16bits_mem8_write();
2011-12-23 01:49:18 +08:00
x = increment_16bit(x);
st16_mem8_write(x);
2011-12-17 12:16:10 +08:00
}
break;
case 1:
2011-12-18 21:19:08 +08:00
if ((mem8 >> 6) == 3) {
2011-12-23 20:24:16 +08:00
reg_idx0 = mem8 & 7;
set_lower_word_in_register(reg_idx0, decrement_16bit(regs[reg_idx0]));
2011-12-17 12:16:10 +08:00
} else {
2011-12-23 20:24:16 +08:00
mem8_loc = segment_translation(mem8);
2011-12-21 10:43:53 +08:00
x = ld_16bits_mem8_write();
2011-12-23 01:49:18 +08:00
x = decrement_16bit(x);
st16_mem8_write(x);
2011-12-17 12:16:10 +08:00
}
break;
case 2:
2011-12-18 21:19:08 +08:00
if ((mem8 >> 6) == 3) {
2011-12-21 10:43:53 +08:00
x = regs[mem8 & 7] & 0xffff;
2011-12-17 12:16:10 +08:00
} else {
2011-12-23 20:24:16 +08:00
mem8_loc = segment_translation(mem8);
2011-12-21 10:43:53 +08:00
x = ld_16bits_mem8_read();
2011-12-17 12:16:10 +08:00
}
2011-12-23 20:24:16 +08:00
vd((eip + physmem8_ptr - initial_mem_ptr));
eip = x, physmem8_ptr = initial_mem_ptr = 0;
2011-12-17 12:16:10 +08:00
break;
case 4:
2011-12-18 21:19:08 +08:00
if ((mem8 >> 6) == 3) {
2011-12-21 10:43:53 +08:00
x = regs[mem8 & 7] & 0xffff;
2011-12-17 12:16:10 +08:00
} else {
2011-12-23 20:24:16 +08:00
mem8_loc = segment_translation(mem8);
2011-12-21 10:43:53 +08:00
x = ld_16bits_mem8_read();
2011-12-17 12:16:10 +08:00
}
2011-12-23 20:24:16 +08:00
eip = x, physmem8_ptr = initial_mem_ptr = 0;
2011-12-17 12:16:10 +08:00
break;
case 6:
2011-12-18 21:19:08 +08:00
if ((mem8 >> 6) == 3) {
2011-12-21 10:43:53 +08:00
x = regs[mem8 & 7];
2011-12-17 12:16:10 +08:00
} else {
2011-12-23 20:24:16 +08:00
mem8_loc = segment_translation(mem8);
2011-12-21 10:43:53 +08:00
x = ld_16bits_mem8_read();
2011-12-17 12:16:10 +08:00
}
2011-12-21 10:43:53 +08:00
vd(x);
2011-12-17 12:16:10 +08:00
break;
case 3:
case 5:
2011-12-18 21:19:08 +08:00
if ((mem8 >> 6) == 3)
abort(6);
2011-12-23 20:24:16 +08:00
mem8_loc = segment_translation(mem8);
2011-12-21 10:43:53 +08:00
x = ld_16bits_mem8_read();
mem8_loc = (mem8_loc + 2) >> 0;
y = ld_16bits_mem8_read();
if (conditional_var == 3)
2011-12-23 20:24:16 +08:00
Ze(0, y, x, (eip + physmem8_ptr - initial_mem_ptr));
2011-12-17 12:16:10 +08:00
else
Oe(y, x);
2011-12-17 12:16:10 +08:00
break;
default:
abort(6);
2011-12-17 12:16:10 +08:00
}
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
2011-12-17 12:16:10 +08:00
case 0x1eb:
2011-12-23 20:24:16 +08:00
x = ((phys_mem8[physmem8_ptr++] << 24) >> 24);
eip = (eip + physmem8_ptr - initial_mem_ptr + x) & 0xffff, physmem8_ptr = initial_mem_ptr = 0;
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
2011-12-17 12:16:10 +08:00
case 0x1e9:
2011-12-23 01:49:18 +08:00
x = ld16_mem8_direct();
2011-12-23 20:24:16 +08:00
eip = (eip + physmem8_ptr - initial_mem_ptr + x) & 0xffff, physmem8_ptr = initial_mem_ptr = 0;
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
2011-12-17 12:16:10 +08:00
case 0x170:
case 0x171:
case 0x172:
case 0x173:
case 0x174:
case 0x175:
case 0x176:
case 0x177:
case 0x178:
case 0x179:
case 0x17a:
case 0x17b:
case 0x17c:
case 0x17d:
case 0x17e:
case 0x17f:
2011-12-23 20:24:16 +08:00
x = ((phys_mem8[physmem8_ptr++] << 24) >> 24);
y = check_status_bits_for_jump(OPbyte & 0xf);
if (y)
2011-12-23 20:24:16 +08:00
eip = (eip + physmem8_ptr - initial_mem_ptr + x) & 0xffff, physmem8_ptr = initial_mem_ptr = 0;
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
2011-12-17 12:16:10 +08:00
case 0x1c2:
2011-12-23 01:49:18 +08:00
y = (ld16_mem8_direct() << 16) >> 16;
2011-12-21 10:43:53 +08:00
x = yd();
regs[4] = (regs[4] & ~SS_mask) | ((regs[4] + 2 + y) & SS_mask);
2011-12-23 20:24:16 +08:00
eip = x, physmem8_ptr = initial_mem_ptr = 0;
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
2011-12-17 12:16:10 +08:00
case 0x1c3:
2011-12-21 10:43:53 +08:00
x = yd();
2011-12-17 12:16:10 +08:00
zd();
2011-12-23 20:24:16 +08:00
eip = x, physmem8_ptr = initial_mem_ptr = 0;
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
2011-12-17 12:16:10 +08:00
case 0x1e8:
2011-12-23 01:49:18 +08:00
x = ld16_mem8_direct();
2011-12-23 20:24:16 +08:00
vd((eip + physmem8_ptr - initial_mem_ptr));
eip = (eip + physmem8_ptr - initial_mem_ptr + x) & 0xffff, physmem8_ptr = initial_mem_ptr = 0;
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
2011-12-17 12:16:10 +08:00
case 0x162:
If();
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
2011-12-17 12:16:10 +08:00
case 0x1a5:
lg();
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
2011-12-17 12:16:10 +08:00
case 0x1a7:
ng();
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
2011-12-17 12:16:10 +08:00
case 0x1ad:
og();
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
2011-12-17 12:16:10 +08:00
case 0x1af:
pg();
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
2011-12-17 12:16:10 +08:00
case 0x1ab:
mg();
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
2011-12-17 12:16:10 +08:00
case 0x16d:
jg();
{
2011-12-17 13:38:46 +08:00
if (cpu.hard_irq != 0 && (cpu.eflags & 0x00000200))
2011-12-23 21:44:05 +08:00
break OUTER_LOOP;
2011-12-17 12:16:10 +08:00
}
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
2011-12-17 12:16:10 +08:00
case 0x16f:
kg();
{
2011-12-17 13:38:46 +08:00
if (cpu.hard_irq != 0 && (cpu.eflags & 0x00000200))
2011-12-23 21:44:05 +08:00
break OUTER_LOOP;
2011-12-17 12:16:10 +08:00
}
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
2011-12-17 12:16:10 +08:00
case 0x1e5:
iopl = (cpu.eflags >> 12) & 3;
if (cpu.cpl > iopl)
abort(13);
2011-12-23 20:24:16 +08:00
x = phys_mem8[physmem8_ptr++];
set_lower_word_in_register(0, cpu.ld16_port(x));
2011-12-17 12:16:10 +08:00
{
2011-12-17 13:38:46 +08:00
if (cpu.hard_irq != 0 && (cpu.eflags & 0x00000200))
2011-12-23 21:44:05 +08:00
break OUTER_LOOP;
2011-12-17 12:16:10 +08:00
}
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
2011-12-17 12:16:10 +08:00
case 0x1e7:
iopl = (cpu.eflags >> 12) & 3;
if (cpu.cpl > iopl)
abort(13);
2011-12-23 20:24:16 +08:00
x = phys_mem8[physmem8_ptr++];
2011-12-21 10:43:53 +08:00
cpu.st16_port(x, regs[0] & 0xffff);
2011-12-17 12:16:10 +08:00
{
2011-12-17 13:38:46 +08:00
if (cpu.hard_irq != 0 && (cpu.eflags & 0x00000200))
2011-12-23 21:44:05 +08:00
break OUTER_LOOP;
2011-12-17 12:16:10 +08:00
}
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
2011-12-17 12:16:10 +08:00
case 0x1ed:
iopl = (cpu.eflags >> 12) & 3;
if (cpu.cpl > iopl)
abort(13);
2011-12-23 20:24:16 +08:00
set_lower_word_in_register(0, cpu.ld16_port(regs[2] & 0xffff));
2011-12-17 12:16:10 +08:00
{
2011-12-17 13:38:46 +08:00
if (cpu.hard_irq != 0 && (cpu.eflags & 0x00000200))
2011-12-23 21:44:05 +08:00
break OUTER_LOOP;
2011-12-17 12:16:10 +08:00
}
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
2011-12-17 12:16:10 +08:00
case 0x1ef:
iopl = (cpu.eflags >> 12) & 3;
if (cpu.cpl > iopl)
abort(13);
2011-12-17 16:08:25 +08:00
cpu.st16_port(regs[2] & 0xffff, regs[0] & 0xffff);
2011-12-17 12:16:10 +08:00
{
2011-12-17 13:38:46 +08:00
if (cpu.hard_irq != 0 && (cpu.eflags & 0x00000200))
2011-12-23 21:44:05 +08:00
break OUTER_LOOP;
2011-12-17 12:16:10 +08:00
}
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
2011-12-17 12:16:10 +08:00
case 0x166:
case 0x167:
case 0x1f0:
case 0x1f2:
case 0x1f3:
case 0x126:
case 0x12e:
case 0x136:
case 0x13e:
case 0x164:
case 0x165:
case 0x100:
case 0x108:
case 0x110:
case 0x118:
case 0x120:
case 0x128:
case 0x130:
case 0x138:
case 0x102:
case 0x10a:
case 0x112:
case 0x11a:
case 0x122:
case 0x12a:
case 0x132:
case 0x13a:
case 0x104:
case 0x10c:
case 0x114:
case 0x11c:
case 0x124:
case 0x12c:
case 0x134:
case 0x13c:
case 0x1a0:
case 0x1a2:
case 0x1d8:
case 0x1d9:
case 0x1da:
case 0x1db:
case 0x1dc:
case 0x1dd:
case 0x1de:
case 0x1df:
case 0x184:
case 0x1a8:
case 0x1f6:
case 0x1c0:
case 0x1d0:
case 0x1d2:
case 0x1fe:
case 0x1cd:
case 0x1ce:
case 0x1f5:
case 0x1f8:
case 0x1f9:
case 0x1fc:
case 0x1fd:
case 0x1fa:
case 0x1fb:
case 0x19e:
case 0x19f:
case 0x1f4:
case 0x127:
case 0x12f:
case 0x137:
case 0x13f:
case 0x1d4:
case 0x1d5:
case 0x16c:
case 0x16e:
case 0x1a4:
case 0x1a6:
case 0x1aa:
case 0x1ac:
case 0x1ae:
case 0x180:
case 0x182:
case 0x186:
case 0x188:
case 0x18a:
case 0x18c:
case 0x18e:
case 0x19b:
case 0x1b0:
case 0x1b1:
case 0x1b2:
case 0x1b3:
case 0x1b4:
case 0x1b5:
case 0x1b6:
case 0x1b7:
case 0x1c6:
case 0x1cc:
case 0x1d7:
case 0x1e4:
case 0x1e6:
case 0x1ec:
case 0x1ee:
case 0x1cf:
case 0x1ca:
case 0x1cb:
case 0x19a:
case 0x19c:
case 0x19d:
case 0x1ea:
case 0x1e0:
case 0x1e1:
case 0x1e2:
case 0x1e3:
OPbyte &= 0xff;
2011-12-17 12:16:10 +08:00
break;
case 0x163:
case 0x1d6:
case 0x1f1:
default:
abort(6);
2011-12-17 12:16:10 +08:00
case 0x10f:
2011-12-23 20:24:16 +08:00
OPbyte = phys_mem8[physmem8_ptr++];
OPbyte |= 0x0100;
switch (OPbyte) {
2011-12-17 12:16:10 +08:00
case 0x180:
case 0x181:
case 0x182:
case 0x183:
case 0x184:
case 0x185:
case 0x186:
case 0x187:
case 0x188:
case 0x189:
case 0x18a:
case 0x18b:
case 0x18c:
case 0x18d:
case 0x18e:
case 0x18f:
2011-12-23 01:49:18 +08:00
x = ld16_mem8_direct();
2011-12-21 09:18:08 +08:00
if (check_status_bits_for_jump(OPbyte & 0xf))
2011-12-23 20:24:16 +08:00
eip = (eip + physmem8_ptr - initial_mem_ptr + x) & 0xffff, physmem8_ptr = initial_mem_ptr = 0;
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
2011-12-17 12:16:10 +08:00
case 0x140:
case 0x141:
case 0x142:
case 0x143:
case 0x144:
case 0x145:
case 0x146:
case 0x147:
case 0x148:
case 0x149:
case 0x14a:
case 0x14b:
case 0x14c:
case 0x14d:
case 0x14e:
case 0x14f:
2011-12-23 20:24:16 +08:00
mem8 = phys_mem8[physmem8_ptr++];
2011-12-18 21:19:08 +08:00
if ((mem8 >> 6) == 3) {
2011-12-21 10:43:53 +08:00
x = regs[mem8 & 7];
2011-12-17 12:16:10 +08:00
} else {
2011-12-23 20:24:16 +08:00
mem8_loc = segment_translation(mem8);
2011-12-21 10:43:53 +08:00
x = ld_16bits_mem8_read();
2011-12-17 12:16:10 +08:00
}
2011-12-21 09:18:08 +08:00
if (check_status_bits_for_jump(OPbyte & 0xf))
2011-12-23 20:24:16 +08:00
set_lower_word_in_register((mem8 >> 3) & 7, x);
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
2011-12-17 12:16:10 +08:00
case 0x1b6:
2011-12-23 20:24:16 +08:00
mem8 = phys_mem8[physmem8_ptr++];
reg_idx1 = (mem8 >> 3) & 7;
2011-12-18 21:19:08 +08:00
if ((mem8 >> 6) == 3) {
2011-12-23 20:24:16 +08:00
reg_idx0 = mem8 & 7;
x = (regs[reg_idx0 & 3] >> ((reg_idx0 & 4) << 1)) & 0xff;
2011-12-17 12:16:10 +08:00
} else {
2011-12-23 20:24:16 +08:00
mem8_loc = segment_translation(mem8);
2011-12-21 10:43:53 +08:00
x = ld_8bits_mem8_read();
2011-12-17 12:16:10 +08:00
}
2011-12-23 20:24:16 +08:00
set_lower_word_in_register(reg_idx1, x);
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
2011-12-17 12:16:10 +08:00
case 0x1be:
2011-12-23 20:24:16 +08:00
mem8 = phys_mem8[physmem8_ptr++];
reg_idx1 = (mem8 >> 3) & 7;
2011-12-18 21:19:08 +08:00
if ((mem8 >> 6) == 3) {
2011-12-23 20:24:16 +08:00
reg_idx0 = mem8 & 7;
x = (regs[reg_idx0 & 3] >> ((reg_idx0 & 4) << 1));
2011-12-17 12:16:10 +08:00
} else {
2011-12-23 20:24:16 +08:00
mem8_loc = segment_translation(mem8);
2011-12-21 10:43:53 +08:00
x = ld_8bits_mem8_read();
2011-12-17 12:16:10 +08:00
}
2011-12-23 20:24:16 +08:00
set_lower_word_in_register(reg_idx1, (((x) << 24) >> 24));
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
2011-12-17 12:16:10 +08:00
case 0x1af:
2011-12-23 20:24:16 +08:00
mem8 = phys_mem8[physmem8_ptr++];
reg_idx1 = (mem8 >> 3) & 7;
2011-12-18 21:19:08 +08:00
if ((mem8 >> 6) == 3) {
y = regs[mem8 & 7];
2011-12-17 12:16:10 +08:00
} else {
2011-12-23 20:24:16 +08:00
mem8_loc = segment_translation(mem8);
y = ld_16bits_mem8_read();
2011-12-17 12:16:10 +08:00
}
2011-12-23 20:24:16 +08:00
set_lower_word_in_register(reg_idx1, Rc(regs[reg_idx1], y));
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
2011-12-17 12:16:10 +08:00
case 0x1c1:
2011-12-23 20:24:16 +08:00
mem8 = phys_mem8[physmem8_ptr++];
reg_idx1 = (mem8 >> 3) & 7;
2011-12-18 21:19:08 +08:00
if ((mem8 >> 6) == 3) {
2011-12-23 20:24:16 +08:00
reg_idx0 = mem8 & 7;
x = regs[reg_idx0];
y = do_16bit_math(0, x, regs[reg_idx1]);
set_lower_word_in_register(reg_idx1, x);
set_lower_word_in_register(reg_idx0, y);
2011-12-17 12:16:10 +08:00
} else {
2011-12-23 20:24:16 +08:00
mem8_loc = segment_translation(mem8);
2011-12-21 10:43:53 +08:00
x = ld_16bits_mem8_write();
2011-12-23 20:24:16 +08:00
y = do_16bit_math(0, x, regs[reg_idx1]);
st16_mem8_write(y);
2011-12-23 20:24:16 +08:00
set_lower_word_in_register(reg_idx1, x);
2011-12-17 12:16:10 +08:00
}
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
2011-12-17 12:16:10 +08:00
case 0x1a0:
case 0x1a8:
vd(cpu.segs[(OPbyte >> 3) & 7].selector);
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
2011-12-17 12:16:10 +08:00
case 0x1a1:
case 0x1a9:
Ie((OPbyte >> 3) & 7, yd());
2011-12-17 12:16:10 +08:00
zd();
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
2011-12-17 12:16:10 +08:00
case 0x1b2:
case 0x1b4:
case 0x1b5:
Vf(OPbyte & 7);
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
2011-12-17 12:16:10 +08:00
case 0x1a4:
case 0x1ac:
2011-12-23 20:24:16 +08:00
mem8 = phys_mem8[physmem8_ptr++];
y = regs[(mem8 >> 3) & 7];
conditional_var = (OPbyte >> 3) & 1;
2011-12-18 21:19:08 +08:00
if ((mem8 >> 6) == 3) {
2011-12-23 20:24:16 +08:00
z = phys_mem8[physmem8_ptr++];
reg_idx0 = mem8 & 7;
set_lower_word_in_register(reg_idx0, oc(conditional_var, regs[reg_idx0], y, z));
2011-12-17 12:16:10 +08:00
} else {
2011-12-23 20:24:16 +08:00
mem8_loc = segment_translation(mem8);
z = phys_mem8[physmem8_ptr++];
2011-12-21 10:43:53 +08:00
x = ld_16bits_mem8_write();
x = oc(conditional_var, x, y, z);
st16_mem8_write(x);
2011-12-17 12:16:10 +08:00
}
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
2011-12-17 12:16:10 +08:00
case 0x1a5:
case 0x1ad:
2011-12-23 20:24:16 +08:00
mem8 = phys_mem8[physmem8_ptr++];
y = regs[(mem8 >> 3) & 7];
z = regs[1];
conditional_var = (OPbyte >> 3) & 1;
2011-12-18 21:19:08 +08:00
if ((mem8 >> 6) == 3) {
2011-12-23 20:24:16 +08:00
reg_idx0 = mem8 & 7;
set_lower_word_in_register(reg_idx0, oc(conditional_var, regs[reg_idx0], y, z));
2011-12-17 12:16:10 +08:00
} else {
2011-12-23 20:24:16 +08:00
mem8_loc = segment_translation(mem8);
2011-12-21 10:43:53 +08:00
x = ld_16bits_mem8_write();
x = oc(conditional_var, x, y, z);
st16_mem8_write(x);
2011-12-17 12:16:10 +08:00
}
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
2011-12-17 12:16:10 +08:00
case 0x1ba:
2011-12-23 20:24:16 +08:00
mem8 = phys_mem8[physmem8_ptr++];
conditional_var = (mem8 >> 3) & 7;
switch (conditional_var) {
2011-12-17 12:16:10 +08:00
case 4:
2011-12-18 21:19:08 +08:00
if ((mem8 >> 6) == 3) {
2011-12-21 10:43:53 +08:00
x = regs[mem8 & 7];
2011-12-23 20:24:16 +08:00
y = phys_mem8[physmem8_ptr++];
2011-12-17 12:16:10 +08:00
} else {
2011-12-23 20:24:16 +08:00
mem8_loc = segment_translation(mem8);
y = phys_mem8[physmem8_ptr++];
2011-12-21 10:43:53 +08:00
x = ld_16bits_mem8_read();
2011-12-17 12:16:10 +08:00
}
tc(x, y);
2011-12-17 12:16:10 +08:00
break;
case 5:
case 6:
case 7:
2011-12-18 21:19:08 +08:00
if ((mem8 >> 6) == 3) {
2011-12-23 20:24:16 +08:00
reg_idx0 = mem8 & 7;
y = phys_mem8[physmem8_ptr++];
regs[reg_idx0] = vc(conditional_var & 3, regs[reg_idx0], y);
2011-12-17 12:16:10 +08:00
} else {
2011-12-23 20:24:16 +08:00
mem8_loc = segment_translation(mem8);
y = phys_mem8[physmem8_ptr++];
2011-12-21 10:43:53 +08:00
x = ld_16bits_mem8_write();
x = vc(conditional_var & 3, x, y);
st16_mem8_write(x);
2011-12-17 12:16:10 +08:00
}
break;
default:
abort(6);
2011-12-17 12:16:10 +08:00
}
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
2011-12-17 12:16:10 +08:00
case 0x1a3:
2011-12-23 20:24:16 +08:00
mem8 = phys_mem8[physmem8_ptr++];
y = regs[(mem8 >> 3) & 7];
2011-12-18 21:19:08 +08:00
if ((mem8 >> 6) == 3) {
2011-12-21 10:43:53 +08:00
x = regs[mem8 & 7];
2011-12-17 12:16:10 +08:00
} else {
2011-12-23 20:24:16 +08:00
mem8_loc = segment_translation(mem8);
mem8_loc = (mem8_loc + (((y & 0xffff) >> 4) << 1)) >> 0;
2011-12-21 10:43:53 +08:00
x = ld_16bits_mem8_read();
2011-12-17 12:16:10 +08:00
}
tc(x, y);
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
2011-12-17 12:16:10 +08:00
case 0x1ab:
case 0x1b3:
case 0x1bb:
2011-12-23 20:24:16 +08:00
mem8 = phys_mem8[physmem8_ptr++];
y = regs[(mem8 >> 3) & 7];
conditional_var = (OPbyte >> 3) & 3;
2011-12-18 21:19:08 +08:00
if ((mem8 >> 6) == 3) {
2011-12-23 20:24:16 +08:00
reg_idx0 = mem8 & 7;
set_lower_word_in_register(reg_idx0, vc(conditional_var, regs[reg_idx0], y));
2011-12-17 12:16:10 +08:00
} else {
2011-12-23 20:24:16 +08:00
mem8_loc = segment_translation(mem8);
mem8_loc = (mem8_loc + (((y & 0xffff) >> 4) << 1)) >> 0;
2011-12-21 10:43:53 +08:00
x = ld_16bits_mem8_write();
x = vc(conditional_var, x, y);
st16_mem8_write(x);
2011-12-17 12:16:10 +08:00
}
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
2011-12-17 12:16:10 +08:00
case 0x1bc:
case 0x1bd:
2011-12-23 20:24:16 +08:00
mem8 = phys_mem8[physmem8_ptr++];
reg_idx1 = (mem8 >> 3) & 7;
2011-12-18 21:19:08 +08:00
if ((mem8 >> 6) == 3) {
y = regs[mem8 & 7];
2011-12-17 12:16:10 +08:00
} else {
2011-12-23 20:24:16 +08:00
mem8_loc = segment_translation(mem8);
y = ld_16bits_mem8_read();
2011-12-17 12:16:10 +08:00
}
2011-12-23 20:24:16 +08:00
x = regs[reg_idx1];
if (OPbyte & 1)
x = Ac(x, y);
2011-12-17 12:16:10 +08:00
else
x = yc(x, y);
2011-12-23 20:24:16 +08:00
set_lower_word_in_register(reg_idx1, x);
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
2011-12-17 12:16:10 +08:00
case 0x1b1:
2011-12-23 20:24:16 +08:00
mem8 = phys_mem8[physmem8_ptr++];
reg_idx1 = (mem8 >> 3) & 7;
2011-12-18 21:19:08 +08:00
if ((mem8 >> 6) == 3) {
2011-12-23 20:24:16 +08:00
reg_idx0 = mem8 & 7;
x = regs[reg_idx0];
y = do_16bit_math(5, regs[0], x);
if (y == 0) {
2011-12-23 20:24:16 +08:00
set_lower_word_in_register(reg_idx0, regs[reg_idx1]);
2011-12-17 12:16:10 +08:00
} else {
2011-12-23 20:24:16 +08:00
set_lower_word_in_register(0, x);
2011-12-17 12:16:10 +08:00
}
} else {
2011-12-23 20:24:16 +08:00
mem8_loc = segment_translation(mem8);
2011-12-21 10:43:53 +08:00
x = ld_16bits_mem8_write();
y = do_16bit_math(5, regs[0], x);
if (y == 0) {
2011-12-23 20:24:16 +08:00
st16_mem8_write(regs[reg_idx1]);
2011-12-17 12:16:10 +08:00
} else {
2011-12-23 20:24:16 +08:00
set_lower_word_in_register(0, x);
2011-12-17 12:16:10 +08:00
}
}
2011-12-23 21:44:05 +08:00
break EXEC_LOOP;
2011-12-17 12:16:10 +08:00
case 0x100:
case 0x101:
case 0x102:
case 0x103:
case 0x120:
case 0x122:
case 0x106:
case 0x123:
case 0x1a2:
case 0x131:
case 0x190:
case 0x191:
case 0x192:
case 0x193:
case 0x194:
case 0x195:
case 0x196:
case 0x197:
case 0x198:
case 0x199:
case 0x19a:
case 0x19b:
case 0x19c:
case 0x19d:
case 0x19e:
case 0x19f:
case 0x1b0:
OPbyte = 0x0f;
2011-12-23 20:24:16 +08:00
physmem8_ptr--;
2011-12-17 12:16:10 +08:00
break;
case 0x104:
case 0x105:
case 0x107:
case 0x108:
case 0x109:
case 0x10a:
case 0x10b:
case 0x10c:
case 0x10d:
case 0x10e:
case 0x10f:
case 0x110:
case 0x111:
case 0x112:
case 0x113:
case 0x114:
case 0x115:
case 0x116:
case 0x117:
case 0x118:
case 0x119:
case 0x11a:
case 0x11b:
case 0x11c:
case 0x11d:
case 0x11e:
case 0x11f:
case 0x121:
case 0x124:
case 0x125:
case 0x126:
case 0x127:
case 0x128:
case 0x129:
case 0x12a:
case 0x12b:
case 0x12c:
case 0x12d:
case 0x12e:
case 0x12f:
case 0x130:
case 0x132:
case 0x133:
case 0x134:
case 0x135:
case 0x136:
case 0x137:
case 0x138:
case 0x139:
case 0x13a:
case 0x13b:
case 0x13c:
case 0x13d:
case 0x13e:
case 0x13f:
case 0x150:
case 0x151:
case 0x152:
case 0x153:
case 0x154:
case 0x155:
case 0x156:
case 0x157:
case 0x158:
case 0x159:
case 0x15a:
case 0x15b:
case 0x15c:
case 0x15d:
case 0x15e:
case 0x15f:
case 0x160:
case 0x161:
case 0x162:
case 0x163:
case 0x164:
case 0x165:
case 0x166:
case 0x167:
case 0x168:
case 0x169:
case 0x16a:
case 0x16b:
case 0x16c:
case 0x16d:
case 0x16e:
case 0x16f:
case 0x170:
case 0x171:
case 0x172:
case 0x173:
case 0x174:
case 0x175:
case 0x176:
case 0x177:
case 0x178:
case 0x179:
case 0x17a:
case 0x17b:
case 0x17c:
case 0x17d:
case 0x17e:
case 0x17f:
case 0x1a6:
case 0x1a7:
case 0x1aa:
case 0x1ae:
case 0x1b7:
case 0x1b8:
case 0x1b9:
case 0x1bf:
case 0x1c0:
default:
abort(6);
2011-12-17 12:16:10 +08:00
}
break;
}
}
}
2011-12-21 10:28:01 +08:00
} while (--cycles_left); //End Giant Core DO WHILE Execution Loop
this.cycle_count += (N_cycles - cycles_left);
2011-12-23 20:24:16 +08:00
this.eip = (eip + physmem8_ptr - initial_mem_ptr);
2011-12-17 20:22:50 +08:00
this.cc_src = _src;
this.cc_dst = _dst;
this.cc_op = _op;
this.cc_op2 = _op2;
this.cc_dst2 = _dst2;
return exit_code;
2011-12-17 12:16:10 +08:00
};
2011-12-17 13:13:37 +08:00
2011-12-21 10:28:01 +08:00
CPU_X86.prototype.exec = function(N_cycles) {
2011-12-23 21:15:54 +08:00
var Dg, exit_code, final_cycle_count, interrupt;
2011-12-21 10:28:01 +08:00
final_cycle_count = this.cycle_count + N_cycles;
exit_code = 256;
2011-12-23 21:15:54 +08:00
interrupt = null;
2011-12-21 10:28:01 +08:00
while (this.cycle_count < final_cycle_count) {
2011-12-17 12:16:10 +08:00
try {
2011-12-23 21:15:54 +08:00
exit_code = this.exec_internal(final_cycle_count - this.cycle_count, interrupt);
if (exit_code != 256)
2011-12-17 12:16:10 +08:00
break;
2011-12-23 21:15:54 +08:00
interrupt = null;
2011-12-17 12:16:10 +08:00
} catch (Fg) {
if (Fg.hasOwnProperty("intno")) {
2011-12-23 21:15:54 +08:00
interrupt = Fg;
2011-12-17 12:16:10 +08:00
} else {
throw Fg;
}
}
}
return exit_code;
2011-12-17 12:16:10 +08:00
};
2011-12-17 13:13:37 +08:00
CPU_X86.prototype.load_binary_ie9 = function(Gg, mem8_loc) {
2011-12-17 12:16:10 +08:00
var Hg, Ig, tg, i;
Hg = new XMLHttpRequest();
Hg.open('GET', Gg, false);
Hg.send(null);
if (Hg.status != 200 && Hg.status != 0) {
throw "Error while loading " + Gg;
}
Ig = new VBArray(Hg.responseBody).toArray();
tg = Ig.length;
for (i = 0; i < tg; i++) {
this.st8_phys(mem8_loc + i, Ig[i]);
2011-12-17 12:16:10 +08:00
}
return tg;
};
2011-12-17 13:13:37 +08:00
CPU_X86.prototype.load_binary = function(Gg, mem8_loc) {
2011-12-17 12:16:10 +08:00
var Hg, Ig, tg, i, Jg, Kg;
if (typeof ActiveXObject == "function")
return this.load_binary_ie9(Gg, mem8_loc);
2011-12-17 12:16:10 +08:00
Hg = new XMLHttpRequest();
Hg.open('GET', Gg, false);
Kg = ('ArrayBuffer' in window && 'Uint8Array' in window);
if (Kg && 'mozResponseType' in Hg) {
Hg.mozResponseType = 'arraybuffer';
} else if (Kg && 'responseType' in Hg) {
Hg.responseType = 'arraybuffer';
} else {
Hg.overrideMimeType('text/plain; charset=x-user-defined');
Kg = false;
}
Hg.send(null);
if (Hg.status != 200 && Hg.status != 0) {
throw "Error while loading " + Gg;
}
if (Kg && 'mozResponse' in Hg) {
Ig = Hg.mozResponse;
} else if (Kg && Hg.mozResponseArrayBuffer) {
Ig = Hg.mozResponseArrayBuffer;
} else if ('responseType' in Hg) {
Ig = Hg.response;
} else {
Ig = Hg.responseText;
Kg = false;
}
if (Kg) {
tg = Ig.byteLength;
Jg = new Uint8Array(Ig, 0, tg);
for (i = 0; i < tg; i++) {
this.st8_phys(mem8_loc + i, Jg[i]);
2011-12-17 12:16:10 +08:00
}
} else {
tg = Ig.length;
for (i = 0; i < tg; i++) {
this.st8_phys(mem8_loc + i, Ig.charCodeAt(i));
2011-12-17 12:16:10 +08:00
}
}
return tg;
};
2011-12-23 20:24:16 +08:00
2011-12-23 21:15:54 +08:00
2011-12-23 20:24:16 +08:00
2011-12-23 21:44:05 +08:00
2011-12-23 20:24:16 +08:00