Restructured ModRM decoding

This commit is contained in:
Jeff Parsons 2015-01-20 20:10:48 -08:00 committed by jeffpar
commit 418f3bd603
13 changed files with 6175 additions and 6516 deletions

View file

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

Binary file not shown.

File diff suppressed because it is too large Load diff

View file

@ -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]++;

View file

@ -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);

View file

@ -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)

View file

@ -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;
}

View file

@ -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, were 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;

View file

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

View file

@ -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;
},
/**

View file

@ -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;
};