Cleaned up conditional jump handling

This commit is contained in:
Jeff Parsons 2015-05-04 19:26:06 -07:00 committed by jeffpar
commit 2784934491
10 changed files with 135 additions and 50 deletions

View file

@ -8,16 +8,16 @@
"ram": [
{ "id": "pc386.ramLow",
"name": "",
"addr": 0x00000,
"size": 0xa0000,
"addr": 0,
"size": 655360,
"test": false
}
],
"rom": [
{ "id": "pc386.romTests",
"name": "",
"addr": 0xf0000,
"size": 0x10000,
"addr": 983296,
"size": 65280,
"file": "/tests/pc/80386/tests.json",
"notify": ""
}

View file

@ -100,8 +100,8 @@ A BackTrack index is encoded as a 32-bit value with three parts:
This represents a total of 31 bits, with bit 31 reserved.
For example, look at one of the last things a ROM does during boot: load a disk sector into RAM. It will be up to the
disk controller (or DMA controller if one is used) to create a BackTrack object representing the sector that was read,
For example, look at one of the last things a ROM does during boot: loading a disk sector into RAM. It will be up to the
disk controller (or DMA controller, if used) to create a BackTrack object representing the sector that was read,
adding that object to the global BackTrack object array, and then associating the corresponding BackTrack index with
the first byte of RAM where the sector was loaded. Subsequent bytes of RAM containing the rest of the sector will refer
to the same BackTrack object, using BackTrack indexes containing offsets 1-511.

View file

@ -1603,7 +1603,7 @@ if (DEBUGGER) {
/*
* When we dump the EXT word, we mask off the LIMIT1619 and BASE2431 bits, because those have already
* been incorporated into the limit and base properties of the segment register; all we care about here
* are whether EXT contains any of the AVAIL (0x10), BIG (0x40) or GRANULARITY (0x80) bits.
* are whether EXT contains any of the AVAIL (0x10), BIG (0x40) or LIMITPAGES (0x80) bits.
*/
this.println(sDump + " dpl=" + str.toHexByte(seg.dpl) + " type=" + str.toHexByte(seg.type >> 8) + " (" + sType + ")" + " ext=" + str.toHexWord(seg.ext & ~(X86.DESC.EXT.LIMIT1619 | X86.DESC.EXT.BASE2431)));
};

View file

@ -103,10 +103,10 @@ var X86 = {
MASK: 0xfff8 // table index
},
DESC: { // Descriptor Table Entry
LIMIT: {
LIMIT: { // LIMIT bits 0-15
OFFSET: 0x0
},
BASE: {
BASE: { // BASE bits 0-15
OFFSET: 0x2
},
ACC: { // bit definitions for the access word (offset 0x4)
@ -166,7 +166,7 @@ var X86 = {
* is 0xffffffff instead of 0xffff.
*/
BIG: 0x0040, // clear if default operand/address size is 16-bit, set if 32-bit
GRANULARITY: 0x0080, // clear if limit is bytes, set if limit is 4Kb pages
LIMITPAGES: 0x0080, // clear if limit granularity is bytes, set if limit granularity is 4Kb pages
BASE2431: 0xff00
},
INVALID: 0 // use X86.DESC.INVALID for invalid DESC values

View file

@ -3197,18 +3197,6 @@ X86CPU.prototype.getIPDisp = function()
return w;
};
/**
* getIPDispWord()
*
* @this {X86CPU}
* @return {number} sign-extended value from the word at the current IP; IP advanced by 2 or 4
*/
X86CPU.prototype.getIPDispWord = function()
{
var w = this.getIPWord();
return (this.dataSize == 2? ((w << 16) >> 16) : w);
};
/**
* getSIBAddr(mod)
*

View file

@ -342,6 +342,23 @@ X86.opMOVcr = function MOVcr()
}
};
/*
* NOTE: The following 16 new conditional jumps actually rely on the OPERAND override setting
* for determining whether a signed 16-bit or 32-bit displacement will be fetched, even though
* the ADDRESS override might seem more intuitive. Think of them as instructions that are loading
* a new operand into IP/EIP.
*
* Also, in 16-bit code, even though a signed rel16 value would seem to imply a range of -32768
* to +32767, any location within a 64Kb code segment outside that range can be reached by choosing
* a displacement in the opposite direction, causing the 16-bit value in EIP to underflow or overflow;
* any underflow or overflow doesn't matter, because only the low 16 bits of EIP are used when a
* 16-bit OPERAND size is in effect.
*
* In fact, for 16-bit jumps, it's simpler to always think of rel16 as an UNSIGNED value added to
* the current EIP, where the result is then truncated to a 16-bit value. This is why we don't have
* to sign-extend rel16 before adding it to the current EIP.
*/
/**
* opJOw()
*
@ -351,7 +368,7 @@ X86.opMOVcr = function MOVcr()
*/
X86.opJOw = function JOw()
{
var disp = this.getIPDispWord();
var disp = this.getIPWord();
if (this.getOF()) {
this.setIP(this.getIP() + disp);
this.nStepCycles -= this.cycleCounts.nOpCyclesJmpC;
@ -369,7 +386,7 @@ X86.opJOw = function JOw()
*/
X86.opJNOw = function JNOw()
{
var disp = this.getIPDispWord();
var disp = this.getIPWord();
if (!this.getOF()) {
this.setIP(this.getIP() + disp);
this.nStepCycles -= this.cycleCounts.nOpCyclesJmpC;
@ -387,7 +404,7 @@ X86.opJNOw = function JNOw()
*/
X86.opJCw = function JCw()
{
var disp = this.getIPDispWord();
var disp = this.getIPWord();
if (this.getCF()) {
this.setIP(this.getIP() + disp);
this.nStepCycles -= this.cycleCounts.nOpCyclesJmpC;
@ -405,7 +422,7 @@ X86.opJCw = function JCw()
*/
X86.opJNCw = function JNCw()
{
var disp = this.getIPDispWord();
var disp = this.getIPWord();
if (!this.getCF()) {
this.setIP(this.getIP() + disp);
this.nStepCycles -= this.cycleCounts.nOpCyclesJmpC;
@ -423,7 +440,7 @@ X86.opJNCw = function JNCw()
*/
X86.opJZw = function JZw()
{
var disp = this.getIPDispWord();
var disp = this.getIPWord();
if (this.getZF()) {
this.setIP(this.getIP() + disp);
this.nStepCycles -= this.cycleCounts.nOpCyclesJmpC;
@ -441,7 +458,7 @@ X86.opJZw = function JZw()
*/
X86.opJNZw = function JNZw()
{
var disp = this.getIPDispWord();
var disp = this.getIPWord();
if (!this.getZF()) {
this.setIP(this.getIP() + disp);
this.nStepCycles -= this.cycleCounts.nOpCyclesJmpC;
@ -459,7 +476,7 @@ X86.opJNZw = function JNZw()
*/
X86.opJBEw = function JBEw()
{
var disp = this.getIPDispWord();
var disp = this.getIPWord();
if (this.getCF() || this.getZF()) {
this.setIP(this.getIP() + disp);
this.nStepCycles -= this.cycleCounts.nOpCyclesJmpC;
@ -477,7 +494,7 @@ X86.opJBEw = function JBEw()
*/
X86.opJNBEw = function JNBEw()
{
var disp = this.getIPDispWord();
var disp = this.getIPWord();
if (!this.getCF() && !this.getZF()) {
this.setIP(this.getIP() + disp);
this.nStepCycles -= this.cycleCounts.nOpCyclesJmpC;
@ -495,7 +512,7 @@ X86.opJNBEw = function JNBEw()
*/
X86.opJSw = function JSw()
{
var disp = this.getIPDispWord();
var disp = this.getIPWord();
if (this.getSF()) {
this.setIP(this.getIP() + disp);
this.nStepCycles -= this.cycleCounts.nOpCyclesJmpC;
@ -513,7 +530,7 @@ X86.opJSw = function JSw()
*/
X86.opJNSw = function JNSw()
{
var disp = this.getIPDispWord();
var disp = this.getIPWord();
if (!this.getSF()) {
this.setIP(this.getIP() + disp);
this.nStepCycles -= this.cycleCounts.nOpCyclesJmpC;
@ -531,7 +548,7 @@ X86.opJNSw = function JNSw()
*/
X86.opJPw = function JPw()
{
var disp = this.getIPDispWord();
var disp = this.getIPWord();
if (this.getPF()) {
this.setIP(this.getIP() + disp);
this.nStepCycles -= this.cycleCounts.nOpCyclesJmpC;
@ -549,7 +566,7 @@ X86.opJPw = function JPw()
*/
X86.opJNPw = function JNPw()
{
var disp = this.getIPDispWord();
var disp = this.getIPWord();
if (!this.getPF()) {
this.setIP(this.getIP() + disp);
this.nStepCycles -= this.cycleCounts.nOpCyclesJmpC;
@ -567,7 +584,7 @@ X86.opJNPw = function JNPw()
*/
X86.opJLw = function JLw()
{
var disp = this.getIPDispWord();
var disp = this.getIPWord();
if (!this.getSF() != !this.getOF()) {
this.setIP(this.getIP() + disp);
this.nStepCycles -= this.cycleCounts.nOpCyclesJmpC;
@ -585,7 +602,7 @@ X86.opJLw = function JLw()
*/
X86.opJNLw = function JNLw()
{
var disp = this.getIPDispWord();
var disp = this.getIPWord();
if (!this.getSF() == !this.getOF()) {
this.setIP(this.getIP() + disp);
this.nStepCycles -= this.cycleCounts.nOpCyclesJmpC;
@ -603,7 +620,7 @@ X86.opJNLw = function JNLw()
*/
X86.opJLEw = function JLEw()
{
var disp = this.getIPDispWord();
var disp = this.getIPWord();
if (this.getZF() || !this.getSF() != !this.getOF()) {
this.setIP(this.getIP() + disp);
this.nStepCycles -= this.cycleCounts.nOpCyclesJmpC;
@ -621,7 +638,7 @@ X86.opJLEw = function JLEw()
*/
X86.opJNLEw = function JNLEw()
{
var disp = this.getIPDispWord();
var disp = this.getIPWord();
if (!this.getZF() && !this.getSF() == !this.getOF()) {
this.setIP(this.getIP() + disp);
this.nStepCycles -= this.cycleCounts.nOpCyclesJmpC;
@ -1301,7 +1318,7 @@ X86.aOps0F[0x06] = X86.opCLTS;
/*
* On all processors (except the 8086/8088, of course), X86.OPCODE.UD2 (0x0F,0x0B), aka "UD2", is an
* instruction guaranteed to raise a #UD (Invalid Opcode) exception (INT 0x06) on all future x86 processors.
* instruction guaranteed to raise a #UD (Invalid Opcode) exception (INT 0x06) on all post-8086 processors.
*/
X86.aOps0F[0x0B] = X86.opInvalid;

View file

@ -3497,6 +3497,10 @@ X86.opESC = function ESC()
/**
* op=0xE0 (LOOPNZ disp)
*
* NOTE: All the instructions in this group (LOOPNZ, LOOPZ, LOOP, and JCXZ) actually
* rely on the ADDRESS override setting for determining whether CX or ECX will be used,
* even though it seems counter-intuitive; ditto for the REP prefix.
*
* @this {X86CPU}
*/
X86.opLOOPNZ = function LOOPNZ()
@ -3513,6 +3517,10 @@ X86.opLOOPNZ = function LOOPNZ()
/**
* op=0xE1 (LOOPZ disp)
*
* NOTE: All the instructions in this group (LOOPNZ, LOOPZ, LOOP, and JCXZ) actually
* rely on the ADDRESS override setting for determining whether CX or ECX will be used,
* even though it seems counter-intuitive; ditto for the REP prefix.
*
* @this {X86CPU}
*/
X86.opLOOPZ = function LOOPZ()
@ -3529,6 +3537,10 @@ X86.opLOOPZ = function LOOPZ()
/**
* op=0xE2 (LOOP disp)
*
* NOTE: All the instructions in this group (LOOPNZ, LOOPZ, LOOP, and JCXZ) actually
* rely on the ADDRESS override setting for determining whether CX or ECX will be used,
* even though it seems counter-intuitive; ditto for the REP prefix.
*
* @this {X86CPU}
*/
X86.opLOOP = function LOOP()
@ -3543,7 +3555,11 @@ X86.opLOOP = function LOOP()
};
/**
* op=0xE3 (JCXZ disp)
* op=0xE3 (JCXZ/JECXZ disp)
*
* NOTE: All the instructions in this group (LOOPNZ, LOOPZ, LOOP, and JCXZ) actually
* rely on the ADDRESS override setting for determining whether CX or ECX will be used,
* even though it seems counter-intuitive; ditto for the REP prefix.
*
* @this {X86CPU}
*/

View file

@ -588,7 +588,7 @@ X86Seg.prototype.loadDesc8 = function(addrDesc, sel, fSuppress)
if (I386 && cpu.model >= X86.MODEL_80386) {
base |= (ext & X86.DESC.EXT.BASE2431) << 16;
limit |= (ext & X86.DESC.EXT.LIMIT1619) << 16;
if (ext & X86.DESC.EXT.GRANULARITY) limit = (limit << 12) | 0xfff;
if (ext & X86.DESC.EXT.LIMITPAGES) limit = (limit << 12) | 0xfff;
}
while (true) {