Restructured ModRM decoding
This commit is contained in:
parent
1ede9acf15
commit
418f3bd603
13 changed files with 6175 additions and 6516 deletions
302
bin/README
302
bin/README
|
|
@ -1,302 +0,0 @@
|
|||
/*
|
||||
* Copyright 2009 The Closure Compiler Authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
//
|
||||
// Contents
|
||||
//
|
||||
|
||||
The Closure Compiler performs checking, instrumentation, and
|
||||
optimizations on JavaScript code. The purpose of this README is to
|
||||
explain how to build and run the Closure Compiler.
|
||||
|
||||
The Closure Compiler requires Java 7 or higher.
|
||||
http://www.java.com/
|
||||
|
||||
|
||||
//
|
||||
// Building The Closure Compiler
|
||||
//
|
||||
|
||||
There are three ways to get a Closure Compiler executable.
|
||||
|
||||
1) Use one we built for you.
|
||||
|
||||
Pre-built Closure binaries can be found at
|
||||
http://code.google.com/p/closure-compiler/downloads/list
|
||||
|
||||
|
||||
2) Check out the source and build it with Apache Ant.
|
||||
|
||||
First, check out the full source tree of the Closure Compiler. There
|
||||
are instructions on how to do this at the project site.
|
||||
http://code.google.com/p/closure-compiler/source/checkout
|
||||
|
||||
Apache Ant is a cross-platform build tool.
|
||||
http://ant.apache.org/
|
||||
|
||||
At the root of the source tree, there is an Ant file named
|
||||
build.xml. To use it, navigate to the same directory and type the
|
||||
command
|
||||
|
||||
ant jar
|
||||
|
||||
This will produce a jar file called "build/compiler.jar".
|
||||
|
||||
|
||||
3) Check out the source and build it with Eclipse.
|
||||
|
||||
Eclipse is a cross-platform IDE.
|
||||
http://www.eclipse.org/
|
||||
|
||||
Under Eclipse's File menu, click "New > Project ..." and create a
|
||||
"Java Project." You will see an options screen. Give the project a
|
||||
name, select "Create project from existing source," and choose the
|
||||
root of the checked-out source tree as the existing directory. Verify
|
||||
that you are using JRE version 7 or higher.
|
||||
|
||||
Eclipse can use the build.xml file to discover rules. When you
|
||||
navigate to the build.xml file, you will see all the build rules in
|
||||
the "Outline" pane. Run the "jar" rule to build the compiler in
|
||||
build/compiler.jar.
|
||||
|
||||
|
||||
//
|
||||
// Running The Closure Compiler
|
||||
//
|
||||
|
||||
Once you have the jar binary, running the Closure Compiler is straightforward.
|
||||
|
||||
On the command line, type
|
||||
|
||||
java -jar compiler.jar
|
||||
|
||||
This starts the compiler in interactive mode. Type
|
||||
|
||||
var x = 17 + 25;
|
||||
|
||||
then hit "Enter", then hit "Ctrl-Z" (on Windows) or "Ctrl-D" (on Mac or Linux)
|
||||
and "Enter" again. The Compiler will respond:
|
||||
|
||||
var x=42;
|
||||
|
||||
The Closure Compiler has many options for reading input from a file,
|
||||
writing output to a file, checking your code, and running
|
||||
optimizations. To learn more, type
|
||||
|
||||
java -jar compiler.jar --help
|
||||
|
||||
You can read more detailed documentation about the many flags at
|
||||
http://code.google.com/closure/compiler/docs/gettingstarted_app.html
|
||||
|
||||
|
||||
//
|
||||
// Compiling Multiple Scripts
|
||||
//
|
||||
|
||||
If you have multiple scripts, you should compile them all together with
|
||||
one compile command.
|
||||
|
||||
java -jar compiler.jar --js=in1.js --js=in2.js ... --js_output_file=out.js
|
||||
|
||||
The Closure Compiler will concatenate the files in the order they're
|
||||
passed at the command line.
|
||||
|
||||
If you need to compile many, many scripts together, you may start to
|
||||
run into problems with managing dependencies between scripts. You
|
||||
should check out the Closure Library. It contains functions for
|
||||
enforcing dependencies between scripts, and a tool called calcdeps.py
|
||||
that knows how to give scripts to the Closure Compiler in the right
|
||||
order.
|
||||
|
||||
http://code.google.com/p/closure-library/
|
||||
|
||||
//
|
||||
// Licensing
|
||||
//
|
||||
|
||||
Unless otherwise stated, all source files are licensed under
|
||||
the Apache License, Version 2.0.
|
||||
|
||||
|
||||
-----
|
||||
Code under:
|
||||
src/com/google/javascript/rhino
|
||||
test/com/google/javascript/rhino
|
||||
|
||||
URL: http://www.mozilla.org/rhino
|
||||
Version: 1.5R3, with heavy modifications
|
||||
License: Netscape Public License and MPL / GPL dual license
|
||||
|
||||
Description: A partial copy of Mozilla Rhino. Mozilla Rhino is an
|
||||
implementation of JavaScript for the JVM. The JavaScript parser and
|
||||
the parse tree data structures were extracted and modified
|
||||
significantly for use by Google's JavaScript compiler.
|
||||
|
||||
Local Modifications: The packages have been renamespaced. All code not
|
||||
relevant to parsing has been removed. A JsDoc parser and static typing
|
||||
system have been added.
|
||||
|
||||
|
||||
-----
|
||||
Code in:
|
||||
lib/rhino
|
||||
|
||||
Rhino
|
||||
URL: http://www.mozilla.org/rhino
|
||||
Version: Trunk
|
||||
License: Netscape Public License and MPL / GPL dual license
|
||||
|
||||
Description: Mozilla Rhino is an implementation of JavaScript for the JVM.
|
||||
|
||||
Local Modifications: Minor changes to parsing JSDoc that usually get pushed
|
||||
up-stream to Rhino trunk.
|
||||
|
||||
|
||||
-----
|
||||
Code in:
|
||||
lib/args4j.jar
|
||||
|
||||
Args4j
|
||||
URL: https://args4j.dev.java.net/
|
||||
Version: 2.0.16
|
||||
License: MIT
|
||||
|
||||
Description:
|
||||
args4j is a small Java class library that makes it easy to parse command line
|
||||
options/arguments in your CUI application.
|
||||
|
||||
Local Modifications: None.
|
||||
|
||||
|
||||
-----
|
||||
Code in:
|
||||
lib/guava.jar
|
||||
|
||||
Guava Libraries
|
||||
URL: http://code.google.com/p/guava-libraries/
|
||||
Version: 15.0
|
||||
License: Apache License 2.0
|
||||
|
||||
Description: Google's core Java libraries.
|
||||
|
||||
Local Modifications: None.
|
||||
|
||||
|
||||
-----
|
||||
Code in:
|
||||
lib/jsr305.jar
|
||||
|
||||
Annotations for software defect detection
|
||||
URL: http://code.google.com/p/jsr-305/
|
||||
Version: svn revision 47
|
||||
License: BSD License
|
||||
|
||||
Description: Annotations for software defect detection.
|
||||
|
||||
Local Modifications: None.
|
||||
|
||||
|
||||
-----
|
||||
Code in:
|
||||
lib/jarjar.jar
|
||||
|
||||
Jar Jar Links
|
||||
URL: http://jarjar.googlecode.com/
|
||||
Version: 1.1
|
||||
License: Apache License 2.0
|
||||
|
||||
Description:
|
||||
A utility for repackaging Java libraries.
|
||||
|
||||
Local Modifications: None.
|
||||
|
||||
|
||||
----
|
||||
Code in:
|
||||
lib/junit.jar
|
||||
|
||||
JUnit
|
||||
URL: http://sourceforge.net/projects/junit/
|
||||
Version: 4.10
|
||||
License: Common Public License 1.0
|
||||
|
||||
Description: A framework for writing and running automated tests in Java.
|
||||
|
||||
Local Modifications: None.
|
||||
|
||||
|
||||
---
|
||||
Code in:
|
||||
lib/protobuf-java.jar
|
||||
|
||||
Protocol Buffers
|
||||
URL: http://code.google.com/p/protobuf/
|
||||
Version: 2.4.1
|
||||
License: New BSD License
|
||||
|
||||
Description: Supporting libraries for protocol buffers,
|
||||
an encoding of structured data.
|
||||
|
||||
Local Modifications: None
|
||||
|
||||
|
||||
---
|
||||
Code in:
|
||||
lib/ant.jar
|
||||
lib/ant-launcher.jar
|
||||
|
||||
URL: http://ant.apache.org/bindownload.cgi
|
||||
Version: 1.8.1
|
||||
License: Apache License 2.0
|
||||
Description:
|
||||
Ant is a Java based build tool. In theory it is kind of like "make"
|
||||
without make's wrinkles and with the full portability of pure java code.
|
||||
|
||||
Local Modifications: None
|
||||
|
||||
|
||||
---
|
||||
Code in:
|
||||
lib/json.jar
|
||||
URL: http://json.org/java/index.html
|
||||
Version: JSON version 20090211
|
||||
License: MIT license
|
||||
Description:
|
||||
JSON is a set of java files for use in transmitting data in JSON format.
|
||||
|
||||
Local Modifications: None
|
||||
|
||||
---
|
||||
Code in
|
||||
lib/mockito-core.jar
|
||||
URL: https://code.google.com/p/mockito
|
||||
Version: 1.9.5
|
||||
License: MIT license
|
||||
Description:
|
||||
Mockito is an open source testing framework for Java. The framework allows the creation of Test Double objects (called "Mock Objects") in automated unit tests for the purpose of Test-driven Development (TDD) or Behavior Driven Development (BDD).
|
||||
|
||||
Local Modifications: None
|
||||
|
||||
---
|
||||
Code in
|
||||
lib/objenesis.jar
|
||||
URL: http://objenesis.org
|
||||
Version: 1.2
|
||||
License: Apache 2.0 license
|
||||
Description:
|
||||
Depended by lib/mockito-core.jar, not used directly.
|
||||
|
||||
Local Modifications: None
|
||||
BIN
bin/compiler.jar
BIN
bin/compiler.jar
Binary file not shown.
File diff suppressed because it is too large
Load diff
|
|
@ -3323,7 +3323,7 @@ ChipSet.prototype.getIRRVector = function(iPIC)
|
|||
|
||||
var nIRQ = pic.nIRQBase + nIRL;
|
||||
if (DEBUG && this.messageEnabled(this.messageBitsIRQ(nIRQ))) {
|
||||
this.printMessage("getIRRVector(): IRQ " + nIRQ + " interrupting @" + str.toHexAddr(this.cpu.regIP, this.cpu.segCS.sel) + " stack=" + str.toHexAddr(this.cpu.regESP, this.cpu.segSS.sel), true);
|
||||
this.printMessage("getIRRVector(): IRQ " + nIRQ + " interrupting @" + str.toHexAddr(this.cpu.regEIP, this.cpu.segCS.sel) + " stack=" + str.toHexAddr(this.cpu.regESP, this.cpu.segSS.sel), true);
|
||||
}
|
||||
if (MAXDEBUG && DEBUGGER) {
|
||||
this.acInterrupts[nIRQ]++;
|
||||
|
|
|
|||
|
|
@ -1580,7 +1580,7 @@ if (DEBUGGER) {
|
|||
this.aMessageRegs[asRegs[17]] = str.toHexWord(cpu.segCS.sel);
|
||||
this.aMessageRegs[asRegs[18]] = str.toHexWord(cpu.segSS.sel);
|
||||
this.aMessageRegs[asRegs[19]] = str.toHexWord(cpu.segDS.sel);
|
||||
this.aMessageRegs[asRegs[20]] = str.toHexWord(cpu.regIP);
|
||||
this.aMessageRegs[asRegs[20]] = str.toHexWord(cpu.regEIP);
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -1593,7 +1593,7 @@ if (DEBUGGER) {
|
|||
Debugger.prototype.message = function(sMessage, fAddress)
|
||||
{
|
||||
if (fAddress) {
|
||||
sMessage += " @" + str.toHexAddr(this.cpu.regIP, this.cpu.segCS.sel);
|
||||
sMessage += " @" + str.toHexAddr(this.cpu.regEIP, this.cpu.segCS.sel);
|
||||
}
|
||||
|
||||
if (this.sMessagePrev && sMessage == this.sMessagePrev) return;
|
||||
|
|
@ -1737,7 +1737,7 @@ if (DEBUGGER) {
|
|||
if (this.traceEnabled !== undefined && this.traceEnabled[prop]) {
|
||||
var trace = Debugger.TRACE[prop];
|
||||
var len = (trace.size >> 2);
|
||||
var s = str.toHexAddr(this.cpu.opEA - this.cpu.segCS.base, this.cpu.segCS.sel) + " " + Debugger.asIns[trace.ins] + "(" + str.toHex(dst, len) + "," + str.toHex(src, len) + "," + (flagsIn === null? "-" : str.toHexWord(flagsIn)) + ") " + str.toHex(result, len) + "," + (flagsOut === null? "-" : str.toHexWord(flagsOut));
|
||||
var s = str.toHexAddr(this.cpu.opLIP - this.cpu.segCS.base, this.cpu.segCS.sel) + " " + Debugger.asIns[trace.ins] + "(" + str.toHex(dst, len) + "," + str.toHex(src, len) + "," + (flagsIn === null? "-" : str.toHexWord(flagsIn)) + ") " + str.toHex(result, len) + "," + (flagsOut === null? "-" : str.toHexWord(flagsOut));
|
||||
if (!this.aTraceBuffer.length) this.aTraceBuffer = new Array(Debugger.TRACE_LIMIT);
|
||||
this.aTraceBuffer[this.iTraceBuffer++] = s;
|
||||
if (this.iTraceBuffer >= this.aTraceBuffer.length) {
|
||||
|
|
@ -1840,7 +1840,7 @@ if (DEBUGGER) {
|
|||
* is good for avoiding breakpoints, but bad for our instruction data collection if
|
||||
* checks are enabled.
|
||||
*/
|
||||
if (this.checksEnabled()) this.checkInstruction(this.cpu.regEIP, true);
|
||||
if (this.checksEnabled()) this.checkInstruction(this.cpu.regLIP, true);
|
||||
}
|
||||
try {
|
||||
var nCyclesStep = this.cpu.stepCPU(nCycles);
|
||||
|
|
@ -1893,7 +1893,7 @@ if (DEBUGGER) {
|
|||
if (fRegs === undefined) fRegs = true;
|
||||
if (fCompact === undefined) fCompact = true;
|
||||
|
||||
this.aAddrNextCode = this.newAddr(this.cpu.regIP, this.cpu.segCS.sel);
|
||||
this.aAddrNextCode = this.newAddr(this.cpu.regEIP, this.cpu.segCS.sel);
|
||||
/*
|
||||
* this.fProcStep used to be a simple boolean, but now it's 0 (or undefined)
|
||||
* if inactive, 1 if stepping over an instruction without a register dump, or 2
|
||||
|
|
@ -1979,7 +1979,7 @@ if (DEBUGGER) {
|
|||
this.historyInit();
|
||||
this.cInstructions = 0;
|
||||
this.nCycles = 0;
|
||||
this.aAddrNextCode = this.newAddr(this.cpu.regIP, this.cpu.segCS.sel);
|
||||
this.aAddrNextCode = this.newAddr(this.cpu.regEIP, this.cpu.segCS.sel);
|
||||
/*
|
||||
* fRunning is set by start() and cleared by stop(). In addition, we clear
|
||||
* it here, so that if the CPU is reset while running, we can prevent stop()
|
||||
|
|
@ -2109,7 +2109,7 @@ if (DEBUGGER) {
|
|||
}
|
||||
this.updateStatus(true, this.fProcStep != 2);
|
||||
this.setFocus();
|
||||
this.clearTempBreakpoint(this.cpu.regEIP);
|
||||
this.clearTempBreakpoint(this.cpu.regLIP);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -2168,12 +2168,12 @@ if (DEBUGGER) {
|
|||
* This is a good example of what NOT to do in a high-frequency function, and defeats
|
||||
* the purpose of preallocating and preinitializing the history array in historyInit():
|
||||
*
|
||||
* this.aOpcodeHistory[this.iOpcodeHistory] = this.newAddr(this.cpu.regIP, this.cpu.segCS.sel, addr);
|
||||
* this.aOpcodeHistory[this.iOpcodeHistory] = this.newAddr(this.cpu.regEIP, this.cpu.segCS.sel, addr);
|
||||
*
|
||||
* As the name implies, newAddr() returns a new "Addr" (Array) object every time it's called.
|
||||
*/
|
||||
var a = this.aOpcodeHistory[this.iOpcodeHistory];
|
||||
a[0] = this.cpu.regIP;
|
||||
a[0] = this.cpu.regEIP;
|
||||
a[1] = this.cpu.segCS.sel;
|
||||
a[2] = addr;
|
||||
if (++this.iOpcodeHistory == this.aOpcodeHistory.length) this.iOpcodeHistory = 0;
|
||||
|
|
@ -3044,7 +3044,7 @@ if (DEBUGGER) {
|
|||
" DI=" + str.toHexWord(this.cpu.regEDI) + '\n';
|
||||
s += this.getSegStr(this.cpu.segDS, fProt) + ' ' + this.getSegStr(this.cpu.segES, fProt) + ' ' + this.getSegStr(this.cpu.segSS, fProt);
|
||||
s += (fProt? '\n' : ' ');
|
||||
s += this.getSegStr(this.cpu.segCS, fProt) + " IP=" + str.toHexWord(this.cpu.regIP) +
|
||||
s += this.getSegStr(this.cpu.segCS, fProt) + " IP=" + str.toHexWord(this.cpu.regEIP) +
|
||||
this.getFlagStr("V") + this.getFlagStr("D") + this.getFlagStr("I") + this.getFlagStr("T") +
|
||||
this.getFlagStr("S") + this.getFlagStr("Z") + this.getFlagStr("A") + this.getFlagStr("P") + this.getFlagStr("C") +
|
||||
" PS=" + str.toHexWord(this.cpu.getPS());
|
||||
|
|
@ -3174,7 +3174,7 @@ if (DEBUGGER) {
|
|||
* treat "PC" as an alias for the 16-bit flags register. So for purposes of parseValue(), "PC" has been removed.
|
||||
*/
|
||||
case "IP":
|
||||
value = this.cpu.regIP;
|
||||
value = this.cpu.regEIP;
|
||||
break;
|
||||
default:
|
||||
value = str.parseInt(sValue);
|
||||
|
|
@ -4342,12 +4342,12 @@ if (DEBUGGER) {
|
|||
case "CS":
|
||||
// fIns = true;
|
||||
this.cpu.setCS(w);
|
||||
this.aAddrNextCode = this.newAddr(this.cpu.regIP, this.cpu.segCS.sel);
|
||||
this.aAddrNextCode = this.newAddr(this.cpu.regEIP, this.cpu.segCS.sel);
|
||||
break;
|
||||
case "IP":
|
||||
// fIns = true;
|
||||
this.cpu.setIP(w);
|
||||
this.aAddrNextCode = this.newAddr(this.cpu.regIP, this.cpu.segCS.sel);
|
||||
this.aAddrNextCode = this.newAddr(this.cpu.regEIP, this.cpu.segCS.sel);
|
||||
break;
|
||||
/*
|
||||
* I used to alias "PC" to "IP", until I discovered that early (perhaps ALL) versions of
|
||||
|
|
@ -4420,7 +4420,7 @@ if (DEBUGGER) {
|
|||
this.println((fCompact? '' : '\n') + this.getRegStr(fProt));
|
||||
|
||||
if (fIns) {
|
||||
this.aAddrNextCode = this.newAddr(this.cpu.regIP, this.cpu.segCS.sel);
|
||||
this.aAddrNextCode = this.newAddr(this.cpu.regEIP, this.cpu.segCS.sel);
|
||||
this.doUnassemble(this.hexAddr(this.aAddrNextCode));
|
||||
}
|
||||
};
|
||||
|
|
@ -4461,7 +4461,7 @@ if (DEBUGGER) {
|
|||
if (!this.fProcStep) {
|
||||
var fPrefix;
|
||||
var fRepeat = false;
|
||||
var aAddr = this.newAddr(this.cpu.regIP, this.cpu.segCS.sel);
|
||||
var aAddr = this.newAddr(this.cpu.regEIP, this.cpu.segCS.sel);
|
||||
do {
|
||||
fPrefix = false;
|
||||
var bOpcode = this.getByte(aAddr);
|
||||
|
|
|
|||
|
|
@ -189,7 +189,7 @@ function Memory(addr, size, fReadOnly, controller)
|
|||
Memory.readNone = function readNone(off)
|
||||
{
|
||||
if (DEBUGGER && this.dbg.messageEnabled(Messages.MEM) /* && !off */) {
|
||||
this.dbg.message("attempt to read invalid block %" + str.toHex(this.addr) + " from " + str.toHexAddr(this.cpu.regIP, this.cpu.segCS.sel));
|
||||
this.dbg.message("attempt to read invalid block %" + str.toHex(this.addr) + " from " + str.toHexAddr(this.cpu.regEIP, this.cpu.segCS.sel));
|
||||
}
|
||||
return 0;
|
||||
};
|
||||
|
|
@ -201,11 +201,12 @@ Memory.readNone = function readNone(off)
|
|||
* @param {number} off
|
||||
* @param {number} v (could be either a byte or word value, since we use the same handler for both kinds of accesses)
|
||||
*/
|
||||
Memory.writeNone = function writeNone(off, v) {
|
||||
Memory.writeNone = function writeNone(off, v)
|
||||
{
|
||||
if (DEBUGGER && this.dbg.messageEnabled(Messages.MEM) /* && !off */) {
|
||||
this.dbg.message("attempt to write 0x" + str.toHexWord(v) + " to invalid block %" + str.toHex(this.addr), true);
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* readByteMemory(off)
|
||||
|
|
|
|||
|
|
@ -469,7 +469,7 @@ X86CPU.PREFETCH = {
|
|||
*
|
||||
* Corresponding to iPrefetchHead is addrPrefetchHead; both are incremented in lock-step.
|
||||
* Whenever the prefetch queue is flushed, it's typically because a new, non-incremental
|
||||
* regEIP has been set, so flushPrefetch() expects to receive that address.
|
||||
* regLIP has been set, so flushPrefetch() expects to receive that address.
|
||||
*
|
||||
* If the prefetch queue does not contain any (or enough) bytes to satisfy a getBytePrefetch()
|
||||
* or getWordPrefetch() request, we force the queue to be filled with the necessary number
|
||||
|
|
@ -786,14 +786,14 @@ X86CPU.prototype.reset = function()
|
|||
* CS Base = 0xFF0000 DS/ES/SS Base = 0x000000 IDT Base = 0x000000
|
||||
* CS Limit = 0xFFFF DS/ES/SS Limit = 0xFFFF IDT Limit = 0x03FF
|
||||
*
|
||||
* We define some additional "registers", such as regEIP. which mirrors the physical address corresponding
|
||||
* to CS:IP (ie, the address of the next opcode). This means that whenever segCS or regIP are explicitly
|
||||
* modified, regEIP must be updated as well. So, when setting segCS or regIP, you should always use setCSIP(),
|
||||
* We define some additional "registers", such as regLIP. which mirrors the linear address corresponding
|
||||
* to CS:IP (ie, the address of the next opcode). This means that whenever segCS or regEIP are explicitly
|
||||
* modified, regLIP must be updated as well. So, when setting segCS or regEIP, you should always use setCSIP(),
|
||||
* which takes both an offset and a segment, or setIP(), whichever is appropriate; in unusual cases where only
|
||||
* segCS is changing (eg, undocumented 8086 opcodes), use setCS().
|
||||
*
|
||||
* The other segment registers (DS, SS and ES) have similar setters (for segDS, segSS and segES), but those
|
||||
* functions do not mirror any segment:offset values in the same way that regEIP mirrors CS:IP.
|
||||
* functions do not mirror any segment:offset values in the same way that regLIP mirrors CS:IP.
|
||||
*
|
||||
* @this {X86CPU}
|
||||
*/
|
||||
|
|
@ -946,12 +946,38 @@ X86CPU.prototype.resetRegs = function()
|
|||
this.segData = this.segDS;
|
||||
this.segStack = this.segSS;
|
||||
this.opFlags = this.opPrefixes = 0;
|
||||
this.opSize = 2;
|
||||
this.opMask = 0xffff;
|
||||
this.opMaskClear = ~this.opMask;
|
||||
this.addrSize = 2;
|
||||
this.addrMask = 0xffff;
|
||||
this.addrMaskClear = ~this.addrMask;
|
||||
|
||||
/*
|
||||
* The following contain the (default) OPERAND size (in terms of number of bytes), and the corresponding masks
|
||||
* for isolating the (src) bits of an OPERAND and clearing the (dst) bits of an OPERAND. These are reset to
|
||||
* their segCS counterparts at the start of every new instruction, but are also set here for documentation purposes.
|
||||
*/
|
||||
this.opSize = this.segCS.opSize;
|
||||
this.opMask = this.segCS.opMask;
|
||||
|
||||
/*
|
||||
* Similarly, the following contain the (default) ADDRESS size (in terms of number of bytes), and the corresponding
|
||||
* masks for isolating the (src) bits of an address and clearing the (dst) bits of an address. Like the OPERAND size
|
||||
* properties, these are reset to their segCS counterparts at the start of every new instruction.
|
||||
*/
|
||||
this.addrSize = this.segCS.addrSize;
|
||||
this.addrMask = this.segCS.addrMask;
|
||||
|
||||
/*
|
||||
* It's also worth noting that instructions that implicitly use the stack also rely on something called STACK size,
|
||||
* which is based on the BIG bit of the last descriptor loaded into SS; use the following segSS properties:
|
||||
*
|
||||
* segSS.addrSize (2 or 4)
|
||||
* segSS.addrMask (0xffff or 0xffffffff)
|
||||
*
|
||||
* As there is no STACK size instruction prefix override, there's no need to propagate these segSS properties
|
||||
* to separate X86CPU properties, as we do for the OPERAND size and ADDRESS size properties.
|
||||
*/
|
||||
|
||||
/*
|
||||
* The default ModRM dispatch tables; the *Word tables will be updated based on the current ADDRESS size,
|
||||
* which is based foremost on segCS.addrSize, but can also be overridden by an ADDRESS size instruction prefix.
|
||||
*/
|
||||
this.aOpModMemByte = X86ModB.aOpModMem;
|
||||
this.aOpModRegByte = X86ModB.aOpModReg;
|
||||
this.aOpModGrpByte = X86ModB.aOpModGrp;
|
||||
|
|
@ -969,7 +995,7 @@ X86CPU.prototype.resetRegs = function()
|
|||
X86CPU.prototype.getChecksum = function()
|
||||
{
|
||||
var sum = (this.regEAX + this.regEBX + this.regECX + this.regEDX + this.regESP + this.regEBP + this.regESI + this.regEDI) | 0;
|
||||
sum = (sum + this.regIP + this.segCS.sel + this.segDS.sel + this.segSS.sel + this.segES.sel + this.getPS()) | 0;
|
||||
sum = (sum + this.regEIP + this.segCS.sel + this.segDS.sel + this.segSS.sel + this.segES.sel + this.getPS()) | 0;
|
||||
return sum;
|
||||
};
|
||||
|
||||
|
|
@ -1009,7 +1035,7 @@ X86CPU.prototype.checkIntNotify = function(nInt)
|
|||
var aNotify = this.aIntNotify[nInt];
|
||||
if (aNotify !== undefined) {
|
||||
for (var i = 0; i < aNotify.length; i++) {
|
||||
if (!aNotify[i][1].call(aNotify[i][0], this.regEIP)) {
|
||||
if (!aNotify[i][1].call(aNotify[i][0], this.regLIP)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
@ -1019,8 +1045,8 @@ X86CPU.prototype.checkIntNotify = function(nInt)
|
|||
* checksEnabled() function, and therefore in fDebugCheck, so for maximum speed, we check fDebugCheck first.
|
||||
*/
|
||||
if (DEBUGGER && this.aFlags.fDebugCheck) {
|
||||
if (this.messageEnabled(Messages.INT) && this.dbg.messageInt(nInt, this.regEIP)) {
|
||||
this.addIntReturn(this.regEIP, function(cpu, nCycles) {
|
||||
if (this.messageEnabled(Messages.INT) && this.dbg.messageInt(nInt, this.regLIP)) {
|
||||
this.addIntReturn(this.regLIP, function(cpu, nCycles) {
|
||||
return function onIntReturn(nLevel) {
|
||||
cpu.dbg.messageIntReturn(nInt, nLevel, cpu.getCycles() - nCycles);
|
||||
};
|
||||
|
|
@ -1160,7 +1186,7 @@ X86CPU.prototype.save = function()
|
|||
{
|
||||
var state = new State(this);
|
||||
state.set(0, [this.regEAX, this.regEBX, this.regECX, this.regEDX, this.regESP, this.regEBP, this.regESI, this.regEDI, this.nIOPL]);
|
||||
state.set(1, [this.regIP, this.segCS.save(), this.segDS.save(), this.segSS.save(), this.segES.save(), this.saveProtMode(), this.getPS()]);
|
||||
state.set(1, [this.regEIP, this.segCS.save(), this.segDS.save(), this.segSS.save(), this.segES.save(), this.saveProtMode(), this.getPS()]);
|
||||
state.set(2, [this.segData.sName, this.segStack.sName, this.opFlags, this.opPrefixes, this.intFlags, this.regEA, this.regEAWrite]);
|
||||
state.set(3, [0, this.nTotalCycles, this.getSpeed()]);
|
||||
state.set(4, this.bus.saveMemory());
|
||||
|
|
@ -1295,9 +1321,9 @@ X86CPU.prototype.getSeg = function(sName)
|
|||
*/
|
||||
X86CPU.prototype.setCS = function(sel)
|
||||
{
|
||||
this.regEIP = this.segCS.load(sel & 0xffff) + this.regIP;
|
||||
this.regLIP = this.segCS.load(sel & 0xffff) + this.regEIP;
|
||||
this.opFlags |= this.OPFLAG_NOINTR8086;
|
||||
if (PREFETCH) this.flushPrefetch(this.regEIP);
|
||||
if (PREFETCH) this.flushPrefetch(this.regLIP);
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -1321,8 +1347,6 @@ X86CPU.prototype.setDS = function(sel)
|
|||
X86CPU.prototype.setSS = function(sel)
|
||||
{
|
||||
this.segSS.load(sel & 0xffff);
|
||||
this.segSS.addrMask = (this.model >= X86.MODEL_80386 && (this.segSS.ext & X86.DESC.EXT.BIG))? 0xffffffff : 0xffff;
|
||||
this.segSS.addrMaskClear = ~this.segSS.addrMask;
|
||||
this.opFlags |= X86.OPFLAG.NOINTR;
|
||||
};
|
||||
|
||||
|
|
@ -1342,9 +1366,9 @@ X86CPU.prototype.setES = function(sel)
|
|||
* setIP(off)
|
||||
*
|
||||
* With the addition of flushPrefetch(), this function should only be called
|
||||
* for non-incremental IP updates; setIP(this.regIP+1) is no longer appropriate.
|
||||
* for non-incremental IP updates; setIP(this.regEIP+1) is no longer appropriate.
|
||||
*
|
||||
* In fact, for performance reasons, it's preferable to increment regIP yourself,
|
||||
* In fact, for performance reasons, it's preferable to increment regEIP yourself,
|
||||
* but you can also call advanceIP() if speed is not important.
|
||||
*
|
||||
* @this {X86CPU}
|
||||
|
|
@ -1352,8 +1376,8 @@ X86CPU.prototype.setES = function(sel)
|
|||
*/
|
||||
X86CPU.prototype.setIP = function(off)
|
||||
{
|
||||
this.regEIP = this.segCS.base + (this.regIP = off & 0xffff);
|
||||
if (PREFETCH) this.flushPrefetch(this.regEIP);
|
||||
this.regLIP = this.segCS.base + (this.regEIP = off & 0xffff);
|
||||
if (PREFETCH) this.flushPrefetch(this.regLIP);
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -1385,11 +1409,11 @@ X86CPU.prototype.setCSIP = function(off, sel, fCall)
|
|||
* We break this operation into the following discrete steps (eg, set IP, load CS, and then update EIP)
|
||||
* so that segCS.load(sel) has the option of modifying IP when sel refers to a gate (call, interrupt, trap, etc).
|
||||
*/
|
||||
this.regIP = off;
|
||||
this.regEIP = off;
|
||||
var base = this.segCS.load(sel);
|
||||
if (base != X86.ADDR_INVALID) {
|
||||
this.regEIP = base + this.regIP;
|
||||
if (PREFETCH) this.flushPrefetch(this.regEIP);
|
||||
this.regLIP = base + this.regEIP;
|
||||
if (PREFETCH) this.flushPrefetch(this.regLIP);
|
||||
return this.segCS.fStackSwitch;
|
||||
}
|
||||
return null;
|
||||
|
|
@ -1403,7 +1427,7 @@ X86CPU.prototype.setCSIP = function(off, sel, fCall)
|
|||
*/
|
||||
X86CPU.prototype.advanceIP = function(inc)
|
||||
{
|
||||
this.regEIP = this.segCS.base + (this.regIP = (this.regIP + inc) & 0xffff);
|
||||
this.regLIP = this.segCS.base + (this.regEIP = (this.regEIP + inc) & 0xffff);
|
||||
if (PREFETCH) this.advancePrefetch(inc);
|
||||
};
|
||||
|
||||
|
|
@ -2251,7 +2275,7 @@ X86CPU.prototype.fillPrefetch = function(n)
|
|||
* Empty the prefetch queue.
|
||||
*
|
||||
* @this {X86CPU}
|
||||
* @param {number} addr is a physical (non-segmented) address of the current program counter (regEIP)
|
||||
* @param {number} addr is a physical (non-segmented) address of the current program counter (regLIP)
|
||||
*/
|
||||
X86CPU.prototype.flushPrefetch = function(addr)
|
||||
{
|
||||
|
|
@ -2279,7 +2303,7 @@ X86CPU.prototype.advancePrefetch = function(inc)
|
|||
this.iPrefetchTail = (this.iPrefetchTail + inc) & X86CPU.PREFETCH.MASK;
|
||||
this.cbPrefetchQueued -= inc;
|
||||
} else {
|
||||
this.flushPrefetch(this.regEIP);
|
||||
this.flushPrefetch(this.regLIP);
|
||||
if (MAXDEBUG) this.printMessage("advancePrefetch(" + inc + "): flushed");
|
||||
}
|
||||
};
|
||||
|
|
@ -2292,9 +2316,9 @@ X86CPU.prototype.advancePrefetch = function(inc)
|
|||
*/
|
||||
X86CPU.prototype.getIPByte = function()
|
||||
{
|
||||
var b = (PREFETCH? this.getBytePrefetch(this.regEIP) : this.getByte(this.regEIP));
|
||||
if (BACKTRACK) this.bus.updateBackTrackCode(this.regEIP, this.backTrack.btiMemLo);
|
||||
this.regEIP = this.segCS.base + (this.regIP = (this.regIP + 1) & 0xffff); // this.advanceIP(1)
|
||||
var b = (PREFETCH? this.getBytePrefetch(this.regLIP) : this.getByte(this.regLIP));
|
||||
if (BACKTRACK) this.bus.updateBackTrackCode(this.regLIP, this.backTrack.btiMemLo);
|
||||
this.regLIP = this.segCS.base + (this.regEIP = (this.regEIP + 1) & 0xffff); // this.advanceIP(1)
|
||||
return b;
|
||||
};
|
||||
|
||||
|
|
@ -2306,9 +2330,9 @@ X86CPU.prototype.getIPByte = function()
|
|||
*/
|
||||
X86CPU.prototype.getIPDisp = function()
|
||||
{
|
||||
var b = ((PREFETCH? this.getBytePrefetch(this.regEIP) : this.getByte(this.regEIP)) << 24) >> 24;
|
||||
if (BACKTRACK) this.bus.updateBackTrackCode(this.regEIP, this.backTrack.btiMemLo);
|
||||
this.regEIP = this.segCS.base + (this.regIP = (this.regIP + 1) & 0xffff); // this.advanceIP(1)
|
||||
var b = ((PREFETCH? this.getBytePrefetch(this.regLIP) : this.getByte(this.regLIP)) << 24) >> 24;
|
||||
if (BACKTRACK) this.bus.updateBackTrackCode(this.regLIP, this.backTrack.btiMemLo);
|
||||
this.regLIP = this.segCS.base + (this.regEIP = (this.regEIP + 1) & 0xffff); // this.advanceIP(1)
|
||||
return b & 0xffff;
|
||||
};
|
||||
|
||||
|
|
@ -2320,12 +2344,12 @@ X86CPU.prototype.getIPDisp = function()
|
|||
*/
|
||||
X86CPU.prototype.getIPWord = function()
|
||||
{
|
||||
var w = (PREFETCH? this.getWordPrefetch(this.regEIP) : this.getWord(this.regEIP));
|
||||
var w = (PREFETCH? this.getWordPrefetch(this.regLIP) : this.getWord(this.regLIP));
|
||||
if (BACKTRACK) {
|
||||
this.bus.updateBackTrackCode(this.regEIP, this.backTrack.btiMemLo);
|
||||
this.bus.updateBackTrackCode(this.regEIP + 1, this.backTrack.btiMemHi);
|
||||
this.bus.updateBackTrackCode(this.regLIP, this.backTrack.btiMemLo);
|
||||
this.bus.updateBackTrackCode(this.regLIP + 1, this.backTrack.btiMemHi);
|
||||
}
|
||||
this.regEIP = this.segCS.base + (this.regIP = (this.regIP + 2) & 0xffff); // this.advanceIP(2)
|
||||
this.regLIP = this.segCS.base + (this.regEIP = (this.regEIP + 2) & 0xffff); // this.advanceIP(2)
|
||||
return w;
|
||||
};
|
||||
|
||||
|
|
@ -2517,7 +2541,7 @@ X86CPU.prototype.displayStatus = function(fForce)
|
|||
this.displayReg("DS", this.segDS.sel);
|
||||
this.displayReg("SS", this.segSS.sel);
|
||||
this.displayReg("ES", this.segES.sel);
|
||||
this.displayReg("IP", this.regIP);
|
||||
this.displayReg("IP", this.regEIP);
|
||||
var regPS = this.getPS();
|
||||
this.displayReg("PS", regPS);
|
||||
this.displayReg("C", (regPS & X86.PS.CF)? 1 : 0, 1);
|
||||
|
|
@ -2544,7 +2568,7 @@ X86CPU.prototype.displayStatus = function(fForce)
|
|||
* stepping vs. running should never change the behavior of the simulation.
|
||||
*
|
||||
* Similarly, the Debugger's execution breakpoints have no involvement with the x86 breakpoint instruction
|
||||
* (0xCC); the Debugger monitors changes to the regEIP register to implement its own execution breakpoints.
|
||||
* (0xCC); the Debugger monitors changes to the regLIP register to implement its own execution breakpoints.
|
||||
*
|
||||
* As a result, the Debugger's complete independence means you can run other 8086/8088 debuggers
|
||||
* (eg, DEBUG) inside the simulation without interference; you can even "debug" them with the Debugger.
|
||||
|
|
@ -2618,10 +2642,16 @@ X86CPU.prototype.stepCPU = function(nMinCycles)
|
|||
if (opPrefixes) {
|
||||
this.opPrefixes |= opPrefixes;
|
||||
} else {
|
||||
this.opEA = this.regEIP;
|
||||
this.opLIP = this.regLIP;
|
||||
this.regEA = this.regEAWrite = X86.ADDR_INVALID;
|
||||
this.segData = this.segDS;
|
||||
this.segStack = this.segSS;
|
||||
|
||||
this.opSize = this.segCS.opSize;
|
||||
this.opMask = this.segCS.opMask;
|
||||
this.addrSize = this.segCS.addrSize;
|
||||
this.addrMask = this.segCS.addrMask;
|
||||
|
||||
this.opPrefixes = this.opFlags & X86.OPFLAG.REPEAT;
|
||||
if (this.intFlags) {
|
||||
if (this.checkINTR()) {
|
||||
|
|
@ -2658,7 +2688,7 @@ X86CPU.prototype.stepCPU = function(nMinCycles)
|
|||
}
|
||||
|
||||
if (DEBUGGER && fDebugCheck) {
|
||||
if (this.dbg.checkInstruction(this.regEIP, fDebugSkip)) {
|
||||
if (this.dbg.checkInstruction(this.regLIP, fDebugSkip)) {
|
||||
this.stopCPU();
|
||||
break;
|
||||
}
|
||||
|
|
@ -2676,11 +2706,11 @@ X86CPU.prototype.stepCPU = function(nMinCycles)
|
|||
this.stopCPU();
|
||||
break;
|
||||
}
|
||||
var t = this.regEIP + this.getCycles();
|
||||
var t = this.regLIP + this.getCycles();
|
||||
var n = this.aSamples[this.iSampleNext];
|
||||
if (n !== -1) {
|
||||
if (n !== t) {
|
||||
this.println("sample deviation at index " + this.iSampleNext + ": current EIP=" + str.toHex(this.regEIP));
|
||||
this.println("sample deviation at index " + this.iSampleNext + ": current EIP=" + str.toHex(this.regLIP));
|
||||
this.stopCPU();
|
||||
break;
|
||||
}
|
||||
|
|
@ -2726,7 +2756,7 @@ X86CPU.prototype.stepCPU = function(nMinCycles)
|
|||
*/
|
||||
if (this.aFlags.fComplete && this.nStepCycles >= this.nSnapCycles && !(this.opFlags & X86.OPFLAG.PREFIXES)) {
|
||||
this.println("cycle miscount: " + (this.nSnapCycles - this.nStepCycles));
|
||||
this.setIP(this.opEA - this.segCS.base);
|
||||
this.setIP(this.opLIP - this.segCS.base);
|
||||
this.stopCPU();
|
||||
break;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -142,6 +142,40 @@ var X86Grps = {
|
|||
return dst;
|
||||
},
|
||||
/**
|
||||
* opGrpADDw(dst, src)
|
||||
*
|
||||
* Notes regarding carry following a 32-bit addition:
|
||||
*
|
||||
* The following table summarizes bit 31 of dst, src, and result, along with the expected carry bit:
|
||||
*
|
||||
* dst src res carry
|
||||
* --- --- --- -----
|
||||
* 0 0 0 0 no
|
||||
* 0 0 1 0 no (there must have been a carry out of bit 30, but it was "absorbed")
|
||||
* 0 1 0 1 yes (there must have been a carry out of bit 30, but it was NOT "absorbed")
|
||||
* 0 1 1 0 no
|
||||
* 1 0 0 1 yes (same as the preceding "yes" case)
|
||||
* 1 0 1 0 no
|
||||
* 1 1 0 1 yes (since the addition of two ones must always produce a carry)
|
||||
* 1 1 1 1 yes (since the addition of two ones must always produce a carry)
|
||||
*
|
||||
* So, we can use “(dst ^ ((dst ^ src) & (src ^ res))) >> 15” to shift the proper carry bit into the conventional
|
||||
* SIZE_WORD position; eg:
|
||||
*
|
||||
* resultValue = ((resultValue >>> 16) | (resultValue & 0xffff)) | (((dst ^ ((dst ^ src) & (src ^ resultValue))) >> 15) & SIZE_WORD);
|
||||
*
|
||||
* Essentially, we’re “cramming” all 32 result bits into the low 16 bits (which will effectively represent the
|
||||
* zero flag), and then setting bit 16 to the effective carry flag. This transforms the zero and carry conditions
|
||||
* for a DWORD computation into the corresponding conditions for a WORD computation. This will slow down 32-bit
|
||||
* addition, but it allows 8-bit and 16-bit addition to remain fast. Languages that support 64-bit values in
|
||||
* conjunction with bit-wise operators can omit that one-line transformation, and we can set SIZE_DWORD to a 33-bit
|
||||
* value, but sadly, we cannot do that in JavaScript.
|
||||
*
|
||||
* Alternatively, we could store src and dst into their own result variables (eg, resultSrc and resultDst) and
|
||||
* compute carry lazily, but that would affect MUCH more existing code (eg, all code that currently inspects carry
|
||||
* with a single bit test). I think the DWORD-to-WORD flag conversion for 32-bit instructions that modify zero
|
||||
* and/or carry) is a more reasonable first step.
|
||||
*
|
||||
* @this {X86CPU}
|
||||
* @param {number} dst
|
||||
* @param {number} src
|
||||
|
|
@ -269,54 +303,22 @@ var X86Grps = {
|
|||
* of updating CARRY and OVERFLOW (and possibly changing resultSize from SIZE_BYTE to SIZE_WORD, or vice versa),
|
||||
* we must take care to preserve SIGN, ZERO, and the other arithmetic flags.
|
||||
*
|
||||
* This code originally left resultParitySign alone, but if resultSize changes, then resultParitySign needs to
|
||||
* change along with it. PARITY is always based on the low 8 bits of resultParitySign, so let's focus on SIGN:
|
||||
* if resultSize is changing from SIZE_BYTE to SIZE_WORD, propagating bit 7 to bit 15 of resultParitySign preserves
|
||||
* SIGN; similarly, if resultSize is changing from SIZE_WORD to SIZE_BYTE, propagating bit 15 to bit 7 preserves
|
||||
* SIGN--but could also alter PARITY. So we must compensate: if bit 15 differs from bit 7, then XOR resultParitySign
|
||||
* with 0xC0, which will flip not only bit 7 but also bit 6, thereby preserving PARITY.
|
||||
*
|
||||
* resultValue merits similar consideration because of the ZERO flag: if resultSize increases, nothing needs to be
|
||||
* done, because the larger size will still pick up any non-zero bits in the lower 8 bits of resultValue, but if it
|
||||
* decreases, we need to OR the upper 8 bits from resultValue into the lower 8 bits.
|
||||
*
|
||||
* Finally, this function must set the CARRY and OVERFLOW flags according to the given result. OVERFLOW is a particular
|
||||
* pain, because it has a dependency on resultParitySign; the simplest solution is to call setOF() or clearOF().
|
||||
* However, in the interest of efficiency, rather than changing resultSize to match the operand size, it's easier
|
||||
* to leave resultSize as-is and simply set CARRY and OVERFLOW based on the previous resultSize, since there isn't
|
||||
* actually any requirement or dependency (that I can think of) that resultSize always reflect the operand size of
|
||||
* the last operation. Since only 2 of the 6 arithmetic flags need to change, that tips the scales in favor of leaving
|
||||
* resultSize alone.
|
||||
*
|
||||
* NOTE: Although I've yet to find confirmation of this for the 8086/8088, OVERFLOW is "undefined" on modern x86
|
||||
* CPUs for shift counts > 1 (in fact, on modern CPUs, OVERFLOW tends to be clear in those situations). Since I set
|
||||
* OVERFLOW the same way for all shift counts, my "well-defined" behavior may or may not match the 8086/8088, but
|
||||
* until I see a defined behavior (or more importantly, some dependency on a different behavior), this seems good enough.
|
||||
*
|
||||
* UPDATE: While the desire to set resultSize to match the operand size is strong, it occurred to me later that
|
||||
* it would be easier to leave resultSize as-is and simply set CARRY and OVERFLOW based on the previous resultSize,
|
||||
* since there isn't actually any requirement or dependency (that I can think of) that resultSize always reflect the
|
||||
* operand size of the last operation. And since only 2 of the 6 arithmetic flags need to change, that tips the scales
|
||||
* in favor of leaving resultSize alone. However, the previous code that worked so hard to update resultSize is still
|
||||
* here, commented out; it works, but it's less efficient.
|
||||
*
|
||||
* @this {X86CPU}
|
||||
* @param {number} result (untruncated, so that we can inspect it for CARRY and OVERFLOW)
|
||||
* @param {number} size
|
||||
*/
|
||||
opGrpRotateFlags: function(result, size) {
|
||||
/*
|
||||
var deltaSize = size - this.resultSize;
|
||||
if (deltaSize) {
|
||||
var bitsXOR = 0;
|
||||
var bitsSign = this.resultParitySign & 0x8080;
|
||||
if (deltaSize > 0) {
|
||||
if (bitsSign == 0x0080 || bitsSign == 0x8000) bitsXOR = 0x8000;
|
||||
} else {
|
||||
if (bitsSign == 0x0080 || bitsSign == 0x8000) bitsXOR = 0x00C0;
|
||||
this.resultValue |= (this.resultValue >> 8);
|
||||
}
|
||||
this.resultParitySign ^= bitsXOR;
|
||||
this.resultSize = size;
|
||||
}
|
||||
this.resultValue = (this.resultValue & (size - 1)) | (result & size);
|
||||
if ((result ^ (result >> 1)) & (size >> 1)) this.setOF(); else this.clearOF();
|
||||
*/
|
||||
this.resultValue = (this.resultValue & (this.resultSize - 1)) | ((result & size)? this.resultSize : 0);
|
||||
if ((result ^ (result >> 1)) & (size >> 1)) this.setOF(); else this.clearOF();
|
||||
},
|
||||
|
|
@ -1110,7 +1112,7 @@ var X86Grps = {
|
|||
* @return {number}
|
||||
*/
|
||||
opGrpCALLw: function(dst, src) {
|
||||
this.pushWord(this.regIP);
|
||||
this.pushWord(this.regEIP);
|
||||
this.setIP(dst);
|
||||
this.nStepCycles -= (this.regEA < 0? this.CYCLES.nOpCyclesCallWR : this.CYCLES.nOpCyclesCallWM);
|
||||
if (EAFUNCS) this.setEAWord = this.setEAWordDisabled; else this.opFlags |= X86.OPFLAG.NOWRITE;
|
||||
|
|
@ -1154,7 +1156,7 @@ var X86Grps = {
|
|||
return X86Grps.opGrpUndefined.call(this, dst, src);
|
||||
}
|
||||
this.setCSIP(dst, this.getWord(this.regEA + 2));
|
||||
if (this.cIntReturn) this.checkIntReturn(this.regEIP);
|
||||
if (this.cIntReturn) this.checkIntReturn(this.regLIP);
|
||||
this.nStepCycles -= this.CYCLES.nOpCyclesJmpDM;
|
||||
if (EAFUNCS) this.setEAWord = this.setEAWordDisabled; else this.opFlags |= X86.OPFLAG.NOWRITE;
|
||||
return dst;
|
||||
|
|
|
|||
|
|
@ -248,7 +248,7 @@ var X86Help = {
|
|||
*
|
||||
* TODO: Determine the cycle cost when a BOUND exception is triggered, over and above nOpCyclesBound.
|
||||
*/
|
||||
this.setIP(this.opEA - this.segCS.base);
|
||||
this.setIP(this.opLIP - this.segCS.base);
|
||||
X86Help.opHelpINT.call(this, X86.EXCEPTION.BOUND_ERR, null, 0);
|
||||
}
|
||||
if (EAFUNCS) this.setEAByte = this.setEAByteDisabled; else this.opFlags |= X86.OPFLAG.NOWRITE;
|
||||
|
|
@ -490,10 +490,10 @@ var X86Help = {
|
|||
*/
|
||||
opHelpCALLF: function(off, sel) {
|
||||
var regCS = this.segCS.sel;
|
||||
var regIP = this.regIP;
|
||||
var regEIP = this.regEIP;
|
||||
if (this.setCSIP(off, sel, true) != null) {
|
||||
this.pushWord(regCS);
|
||||
this.pushWord(regIP);
|
||||
this.pushWord(regEIP);
|
||||
}
|
||||
},
|
||||
/**
|
||||
|
|
@ -506,10 +506,10 @@ var X86Help = {
|
|||
* @param {number} n
|
||||
*/
|
||||
opHelpRETF: function(n) {
|
||||
var regIP = this.popWord();
|
||||
var regEIP = this.popWord();
|
||||
var regCS = this.popWord();
|
||||
if (n) this.regESP = (this.regESP + n) & 0xffff;
|
||||
if (this.setCSIP(regIP, regCS, false)) {
|
||||
if (this.setCSIP(regEIP, regCS, false)) {
|
||||
if (n) this.regESP = (this.regESP + n) & 0xffff;
|
||||
/*
|
||||
* As per Intel documentation: "If any of [the DS or ES] registers refer to segments whose DPL is
|
||||
|
|
@ -529,7 +529,7 @@ var X86Help = {
|
|||
this.segES.load(0);
|
||||
}
|
||||
}
|
||||
if (n == 2 && this.cIntReturn) this.checkIntReturn(this.regEIP);
|
||||
if (n == 2 && this.cIntReturn) this.checkIntReturn(this.regLIP);
|
||||
},
|
||||
/**
|
||||
* opHelpINT(nIDT, nError, nCycles)
|
||||
|
|
@ -554,14 +554,14 @@ var X86Help = {
|
|||
this.segCS.fCall = true;
|
||||
var regPS = this.getPS();
|
||||
var regCS = this.segCS.sel;
|
||||
var regIP = this.regIP;
|
||||
var regEIP = this.regEIP;
|
||||
var base = this.segCS.loadIDT(nIDT);
|
||||
if (base != X86.ADDR_INVALID) {
|
||||
this.regEIP = base + this.regIP;
|
||||
if (PREFETCH) this.flushPrefetch(this.regEIP);
|
||||
this.regLIP = base + this.regEIP;
|
||||
if (PREFETCH) this.flushPrefetch(this.regLIP);
|
||||
this.pushWord(regPS);
|
||||
this.pushWord(regCS);
|
||||
this.pushWord(regIP);
|
||||
this.pushWord(regEIP);
|
||||
if (nError != null) this.pushWord(nError);
|
||||
this.nFault = -1;
|
||||
}
|
||||
|
|
@ -585,12 +585,12 @@ var X86Help = {
|
|||
}
|
||||
}
|
||||
var cpl = this.segCS.cpl;
|
||||
var regIP = this.popWord();
|
||||
var regEIP = this.popWord();
|
||||
var regCS = this.popWord();
|
||||
var regPS = this.popWord();
|
||||
if (this.setCSIP(regIP, regCS, false) != null) {
|
||||
if (this.setCSIP(regEIP, regCS, false) != null) {
|
||||
this.setPS(regPS, cpl);
|
||||
if (this.cIntReturn) this.checkIntReturn(this.regEIP);
|
||||
if (this.cIntReturn) this.checkIntReturn(this.regLIP);
|
||||
}
|
||||
},
|
||||
/**
|
||||
|
|
@ -599,7 +599,7 @@ var X86Help = {
|
|||
* @this {X86CPU}
|
||||
*/
|
||||
opHelpDIVOverflow: function() {
|
||||
this.setIP(this.opEA - this.segCS.base);
|
||||
this.setIP(this.opLIP - this.segCS.base);
|
||||
/*
|
||||
* TODO: Determine the proper cycle cost.
|
||||
*/
|
||||
|
|
@ -619,7 +619,7 @@ var X86Help = {
|
|||
{
|
||||
if (!this.aFlags.fComplete) {
|
||||
this.printMessage("Fault " + str.toHexByte(nFault) + " blocked by Debugger", Messages.WARN);
|
||||
this.setIP(this.opEA - this.segCS.base);
|
||||
this.setIP(this.opLIP - this.segCS.base);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -629,7 +629,7 @@ var X86Help = {
|
|||
/*
|
||||
* Single-fault (error code is passed through, and the responsible instruction is restartable)
|
||||
*/
|
||||
this.setIP(this.opEA - this.segCS.base);
|
||||
this.setIP(this.opLIP - this.segCS.base);
|
||||
fDispatch = true;
|
||||
} else if (this.nFault != X86.EXCEPTION.DF_FAULT) {
|
||||
/*
|
||||
|
|
@ -691,7 +691,7 @@ var X86Help = {
|
|||
opHelpFaultMessage: function(nFault, nError, fHalt)
|
||||
{
|
||||
var bitsMessage = Messages.FAULT;
|
||||
var bOpcode = this.bus.getByteDirect(this.regEIP);
|
||||
var bOpcode = this.bus.getByteDirect(this.regLIP);
|
||||
|
||||
/*
|
||||
* OS/2 1.0 uses an INT3 (0xCC) opcode in conjunction with an invalid IDT to trigger a triple-fault
|
||||
|
|
@ -716,7 +716,7 @@ var X86Help = {
|
|||
* (Power-On Self Test); we don't want to ignore those, but we don't want to halt on them either. We
|
||||
* detect those faults by virtue of EIP being in the range %0F0000 to %0FFFFF.
|
||||
*/
|
||||
if (this.regEIP >= 0x0F0000 && this.regEIP <= 0x0FFFFF) {
|
||||
if (this.regLIP >= 0x0F0000 && this.regLIP <= 0x0FFFFF) {
|
||||
fHalt = false;
|
||||
}
|
||||
|
||||
|
|
@ -729,7 +729,7 @@ var X86Help = {
|
|||
}
|
||||
|
||||
if (this.messageEnabled(bitsMessage) || fHalt) {
|
||||
var sMessage = (fHalt? '\n' : '') + "Fault " + str.toHexByte(nFault) + (nError != null? " (" + str.toHexWord(nError) + ")" : "") + " on opcode 0x" + str.toHexByte(bOpcode) + " at " + str.toHexAddr(this.regIP, this.segCS.sel) + " (%" + str.toHex(this.regEIP, 6) + ")";
|
||||
var sMessage = (fHalt? '\n' : '') + "Fault " + str.toHexByte(nFault) + (nError != null? " (" + str.toHexWord(nError) + ")" : "") + " on opcode 0x" + str.toHexByte(bOpcode) + " at " + str.toHexAddr(this.regEIP, this.segCS.sel) + " (%" + str.toHex(this.regLIP, 6) + ")";
|
||||
var fRunning = this.aFlags.fRunning;
|
||||
if (this.printMessage(sMessage, bitsMessage)) {
|
||||
if (fHalt) {
|
||||
|
|
@ -767,8 +767,8 @@ var X86Help = {
|
|||
* @this {X86CPU}
|
||||
*/
|
||||
opHelpUndefined: function() {
|
||||
this.setIP(this.opEA - this.segCS.base);
|
||||
this.setError("Undefined opcode 0x" + str.toHexByte(this.bus.getByteDirect(this.regEIP)) + " at " + str.toHexAddr(this.regIP, this.segCS.sel));
|
||||
this.setIP(this.opLIP - this.segCS.base);
|
||||
this.setError("Undefined opcode 0x" + str.toHexByte(this.bus.getByteDirect(this.regLIP)) + " at " + str.toHexAddr(this.regEIP, this.segCS.sel));
|
||||
this.stopCPU();
|
||||
}
|
||||
};
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
|
@ -98,7 +98,7 @@ var X86OpXX = {
|
|||
* op=0x05 (add AX,imm16)
|
||||
*/
|
||||
opADDAXw: function() {
|
||||
this.regEAX = (this.regEAX & this.opMaskClear) | X86Grps.opGrpADDw.call(this, this.regEAX & this.opMask, this.getIPWord());
|
||||
this.regEAX = (this.regEAX & ~this.opMask) | X86Grps.opGrpADDw.call(this, this.regEAX & this.opMask, this.getIPWord());
|
||||
/*
|
||||
* In the absence of any EA calculations, opGrpADDw() will deduct nOpCyclesArithRR, and for all CPUs through
|
||||
* the 80286, we need deduct only one more cycle.
|
||||
|
|
@ -174,7 +174,7 @@ var X86OpXX = {
|
|||
* op=0x0D (or AX,imm16)
|
||||
*/
|
||||
opORAXw: function() {
|
||||
this.regEAX = (this.regEAX & this.opMaskClear) | X86Grps.opGrpORw.call(this, this.regEAX & this.opMask, this.getIPWord());
|
||||
this.regEAX = (this.regEAX & ~this.opMask) | X86Grps.opGrpORw.call(this, this.regEAX & this.opMask, this.getIPWord());
|
||||
/*
|
||||
* In the absence of any EA calculations, opGrpORw() will deduct nOpCyclesArithRR, and for all CPUs through
|
||||
* the 80286, we need deduct only one more cycle.
|
||||
|
|
@ -258,7 +258,7 @@ var X86OpXX = {
|
|||
* op=0x15 (adc AX,imm16)
|
||||
*/
|
||||
opADCAXw: function() {
|
||||
this.regEAX = (this.regEAX & this.opMaskClear) | X86Grps.opGrpADCw.call(this, this.regEAX & this.opMask, this.getIPWord());
|
||||
this.regEAX = (this.regEAX & ~this.opMask) | X86Grps.opGrpADCw.call(this, this.regEAX & this.opMask, this.getIPWord());
|
||||
/*
|
||||
* In the absence of any EA calculations, opGrpADCw() will deduct nOpCyclesArithRR, and for all CPUs through
|
||||
* the 80286, we need deduct only one more cycle.
|
||||
|
|
@ -334,7 +334,7 @@ var X86OpXX = {
|
|||
* op=0x1D (sbb AX,imm16)
|
||||
*/
|
||||
opSBBAXw: function() {
|
||||
this.regEAX = (this.regEAX & this.opMaskClear) | X86Grps.opGrpSBBw.call(this, this.regEAX & this.opMask, this.getIPWord());
|
||||
this.regEAX = (this.regEAX & ~this.opMask) | X86Grps.opGrpSBBw.call(this, this.regEAX & this.opMask, this.getIPWord());
|
||||
/*
|
||||
* In the absence of any EA calculations, opGrpSBBw() will deduct nOpCyclesArithRR, and for all CPUs through
|
||||
* the 80286, we need deduct only one more cycle.
|
||||
|
|
@ -410,7 +410,7 @@ var X86OpXX = {
|
|||
* op=0x25 (and AX,imm16)
|
||||
*/
|
||||
opANDAXw: function() {
|
||||
this.regEAX = (this.regEAX & this.opMaskClear) | X86Grps.opGrpANDw.call(this, this.regEAX & this.opMask, this.getIPWord());
|
||||
this.regEAX = (this.regEAX & ~this.opMask) | X86Grps.opGrpANDw.call(this, this.regEAX & this.opMask, this.getIPWord());
|
||||
/*
|
||||
* In the absence of any EA calculations, opGrpANDw() will deduct nOpCyclesArithRR, and for all CPUs through
|
||||
* the 80286, we need deduct only one more cycle.
|
||||
|
|
@ -505,7 +505,7 @@ var X86OpXX = {
|
|||
* op=0x2D (sub AX,imm16)
|
||||
*/
|
||||
opSUBAXw: function() {
|
||||
this.regEAX = (this.regEAX & this.opMaskClear) | X86Grps.opGrpSUBw.call(this, this.regEAX & this.opMask, this.getIPWord());
|
||||
this.regEAX = (this.regEAX & ~this.opMask) | X86Grps.opGrpSUBw.call(this, this.regEAX & this.opMask, this.getIPWord());
|
||||
/*
|
||||
* In the absence of any EA calculations, opGrpSUBw() will deduct nOpCyclesArithRR, and for all CPUs
|
||||
* through the 80286, we need deduct only one more cycle.
|
||||
|
|
@ -600,7 +600,7 @@ var X86OpXX = {
|
|||
* op=0x35 (xor AX,imm16)
|
||||
*/
|
||||
opXORAXw: function() {
|
||||
this.regEAX = (this.regEAX & this.opMaskClear) | X86Grps.opGrpXORw.call(this, this.regEAX & this.opMask, this.getIPWord());
|
||||
this.regEAX = (this.regEAX & ~this.opMask) | X86Grps.opGrpXORw.call(this, this.regEAX & this.opMask, this.getIPWord());
|
||||
/*
|
||||
* In the absence of any EA calculations, opGrpXORw() will deduct nOpCyclesArithRR, and for all CPUs through
|
||||
* the 80286, we need deduct only one more cycle.
|
||||
|
|
@ -759,7 +759,7 @@ var X86OpXX = {
|
|||
*/
|
||||
opINCAX: function() {
|
||||
this.resultAuxOverflow = this.regEAX;
|
||||
this.regEAX = (this.regEAX & this.opMaskClear) | (this.resultParitySign = this.regEAX + 1) & this.opMask;
|
||||
this.regEAX = (this.regEAX & ~this.opMask) | (this.resultParitySign = this.regEAX + 1) & this.opMask;
|
||||
this.resultValue = this.regEAX | (((this.resultValue & this.resultSize)? 1 : 0) << 16);
|
||||
this.resultSize = X86.RESULT.SIZE_WORD;
|
||||
this.nStepCycles -= 2; // this form of INC takes 2 cycles on all CPUs
|
||||
|
|
@ -771,7 +771,7 @@ var X86OpXX = {
|
|||
*/
|
||||
opINCCX: function() {
|
||||
this.resultAuxOverflow = this.regECX;
|
||||
this.regECX = (this.regECX & this.opMaskClear) | (this.resultParitySign = this.regECX + 1) & this.opMask;
|
||||
this.regECX = (this.regECX & ~this.opMask) | (this.resultParitySign = this.regECX + 1) & this.opMask;
|
||||
this.resultValue = this.regECX | (((this.resultValue & this.resultSize)? 1 : 0) << 16);
|
||||
this.resultSize = X86.RESULT.SIZE_WORD;
|
||||
this.nStepCycles -= 2; // this form of INC takes 2 cycles on all CPUs
|
||||
|
|
@ -783,7 +783,7 @@ var X86OpXX = {
|
|||
*/
|
||||
opINCDX: function() {
|
||||
this.resultAuxOverflow = this.regEDX;
|
||||
this.regEDX = (this.regEDX & this.opMaskClear) | (this.resultParitySign = this.regEDX + 1) & this.opMask;
|
||||
this.regEDX = (this.regEDX & ~this.opMask) | (this.resultParitySign = this.regEDX + 1) & this.opMask;
|
||||
this.resultValue = this.regEDX | (((this.resultValue & this.resultSize)? 1 : 0) << 16);
|
||||
this.resultSize = X86.RESULT.SIZE_WORD;
|
||||
this.nStepCycles -= 2; // this form of INC takes 2 cycles on all CPUs
|
||||
|
|
@ -795,7 +795,7 @@ var X86OpXX = {
|
|||
*/
|
||||
opINCBX: function() {
|
||||
this.resultAuxOverflow = this.regEBX;
|
||||
this.regEBX = (this.regEBX & this.opMaskClear) | (this.resultParitySign = this.regEBX + 1) & this.opMask;
|
||||
this.regEBX = (this.regEBX & ~this.opMask) | (this.resultParitySign = this.regEBX + 1) & this.opMask;
|
||||
this.resultValue = this.regEBX | (((this.resultValue & this.resultSize)? 1 : 0) << 16);
|
||||
this.resultSize = X86.RESULT.SIZE_WORD;
|
||||
this.nStepCycles -= 2; // this form of INC takes 2 cycles on all CPUs
|
||||
|
|
@ -807,7 +807,7 @@ var X86OpXX = {
|
|||
*/
|
||||
opINCSP: function() {
|
||||
this.resultAuxOverflow = this.regESP;
|
||||
this.regESP = (this.regESP & this.opMaskClear) | (this.resultParitySign = this.regESP + 1) & this.opMask;
|
||||
this.regESP = (this.regESP & ~this.opMask) | (this.resultParitySign = this.regESP + 1) & this.opMask;
|
||||
this.resultValue = this.regESP | (((this.resultValue & this.resultSize)? 1 : 0) << 16);
|
||||
this.resultSize = X86.RESULT.SIZE_WORD;
|
||||
this.nStepCycles -= 2; // this form of INC takes 2 cycles on all CPUs
|
||||
|
|
@ -819,7 +819,7 @@ var X86OpXX = {
|
|||
*/
|
||||
opINCBP: function() {
|
||||
this.resultAuxOverflow = this.regEBP;
|
||||
this.regEBP = (this.regEBP & this.opMaskClear) | (this.resultParitySign = this.regEBP + 1) & this.opMask;
|
||||
this.regEBP = (this.regEBP & ~this.opMask) | (this.resultParitySign = this.regEBP + 1) & this.opMask;
|
||||
this.resultValue = this.regEBP | (((this.resultValue & this.resultSize)? 1 : 0) << 16);
|
||||
this.resultSize = X86.RESULT.SIZE_WORD;
|
||||
this.nStepCycles -= 2; // this form of INC takes 2 cycles on all CPUs
|
||||
|
|
@ -831,7 +831,7 @@ var X86OpXX = {
|
|||
*/
|
||||
opINCSI: function() {
|
||||
this.resultAuxOverflow = this.regESI;
|
||||
this.regESI = (this.regESI & this.opMaskClear) | (this.resultParitySign = this.regESI + 1) & this.opMask;
|
||||
this.regESI = (this.regESI & ~this.opMask) | (this.resultParitySign = this.regESI + 1) & this.opMask;
|
||||
this.resultValue = this.regESI | (((this.resultValue & this.resultSize)? 1 : 0) << 16);
|
||||
this.resultSize = X86.RESULT.SIZE_WORD;
|
||||
this.nStepCycles -= 2; // this form of INC takes 2 cycles on all CPUs
|
||||
|
|
@ -843,7 +843,7 @@ var X86OpXX = {
|
|||
*/
|
||||
opINCDI: function() {
|
||||
this.resultAuxOverflow = this.regEDI;
|
||||
this.regEDI = (this.regEDI & this.opMaskClear) | (this.resultParitySign = this.regEDI + 1) & this.opMask;
|
||||
this.regEDI = (this.regEDI & ~this.opMask) | (this.resultParitySign = this.regEDI + 1) & this.opMask;
|
||||
this.resultValue = this.regEDI | (((this.resultValue & this.resultSize)? 1 : 0) << 16);
|
||||
this.resultSize = X86.RESULT.SIZE_WORD;
|
||||
this.nStepCycles -= 2; // this form of INC takes 2 cycles on all CPUs
|
||||
|
|
@ -855,7 +855,7 @@ var X86OpXX = {
|
|||
*/
|
||||
opDECAX: function() {
|
||||
this.resultAuxOverflow = this.regEAX;
|
||||
this.regEAX = (this.regEAX & this.opMaskClear) | (this.resultParitySign = this.regEAX - 1) & this.opMask;
|
||||
this.regEAX = (this.regEAX & ~this.opMask) | (this.resultParitySign = this.regEAX - 1) & this.opMask;
|
||||
this.resultValue = this.regEAX | (((this.resultValue & this.resultSize)? 1 : 0) << 16);
|
||||
this.resultSize = X86.RESULT.SIZE_WORD;
|
||||
this.nStepCycles -= 2; // this form of DEC takes 2 cycles on all CPUs
|
||||
|
|
@ -867,7 +867,7 @@ var X86OpXX = {
|
|||
*/
|
||||
opDECCX: function() {
|
||||
this.resultAuxOverflow = this.regECX;
|
||||
this.regECX = (this.regECX & this.opMaskClear) | (this.resultParitySign = this.regECX - 1) & this.opMask;
|
||||
this.regECX = (this.regECX & ~this.opMask) | (this.resultParitySign = this.regECX - 1) & this.opMask;
|
||||
this.resultValue = this.regECX | (((this.resultValue & this.resultSize)? 1 : 0) << 16);
|
||||
this.resultSize = X86.RESULT.SIZE_WORD;
|
||||
this.nStepCycles -= 2; // this form of DEC takes 2 cycles on all CPUs
|
||||
|
|
@ -879,7 +879,7 @@ var X86OpXX = {
|
|||
*/
|
||||
opDECDX: function() {
|
||||
this.resultAuxOverflow = this.regEDX;
|
||||
this.regEDX = (this.regEDX & this.opMaskClear) | (this.resultParitySign = this.regEDX - 1) & this.opMask;
|
||||
this.regEDX = (this.regEDX & ~this.opMask) | (this.resultParitySign = this.regEDX - 1) & this.opMask;
|
||||
this.resultValue = this.regEDX | (((this.resultValue & this.resultSize)? 1 : 0) << 16);
|
||||
this.resultSize = X86.RESULT.SIZE_WORD;
|
||||
this.nStepCycles -= 2; // this form of DEC takes 2 cycles on all CPUs
|
||||
|
|
@ -891,7 +891,7 @@ var X86OpXX = {
|
|||
*/
|
||||
opDECBX: function() {
|
||||
this.resultAuxOverflow = this.regEBX;
|
||||
this.regEBX = (this.regEBX & this.opMaskClear) | (this.resultParitySign = this.regEBX - 1) & this.opMask;
|
||||
this.regEBX = (this.regEBX & ~this.opMask) | (this.resultParitySign = this.regEBX - 1) & this.opMask;
|
||||
this.resultValue = this.regEBX | (((this.resultValue & this.resultSize)? 1 : 0) << 16);
|
||||
this.resultSize = X86.RESULT.SIZE_WORD;
|
||||
this.nStepCycles -= 2; // this form of DEC takes 2 cycles on all CPUs
|
||||
|
|
@ -903,7 +903,7 @@ var X86OpXX = {
|
|||
*/
|
||||
opDECSP: function() {
|
||||
this.resultAuxOverflow = this.regESP;
|
||||
this.regESP = (this.regESP & this.opMaskClear) | (this.resultParitySign = this.regESP - 1) & this.opMask;
|
||||
this.regESP = (this.regESP & ~this.opMask) | (this.resultParitySign = this.regESP - 1) & this.opMask;
|
||||
this.resultValue = this.regESP | (((this.resultValue & this.resultSize)? 1 : 0) << 16);
|
||||
this.resultSize = X86.RESULT.SIZE_WORD;
|
||||
this.nStepCycles -= 2; // this form of DEC takes 2 cycles on all CPUs
|
||||
|
|
@ -915,7 +915,7 @@ var X86OpXX = {
|
|||
*/
|
||||
opDECBP: function() {
|
||||
this.resultAuxOverflow = this.regEBP;
|
||||
this.regEBP = (this.regEBP & this.opMaskClear) | (this.resultParitySign = this.regEBP - 1) & this.opMask;
|
||||
this.regEBP = (this.regEBP & ~this.opMask) | (this.resultParitySign = this.regEBP - 1) & this.opMask;
|
||||
this.resultValue = this.regEBP | (((this.resultValue & this.resultSize)? 1 : 0) << 16);
|
||||
this.resultSize = X86.RESULT.SIZE_WORD;
|
||||
this.nStepCycles -= 2; // this form of DEC takes 2 cycles on all CPUs
|
||||
|
|
@ -927,7 +927,7 @@ var X86OpXX = {
|
|||
*/
|
||||
opDECSI: function() {
|
||||
this.resultAuxOverflow = this.regESI;
|
||||
this.regESI = (this.regESI & this.opMaskClear) | (this.resultParitySign = this.regESI - 1) & this.opMask;
|
||||
this.regESI = (this.regESI & ~this.opMask) | (this.resultParitySign = this.regESI - 1) & this.opMask;
|
||||
this.resultValue = this.regESI | (((this.resultValue & this.resultSize)? 1 : 0) << 16);
|
||||
this.resultSize = X86.RESULT.SIZE_WORD;
|
||||
this.nStepCycles -= 2; // this form of DEC takes 2 cycles on all CPUs
|
||||
|
|
@ -939,7 +939,7 @@ var X86OpXX = {
|
|||
*/
|
||||
opDECDI: function() {
|
||||
this.resultAuxOverflow = this.regEDI;
|
||||
this.regEDI = (this.regEDI & this.opMaskClear) | (this.resultParitySign = this.regEDI - 1) & this.opMask;
|
||||
this.regEDI = (this.regEDI & ~this.opMask) | (this.resultParitySign = this.regEDI - 1) & this.opMask;
|
||||
this.resultValue = this.regEDI | (((this.resultValue & this.resultSize)? 1 : 0) << 16);
|
||||
this.resultSize = X86.RESULT.SIZE_WORD;
|
||||
this.nStepCycles -= 2; // this form of DEC takes 2 cycles on all CPUs
|
||||
|
|
@ -1032,7 +1032,7 @@ var X86OpXX = {
|
|||
* op=0x58 (pop AX)
|
||||
*/
|
||||
opPOPAX: function() {
|
||||
this.regEAX = (this.regEAX & this.opMaskClear) | this.popWord();
|
||||
this.regEAX = (this.regEAX & ~this.opMask) | this.popWord();
|
||||
this.nStepCycles -= this.CYCLES.nOpCyclesPopReg;
|
||||
},
|
||||
/**
|
||||
|
|
@ -1041,7 +1041,7 @@ var X86OpXX = {
|
|||
* op=0x59 (pop CX)
|
||||
*/
|
||||
opPOPCX: function() {
|
||||
this.regECX = (this.regECX & this.opMaskClear) | this.popWord();
|
||||
this.regECX = (this.regECX & ~this.opMask) | this.popWord();
|
||||
this.nStepCycles -= this.CYCLES.nOpCyclesPopReg;
|
||||
},
|
||||
/**
|
||||
|
|
@ -1050,7 +1050,7 @@ var X86OpXX = {
|
|||
* op=0x5A (pop DX)
|
||||
*/
|
||||
opPOPDX: function() {
|
||||
this.regEDX = (this.regEDX & this.opMaskClear) | this.popWord();
|
||||
this.regEDX = (this.regEDX & ~this.opMask) | this.popWord();
|
||||
this.nStepCycles -= this.CYCLES.nOpCyclesPopReg;
|
||||
},
|
||||
/**
|
||||
|
|
@ -1059,7 +1059,7 @@ var X86OpXX = {
|
|||
* op=0x5B (pop BX)
|
||||
*/
|
||||
opPOPBX: function() {
|
||||
this.regEBX = (this.regEBX & this.opMaskClear) | this.popWord();
|
||||
this.regEBX = (this.regEBX & ~this.opMask) | this.popWord();
|
||||
this.nStepCycles -= this.CYCLES.nOpCyclesPopReg;
|
||||
},
|
||||
/**
|
||||
|
|
@ -1068,7 +1068,7 @@ var X86OpXX = {
|
|||
* op=0x5C (pop SP)
|
||||
*/
|
||||
opPOPSP: function() {
|
||||
this.regESP = (this.regESP & this.opMaskClear) | this.popWord();
|
||||
this.regESP = (this.regESP & ~this.opMask) | this.popWord();
|
||||
this.nStepCycles -= this.CYCLES.nOpCyclesPopReg;
|
||||
},
|
||||
/**
|
||||
|
|
@ -1077,7 +1077,7 @@ var X86OpXX = {
|
|||
* op=0x5D (pop BP)
|
||||
*/
|
||||
opPOPBP: function() {
|
||||
this.regEBP = (this.regEBP & this.opMaskClear) | this.popWord();
|
||||
this.regEBP = (this.regEBP & ~this.opMask) | this.popWord();
|
||||
this.nStepCycles -= this.CYCLES.nOpCyclesPopReg;
|
||||
},
|
||||
/**
|
||||
|
|
@ -1086,7 +1086,7 @@ var X86OpXX = {
|
|||
* op=0x5E (pop SI)
|
||||
*/
|
||||
opPOPSI: function() {
|
||||
this.regESI = (this.regESI & this.opMaskClear) | this.popWord();
|
||||
this.regESI = (this.regESI & ~this.opMask) | this.popWord();
|
||||
this.nStepCycles -= this.CYCLES.nOpCyclesPopReg;
|
||||
},
|
||||
/**
|
||||
|
|
@ -1095,7 +1095,7 @@ var X86OpXX = {
|
|||
* op=0x5F (pop DI)
|
||||
*/
|
||||
opPOPDI: function() {
|
||||
this.regEDI = (this.regEDI & this.opMaskClear) | this.popWord();
|
||||
this.regEDI = (this.regEDI & ~this.opMask) | this.popWord();
|
||||
this.nStepCycles -= this.CYCLES.nOpCyclesPopReg;
|
||||
},
|
||||
/**
|
||||
|
|
@ -1121,14 +1121,14 @@ var X86OpXX = {
|
|||
* op=0x61 (popa) (80186/80188 and up)
|
||||
*/
|
||||
opPOPA: function() {
|
||||
this.regEDI = (this.regEDI & this.opMaskClear) | this.popWord();
|
||||
this.regESI = (this.regESI & this.opMaskClear) | this.popWord();
|
||||
this.regEBP = (this.regEBP & this.opMaskClear) | this.popWord();
|
||||
this.regEDI = (this.regEDI & ~this.opMask) | this.popWord();
|
||||
this.regESI = (this.regESI & ~this.opMask) | this.popWord();
|
||||
this.regEBP = (this.regEBP & ~this.opMask) | this.popWord();
|
||||
this.regESP += this.opSize;
|
||||
this.regEBX = (this.regEBX & this.opMaskClear) | this.popWord();
|
||||
this.regEDX = (this.regEDX & this.opMaskClear) | this.popWord();
|
||||
this.regECX = (this.regECX & this.opMaskClear) | this.popWord();
|
||||
this.regEAX = (this.regEAX & this.opMaskClear) | this.popWord();
|
||||
this.regEBX = (this.regEBX & ~this.opMask) | this.popWord();
|
||||
this.regEDX = (this.regEDX & ~this.opMask) | this.popWord();
|
||||
this.regECX = (this.regECX & ~this.opMask) | this.popWord();
|
||||
this.regEAX = (this.regEAX & ~this.opMask) | this.popWord();
|
||||
this.nStepCycles -= this.CYCLES.nOpCyclesPopAll;
|
||||
},
|
||||
/**
|
||||
|
|
@ -1211,10 +1211,10 @@ var X86OpXX = {
|
|||
}
|
||||
|
||||
if (nReps--) {
|
||||
var b = this.bus.checkPortInputNotify(this.regEDX, this.regEIP - nDelta - 1);
|
||||
var b = this.bus.checkPortInputNotify(this.regEDX, this.regLIP - nDelta - 1);
|
||||
if (BACKTRACK) this.backTrack.btiMemLo = this.backTrack.btiIO;
|
||||
this.setSOByte(this.segES, this.regEDI & this.addrMask, b);
|
||||
this.regEDI = (this.regEDI & this.addrMaskClear) | ((this.regEDI + ((this.regPS & X86.PS.DF)? -1 : 1)) & this.addrMask);
|
||||
this.regEDI = (this.regEDI & ~this.addrMask) | ((this.regEDI + ((this.regPS & X86.PS.DF)? -1 : 1)) & this.addrMask);
|
||||
this.nStepCycles -= nCycles;
|
||||
this.regECX -= nDelta;
|
||||
if (nReps) {
|
||||
|
|
@ -1224,6 +1224,7 @@ var X86OpXX = {
|
|||
* the interrupt handler will return us to an invalid state.
|
||||
*/
|
||||
this.advanceIP(-2); // this instruction does not support segment overrides
|
||||
this.assert(this.regLIP == this.opLIP);
|
||||
this.opFlags |= X86.OPFLAG.REPEAT;
|
||||
}
|
||||
}
|
||||
|
|
@ -1257,13 +1258,13 @@ var X86OpXX = {
|
|||
if (this.opPrefixes & X86.OPFLAG.REPEAT) nCycles = 4;
|
||||
}
|
||||
if (nReps--) {
|
||||
var addrFrom = this.regEIP - nDelta - 1;
|
||||
var addrFrom = this.regLIP - nDelta - 1;
|
||||
var w = this.bus.checkPortInputNotify(this.regEDX, addrFrom);
|
||||
if (BACKTRACK) this.backTrack.btiMemLo = this.backTrack.btiIO;
|
||||
w |= (this.bus.checkPortInputNotify(this.regEDX, addrFrom) << 8);
|
||||
if (BACKTRACK) this.backTrack.btiMemHi = this.backTrack.btiIO;
|
||||
this.setSOWord(this.segES, this.regEDI & this.addrMask, w);
|
||||
this.regEDI = (this.regEDI & this.addrMaskClear) | ((this.regEDI + ((this.regPS & X86.PS.DF)? -2 : 2)) & this.addrMask);
|
||||
this.regEDI = (this.regEDI & ~this.addrMask) | ((this.regEDI + ((this.regPS & X86.PS.DF)? -2 : 2)) & this.addrMask);
|
||||
this.nStepCycles -= nCycles;
|
||||
this.regECX -= nDelta;
|
||||
if (nReps) {
|
||||
|
|
@ -1273,6 +1274,7 @@ var X86OpXX = {
|
|||
* the interrupt handler will return us to an invalid state.
|
||||
*/
|
||||
this.advanceIP(-2); // this instruction does not support segment overrides
|
||||
this.assert(this.regLIP == this.opLIP);
|
||||
this.opFlags |= X86.OPFLAG.REPEAT;
|
||||
}
|
||||
}
|
||||
|
|
@ -1305,10 +1307,10 @@ var X86OpXX = {
|
|||
}
|
||||
if (nReps--) {
|
||||
var b = this.getSOByte(this.segDS, this.regESI & this.addrMask);
|
||||
this.regESI = (this.regESI & this.addrMaskClear) | ((this.regESI + ((this.regPS & X86.PS.DF)? -1 : 1)) & this.addrMask);
|
||||
this.regESI = (this.regESI & ~this.addrMask) | ((this.regESI + ((this.regPS & X86.PS.DF)? -1 : 1)) & this.addrMask);
|
||||
this.nStepCycles -= nCycles;
|
||||
this.regECX -= nDelta;
|
||||
this.bus.checkPortOutputNotify(this.regEDX, b, this.regEIP - nDelta - 1);
|
||||
this.bus.checkPortOutputNotify(this.regEDX, b, this.regLIP - nDelta - 1);
|
||||
if (nReps) {
|
||||
/*
|
||||
* We have to back up to the prefix byte(s), not just to the string instruction,
|
||||
|
|
@ -1316,6 +1318,7 @@ var X86OpXX = {
|
|||
* the interrupt handler will return us to an invalid state.
|
||||
*/
|
||||
this.advanceIP(-2); // this instruction does not support segment overrides
|
||||
this.assert(this.regLIP == this.opLIP);
|
||||
this.opFlags |= X86.OPFLAG.REPEAT;
|
||||
}
|
||||
}
|
||||
|
|
@ -1348,10 +1351,10 @@ var X86OpXX = {
|
|||
}
|
||||
if (nReps--) {
|
||||
var w = this.getSOWord(this.segDS, this.regESI & this.addrMask);
|
||||
this.regESI = (this.regESI & this.addrMaskClear) | ((this.regESI + ((this.regPS & X86.PS.DF)? -2 : 2)) & this.addrMask);
|
||||
this.regESI = (this.regESI & ~this.addrMask) | ((this.regESI + ((this.regPS & X86.PS.DF)? -2 : 2)) & this.addrMask);
|
||||
this.nStepCycles -= nCycles;
|
||||
this.regECX -= nDelta;
|
||||
var addrFrom = this.regEIP - nDelta - 1;
|
||||
var addrFrom = this.regLIP - nDelta - 1;
|
||||
this.bus.checkPortOutputNotify(this.regEDX, w & 0xff, addrFrom);
|
||||
this.bus.checkPortOutputNotify(this.regEDX, w >> 8, addrFrom);
|
||||
if (nReps) {
|
||||
|
|
@ -1361,6 +1364,7 @@ var X86OpXX = {
|
|||
* the interrupt handler will return us to an invalid state.
|
||||
*/
|
||||
this.advanceIP(-2); // this instruction does not support segment overrides
|
||||
this.assert(this.regLIP == this.opLIP);
|
||||
this.opFlags |= X86.OPFLAG.REPEAT;
|
||||
}
|
||||
}
|
||||
|
|
@ -1373,7 +1377,7 @@ var X86OpXX = {
|
|||
opJO: function() {
|
||||
var disp = this.getIPDisp();
|
||||
if (this.getOF()) {
|
||||
this.setIP(this.regIP + disp);
|
||||
this.setIP(this.regEIP + disp);
|
||||
this.nStepCycles -= this.CYCLES.nOpCyclesJmpC;
|
||||
return;
|
||||
}
|
||||
|
|
@ -1387,7 +1391,7 @@ var X86OpXX = {
|
|||
opJNO: function() {
|
||||
var disp = this.getIPDisp();
|
||||
if (!this.getOF()) {
|
||||
this.setIP(this.regIP + disp);
|
||||
this.setIP(this.regEIP + disp);
|
||||
this.nStepCycles -= this.CYCLES.nOpCyclesJmpC;
|
||||
return;
|
||||
}
|
||||
|
|
@ -1401,7 +1405,7 @@ var X86OpXX = {
|
|||
opJC: function() {
|
||||
var disp = this.getIPDisp();
|
||||
if (this.getCF()) {
|
||||
this.setIP(this.regIP + disp);
|
||||
this.setIP(this.regEIP + disp);
|
||||
this.nStepCycles -= this.CYCLES.nOpCyclesJmpC;
|
||||
return;
|
||||
}
|
||||
|
|
@ -1415,7 +1419,7 @@ var X86OpXX = {
|
|||
opJNC: function() {
|
||||
var disp = this.getIPDisp();
|
||||
if (!this.getCF()) {
|
||||
this.setIP(this.regIP + disp);
|
||||
this.setIP(this.regEIP + disp);
|
||||
this.nStepCycles -= this.CYCLES.nOpCyclesJmpC;
|
||||
return;
|
||||
}
|
||||
|
|
@ -1429,7 +1433,7 @@ var X86OpXX = {
|
|||
opJZ: function() {
|
||||
var disp = this.getIPDisp();
|
||||
if (this.getZF()) {
|
||||
this.setIP(this.regIP + disp);
|
||||
this.setIP(this.regEIP + disp);
|
||||
this.nStepCycles -= this.CYCLES.nOpCyclesJmpC;
|
||||
return;
|
||||
}
|
||||
|
|
@ -1443,7 +1447,7 @@ var X86OpXX = {
|
|||
opJNZ: function() {
|
||||
var disp = this.getIPDisp();
|
||||
if (!this.getZF()) {
|
||||
this.setIP(this.regIP + disp);
|
||||
this.setIP(this.regEIP + disp);
|
||||
this.nStepCycles -= this.CYCLES.nOpCyclesJmpC;
|
||||
return;
|
||||
}
|
||||
|
|
@ -1457,7 +1461,7 @@ var X86OpXX = {
|
|||
opJBE: function() {
|
||||
var disp = this.getIPDisp();
|
||||
if (this.getCF() || this.getZF()) {
|
||||
this.setIP(this.regIP + disp);
|
||||
this.setIP(this.regEIP + disp);
|
||||
this.nStepCycles -= this.CYCLES.nOpCyclesJmpC;
|
||||
return;
|
||||
}
|
||||
|
|
@ -1471,7 +1475,7 @@ var X86OpXX = {
|
|||
opJNBE: function() {
|
||||
var disp = this.getIPDisp();
|
||||
if (!this.getCF() && !this.getZF()) {
|
||||
this.setIP(this.regIP + disp);
|
||||
this.setIP(this.regEIP + disp);
|
||||
this.nStepCycles -= this.CYCLES.nOpCyclesJmpC;
|
||||
return;
|
||||
}
|
||||
|
|
@ -1485,7 +1489,7 @@ var X86OpXX = {
|
|||
opJS: function() {
|
||||
var disp = this.getIPDisp();
|
||||
if (this.getSF()) {
|
||||
this.setIP(this.regIP + disp);
|
||||
this.setIP(this.regEIP + disp);
|
||||
this.nStepCycles -= this.CYCLES.nOpCyclesJmpC;
|
||||
return;
|
||||
}
|
||||
|
|
@ -1499,7 +1503,7 @@ var X86OpXX = {
|
|||
opJNS: function() {
|
||||
var disp = this.getIPDisp();
|
||||
if (!this.getSF()) {
|
||||
this.setIP(this.regIP + disp);
|
||||
this.setIP(this.regEIP + disp);
|
||||
this.nStepCycles -= this.CYCLES.nOpCyclesJmpC;
|
||||
return;
|
||||
}
|
||||
|
|
@ -1513,7 +1517,7 @@ var X86OpXX = {
|
|||
opJP: function() {
|
||||
var disp = this.getIPDisp();
|
||||
if (this.getPF()) {
|
||||
this.setIP(this.regIP + disp);
|
||||
this.setIP(this.regEIP + disp);
|
||||
this.nStepCycles -= this.CYCLES.nOpCyclesJmpC;
|
||||
return;
|
||||
}
|
||||
|
|
@ -1527,7 +1531,7 @@ var X86OpXX = {
|
|||
opJNP: function() {
|
||||
var disp = this.getIPDisp();
|
||||
if (!this.getPF()) {
|
||||
this.setIP(this.regIP + disp);
|
||||
this.setIP(this.regEIP + disp);
|
||||
this.nStepCycles -= this.CYCLES.nOpCyclesJmpC;
|
||||
return;
|
||||
}
|
||||
|
|
@ -1541,7 +1545,7 @@ var X86OpXX = {
|
|||
opJL: function() {
|
||||
var disp = this.getIPDisp();
|
||||
if (!this.getSF() != !this.getOF()) { // jshint ignore:line
|
||||
this.setIP(this.regIP + disp);
|
||||
this.setIP(this.regEIP + disp);
|
||||
this.nStepCycles -= this.CYCLES.nOpCyclesJmpC;
|
||||
return;
|
||||
}
|
||||
|
|
@ -1555,7 +1559,7 @@ var X86OpXX = {
|
|||
opJNL: function() {
|
||||
var disp = this.getIPDisp();
|
||||
if (!this.getSF() == !this.getOF()) { // jshint ignore:line
|
||||
this.setIP(this.regIP + disp);
|
||||
this.setIP(this.regEIP + disp);
|
||||
this.nStepCycles -= this.CYCLES.nOpCyclesJmpC;
|
||||
return;
|
||||
}
|
||||
|
|
@ -1569,7 +1573,7 @@ var X86OpXX = {
|
|||
opJLE: function() {
|
||||
var disp = this.getIPDisp();
|
||||
if (this.getZF() || !this.getSF() != !this.getOF()) { // jshint ignore:line
|
||||
this.setIP(this.regIP + disp);
|
||||
this.setIP(this.regEIP + disp);
|
||||
this.nStepCycles -= this.CYCLES.nOpCyclesJmpC;
|
||||
return;
|
||||
}
|
||||
|
|
@ -1583,7 +1587,7 @@ var X86OpXX = {
|
|||
opJNLE: function() {
|
||||
var disp = this.getIPDisp();
|
||||
if (!this.getZF() && !this.getSF() == !this.getOF()) { // jshint ignore:line
|
||||
this.setIP(this.regIP + disp);
|
||||
this.setIP(this.regEIP + disp);
|
||||
this.nStepCycles -= this.CYCLES.nOpCyclesJmpC;
|
||||
return;
|
||||
}
|
||||
|
|
@ -1881,8 +1885,8 @@ var X86OpXX = {
|
|||
*/
|
||||
opXCHGCX: function() {
|
||||
var temp = this.regEAX;
|
||||
this.regEAX = (this.regEAX & this.opMaskClear) | (this.regECX & this.opMask);
|
||||
this.regECX = (this.regECX & this.opMaskClear) | (temp & this.opMask);
|
||||
this.regEAX = (this.regEAX & ~this.opMask) | (this.regECX & this.opMask);
|
||||
this.regECX = (this.regECX & ~this.opMask) | (temp & this.opMask);
|
||||
this.nStepCycles -= 3; // this form of XCHG takes 3 cycles on all CPUs
|
||||
},
|
||||
/**
|
||||
|
|
@ -1892,8 +1896,8 @@ var X86OpXX = {
|
|||
*/
|
||||
opXCHGDX: function() {
|
||||
var temp = this.regEAX;
|
||||
this.regEAX = (this.regEAX & this.opMaskClear) | (this.regEDX & this.opMask);
|
||||
this.regEDX = (this.regEDX & this.opMaskClear) | (temp & this.opMask);
|
||||
this.regEAX = (this.regEAX & ~this.opMask) | (this.regEDX & this.opMask);
|
||||
this.regEDX = (this.regEDX & ~this.opMask) | (temp & this.opMask);
|
||||
this.nStepCycles -= 3; // this form of XCHG takes 3 cycles on all CPUs
|
||||
},
|
||||
/**
|
||||
|
|
@ -1903,8 +1907,8 @@ var X86OpXX = {
|
|||
*/
|
||||
opXCHGBX: function() {
|
||||
var temp = this.regEAX;
|
||||
this.regEAX = (this.regEAX & this.opMaskClear) | (this.regEBX & this.opMask);
|
||||
this.regEBX = (this.regEBX & this.opMaskClear) | (temp & this.opMask);
|
||||
this.regEAX = (this.regEAX & ~this.opMask) | (this.regEBX & this.opMask);
|
||||
this.regEBX = (this.regEBX & ~this.opMask) | (temp & this.opMask);
|
||||
this.nStepCycles -= 3; // this form of XCHG takes 3 cycles on all CPUs
|
||||
},
|
||||
/**
|
||||
|
|
@ -1914,8 +1918,8 @@ var X86OpXX = {
|
|||
*/
|
||||
opXCHGSP: function() {
|
||||
var temp = this.regEAX;
|
||||
this.regEAX = (this.regEAX & this.opMaskClear) | (this.regESP & this.opMask);
|
||||
this.regESP = (this.regESP & this.opMaskClear) | (temp & this.opMask);
|
||||
this.regEAX = (this.regEAX & ~this.opMask) | (this.regESP & this.opMask);
|
||||
this.regESP = (this.regESP & ~this.opMask) | (temp & this.opMask);
|
||||
this.nStepCycles -= 3; // this form of XCHG takes 3 cycles on all CPUs
|
||||
},
|
||||
/**
|
||||
|
|
@ -1925,8 +1929,8 @@ var X86OpXX = {
|
|||
*/
|
||||
opXCHGBP: function() {
|
||||
var temp = this.regEAX;
|
||||
this.regEAX = (this.regEAX & this.opMaskClear) | (this.regEBP & this.opMask);
|
||||
this.regEBP = (this.regEBP & this.opMaskClear) | (temp & this.opMask);
|
||||
this.regEAX = (this.regEAX & ~this.opMask) | (this.regEBP & this.opMask);
|
||||
this.regEBP = (this.regEBP & ~this.opMask) | (temp & this.opMask);
|
||||
this.nStepCycles -= 3; // this form of XCHG takes 3 cycles on all CPUs
|
||||
},
|
||||
/**
|
||||
|
|
@ -1936,8 +1940,8 @@ var X86OpXX = {
|
|||
*/
|
||||
opXCHGSI: function() {
|
||||
var temp = this.regEAX;
|
||||
this.regEAX = (this.regEAX & this.opMaskClear) | (this.regESI & this.opMask);
|
||||
this.regESI = (this.regESI & this.opMaskClear) | (temp & this.opMask);
|
||||
this.regEAX = (this.regEAX & ~this.opMask) | (this.regESI & this.opMask);
|
||||
this.regESI = (this.regESI & ~this.opMask) | (temp & this.opMask);
|
||||
this.nStepCycles -= 3; // this form of XCHG takes 3 cycles on all CPUs
|
||||
},
|
||||
/**
|
||||
|
|
@ -1947,8 +1951,8 @@ var X86OpXX = {
|
|||
*/
|
||||
opXCHGDI: function() {
|
||||
var temp = this.regEAX;
|
||||
this.regEAX = (this.regEAX & this.opMaskClear) | (this.regEDI & this.opMask);
|
||||
this.regEDI = (this.regEDI & this.opMaskClear) | (temp & this.opMask);
|
||||
this.regEAX = (this.regEAX & ~this.opMask) | (this.regEDI & this.opMask);
|
||||
this.regEDI = (this.regEDI & ~this.opMask) | (temp & this.opMask);
|
||||
this.nStepCycles -= 3; // this form of XCHG takes 3 cycles on all CPUs
|
||||
},
|
||||
/**
|
||||
|
|
@ -1958,7 +1962,7 @@ var X86OpXX = {
|
|||
*/
|
||||
opCBW: function() {
|
||||
if (this.opSize == 2) {
|
||||
this.regEAX = (this.regEAX & this.opMaskClear) | (((this.regEAX << 24) >> 24) & 0xffff);
|
||||
this.regEAX = (this.regEAX & ~this.opMask) | (((this.regEAX << 24) >> 24) & 0xffff);
|
||||
} else {
|
||||
this.regEAX = ((this.regEAX << 16) >> 16);
|
||||
}
|
||||
|
|
@ -1971,7 +1975,7 @@ var X86OpXX = {
|
|||
*/
|
||||
opCWD: function() {
|
||||
if (this.opSize == 2) {
|
||||
this.regEDX = (this.regEDX & this.opMaskClear) | ((this.regEAX & 0x8000)? 0xffff : 0);
|
||||
this.regEDX = (this.regEDX & ~this.opMask) | ((this.regEAX & 0x8000)? 0xffff : 0);
|
||||
} else {
|
||||
this.regEDX = (this.regEAX & 0x80000000)? 0xffffffff : 0;
|
||||
}
|
||||
|
|
@ -2064,7 +2068,7 @@ var X86OpXX = {
|
|||
* op=0xA1 (mov AX,mem)
|
||||
*/
|
||||
opMOVAXDst: function() {
|
||||
this.regEAX = (this.regEAX & this.opMaskClear) | this.getEAWord(this.segData, this.getIPWord());
|
||||
this.regEAX = (this.regEAX & ~this.opMask) | this.getEAWord(this.segData, this.getIPWord());
|
||||
this.nStepCycles -= this.CYCLES.nOpCyclesMovAM;
|
||||
},
|
||||
/**
|
||||
|
|
@ -2109,8 +2113,8 @@ var X86OpXX = {
|
|||
if (nReps--) {
|
||||
var nInc = ((this.regPS & X86.PS.DF)? -1 : 1);
|
||||
this.setSOByte(this.segES, this.regEDI & this.addrMask, this.getEAByte(this.segData, this.regESI));
|
||||
this.regESI = (this.regESI & this.addrMaskClear) | ((this.regESI + nInc) & this.addrMask);
|
||||
this.regEDI = (this.regEDI & this.addrMaskClear) | ((this.regEDI + nInc) & this.addrMask);
|
||||
this.regESI = (this.regESI & ~this.addrMask) | ((this.regESI + nInc) & this.addrMask);
|
||||
this.regEDI = (this.regEDI & ~this.addrMask) | ((this.regEDI + nInc) & this.addrMask);
|
||||
this.nStepCycles -= nCycles;
|
||||
this.regECX -= nDelta;
|
||||
if (nReps) {
|
||||
|
|
@ -2124,6 +2128,7 @@ var X86OpXX = {
|
|||
* string instructions with multiple prefixes.
|
||||
*/
|
||||
this.advanceIP(((this.opPrefixes & X86.OPFLAG.SEG)? -3 : -2));
|
||||
this.assert(this.regLIP == this.opLIP);
|
||||
this.opFlags |= X86.OPFLAG.REPEAT;
|
||||
}
|
||||
}
|
||||
|
|
@ -2146,8 +2151,8 @@ var X86OpXX = {
|
|||
if (nReps--) {
|
||||
var nInc = ((this.regPS & X86.PS.DF)? -2 : 2);
|
||||
this.setSOWord(this.segES, this.regEDI & this.addrMask, this.getEAWord(this.segData, this.regESI));
|
||||
this.regESI = (this.regESI & this.addrMaskClear) | ((this.regESI + nInc) & this.addrMask);
|
||||
this.regEDI = (this.regEDI & this.addrMaskClear) | ((this.regEDI + nInc) & this.addrMask);
|
||||
this.regESI = (this.regESI & ~this.addrMask) | ((this.regESI + nInc) & this.addrMask);
|
||||
this.regEDI = (this.regEDI & ~this.addrMask) | ((this.regEDI + nInc) & this.addrMask);
|
||||
this.nStepCycles -= nCycles;
|
||||
this.regECX -= nDelta;
|
||||
if (nReps) {
|
||||
|
|
@ -2161,6 +2166,7 @@ var X86OpXX = {
|
|||
* string instructions with multiple prefixes.
|
||||
*/
|
||||
this.advanceIP(((this.opPrefixes & X86.OPFLAG.SEG)? -3 : -2));
|
||||
this.assert(this.regLIP == this.opLIP);
|
||||
this.opFlags |= X86.OPFLAG.REPEAT;
|
||||
}
|
||||
}
|
||||
|
|
@ -2185,8 +2191,8 @@ var X86OpXX = {
|
|||
var bDst = this.getEAByte(this.segData, this.regESI & this.addrMask);
|
||||
var bSrc = this.modEAByte(this.segES, this.regEDI & this.addrMask);
|
||||
X86Grps.opGrpCMPb.call(this, bDst, bSrc);
|
||||
this.regESI = (this.regESI & this.addrMaskClear) | ((this.regESI + nInc) & this.addrMask);
|
||||
this.regEDI = (this.regEDI & this.addrMaskClear) | ((this.regEDI + nInc) & this.addrMask);
|
||||
this.regESI = (this.regESI & ~this.addrMask) | ((this.regESI + nInc) & this.addrMask);
|
||||
this.regEDI = (this.regEDI & ~this.addrMask) | ((this.regEDI + nInc) & this.addrMask);
|
||||
/*
|
||||
* NOTE: As long as we're calling opGrpCMPb(), all our cycle times must be reduced by nOpCyclesArithRM
|
||||
*/
|
||||
|
|
@ -2208,6 +2214,7 @@ var X86OpXX = {
|
|||
* string instructions with multiple prefixes.
|
||||
*/
|
||||
this.advanceIP(((this.opPrefixes & X86.OPFLAG.SEG)? -3 : -2));
|
||||
this.assert(this.regLIP == this.opLIP);
|
||||
this.opFlags |= X86.OPFLAG.REPEAT;
|
||||
}
|
||||
if (EAFUNCS) this.setEAByte = this.setEAByteEnabled;
|
||||
|
|
@ -2233,8 +2240,8 @@ var X86OpXX = {
|
|||
var wDst = this.getEAWord(this.segData, this.regESI & this.addrMask);
|
||||
var wSrc = this.modEAWord(this.segES, this.regEDI & this.addrMask);
|
||||
X86Grps.opGrpCMPw.call(this, wDst, wSrc);
|
||||
this.regESI = (this.regESI & this.addrMaskClear) | ((this.regESI + nInc) & this.addrMask);
|
||||
this.regEDI = (this.regEDI & this.addrMaskClear) | ((this.regEDI + nInc) & this.addrMask);
|
||||
this.regESI = (this.regESI & ~this.addrMask) | ((this.regESI + nInc) & this.addrMask);
|
||||
this.regEDI = (this.regEDI & ~this.addrMask) | ((this.regEDI + nInc) & this.addrMask);
|
||||
/*
|
||||
* NOTE: As long as we're calling opGrpCMPw(), all our cycle times must be reduced by nOpCyclesArithRM
|
||||
*/
|
||||
|
|
@ -2256,6 +2263,7 @@ var X86OpXX = {
|
|||
* string instructions with multiple prefixes.
|
||||
*/
|
||||
this.advanceIP(((this.opPrefixes & X86.OPFLAG.SEG)? -3 : -2));
|
||||
this.assert(this.regLIP == this.opLIP);
|
||||
this.opFlags |= X86.OPFLAG.REPEAT;
|
||||
}
|
||||
if (EAFUNCS) this.setEAWord = this.setEAWordEnabled;
|
||||
|
|
@ -2305,7 +2313,7 @@ var X86OpXX = {
|
|||
* NOTE: We rely on setSOByte() to truncate regEAX to 8 bits; if setSOByte() changes, mask AX below.
|
||||
*/
|
||||
this.setSOByte(this.segES, this.regEDI & this.addrMask, this.regEAX);
|
||||
this.regEDI = (this.regEDI & this.addrMaskClear) | ((this.regEDI + ((this.regPS & X86.PS.DF)? -1 : 1)) & this.addrMask);
|
||||
this.regEDI = (this.regEDI & ~this.addrMask) | ((this.regEDI + ((this.regPS & X86.PS.DF)? -1 : 1)) & this.addrMask);
|
||||
this.nStepCycles -= nCycles;
|
||||
this.regECX -= nDelta;
|
||||
if (nReps) {
|
||||
|
|
@ -2315,7 +2323,7 @@ var X86OpXX = {
|
|||
* the interrupt handler will return us to an invalid state.
|
||||
*/
|
||||
this.advanceIP(-2); // this instruction does not support segment overrides
|
||||
this.assert(this.regEIP == this.opEA);
|
||||
this.assert(this.regLIP == this.opLIP);
|
||||
this.opFlags |= X86.OPFLAG.REPEAT;
|
||||
}
|
||||
}
|
||||
|
|
@ -2345,7 +2353,7 @@ var X86OpXX = {
|
|||
* if you think the cycle times here are too high.
|
||||
*/
|
||||
this.setSOWord(this.segES, this.regEDI & this.addrMask, this.regEAX);
|
||||
this.regEDI = (this.regEDI & this.addrMaskClear) | ((this.regEDI + ((this.regPS & X86.PS.DF)? -2 : 2)) & this.addrMask);
|
||||
this.regEDI = (this.regEDI & ~this.addrMask) | ((this.regEDI + ((this.regPS & X86.PS.DF)? -2 : 2)) & this.addrMask);
|
||||
this.nStepCycles -= nCycles;
|
||||
this.regECX -= nDelta;
|
||||
if (nReps) {
|
||||
|
|
@ -2355,6 +2363,7 @@ var X86OpXX = {
|
|||
* the interrupt handler will return us to an invalid state.
|
||||
*/
|
||||
this.advanceIP(-2); // this instruction does not support segment overrides
|
||||
this.assert(this.regLIP == this.opLIP);
|
||||
this.opFlags |= X86.OPFLAG.REPEAT;
|
||||
}
|
||||
}
|
||||
|
|
@ -2376,7 +2385,7 @@ var X86OpXX = {
|
|||
}
|
||||
if (nReps--) {
|
||||
this.regEAX = (this.regEAX & ~0xff) | this.getEAByte(this.segData, this.regESI & this.addrMask);
|
||||
this.regESI = (this.regESI & this.addrMaskClear) | ((this.regESI + ((this.regPS & X86.PS.DF)? -1 : 1)) & this.addrMask);
|
||||
this.regESI = (this.regESI & ~this.addrMask) | ((this.regESI + ((this.regPS & X86.PS.DF)? -1 : 1)) & this.addrMask);
|
||||
this.nStepCycles -= nCycles;
|
||||
this.regECX -= nDelta;
|
||||
if (nReps) {
|
||||
|
|
@ -2390,6 +2399,7 @@ var X86OpXX = {
|
|||
* string instructions with multiple prefixes.
|
||||
*/
|
||||
this.advanceIP(((this.opPrefixes & X86.OPFLAG.SEG)? -3 : -2));
|
||||
this.assert(this.regLIP == this.opLIP);
|
||||
this.opFlags |= X86.OPFLAG.REPEAT;
|
||||
}
|
||||
}
|
||||
|
|
@ -2411,7 +2421,7 @@ var X86OpXX = {
|
|||
}
|
||||
if (nReps--) {
|
||||
this.regEAX = this.getEAWord(this.segData, this.regESI & this.addrMask);
|
||||
this.regESI = (this.regESI & this.addrMaskClear) | ((this.regESI + ((this.regPS & X86.PS.DF)? -2 : 2)) & this.addrMask);
|
||||
this.regESI = (this.regESI & ~this.addrMask) | ((this.regESI + ((this.regPS & X86.PS.DF)? -2 : 2)) & this.addrMask);
|
||||
this.nStepCycles -= nCycles;
|
||||
this.regECX -= nDelta;
|
||||
if (nReps) {
|
||||
|
|
@ -2425,6 +2435,7 @@ var X86OpXX = {
|
|||
* string instructions with multiple prefixes.
|
||||
*/
|
||||
this.advanceIP(((this.opPrefixes & X86.OPFLAG.SEG)? -3 : -2));
|
||||
this.assert(this.regLIP == this.opLIP);
|
||||
this.opFlags |= X86.OPFLAG.REPEAT;
|
||||
}
|
||||
}
|
||||
|
|
@ -2446,7 +2457,7 @@ var X86OpXX = {
|
|||
}
|
||||
if (nReps--) {
|
||||
X86Grps.opGrpCMPb.call(this, this.regEAX & 0xff, this.modEAByte(this.segES, this.regEDI & this.addrMask));
|
||||
this.regEDI = (this.regEDI & this.addrMaskClear) | ((this.regEDI + ((this.regPS & X86.PS.DF)? -1 : 1)) & this.addrMask);
|
||||
this.regEDI = (this.regEDI & ~this.addrMask) | ((this.regEDI + ((this.regPS & X86.PS.DF)? -1 : 1)) & this.addrMask);
|
||||
/*
|
||||
* NOTE: As long as we're calling opGrpCMPb(), all our cycle times must be reduced by nOpCyclesArithRM
|
||||
*/
|
||||
|
|
@ -2464,6 +2475,7 @@ var X86OpXX = {
|
|||
* the interrupt handler will return us to an invalid state.
|
||||
*/
|
||||
this.advanceIP(-2); // this instruction does not support segment overrides
|
||||
this.assert(this.regLIP == this.opLIP);
|
||||
this.opFlags |= X86.OPFLAG.REPEAT;
|
||||
}
|
||||
if (EAFUNCS) this.setEAByte = this.setEAByteEnabled;
|
||||
|
|
@ -2486,7 +2498,7 @@ var X86OpXX = {
|
|||
}
|
||||
if (nReps--) {
|
||||
X86Grps.opGrpCMPw.call(this, this.regEAX, this.modEAWord(this.segES, this.regEDI & this.addrMask));
|
||||
this.regEDI = (this.regEDI & this.addrMaskClear) | ((this.regEDI + ((this.regPS & X86.PS.DF)? -2 : 2)) & this.addrMask);
|
||||
this.regEDI = (this.regEDI & ~this.addrMask) | ((this.regEDI + ((this.regPS & X86.PS.DF)? -2 : 2)) & this.addrMask);
|
||||
/*
|
||||
* NOTE: As long as we're calling opGrpCMPb(), all our cycle times must be reduced by nOpCyclesArithRM
|
||||
*/
|
||||
|
|
@ -2504,6 +2516,7 @@ var X86OpXX = {
|
|||
* the interrupt handler will return us to an invalid state.
|
||||
*/
|
||||
this.advanceIP(-2); // this instruction does not support segment overrides
|
||||
this.assert(this.regLIP == this.opLIP);
|
||||
this.opFlags |= X86.OPFLAG.REPEAT;
|
||||
}
|
||||
if (EAFUNCS) this.setEAWord = this.setEAWordEnabled;
|
||||
|
|
@ -2587,7 +2600,7 @@ var X86OpXX = {
|
|||
* op=0xB8 (mov AX,imm16)
|
||||
*/
|
||||
opMOVAXw: function() {
|
||||
this.regEAX = (this.regEAX & this.opMaskClear) | this.getIPWord();
|
||||
this.regEAX = (this.regEAX & ~this.opMask) | this.getIPWord();
|
||||
this.nStepCycles -= this.CYCLES.nOpCyclesLAHF;
|
||||
},
|
||||
/**
|
||||
|
|
@ -2596,7 +2609,7 @@ var X86OpXX = {
|
|||
* op=0xB9 (mov CX,imm16)
|
||||
*/
|
||||
opMOVCXw: function() {
|
||||
this.regECX = (this.regECX & this.opMaskClear) | this.getIPWord();
|
||||
this.regECX = (this.regECX & ~this.opMask) | this.getIPWord();
|
||||
this.nStepCycles -= this.CYCLES.nOpCyclesLAHF;
|
||||
},
|
||||
/**
|
||||
|
|
@ -2605,7 +2618,7 @@ var X86OpXX = {
|
|||
* op=0xBA (mov DX,imm16)
|
||||
*/
|
||||
opMOVDXw: function() {
|
||||
this.regEDX = (this.regEDX & this.opMaskClear) | this.getIPWord();
|
||||
this.regEDX = (this.regEDX & ~this.opMask) | this.getIPWord();
|
||||
this.nStepCycles -= this.CYCLES.nOpCyclesLAHF;
|
||||
},
|
||||
/**
|
||||
|
|
@ -2614,7 +2627,7 @@ var X86OpXX = {
|
|||
* op=0xBB (mov BX,imm16)
|
||||
*/
|
||||
opMOVBXw: function() {
|
||||
this.regEBX = (this.regEBX & this.opMaskClear) | this.getIPWord();
|
||||
this.regEBX = (this.regEBX & ~this.opMask) | this.getIPWord();
|
||||
this.nStepCycles -= this.CYCLES.nOpCyclesLAHF;
|
||||
},
|
||||
/**
|
||||
|
|
@ -2623,7 +2636,7 @@ var X86OpXX = {
|
|||
* op=0xBC (mov SP,imm16)
|
||||
*/
|
||||
opMOVSPw: function() {
|
||||
this.regESP = (this.regESP & this.opMaskClear) | this.getIPWord();
|
||||
this.regESP = (this.regESP & ~this.opMask) | this.getIPWord();
|
||||
this.nStepCycles -= this.CYCLES.nOpCyclesLAHF;
|
||||
},
|
||||
/**
|
||||
|
|
@ -2632,7 +2645,7 @@ var X86OpXX = {
|
|||
* op=0xBD (mov BP,imm16)
|
||||
*/
|
||||
opMOVBPw: function() {
|
||||
this.regEBP = (this.regEBP & this.opMaskClear) | this.getIPWord();
|
||||
this.regEBP = (this.regEBP & ~this.opMask) | this.getIPWord();
|
||||
this.nStepCycles -= this.CYCLES.nOpCyclesLAHF;
|
||||
},
|
||||
/**
|
||||
|
|
@ -2641,7 +2654,7 @@ var X86OpXX = {
|
|||
* op=0xBE (mov SI,imm16)
|
||||
*/
|
||||
opMOVSIw: function() {
|
||||
this.regESI = (this.regESI & this.opMaskClear) | this.getIPWord();
|
||||
this.regESI = (this.regESI & ~this.opMask) | this.getIPWord();
|
||||
this.nStepCycles -= this.CYCLES.nOpCyclesLAHF;
|
||||
},
|
||||
/**
|
||||
|
|
@ -2650,7 +2663,7 @@ var X86OpXX = {
|
|||
* op=0xBF (mov DI,imm16)
|
||||
*/
|
||||
opMOVDIw: function() {
|
||||
this.regEDI = (this.regEDI & this.opMaskClear) | this.getIPWord();
|
||||
this.regEDI = (this.regEDI & ~this.opMask) | this.getIPWord();
|
||||
this.nStepCycles -= this.CYCLES.nOpCyclesLAHF;
|
||||
},
|
||||
/**
|
||||
|
|
@ -2677,7 +2690,7 @@ var X86OpXX = {
|
|||
opRETn: function() {
|
||||
var n = this.getIPWord();
|
||||
this.setIP(this.popWord());
|
||||
this.regESP = (this.regESP & this.addrMaskClear) | ((this.regESP + (n << (this.opSize >> 2))) & this.addrMask);
|
||||
this.regESP = (this.regESP & ~this.addrMask) | ((this.regESP + (n << (this.opSize >> 2))) & this.addrMask);
|
||||
this.nStepCycles -= this.CYCLES.nOpCyclesRetn;
|
||||
},
|
||||
/**
|
||||
|
|
@ -2773,13 +2786,13 @@ var X86OpXX = {
|
|||
if (bLevel > 0) {
|
||||
this.nStepCycles -= (bLevel << 2) + (bLevel > 1? 1 : 0);
|
||||
while (--bLevel) {
|
||||
this.regEBP = (this.regEBP & this.segSS.addrMaskClear) | ((this.regEBP - this.opSize) & this.segSS.addrMask);
|
||||
this.regEBP = (this.regEBP & ~this.segSS.addrMask) | ((this.regEBP - this.opSize) & this.segSS.addrMask);
|
||||
this.pushWord(this.getSOWord(this.segSS, this.regEBP & this.segSS.addrMask));
|
||||
}
|
||||
this.pushWord(wFrame);
|
||||
}
|
||||
this.regEBP = (this.regEBP & this.segSS.addrMaskClear) | wFrame;
|
||||
this.regESP = (this.regESP & this.segSS.addrMaskClear) | ((this.regESP - wLocal) & this.segSS.addrMask);
|
||||
this.regEBP = (this.regEBP & ~this.segSS.addrMask) | wFrame;
|
||||
this.regESP = (this.regESP & ~this.segSS.addrMask) | ((this.regESP - wLocal) & this.segSS.addrMask);
|
||||
},
|
||||
/**
|
||||
* @this {X86CPU}
|
||||
|
|
@ -2789,8 +2802,8 @@ var X86OpXX = {
|
|||
* op=0xC9 (leave) (80186/80188 and up)
|
||||
*/
|
||||
opLEAVE: function() {
|
||||
this.regESP = (this.regESP & this.segSS.addrMaskClear) | (this.regEBP & this.segSS.addrMask);
|
||||
this.regEBP = (this.regEBP & this.opMaskClear) | (this.popWord() & this.opMask);
|
||||
this.regESP = (this.regESP & ~this.segSS.addrMask) | (this.regEBP & this.segSS.addrMask);
|
||||
this.regEBP = (this.regEBP & ~this.opMask) | (this.popWord() & this.opMask);
|
||||
/*
|
||||
* NOTE: 5 is the cycle time for the 80286; the 80186/80188 has a cycle time of 8. However, accurate cycle
|
||||
* counts for the 80186/80188 is low priority. TODO: Fix this someday.
|
||||
|
|
@ -2976,7 +2989,7 @@ var X86OpXX = {
|
|||
opLOOPNZ: function() {
|
||||
var disp = this.getIPDisp();
|
||||
if ((this.regECX = (this.regECX - 1) & 0xffff) && (this.resultValue & (this.resultSize - 1))) {
|
||||
this.setIP(this.regIP + disp);
|
||||
this.setIP(this.regEIP + disp);
|
||||
this.nStepCycles -= this.CYCLES.nOpCyclesLoopNZ;
|
||||
return;
|
||||
}
|
||||
|
|
@ -2990,7 +3003,7 @@ var X86OpXX = {
|
|||
opLOOPZ: function() {
|
||||
var disp = this.getIPDisp();
|
||||
if ((this.regECX = (this.regECX - 1) & 0xffff) && !(this.resultValue & (this.resultSize - 1))) {
|
||||
this.setIP(this.regIP + disp);
|
||||
this.setIP(this.regEIP + disp);
|
||||
this.nStepCycles -= this.CYCLES.nOpCyclesLoopZ;
|
||||
return;
|
||||
}
|
||||
|
|
@ -3004,7 +3017,7 @@ var X86OpXX = {
|
|||
opLOOP: function() {
|
||||
var disp = this.getIPDisp();
|
||||
if ((this.regECX = (this.regECX - 1) & 0xffff)) {
|
||||
this.setIP(this.regIP + disp);
|
||||
this.setIP(this.regEIP + disp);
|
||||
this.nStepCycles -= this.CYCLES.nOpCyclesLoop;
|
||||
return;
|
||||
}
|
||||
|
|
@ -3018,7 +3031,7 @@ var X86OpXX = {
|
|||
opJCXZ: function() {
|
||||
var disp = this.getIPDisp();
|
||||
if (!this.regECX) {
|
||||
this.setIP(this.regIP + disp);
|
||||
this.setIP(this.regEIP + disp);
|
||||
this.nStepCycles -= this.CYCLES.nOpCyclesLoopZ;
|
||||
return;
|
||||
}
|
||||
|
|
@ -3031,7 +3044,7 @@ var X86OpXX = {
|
|||
*/
|
||||
opINb: function() {
|
||||
var port = this.getIPByte();
|
||||
this.regEAX = (this.regEAX & ~0xff) | this.bus.checkPortInputNotify(port, this.regEIP - 2);
|
||||
this.regEAX = (this.regEAX & ~0xff) | this.bus.checkPortInputNotify(port, this.regLIP - 2);
|
||||
if (BACKTRACK) this.backTrack.btiAL = this.backTrack.btiIO;
|
||||
this.nStepCycles -= this.CYCLES.nOpCyclesInP;
|
||||
},
|
||||
|
|
@ -3042,9 +3055,9 @@ var X86OpXX = {
|
|||
*/
|
||||
opINw: function() {
|
||||
var port = this.getIPByte();
|
||||
this.regEAX = this.bus.checkPortInputNotify(port, this.regEIP - 2);
|
||||
this.regEAX = this.bus.checkPortInputNotify(port, this.regLIP - 2);
|
||||
if (BACKTRACK) this.backTrack.btiAL = this.backTrack.btiIO;
|
||||
this.regEAX |= (this.bus.checkPortInputNotify((port + 1) & 0xffff, this.regEIP - 2) << 8);
|
||||
this.regEAX |= (this.bus.checkPortInputNotify((port + 1) & 0xffff, this.regLIP - 2) << 8);
|
||||
if (BACKTRACK) this.backTrack.btiAH = this.backTrack.btiIO;
|
||||
this.nStepCycles -= this.CYCLES.nOpCyclesInP;
|
||||
},
|
||||
|
|
@ -3055,7 +3068,7 @@ var X86OpXX = {
|
|||
*/
|
||||
opOUTb: function() {
|
||||
var port = this.getIPByte();
|
||||
this.bus.checkPortOutputNotify(port, this.regEAX & 0xff, this.regEIP - 2);
|
||||
this.bus.checkPortOutputNotify(port, this.regEAX & 0xff, this.regLIP - 2);
|
||||
this.nStepCycles -= this.CYCLES.nOpCyclesOutP;
|
||||
},
|
||||
/**
|
||||
|
|
@ -3065,8 +3078,8 @@ var X86OpXX = {
|
|||
*/
|
||||
opOUTw: function() {
|
||||
var port = this.getIPByte();
|
||||
this.bus.checkPortOutputNotify(port, this.regEAX & 0xff, this.regEIP - 2);
|
||||
this.bus.checkPortOutputNotify((port + 1) & 0xffff, this.regEAX >> 8, this.regEIP - 2);
|
||||
this.bus.checkPortOutputNotify(port, this.regEAX & 0xff, this.regLIP - 2);
|
||||
this.bus.checkPortOutputNotify((port + 1) & 0xffff, this.regEAX >> 8, this.regLIP - 2);
|
||||
this.nStepCycles -= this.CYCLES.nOpCyclesOutP;
|
||||
},
|
||||
/**
|
||||
|
|
@ -3076,8 +3089,8 @@ var X86OpXX = {
|
|||
*/
|
||||
opCALL: function() {
|
||||
var disp = this.getIPWord();
|
||||
this.pushWord(this.regIP);
|
||||
this.setIP(this.regIP + disp);
|
||||
this.pushWord(this.regEIP);
|
||||
this.setIP(this.regEIP + disp);
|
||||
this.nStepCycles -= this.CYCLES.nOpCyclesCall;
|
||||
},
|
||||
/**
|
||||
|
|
@ -3087,7 +3100,7 @@ var X86OpXX = {
|
|||
*/
|
||||
opJMP: function() {
|
||||
var disp = this.getIPWord();
|
||||
this.setIP(this.regIP + disp);
|
||||
this.setIP(this.regEIP + disp);
|
||||
this.nStepCycles -= this.CYCLES.nOpCyclesJmp;
|
||||
},
|
||||
/**
|
||||
|
|
@ -3106,7 +3119,7 @@ var X86OpXX = {
|
|||
*/
|
||||
opJMPs: function() {
|
||||
var disp = this.getIPDisp();
|
||||
this.setIP(this.regIP + disp);
|
||||
this.setIP(this.regEIP + disp);
|
||||
this.nStepCycles -= this.CYCLES.nOpCyclesJmp;
|
||||
},
|
||||
/**
|
||||
|
|
@ -3115,7 +3128,7 @@ var X86OpXX = {
|
|||
* op=0xEC (in AL,dx)
|
||||
*/
|
||||
opINDXb: function() {
|
||||
this.regEAX = (this.regEAX & ~0xff) | this.bus.checkPortInputNotify(this.regEDX, this.regEIP - 1);
|
||||
this.regEAX = (this.regEAX & ~0xff) | this.bus.checkPortInputNotify(this.regEDX, this.regLIP - 1);
|
||||
if (BACKTRACK) this.backTrack.btiAL = this.backTrack.btiIO;
|
||||
this.nStepCycles -= this.CYCLES.nOpCyclesInDX;
|
||||
},
|
||||
|
|
@ -3125,9 +3138,9 @@ var X86OpXX = {
|
|||
* op=0xED (in AX,dx)
|
||||
*/
|
||||
opINDXw: function() {
|
||||
this.regEAX = this.bus.checkPortInputNotify(this.regEDX, this.regEIP - 1);
|
||||
this.regEAX = this.bus.checkPortInputNotify(this.regEDX, this.regLIP - 1);
|
||||
if (BACKTRACK) this.backTrack.btiAL = this.backTrack.btiIO;
|
||||
this.regEAX |= (this.bus.checkPortInputNotify((this.regEDX + 1) & 0xffff, this.regEIP - 1) << 8);
|
||||
this.regEAX |= (this.bus.checkPortInputNotify((this.regEDX + 1) & 0xffff, this.regLIP - 1) << 8);
|
||||
if (BACKTRACK) this.backTrack.btiAH = this.backTrack.btiIO;
|
||||
this.nStepCycles -= this.CYCLES.nOpCyclesInDX;
|
||||
},
|
||||
|
|
@ -3137,7 +3150,7 @@ var X86OpXX = {
|
|||
* op=0xEE (out dx,AL)
|
||||
*/
|
||||
opOUTDXb: function() {
|
||||
this.bus.checkPortOutputNotify(this.regEDX, this.regEAX & 0xff, this.regEIP - 1);
|
||||
this.bus.checkPortOutputNotify(this.regEDX, this.regEAX & 0xff, this.regLIP - 1);
|
||||
this.nStepCycles -= this.CYCLES.nOpCyclesOutDX;
|
||||
},
|
||||
/**
|
||||
|
|
@ -3146,8 +3159,8 @@ var X86OpXX = {
|
|||
* op=0xEF (out dx,AX)
|
||||
*/
|
||||
opOUTDXw: function() {
|
||||
this.bus.checkPortOutputNotify(this.regEDX, this.regEAX & 0xff, this.regEIP - 1);
|
||||
this.bus.checkPortOutputNotify((this.regEDX + 1) & 0xffff, this.regEAX >> 8, this.regEIP - 1);
|
||||
this.bus.checkPortOutputNotify(this.regEDX, this.regEAX & 0xff, this.regLIP - 1);
|
||||
this.bus.checkPortOutputNotify((this.regEDX + 1) & 0xffff, this.regEAX >> 8, this.regLIP - 1);
|
||||
this.nStepCycles -= this.CYCLES.nOpCyclesOutDX;
|
||||
},
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -58,6 +58,7 @@ function X86Seg(cpu, id, sName, fProt)
|
|||
this.base = 0;
|
||||
this.limit = 0xffff;
|
||||
this.acc = 0;
|
||||
this.ext = 0;
|
||||
this.addrDesc = X86.ADDR_INVALID;
|
||||
this.cpl = 0;
|
||||
this.dpl = 0;
|
||||
|
|
@ -117,7 +118,8 @@ X86Seg.ID = {
|
|||
X86Seg.loadReal = function loadReal(sel, fSuppress)
|
||||
{
|
||||
this.sel = sel;
|
||||
this.ext = 0;
|
||||
this.opSize = this.addrSize = 2;
|
||||
this.opMask = this.addrMask = 0xffff;
|
||||
return this.base = sel << 4;
|
||||
};
|
||||
|
||||
|
|
@ -204,11 +206,10 @@ X86Seg.loadRealIDT = function loadRealIDT(nIDT)
|
|||
*
|
||||
* TODO: Verify that 80286 real-mode actually enforces the above. See http://localhost:8088/pubs/pc/reference/intel/80286/progref/#page-260
|
||||
*/
|
||||
var offIDT = cpu.addrIDT + (nIDT << 2);
|
||||
cpu.regIP = cpu.getWord(offIDT);
|
||||
this.sel = cpu.getWord(offIDT + 2);
|
||||
var addrIDT = cpu.addrIDT + (nIDT << 2);
|
||||
cpu.regEIP = cpu.getWord(addrIDT);
|
||||
cpu.regPS &= ~(X86.PS.TF | X86.PS.IF);
|
||||
return this.base = this.sel << 4;
|
||||
return this.load(cpu.getWord(addrIDT + 2));
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -422,7 +423,7 @@ X86Seg.switchTSS = function switchTSS(selNew, fNest)
|
|||
cpu.setWord(cpu.segTSS.addrDesc + X86.DESC.ACC.OFFSET, cpu.segTSS.acc |= X86.DESC.ACC.TYPE.TSS_BUSY);
|
||||
cpu.segTSS.type = X86.DESC.ACC.TYPE.TSS_BUSY;
|
||||
}
|
||||
cpu.setWord(addrOld + X86.TSS.TASK_IP, cpu.regIP);
|
||||
cpu.setWord(addrOld + X86.TSS.TASK_IP, cpu.regEIP);
|
||||
cpu.setWord(addrOld + X86.TSS.TASK_PS, cpu.getPS());
|
||||
cpu.setWord(addrOld + X86.TSS.TASK_AX, cpu.regEAX);
|
||||
cpu.setWord(addrOld + X86.TSS.TASK_CX, cpu.regECX);
|
||||
|
|
@ -640,7 +641,7 @@ X86Seg.prototype.loadDesc8 = function(addrDesc, sel, fSuppress)
|
|||
base = X86.ADDR_INVALID;
|
||||
break;
|
||||
}
|
||||
cpu.regIP = limit;
|
||||
cpu.regEIP = limit;
|
||||
if (this.cpl < cplPrev) {
|
||||
if (fCall !== true) {
|
||||
cpu.assert(false);
|
||||
|
|
@ -846,6 +847,13 @@ X86Seg.prototype.updateMode = function(fProt)
|
|||
}
|
||||
this.cpl = this.sel & X86.SEL.RPL;
|
||||
this.dpl = (this.acc & X86.DESC.ACC.DPL.MASK) >> X86.DESC.ACC.DPL.SHIFT;
|
||||
if (this.cpu.model < X86.MODEL_80386 || !(this.ext & X86.DESC.EXT.BIG)) {
|
||||
this.opSize = 2;
|
||||
this.opMask = 0xffff;
|
||||
} else {
|
||||
this.opSize = 4;
|
||||
this.opMask = 0xffffffff;
|
||||
}
|
||||
} else {
|
||||
this.load = X86Seg.loadReal;
|
||||
this.loadIDT = X86Seg.loadRealIDT;
|
||||
|
|
@ -854,7 +862,11 @@ X86Seg.prototype.updateMode = function(fProt)
|
|||
this.limit = 0xffff;
|
||||
this.cpl = this.dpl = 0;
|
||||
this.addrDesc = X86.ADDR_INVALID;
|
||||
this.opSize = 2;
|
||||
this.opMask = 0xffff;
|
||||
}
|
||||
this.addrSize = this.opSize;
|
||||
this.addrMask = this.opMask;
|
||||
return fProt;
|
||||
};
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue