4198 lines
123 KiB
JavaScript
4198 lines
123 KiB
JavaScript
/**
|
|
* @fileoverview Implements PCx86 general-purpose ModRegRM decoding.
|
|
* @author <a href="mailto:Jeff@pcjs.org">Jeff Parsons</a>
|
|
* @copyright © Jeff Parsons 2012-2017
|
|
*
|
|
* This file is part of PCjs, a computer emulation software project at <http://pcjs.org/>.
|
|
*
|
|
* PCjs is free software: you can redistribute it and/or modify it under the terms of the
|
|
* GNU General Public License as published by the Free Software Foundation, either version 3
|
|
* of the License, or (at your option) any later version.
|
|
*
|
|
* PCjs is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
|
|
* even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License along with PCjs. If not,
|
|
* see <http://www.gnu.org/licenses/gpl.html>.
|
|
*
|
|
* You are required to include the above copyright notice in every modified copy of this work
|
|
* and to display that copyright notice when the software starts running; see COPYRIGHT in
|
|
* <http://pcjs.org/modules/shared/lib/defines.js>.
|
|
*
|
|
* Some PCjs files also attempt to load external resource files, such as character-image files,
|
|
* ROM files, and disk image files. Those external resource files are not considered part of PCjs
|
|
* for purposes of the GNU General Public License, and the author does not claim any copyright
|
|
* as to their contents.
|
|
*/
|
|
|
|
"use strict";
|
|
|
|
if (NODE) {
|
|
var str = require("../../shared/lib/strlib");
|
|
var X86 = require("./x86");
|
|
}
|
|
|
|
/*
|
|
* Before 80386 support was added to PCx86, the approach to decoding ModRegRM bytes (which I usually
|
|
* just call ModRM bytes) used one generated function per ModRM value. This was optimal for 16-bit processors,
|
|
* because the functions were small, and it was maximally efficient, turning the entire ModRM decoding operation
|
|
* into one table lookup and function call.
|
|
*
|
|
* However, that approach didn't scale well for 32-bit processors, which had extended ModRM capabilities in both
|
|
* the addressing mode dimension and the operand size dimension. So I've rewritten ModRM decoding as 18 functions.
|
|
* The first 9 are for 16-bit addressing modes, and the second 9 are for 32-bit addressing modes. Within each
|
|
* group of 9, there are 3 for 8-bit operands, 3 for 16-bit operands, and 3 for 32-bit operands. And each group of 3
|
|
* contains functions for register-source, memory-source, and group-source.
|
|
*
|
|
* Each of the 18 functions must do additional work to examine the ModRM bits, which makes decoding slightly slower,
|
|
* but it's not really noticeable, and the speed difference didn't justify the additional generated code. So one much
|
|
* smaller file (x86mods.js) replaces a host of older files (x86modb.js, x86modw.js, x86modb16.js, x86modw16.js,
|
|
* x86modb32.js, x86modw32.js, and x86modsib.js).
|
|
*
|
|
* You can dig up the older files from the repository if you're curious, or you can run /modules/pcx86/bin/x86gen.js to
|
|
* get a sense of what they contained (x86gen.js created most of the code, but it still had to be massaged afterward).
|
|
*/
|
|
|
|
/**
|
|
* modRegByte16(fn)
|
|
*
|
|
* @this {X86CPU}
|
|
* @param {function(number,number)} fn (dst,src)
|
|
*/
|
|
X86.modRegByte16 = function(fn)
|
|
{
|
|
var dst, src;
|
|
var bModRM = (this.bModRM = this.getIPByte()) & 0xC7;
|
|
|
|
switch(bModRM) {
|
|
case 0x00:
|
|
src = this.getEAByteData(this.regEBX + this.regESI);
|
|
this.nStepCycles -= this.cycleCounts.nEACyclesBaseIndex;
|
|
break;
|
|
case 0x01:
|
|
src = this.getEAByteData(this.regEBX + this.regEDI);
|
|
this.nStepCycles -= this.cycleCounts.nEACyclesBaseIndexExtra;
|
|
break;
|
|
case 0x02:
|
|
src = this.getEAByteStack(this.regEBP + this.regESI);
|
|
this.nStepCycles -= this.cycleCounts.nEACyclesBaseIndexExtra;
|
|
break;
|
|
case 0x03:
|
|
src = this.getEAByteStack(this.regEBP + this.regEDI);
|
|
this.nStepCycles -= this.cycleCounts.nEACyclesBaseIndex;
|
|
break;
|
|
case 0x04:
|
|
src = this.getEAByteData(this.regESI);
|
|
this.nStepCycles -= this.cycleCounts.nEACyclesBase;
|
|
break;
|
|
case 0x05:
|
|
src = this.getEAByteData(this.regEDI);
|
|
this.nStepCycles -= this.cycleCounts.nEACyclesBase;
|
|
break;
|
|
case 0x06:
|
|
src = this.getEAByteData(this.getIPAddr());
|
|
this.nStepCycles -= this.cycleCounts.nEACyclesDisp;
|
|
break;
|
|
case 0x07:
|
|
src = this.getEAByteData(this.regEBX);
|
|
this.nStepCycles -= this.cycleCounts.nEACyclesBase;
|
|
break;
|
|
case 0x40:
|
|
src = this.getEAByteData(this.regEBX + this.regESI + this.getIPDisp());
|
|
this.nStepCycles -= this.cycleCounts.nEACyclesBaseIndexDisp;
|
|
break;
|
|
case 0x41:
|
|
src = this.getEAByteData(this.regEBX + this.regEDI + this.getIPDisp());
|
|
this.nStepCycles -= this.cycleCounts.nEACyclesBaseIndexDispExtra;
|
|
break;
|
|
case 0x42:
|
|
src = this.getEAByteStack(this.regEBP + this.regESI + this.getIPDisp());
|
|
this.nStepCycles -= this.cycleCounts.nEACyclesBaseIndexDispExtra;
|
|
break;
|
|
case 0x43:
|
|
src = this.getEAByteStack(this.regEBP + this.regEDI + this.getIPDisp());
|
|
this.nStepCycles -= this.cycleCounts.nEACyclesBaseIndexDisp;
|
|
break;
|
|
case 0x44:
|
|
src = this.getEAByteData(this.regESI + this.getIPDisp());
|
|
this.nStepCycles -= this.cycleCounts.nEACyclesBaseDisp;
|
|
break;
|
|
case 0x45:
|
|
src = this.getEAByteData(this.regEDI + this.getIPDisp());
|
|
this.nStepCycles -= this.cycleCounts.nEACyclesBaseDisp;
|
|
break;
|
|
case 0x46:
|
|
src = this.getEAByteStack(this.regEBP + this.getIPDisp());
|
|
this.nStepCycles -= this.cycleCounts.nEACyclesBaseDisp;
|
|
break;
|
|
case 0x47:
|
|
src = this.getEAByteData(this.regEBX + this.getIPDisp());
|
|
this.nStepCycles -= this.cycleCounts.nEACyclesBaseDisp;
|
|
break;
|
|
case 0x80:
|
|
src = this.getEAByteData(this.regEBX + this.regESI + this.getIPAddr());
|
|
this.nStepCycles -= this.cycleCounts.nEACyclesBaseIndexDisp;
|
|
break;
|
|
case 0x81:
|
|
src = this.getEAByteData(this.regEBX + this.regEDI + this.getIPAddr());
|
|
this.nStepCycles -= this.cycleCounts.nEACyclesBaseIndexDispExtra;
|
|
break;
|
|
case 0x82:
|
|
src = this.getEAByteStack(this.regEBP + this.regESI + this.getIPAddr());
|
|
this.nStepCycles -= this.cycleCounts.nEACyclesBaseIndexDispExtra;
|
|
break;
|
|
case 0x83:
|
|
src = this.getEAByteStack(this.regEBP + this.regEDI + this.getIPAddr());
|
|
this.nStepCycles -= this.cycleCounts.nEACyclesBaseIndexDisp;
|
|
break;
|
|
case 0x84:
|
|
src = this.getEAByteData(this.regESI + this.getIPAddr());
|
|
this.nStepCycles -= this.cycleCounts.nEACyclesBaseDisp;
|
|
break;
|
|
case 0x85:
|
|
src = this.getEAByteData(this.regEDI + this.getIPAddr());
|
|
this.nStepCycles -= this.cycleCounts.nEACyclesBaseDisp;
|
|
break;
|
|
case 0x86:
|
|
src = this.getEAByteStack(this.regEBP + this.getIPAddr());
|
|
this.nStepCycles -= this.cycleCounts.nEACyclesBaseDisp;
|
|
break;
|
|
case 0x87:
|
|
src = this.getEAByteData(this.regEBX + this.getIPAddr());
|
|
this.nStepCycles -= this.cycleCounts.nEACyclesBaseDisp;
|
|
break;
|
|
case 0xC0:
|
|
src = this.regEAX & 0xff;
|
|
if (BACKTRACK) this.backTrack.btiEALo = this.backTrack.btiAL;
|
|
break;
|
|
case 0xC1:
|
|
src = this.regECX & 0xff;
|
|
if (BACKTRACK) this.backTrack.btiEALo = this.backTrack.btiCL;
|
|
break;
|
|
case 0xC2:
|
|
src = this.regEDX & 0xff;
|
|
if (BACKTRACK) this.backTrack.btiEALo = this.backTrack.btiDL;
|
|
break;
|
|
case 0xC3:
|
|
src = this.regEBX & 0xff;
|
|
if (BACKTRACK) this.backTrack.btiEALo = this.backTrack.btiBL;
|
|
break;
|
|
case 0xC4:
|
|
src = (this.regEAX >> 8) & 0xff;
|
|
if (BACKTRACK) this.backTrack.btiEALo = this.backTrack.btiAH;
|
|
break;
|
|
case 0xC5:
|
|
src = (this.regECX >> 8) & 0xff;
|
|
if (BACKTRACK) this.backTrack.btiEALo = this.backTrack.btiCH;
|
|
break;
|
|
case 0xC6:
|
|
src = (this.regEDX >> 8) & 0xff;
|
|
if (BACKTRACK) this.backTrack.btiEALo = this.backTrack.btiDH;
|
|
break;
|
|
case 0xC7:
|
|
src = (this.regEBX >> 8) & 0xff;
|
|
if (BACKTRACK) this.backTrack.btiEALo = this.backTrack.btiBH;
|
|
break;
|
|
default:
|
|
src = 0;
|
|
this.assert(false, "modRegByte16(): unrecognized modrm byte " + str.toHexByte(bModRM));
|
|
break;
|
|
}
|
|
|
|
var reg = (this.bModRM >> 3) & 0x7;
|
|
|
|
switch(reg) {
|
|
case 0x0:
|
|
dst = this.regEAX & 0xff;
|
|
break;
|
|
case 0x1:
|
|
dst = this.regECX & 0xff;
|
|
break;
|
|
case 0x2:
|
|
dst = this.regEDX & 0xff;
|
|
break;
|
|
case 0x3:
|
|
dst = this.regEBX & 0xff;
|
|
break;
|
|
case 0x4:
|
|
dst = (this.regEAX >> 8) & 0xff;
|
|
break;
|
|
case 0x5:
|
|
dst = (this.regECX >> 8) & 0xff;
|
|
break;
|
|
case 0x6:
|
|
dst = (this.regEDX >> 8) & 0xff;
|
|
break;
|
|
case 0x7:
|
|
dst = (this.regEBX >> 8) & 0xff;
|
|
break;
|
|
default:
|
|
dst = 0;
|
|
break;
|
|
}
|
|
|
|
var b = fn.call(this, dst, src);
|
|
|
|
switch(reg) {
|
|
case 0x0:
|
|
this.regEAX = (this.regEAX & ~0xff) | b;
|
|
if (BACKTRACK) this.backTrack.btiAL = this.backTrack.btiEALo;
|
|
break;
|
|
case 0x1:
|
|
this.regECX = (this.regECX & ~0xff) | b;
|
|
if (BACKTRACK) this.backTrack.btiCL = this.backTrack.btiEALo;
|
|
break;
|
|
case 0x2:
|
|
this.regEDX = (this.regEDX & ~0xff) | b;
|
|
if (BACKTRACK) this.backTrack.btiDL = this.backTrack.btiEALo;
|
|
break;
|
|
case 0x3:
|
|
this.regEBX = (this.regEBX & ~0xff) | b;
|
|
if (BACKTRACK) this.backTrack.btiBL = this.backTrack.btiEALo;
|
|
break;
|
|
case 0x4:
|
|
this.regEAX = (this.regEAX & ~0xff00) | (b << 8);
|
|
if (BACKTRACK) this.backTrack.btiAH = this.backTrack.btiEALo;
|
|
break;
|
|
case 0x5:
|
|
this.regECX = (this.regECX & ~0xff00) | (b << 8);
|
|
if (BACKTRACK) this.backTrack.btiCH = this.backTrack.btiEALo;
|
|
break;
|
|
case 0x6:
|
|
this.regEDX = (this.regEDX & ~0xff00) | (b << 8);
|
|
if (BACKTRACK) this.backTrack.btiDH = this.backTrack.btiEALo;
|
|
break;
|
|
case 0x7:
|
|
this.regEBX = (this.regEBX & ~0xff00) | (b << 8);
|
|
if (BACKTRACK) this.backTrack.btiBH = this.backTrack.btiEALo;
|
|
break;
|
|
}
|
|
};
|
|
|
|
/**
|
|
* modMemByte16(fn)
|
|
*
|
|
* @this {X86CPU}
|
|
* @param {function(number,number)} fn (dst,src)
|
|
*/
|
|
X86.modMemByte16 = function(fn)
|
|
{
|
|
var dst, src;
|
|
var bModRM = (this.bModRM = this.getIPByte()) & 0xC7;
|
|
|
|
switch(bModRM) {
|
|
case 0x00:
|
|
dst = this.getEAByteData(this.regEBX + this.regESI);
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x01:
|
|
dst = this.getEAByteData(this.regEBX + this.regEDI);
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x02:
|
|
dst = this.getEAByteStack(this.regEBP + this.regESI);
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x03:
|
|
dst = this.getEAByteStack(this.regEBP + this.regEDI);
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x04:
|
|
dst = this.getEAByteData(this.regESI);
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x05:
|
|
dst = this.getEAByteData(this.regEDI);
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x06:
|
|
dst = this.getEAByteData(this.getIPAddr());
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x07:
|
|
dst = this.getEAByteData(this.regEBX);
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x40:
|
|
dst = this.getEAByteData(this.regEBX + this.regESI + this.getIPDisp());
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x41:
|
|
dst = this.getEAByteData(this.regEBX + this.regEDI + this.getIPDisp());
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x42:
|
|
dst = this.getEAByteStack(this.regEBP + this.regESI + this.getIPDisp());
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x43:
|
|
dst = this.getEAByteStack(this.regEBP + this.regEDI + this.getIPDisp());
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x44:
|
|
dst = this.getEAByteData(this.regESI + this.getIPDisp());
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x45:
|
|
dst = this.getEAByteData(this.regEDI + this.getIPDisp());
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x46:
|
|
dst = this.getEAByteStack(this.regEBP + this.getIPDisp());
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x47:
|
|
dst = this.getEAByteData(this.regEBX + this.getIPDisp());
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x80:
|
|
dst = this.getEAByteData(this.regEBX + this.regESI + this.getIPAddr());
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x81:
|
|
dst = this.getEAByteData(this.regEBX + this.regEDI + this.getIPAddr());
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x82:
|
|
dst = this.getEAByteStack(this.regEBP + this.regESI + this.getIPAddr());
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x83:
|
|
dst = this.getEAByteStack(this.regEBP + this.regEDI + this.getIPAddr());
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x84:
|
|
dst = this.getEAByteData(this.regESI + this.getIPAddr());
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x85:
|
|
dst = this.getEAByteData(this.regEDI + this.getIPAddr());
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x86:
|
|
dst = this.getEAByteStack(this.regEBP + this.getIPAddr());
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x87:
|
|
dst = this.getEAByteData(this.regEBX + this.getIPAddr());
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0xC0:
|
|
dst = this.regEAX & 0xff;
|
|
break;
|
|
case 0xC1:
|
|
dst = this.regECX & 0xff;
|
|
break;
|
|
case 0xC2:
|
|
dst = this.regEDX & 0xff;
|
|
break;
|
|
case 0xC3:
|
|
dst = this.regEBX & 0xff;
|
|
break;
|
|
case 0xC4:
|
|
dst = (this.regEAX >> 8) & 0xff;
|
|
break;
|
|
case 0xC5:
|
|
dst = (this.regECX >> 8) & 0xff;
|
|
break;
|
|
case 0xC6:
|
|
dst = (this.regEDX >> 8) & 0xff;
|
|
break;
|
|
case 0xC7:
|
|
dst = (this.regEBX >> 8) & 0xff;
|
|
break;
|
|
default:
|
|
dst = 0;
|
|
this.assert(false, "modMemByte16(): unrecognized modrm byte " + str.toHexByte(bModRM));
|
|
break;
|
|
}
|
|
|
|
var reg = (this.bModRM >> 3) & 0x7;
|
|
|
|
switch(reg) {
|
|
case 0x0:
|
|
src = this.regEAX & 0xff;
|
|
if (BACKTRACK) this.backTrack.btiEALo = this.backTrack.btiAL;
|
|
break;
|
|
case 0x1:
|
|
src = this.regECX & 0xff;
|
|
if (BACKTRACK) this.backTrack.btiEALo = this.backTrack.btiCL;
|
|
break;
|
|
case 0x2:
|
|
src = this.regEDX & 0xff;
|
|
if (BACKTRACK) this.backTrack.btiEALo = this.backTrack.btiDL;
|
|
break;
|
|
case 0x3:
|
|
src = this.regEBX & 0xff;
|
|
if (BACKTRACK) this.backTrack.btiEALo = this.backTrack.btiBL;
|
|
break;
|
|
case 0x4:
|
|
src = (this.regEAX >> 8) & 0xff;
|
|
if (BACKTRACK) this.backTrack.btiEALo = this.backTrack.btiAH;
|
|
break;
|
|
case 0x5:
|
|
src = (this.regECX >> 8) & 0xff;
|
|
if (BACKTRACK) this.backTrack.btiEALo = this.backTrack.btiCH;
|
|
break;
|
|
case 0x6:
|
|
src = (this.regEDX >> 8) & 0xff;
|
|
if (BACKTRACK) this.backTrack.btiEALo = this.backTrack.btiDH;
|
|
break;
|
|
case 0x7:
|
|
src = (this.regEBX >> 8) & 0xff;
|
|
if (BACKTRACK) this.backTrack.btiEALo = this.backTrack.btiBH;
|
|
break;
|
|
default:
|
|
src = 0;
|
|
break;
|
|
}
|
|
|
|
var b = fn.call(this, dst, src);
|
|
|
|
switch(bModRM) {
|
|
case 0x00:
|
|
case 0x03:
|
|
this.setEAByte(b);
|
|
this.nStepCycles -= this.cycleCounts.nEACyclesBaseIndex;
|
|
break;
|
|
case 0x01:
|
|
case 0x02:
|
|
this.setEAByte(b);
|
|
this.nStepCycles -= this.cycleCounts.nEACyclesBaseIndexExtra;
|
|
break;
|
|
case 0x04:
|
|
case 0x05:
|
|
case 0x07:
|
|
this.setEAByte(b);
|
|
this.nStepCycles -= this.cycleCounts.nEACyclesBase;
|
|
break;
|
|
case 0x06:
|
|
this.setEAByte(b);
|
|
this.nStepCycles -= this.cycleCounts.nEACyclesDisp;
|
|
break;
|
|
case 0x40:
|
|
case 0x43:
|
|
case 0x80:
|
|
case 0x83:
|
|
this.setEAByte(b);
|
|
this.nStepCycles -= this.cycleCounts.nEACyclesBaseIndexDisp;
|
|
break;
|
|
case 0x41:
|
|
case 0x42:
|
|
case 0x81:
|
|
case 0x82:
|
|
this.setEAByte(b);
|
|
this.nStepCycles -= this.cycleCounts.nEACyclesBaseIndexDispExtra;
|
|
break;
|
|
case 0x44:
|
|
case 0x45:
|
|
case 0x46:
|
|
case 0x47:
|
|
case 0x84:
|
|
case 0x85:
|
|
case 0x86:
|
|
case 0x87:
|
|
this.setEAByte(b);
|
|
this.nStepCycles -= this.cycleCounts.nEACyclesBaseDisp;
|
|
break;
|
|
case 0xC0:
|
|
this.regEAX = (this.regEAX & ~0xff) | b;
|
|
if (BACKTRACK) this.backTrack.btiAL = this.backTrack.btiEALo;
|
|
break;
|
|
case 0xC1:
|
|
this.regECX = (this.regECX & ~0xff) | b;
|
|
if (BACKTRACK) this.backTrack.btiCL = this.backTrack.btiEALo;
|
|
break;
|
|
case 0xC2:
|
|
this.regEDX = (this.regEDX & ~0xff) | b;
|
|
if (BACKTRACK) this.backTrack.btiDL = this.backTrack.btiEALo;
|
|
break;
|
|
case 0xC3:
|
|
this.regEBX = (this.regEBX & ~0xff) | b;
|
|
if (BACKTRACK) this.backTrack.btiBL = this.backTrack.btiEALo;
|
|
break;
|
|
case 0xC4:
|
|
this.regEAX = (this.regEAX & ~0xff00) | (b << 8);
|
|
if (BACKTRACK) this.backTrack.btiAH = this.backTrack.btiEALo;
|
|
break;
|
|
case 0xC5:
|
|
this.regECX = (this.regECX & ~0xff00) | (b << 8);
|
|
if (BACKTRACK) this.backTrack.btiCH = this.backTrack.btiEALo;
|
|
break;
|
|
case 0xC6:
|
|
this.regEDX = (this.regEDX & ~0xff00) | (b << 8);
|
|
if (BACKTRACK) this.backTrack.btiDH = this.backTrack.btiEALo;
|
|
break;
|
|
case 0xC7:
|
|
this.regEBX = (this.regEBX & ~0xff00) | (b << 8);
|
|
if (BACKTRACK) this.backTrack.btiBH = this.backTrack.btiEALo;
|
|
break;
|
|
default:
|
|
this.assert(false, "modMemByte16(): unrecognized modrm byte " + str.toHexByte(bModRM));
|
|
break;
|
|
}
|
|
};
|
|
|
|
/**
|
|
* modGrpByte16(afnGrp, fnSrc)
|
|
*
|
|
* @this {X86CPU}
|
|
* @param {Array.<function(number,number)>} afnGrp
|
|
* @param {function()} fnSrc
|
|
*/
|
|
X86.modGrpByte16 = function(afnGrp, fnSrc) {
|
|
var dst;
|
|
var bModRM = (this.bModRM = this.getIPByte()) & 0xC7;
|
|
|
|
switch(bModRM) {
|
|
case 0x00:
|
|
dst = this.getEAByteData(this.regEBX + this.regESI);
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x01:
|
|
dst = this.getEAByteData(this.regEBX + this.regEDI);
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x02:
|
|
dst = this.getEAByteStack(this.regEBP + this.regESI);
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x03:
|
|
dst = this.getEAByteStack(this.regEBP + this.regEDI);
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x04:
|
|
dst = this.getEAByteData(this.regESI);
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x05:
|
|
dst = this.getEAByteData(this.regEDI);
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x06:
|
|
dst = this.getEAByteData(this.getIPAddr());
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x07:
|
|
dst = this.getEAByteData(this.regEBX);
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x40:
|
|
dst = this.getEAByteData(this.regEBX + this.regESI + this.getIPDisp());
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x41:
|
|
dst = this.getEAByteData(this.regEBX + this.regEDI + this.getIPDisp());
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x42:
|
|
dst = this.getEAByteStack(this.regEBP + this.regESI + this.getIPDisp());
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x43:
|
|
dst = this.getEAByteStack(this.regEBP + this.regEDI + this.getIPDisp());
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x44:
|
|
dst = this.getEAByteData(this.regESI + this.getIPDisp());
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x45:
|
|
dst = this.getEAByteData(this.regEDI + this.getIPDisp());
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x46:
|
|
dst = this.getEAByteStack(this.regEBP + this.getIPDisp());
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x47:
|
|
dst = this.getEAByteData(this.regEBX + this.getIPDisp());
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x80:
|
|
dst = this.getEAByteData(this.regEBX + this.regESI + this.getIPAddr());
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x81:
|
|
dst = this.getEAByteData(this.regEBX + this.regEDI + this.getIPAddr());
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x82:
|
|
dst = this.getEAByteStack(this.regEBP + this.regESI + this.getIPAddr());
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x83:
|
|
dst = this.getEAByteStack(this.regEBP + this.regEDI + this.getIPAddr());
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x84:
|
|
dst = this.getEAByteData(this.regESI + this.getIPAddr());
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x85:
|
|
dst = this.getEAByteData(this.regEDI + this.getIPAddr());
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x86:
|
|
dst = this.getEAByteStack(this.regEBP + this.getIPAddr());
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x87:
|
|
dst = this.getEAByteData(this.regEBX + this.getIPAddr());
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0xC0:
|
|
dst = this.regEAX & 0xff;
|
|
break;
|
|
case 0xC1:
|
|
dst = this.regECX & 0xff;
|
|
break;
|
|
case 0xC2:
|
|
dst = this.regEDX & 0xff;
|
|
break;
|
|
case 0xC3:
|
|
dst = this.regEBX & 0xff;
|
|
break;
|
|
case 0xC4:
|
|
dst = (this.regEAX >> 8) & 0xff;
|
|
break;
|
|
case 0xC5:
|
|
dst = (this.regECX >> 8) & 0xff;
|
|
break;
|
|
case 0xC6:
|
|
dst = (this.regEDX >> 8) & 0xff;
|
|
break;
|
|
case 0xC7:
|
|
dst = (this.regEBX >> 8) & 0xff;
|
|
break;
|
|
default:
|
|
dst = 0;
|
|
this.assert(false, "modGrpByte16(): unrecognized modrm byte " + str.toHexByte(bModRM));
|
|
break;
|
|
}
|
|
|
|
var reg = (this.bModRM >> 3) & 0x7;
|
|
|
|
var b = afnGrp[reg].call(this, dst, fnSrc.call(this));
|
|
|
|
switch(bModRM) {
|
|
case 0x00:
|
|
case 0x03:
|
|
this.setEAByte(b);
|
|
this.nStepCycles -= this.cycleCounts.nEACyclesBaseIndex;
|
|
break;
|
|
case 0x01:
|
|
case 0x02:
|
|
this.setEAByte(b);
|
|
this.nStepCycles -= this.cycleCounts.nEACyclesBaseIndexExtra;
|
|
break;
|
|
case 0x04:
|
|
case 0x05:
|
|
case 0x07:
|
|
this.setEAByte(b);
|
|
this.nStepCycles -= this.cycleCounts.nEACyclesBase;
|
|
break;
|
|
case 0x06:
|
|
this.setEAByte(b);
|
|
this.nStepCycles -= this.cycleCounts.nEACyclesDisp;
|
|
break;
|
|
case 0x40:
|
|
case 0x43:
|
|
case 0x80:
|
|
case 0x83:
|
|
this.setEAByte(b);
|
|
this.nStepCycles -= this.cycleCounts.nEACyclesBaseIndexDisp;
|
|
break;
|
|
case 0x41:
|
|
case 0x42:
|
|
case 0x81:
|
|
case 0x82:
|
|
this.setEAByte(b);
|
|
this.nStepCycles -= this.cycleCounts.nEACyclesBaseIndexDispExtra;
|
|
break;
|
|
case 0x44:
|
|
case 0x45:
|
|
case 0x46:
|
|
case 0x47:
|
|
case 0x84:
|
|
case 0x85:
|
|
case 0x86:
|
|
case 0x87:
|
|
this.setEAByte(b);
|
|
this.nStepCycles -= this.cycleCounts.nEACyclesBaseDisp;
|
|
break;
|
|
case 0xC0:
|
|
this.regEAX = (this.regEAX & ~0xff) | b;
|
|
break;
|
|
case 0xC1:
|
|
this.regECX = (this.regECX & ~0xff) | b;
|
|
break;
|
|
case 0xC2:
|
|
this.regEDX = (this.regEDX & ~0xff) | b;
|
|
break;
|
|
case 0xC3:
|
|
this.regEBX = (this.regEBX & ~0xff) | b;
|
|
break;
|
|
case 0xC4:
|
|
this.regEAX = (this.regEAX & ~0xff00) | (b << 8);
|
|
break;
|
|
case 0xC5:
|
|
this.regECX = (this.regECX & ~0xff00) | (b << 8);
|
|
break;
|
|
case 0xC6:
|
|
this.regEDX = (this.regEDX & ~0xff00) | (b << 8);
|
|
break;
|
|
case 0xC7:
|
|
this.regEBX = (this.regEBX & ~0xff00) | (b << 8);
|
|
break;
|
|
}
|
|
};
|
|
|
|
/**
|
|
* modRegShort16(fn)
|
|
*
|
|
* @this {X86CPU}
|
|
* @param {function(number,number)} fn (dst,src)
|
|
*/
|
|
X86.modRegShort16 = function(fn)
|
|
{
|
|
var dst, src;
|
|
var bModRM = (this.bModRM = this.getIPByte()) & 0xC7;
|
|
|
|
switch(bModRM) {
|
|
case 0x00:
|
|
src = this.getEAShortData(this.regEBX + this.regESI);
|
|
this.nStepCycles -= this.cycleCounts.nEACyclesBaseIndex;
|
|
break;
|
|
case 0x01:
|
|
src = this.getEAShortData(this.regEBX + this.regEDI);
|
|
this.nStepCycles -= this.cycleCounts.nEACyclesBaseIndexExtra;
|
|
break;
|
|
case 0x02:
|
|
src = this.getEAShortStack(this.regEBP + this.regESI);
|
|
this.nStepCycles -= this.cycleCounts.nEACyclesBaseIndexExtra;
|
|
break;
|
|
case 0x03:
|
|
src = this.getEAShortStack(this.regEBP + this.regEDI);
|
|
this.nStepCycles -= this.cycleCounts.nEACyclesBaseIndex;
|
|
break;
|
|
case 0x04:
|
|
src = this.getEAShortData(this.regESI);
|
|
this.nStepCycles -= this.cycleCounts.nEACyclesBase;
|
|
break;
|
|
case 0x05:
|
|
src = this.getEAShortData(this.regEDI);
|
|
this.nStepCycles -= this.cycleCounts.nEACyclesBase;
|
|
break;
|
|
case 0x06:
|
|
src = this.getEAShortData(this.getIPAddr());
|
|
this.nStepCycles -= this.cycleCounts.nEACyclesDisp;
|
|
break;
|
|
case 0x07:
|
|
src = this.getEAShortData(this.regEBX);
|
|
this.nStepCycles -= this.cycleCounts.nEACyclesBase;
|
|
break;
|
|
case 0x40:
|
|
src = this.getEAShortData(this.regEBX + this.regESI + this.getIPDisp());
|
|
this.nStepCycles -= this.cycleCounts.nEACyclesBaseIndexDisp;
|
|
break;
|
|
case 0x41:
|
|
src = this.getEAShortData(this.regEBX + this.regEDI + this.getIPDisp());
|
|
this.nStepCycles -= this.cycleCounts.nEACyclesBaseIndexDispExtra;
|
|
break;
|
|
case 0x42:
|
|
src = this.getEAShortStack(this.regEBP + this.regESI + this.getIPDisp());
|
|
this.nStepCycles -= this.cycleCounts.nEACyclesBaseIndexDispExtra;
|
|
break;
|
|
case 0x43:
|
|
src = this.getEAShortStack(this.regEBP + this.regEDI + this.getIPDisp());
|
|
this.nStepCycles -= this.cycleCounts.nEACyclesBaseIndexDisp;
|
|
break;
|
|
case 0x44:
|
|
src = this.getEAShortData(this.regESI + this.getIPDisp());
|
|
this.nStepCycles -= this.cycleCounts.nEACyclesBaseDisp;
|
|
break;
|
|
case 0x45:
|
|
src = this.getEAShortData(this.regEDI + this.getIPDisp());
|
|
this.nStepCycles -= this.cycleCounts.nEACyclesBaseDisp;
|
|
break;
|
|
case 0x46:
|
|
src = this.getEAShortStack(this.regEBP + this.getIPDisp());
|
|
this.nStepCycles -= this.cycleCounts.nEACyclesBaseDisp;
|
|
break;
|
|
case 0x47:
|
|
src = this.getEAShortData(this.regEBX + this.getIPDisp());
|
|
this.nStepCycles -= this.cycleCounts.nEACyclesBaseDisp;
|
|
break;
|
|
case 0x80:
|
|
src = this.getEAShortData(this.regEBX + this.regESI + this.getIPAddr());
|
|
this.nStepCycles -= this.cycleCounts.nEACyclesBaseIndexDisp;
|
|
break;
|
|
case 0x81:
|
|
src = this.getEAShortData(this.regEBX + this.regEDI + this.getIPAddr());
|
|
this.nStepCycles -= this.cycleCounts.nEACyclesBaseIndexDispExtra;
|
|
break;
|
|
case 0x82:
|
|
src = this.getEAShortStack(this.regEBP + this.regESI + this.getIPAddr());
|
|
this.nStepCycles -= this.cycleCounts.nEACyclesBaseIndexDispExtra;
|
|
break;
|
|
case 0x83:
|
|
src = this.getEAShortStack(this.regEBP + this.regEDI + this.getIPAddr());
|
|
this.nStepCycles -= this.cycleCounts.nEACyclesBaseIndexDisp;
|
|
break;
|
|
case 0x84:
|
|
src = this.getEAShortData(this.regESI + this.getIPAddr());
|
|
this.nStepCycles -= this.cycleCounts.nEACyclesBaseDisp;
|
|
break;
|
|
case 0x85:
|
|
src = this.getEAShortData(this.regEDI + this.getIPAddr());
|
|
this.nStepCycles -= this.cycleCounts.nEACyclesBaseDisp;
|
|
break;
|
|
case 0x86:
|
|
src = this.getEAShortStack(this.regEBP + this.getIPAddr());
|
|
this.nStepCycles -= this.cycleCounts.nEACyclesBaseDisp;
|
|
break;
|
|
case 0x87:
|
|
src = this.getEAShortData(this.regEBX + this.getIPAddr());
|
|
this.nStepCycles -= this.cycleCounts.nEACyclesBaseDisp;
|
|
break;
|
|
case 0xC0:
|
|
src = this.regEAX & 0xffff;
|
|
if (BACKTRACK) {
|
|
this.backTrack.btiEALo = this.backTrack.btiAL; this.backTrack.btiEAHi = this.backTrack.btiAH;
|
|
}
|
|
break;
|
|
case 0xC1:
|
|
src = this.regECX & 0xffff;
|
|
if (BACKTRACK) {
|
|
this.backTrack.btiEALo = this.backTrack.btiCL; this.backTrack.btiEAHi = this.backTrack.btiCH;
|
|
}
|
|
break;
|
|
case 0xC2:
|
|
src = this.regEDX & 0xffff;
|
|
if (BACKTRACK) {
|
|
this.backTrack.btiEALo = this.backTrack.btiDL; this.backTrack.btiEAHi = this.backTrack.btiDH;
|
|
}
|
|
break;
|
|
case 0xC3:
|
|
src = this.regEBX & 0xffff;
|
|
if (BACKTRACK) {
|
|
this.backTrack.btiEALo = this.backTrack.btiBL; this.backTrack.btiEAHi = this.backTrack.btiBH;
|
|
}
|
|
break;
|
|
case 0xC4:
|
|
src = this.getSP() & 0xffff;
|
|
if (BACKTRACK) {
|
|
this.backTrack.btiEALo = X86.BTINFO.SP_LO; this.backTrack.btiEAHi = X86.BTINFO.SP_HI;
|
|
}
|
|
break;
|
|
case 0xC5:
|
|
src = this.regEBP & 0xffff;
|
|
if (BACKTRACK) {
|
|
this.backTrack.btiEALo = this.backTrack.btiBPLo; this.backTrack.btiEAHi = this.backTrack.btiBPHi;
|
|
}
|
|
break;
|
|
case 0xC6:
|
|
src = this.regESI & 0xffff;
|
|
if (BACKTRACK) {
|
|
this.backTrack.btiEALo = this.backTrack.btiSILo; this.backTrack.btiEAHi = this.backTrack.btiSIHi;
|
|
}
|
|
break;
|
|
case 0xC7:
|
|
src = this.regEDI & 0xffff;
|
|
if (BACKTRACK) {
|
|
this.backTrack.btiEALo = this.backTrack.btiDILo; this.backTrack.btiEAHi = this.backTrack.btiDIHi;
|
|
}
|
|
break;
|
|
default:
|
|
src = 0;
|
|
this.assert(false, "modRegShort16(): unrecognized modrm byte " + str.toHexByte(bModRM));
|
|
break;
|
|
}
|
|
|
|
var reg = (this.bModRM >> 3) & 0x7;
|
|
|
|
switch(reg) {
|
|
case 0x0:
|
|
dst = this.regEAX & 0xffff;
|
|
break;
|
|
case 0x1:
|
|
dst = this.regECX & 0xffff;
|
|
break;
|
|
case 0x2:
|
|
dst = this.regEDX & 0xffff;
|
|
break;
|
|
case 0x3:
|
|
dst = this.regEBX & 0xffff;
|
|
break;
|
|
case 0x4:
|
|
dst = this.getSP() & 0xffff;
|
|
break;
|
|
case 0x5:
|
|
dst = this.regEBP & 0xffff;
|
|
break;
|
|
case 0x6:
|
|
dst = this.regESI & 0xffff;
|
|
break;
|
|
case 0x7:
|
|
dst = this.regEDI & 0xffff;
|
|
break;
|
|
default:
|
|
dst = 0;
|
|
break;
|
|
}
|
|
|
|
var w = fn.call(this, dst, src);
|
|
|
|
switch(reg) {
|
|
case 0x0:
|
|
this.regEAX = (this.regEAX & ~0xffff) | w;
|
|
if (BACKTRACK) {
|
|
this.backTrack.btiAL = this.backTrack.btiEALo; this.backTrack.btiAH = this.backTrack.btiEAHi;
|
|
}
|
|
break;
|
|
case 0x1:
|
|
this.regECX = (this.regECX & ~0xffff) | w;
|
|
if (BACKTRACK) {
|
|
this.backTrack.btiCL = this.backTrack.btiEALo; this.backTrack.btiCH = this.backTrack.btiEAHi;
|
|
}
|
|
break;
|
|
case 0x2:
|
|
this.regEDX = (this.regEDX & ~0xffff) | w;
|
|
if (BACKTRACK) {
|
|
this.backTrack.btiDL = this.backTrack.btiEALo; this.backTrack.btiDH = this.backTrack.btiEAHi;
|
|
}
|
|
break;
|
|
case 0x3:
|
|
this.regEBX = (this.regEBX & ~0xffff) | w;
|
|
if (BACKTRACK) {
|
|
this.backTrack.btiBL = this.backTrack.btiEALo; this.backTrack.btiBH = this.backTrack.btiEAHi;
|
|
}
|
|
break;
|
|
case 0x4:
|
|
this.setSP((this.getSP() & ~0xffff) | w);
|
|
break;
|
|
case 0x5:
|
|
this.regEBP = (this.regEBP & ~0xffff) | w;
|
|
if (BACKTRACK) {
|
|
this.backTrack.btiBPLo = this.backTrack.btiEALo; this.backTrack.btiBPHi = this.backTrack.btiEAHi;
|
|
}
|
|
break;
|
|
case 0x6:
|
|
this.regESI = (this.regESI & ~0xffff) | w;
|
|
if (BACKTRACK) {
|
|
this.backTrack.btiSILo = this.backTrack.btiEALo; this.backTrack.btiSIHi = this.backTrack.btiEAHi;
|
|
}
|
|
break;
|
|
case 0x7:
|
|
this.regEDI = (this.regEDI & ~0xffff) | w;
|
|
if (BACKTRACK) {
|
|
this.backTrack.btiDILo = this.backTrack.btiEALo; this.backTrack.btiDIHi = this.backTrack.btiEAHi;
|
|
}
|
|
break;
|
|
}
|
|
};
|
|
|
|
/**
|
|
* modMemShort16(fn)
|
|
*
|
|
* @this {X86CPU}
|
|
* @param {function(number,number)} fn (dst,src)
|
|
*/
|
|
X86.modMemShort16 = function(fn)
|
|
{
|
|
var dst, src;
|
|
var bModRM = (this.bModRM = this.getIPByte()) & 0xC7;
|
|
|
|
switch(bModRM) {
|
|
case 0x00:
|
|
dst = this.getEAShortData(this.regEBX + this.regESI);
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x01:
|
|
dst = this.getEAShortData(this.regEBX + this.regEDI);
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x02:
|
|
dst = this.getEAShortStack(this.regEBP + this.regESI);
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x03:
|
|
dst = this.getEAShortStack(this.regEBP + this.regEDI);
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x04:
|
|
dst = this.getEAShortData(this.regESI);
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x05:
|
|
dst = this.getEAShortData(this.regEDI);
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x06:
|
|
dst = this.getEAShortData(this.getIPAddr());
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x07:
|
|
dst = this.getEAShortData(this.regEBX);
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x40:
|
|
dst = this.getEAShortData(this.regEBX + this.regESI + this.getIPDisp());
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x41:
|
|
dst = this.getEAShortData(this.regEBX + this.regEDI + this.getIPDisp());
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x42:
|
|
dst = this.getEAShortStack(this.regEBP + this.regESI + this.getIPDisp());
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x43:
|
|
dst = this.getEAShortStack(this.regEBP + this.regEDI + this.getIPDisp());
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x44:
|
|
dst = this.getEAShortData(this.regESI + this.getIPDisp());
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x45:
|
|
dst = this.getEAShortData(this.regEDI + this.getIPDisp());
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x46:
|
|
dst = this.getEAShortStack(this.regEBP + this.getIPDisp());
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x47:
|
|
dst = this.getEAShortData(this.regEBX + this.getIPDisp());
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x80:
|
|
dst = this.getEAShortData(this.regEBX + this.regESI + this.getIPAddr());
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x81:
|
|
dst = this.getEAShortData(this.regEBX + this.regEDI + this.getIPAddr());
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x82:
|
|
dst = this.getEAShortStack(this.regEBP + this.regESI + this.getIPAddr());
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x83:
|
|
dst = this.getEAShortStack(this.regEBP + this.regEDI + this.getIPAddr());
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x84:
|
|
dst = this.getEAShortData(this.regESI + this.getIPAddr());
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x85:
|
|
dst = this.getEAShortData(this.regEDI + this.getIPAddr());
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x86:
|
|
dst = this.getEAShortStack(this.regEBP + this.getIPAddr());
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x87:
|
|
dst = this.getEAShortData(this.regEBX + this.getIPAddr());
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0xC0:
|
|
dst = this.regEAX & 0xffff;
|
|
break;
|
|
case 0xC1:
|
|
dst = this.regECX & 0xffff;
|
|
break;
|
|
case 0xC2:
|
|
dst = this.regEDX & 0xffff;
|
|
break;
|
|
case 0xC3:
|
|
dst = this.regEBX & 0xffff;
|
|
break;
|
|
case 0xC4:
|
|
dst = this.getSP() & 0xffff;
|
|
break;
|
|
case 0xC5:
|
|
dst = this.regEBP & 0xffff;
|
|
break;
|
|
case 0xC6:
|
|
dst = this.regESI & 0xffff;
|
|
break;
|
|
case 0xC7:
|
|
dst = this.regEDI & 0xffff;
|
|
break;
|
|
default:
|
|
dst = 0;
|
|
this.assert(false, "modMemShort16(): unrecognized modrm byte " + str.toHexByte(bModRM));
|
|
break;
|
|
}
|
|
|
|
var reg = (this.bModRM >> 3) & 0x7;
|
|
|
|
switch(reg) {
|
|
case 0x0:
|
|
src = this.regEAX & 0xffff;
|
|
if (BACKTRACK) {
|
|
this.backTrack.btiEALo = this.backTrack.btiAL; this.backTrack.btiEAHi = this.backTrack.btiAH;
|
|
}
|
|
break;
|
|
case 0x1:
|
|
src = this.regECX & 0xffff;
|
|
if (BACKTRACK) {
|
|
this.backTrack.btiEALo = this.backTrack.btiCL; this.backTrack.btiEAHi = this.backTrack.btiCH;
|
|
}
|
|
break;
|
|
case 0x2:
|
|
src = this.regEDX & 0xffff;
|
|
if (BACKTRACK) {
|
|
this.backTrack.btiEALo = this.backTrack.btiDL; this.backTrack.btiEAHi = this.backTrack.btiDH;
|
|
}
|
|
break;
|
|
case 0x3:
|
|
src = this.regEBX & 0xffff;
|
|
if (BACKTRACK) {
|
|
this.backTrack.btiEALo = this.backTrack.btiBL; this.backTrack.btiEAHi = this.backTrack.btiBH;
|
|
}
|
|
break;
|
|
case 0x4:
|
|
src = this.getSP() & 0xffff;
|
|
if (BACKTRACK) {
|
|
this.backTrack.btiEALo = X86.BTINFO.SP_LO; this.backTrack.btiEAHi = X86.BTINFO.SP_HI;
|
|
}
|
|
break;
|
|
case 0x5:
|
|
src = this.regEBP & 0xffff;
|
|
if (BACKTRACK) {
|
|
this.backTrack.btiEALo = this.backTrack.btiBPLo; this.backTrack.btiEAHi = this.backTrack.btiBPHi;
|
|
}
|
|
break;
|
|
case 0x6:
|
|
src = this.regESI & 0xffff;
|
|
if (BACKTRACK) {
|
|
this.backTrack.btiEALo = this.backTrack.btiSILo; this.backTrack.btiEAHi = this.backTrack.btiSIHi;
|
|
}
|
|
break;
|
|
case 0x7:
|
|
src = this.regEDI & 0xffff;
|
|
if (BACKTRACK) {
|
|
this.backTrack.btiEALo = this.backTrack.btiDILo; this.backTrack.btiEAHi = this.backTrack.btiDIHi;
|
|
}
|
|
break;
|
|
default:
|
|
src = 0;
|
|
break;
|
|
}
|
|
|
|
var w = fn.call(this, dst, src);
|
|
|
|
switch(bModRM) {
|
|
case 0x00:
|
|
case 0x03:
|
|
this.setEAShort(w);
|
|
this.nStepCycles -= this.cycleCounts.nEACyclesBaseIndex;
|
|
break;
|
|
case 0x01:
|
|
case 0x02:
|
|
this.setEAShort(w);
|
|
this.nStepCycles -= this.cycleCounts.nEACyclesBaseIndexExtra;
|
|
break;
|
|
case 0x04:
|
|
case 0x05:
|
|
case 0x07:
|
|
this.setEAShort(w);
|
|
this.nStepCycles -= this.cycleCounts.nEACyclesBase;
|
|
break;
|
|
case 0x06:
|
|
this.setEAShort(w);
|
|
this.nStepCycles -= this.cycleCounts.nEACyclesDisp;
|
|
break;
|
|
case 0x40:
|
|
case 0x43:
|
|
case 0x80:
|
|
case 0x83:
|
|
this.setEAShort(w);
|
|
this.nStepCycles -= this.cycleCounts.nEACyclesBaseIndexDisp;
|
|
break;
|
|
case 0x41:
|
|
case 0x42:
|
|
case 0x81:
|
|
case 0x82:
|
|
this.setEAShort(w);
|
|
this.nStepCycles -= this.cycleCounts.nEACyclesBaseIndexDispExtra;
|
|
break;
|
|
case 0x44:
|
|
case 0x45:
|
|
case 0x46:
|
|
case 0x47:
|
|
case 0x84:
|
|
case 0x85:
|
|
case 0x86:
|
|
case 0x87:
|
|
this.setEAShort(w);
|
|
this.nStepCycles -= this.cycleCounts.nEACyclesBaseDisp;
|
|
break;
|
|
case 0xC0:
|
|
this.regEAX = (this.regEAX & ~0xffff) | w;
|
|
if (BACKTRACK) {
|
|
this.backTrack.btiAL = this.backTrack.btiEALo; this.backTrack.btiAH = this.backTrack.btiEAHi;
|
|
}
|
|
break;
|
|
case 0xC1:
|
|
this.regECX = (this.regECX & ~0xffff) | w;
|
|
if (BACKTRACK) {
|
|
this.backTrack.btiCL = this.backTrack.btiEALo; this.backTrack.btiCH = this.backTrack.btiEAHi;
|
|
}
|
|
break;
|
|
case 0xC2:
|
|
this.regEDX = (this.regEDX & ~0xffff) | w;
|
|
if (BACKTRACK) {
|
|
this.backTrack.btiDL = this.backTrack.btiEALo; this.backTrack.btiDH = this.backTrack.btiEAHi;
|
|
}
|
|
break;
|
|
case 0xC3:
|
|
this.regEBX = (this.regEBX & ~0xffff) | w;
|
|
if (BACKTRACK) {
|
|
this.backTrack.btiBL = this.backTrack.btiEALo; this.backTrack.btiBH = this.backTrack.btiEAHi;
|
|
}
|
|
break;
|
|
case 0xC4:
|
|
this.setSP((this.getSP() & ~0xffff) | w);
|
|
break;
|
|
case 0xC5:
|
|
this.regEBP = (this.regEBP & ~0xffff) | w;
|
|
if (BACKTRACK) {
|
|
this.backTrack.btiBPLo = this.backTrack.btiEALo; this.backTrack.btiBPHi = this.backTrack.btiEAHi;
|
|
}
|
|
break;
|
|
case 0xC6:
|
|
this.regESI = (this.regESI & ~0xffff) | w;
|
|
if (BACKTRACK) {
|
|
this.backTrack.btiSILo = this.backTrack.btiEALo; this.backTrack.btiSIHi = this.backTrack.btiEAHi;
|
|
}
|
|
break;
|
|
case 0xC7:
|
|
this.regEDI = (this.regEDI & ~0xffff) | w;
|
|
if (BACKTRACK) {
|
|
this.backTrack.btiDILo = this.backTrack.btiEALo; this.backTrack.btiDIHi = this.backTrack.btiEAHi;
|
|
}
|
|
break;
|
|
default:
|
|
this.assert(false, "modMemShort16(): unrecognized modrm byte " + str.toHexByte(bModRM));
|
|
break;
|
|
}
|
|
};
|
|
|
|
/**
|
|
* modGrpShort16(afnGrp, fnSrc)
|
|
*
|
|
* @this {X86CPU}
|
|
* @param {Array.<function(number,number)>} afnGrp
|
|
* @param {function()} fnSrc
|
|
*/
|
|
X86.modGrpShort16 = function(afnGrp, fnSrc) {
|
|
var dst;
|
|
var bModRM = (this.bModRM = this.getIPByte()) & 0xC7;
|
|
|
|
switch(bModRM) {
|
|
case 0x00:
|
|
dst = this.getEAShortData(this.regEBX + this.regESI);
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x01:
|
|
dst = this.getEAShortData(this.regEBX + this.regEDI);
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x02:
|
|
dst = this.getEAShortStack(this.regEBP + this.regESI);
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x03:
|
|
dst = this.getEAShortStack(this.regEBP + this.regEDI);
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x04:
|
|
dst = this.getEAShortData(this.regESI);
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x05:
|
|
dst = this.getEAShortData(this.regEDI);
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x06:
|
|
dst = this.getEAShortData(this.getIPAddr());
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x07:
|
|
dst = this.getEAShortData(this.regEBX);
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x40:
|
|
dst = this.getEAShortData(this.regEBX + this.regESI + this.getIPDisp());
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x41:
|
|
dst = this.getEAShortData(this.regEBX + this.regEDI + this.getIPDisp());
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x42:
|
|
dst = this.getEAShortStack(this.regEBP + this.regESI + this.getIPDisp());
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x43:
|
|
dst = this.getEAShortStack(this.regEBP + this.regEDI + this.getIPDisp());
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x44:
|
|
dst = this.getEAShortData(this.regESI + this.getIPDisp());
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x45:
|
|
dst = this.getEAShortData(this.regEDI + this.getIPDisp());
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x46:
|
|
dst = this.getEAShortStack(this.regEBP + this.getIPDisp());
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x47:
|
|
dst = this.getEAShortData(this.regEBX + this.getIPDisp());
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x80:
|
|
dst = this.getEAShortData(this.regEBX + this.regESI + this.getIPAddr());
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x81:
|
|
dst = this.getEAShortData(this.regEBX + this.regEDI + this.getIPAddr());
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x82:
|
|
dst = this.getEAShortStack(this.regEBP + this.regESI + this.getIPAddr());
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x83:
|
|
dst = this.getEAShortStack(this.regEBP + this.regEDI + this.getIPAddr());
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x84:
|
|
dst = this.getEAShortData(this.regESI + this.getIPAddr());
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x85:
|
|
dst = this.getEAShortData(this.regEDI + this.getIPAddr());
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x86:
|
|
dst = this.getEAShortStack(this.regEBP + this.getIPAddr());
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x87:
|
|
dst = this.getEAShortData(this.regEBX + this.getIPAddr());
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0xC0:
|
|
dst = this.regEAX & 0xffff;
|
|
break;
|
|
case 0xC1:
|
|
dst = this.regECX & 0xffff;
|
|
break;
|
|
case 0xC2:
|
|
dst = this.regEDX & 0xffff;
|
|
break;
|
|
case 0xC3:
|
|
dst = this.regEBX & 0xffff;
|
|
break;
|
|
case 0xC4:
|
|
dst = this.getSP() & 0xffff;
|
|
break;
|
|
case 0xC5:
|
|
dst = this.regEBP & 0xffff;
|
|
break;
|
|
case 0xC6:
|
|
dst = this.regESI & 0xffff;
|
|
break;
|
|
case 0xC7:
|
|
dst = this.regEDI & 0xffff;
|
|
break;
|
|
default:
|
|
dst = 0;
|
|
this.assert(false, "modGrpShort16(): unrecognized modrm byte " + str.toHexByte(bModRM));
|
|
break;
|
|
}
|
|
|
|
var reg = (this.bModRM >> 3) & 0x7;
|
|
|
|
var w = afnGrp[reg].call(this, dst, fnSrc.call(this));
|
|
|
|
switch(bModRM) {
|
|
case 0x00:
|
|
case 0x03:
|
|
this.setEAShort(w);
|
|
this.nStepCycles -= this.cycleCounts.nEACyclesBaseIndex;
|
|
break;
|
|
case 0x01:
|
|
case 0x02:
|
|
this.setEAShort(w);
|
|
this.nStepCycles -= this.cycleCounts.nEACyclesBaseIndexExtra;
|
|
break;
|
|
case 0x04:
|
|
case 0x05:
|
|
case 0x07:
|
|
this.setEAShort(w);
|
|
this.nStepCycles -= this.cycleCounts.nEACyclesBase;
|
|
break;
|
|
case 0x06:
|
|
this.setEAShort(w);
|
|
this.nStepCycles -= this.cycleCounts.nEACyclesDisp;
|
|
break;
|
|
case 0x40:
|
|
case 0x43:
|
|
case 0x80:
|
|
case 0x83:
|
|
this.setEAShort(w);
|
|
this.nStepCycles -= this.cycleCounts.nEACyclesBaseIndexDisp;
|
|
break;
|
|
case 0x41:
|
|
case 0x42:
|
|
case 0x81:
|
|
case 0x82:
|
|
this.setEAShort(w);
|
|
this.nStepCycles -= this.cycleCounts.nEACyclesBaseIndexDispExtra;
|
|
break;
|
|
case 0x44:
|
|
case 0x45:
|
|
case 0x46:
|
|
case 0x47:
|
|
case 0x84:
|
|
case 0x85:
|
|
case 0x86:
|
|
case 0x87:
|
|
this.setEAShort(w);
|
|
this.nStepCycles -= this.cycleCounts.nEACyclesBaseDisp;
|
|
break;
|
|
case 0xC0:
|
|
this.regEAX = (this.regEAX & ~0xffff) | w;
|
|
break;
|
|
case 0xC1:
|
|
this.regECX = (this.regECX & ~0xffff) | w;
|
|
break;
|
|
case 0xC2:
|
|
this.regEDX = (this.regEDX & ~0xffff) | w;
|
|
break;
|
|
case 0xC3:
|
|
this.regEBX = (this.regEBX & ~0xffff) | w;
|
|
break;
|
|
case 0xC4:
|
|
this.setSP((this.getSP() & ~0xffff) | w);
|
|
break;
|
|
case 0xC5:
|
|
this.regEBP = (this.regEBP & ~0xffff) | w;
|
|
break;
|
|
case 0xC6:
|
|
this.regESI = (this.regESI & ~0xffff) | w;
|
|
break;
|
|
case 0xC7:
|
|
this.regEDI = (this.regEDI & ~0xffff) | w;
|
|
break;
|
|
}
|
|
};
|
|
|
|
/**
|
|
* modRegLong16(fn)
|
|
*
|
|
* @this {X86CPU}
|
|
* @param {function(number,number)} fn (dst,src)
|
|
*/
|
|
X86.modRegLong16 = function(fn)
|
|
{
|
|
var dst, src;
|
|
var bModRM = (this.bModRM = this.getIPByte()) & 0xC7;
|
|
|
|
switch(bModRM) {
|
|
case 0x00:
|
|
src = this.getEALongData(this.regEBX + this.regESI);
|
|
this.nStepCycles -= this.cycleCounts.nEACyclesBaseIndex;
|
|
break;
|
|
case 0x01:
|
|
src = this.getEALongData(this.regEBX + this.regEDI);
|
|
this.nStepCycles -= this.cycleCounts.nEACyclesBaseIndexExtra;
|
|
break;
|
|
case 0x02:
|
|
src = this.getEALongStack(this.regEBP + this.regESI);
|
|
this.nStepCycles -= this.cycleCounts.nEACyclesBaseIndexExtra;
|
|
break;
|
|
case 0x03:
|
|
src = this.getEALongStack(this.regEBP + this.regEDI);
|
|
this.nStepCycles -= this.cycleCounts.nEACyclesBaseIndex;
|
|
break;
|
|
case 0x04:
|
|
src = this.getEALongData(this.regESI);
|
|
this.nStepCycles -= this.cycleCounts.nEACyclesBase;
|
|
break;
|
|
case 0x05:
|
|
src = this.getEALongData(this.regEDI);
|
|
this.nStepCycles -= this.cycleCounts.nEACyclesBase;
|
|
break;
|
|
case 0x06:
|
|
src = this.getEALongData(this.getIPAddr());
|
|
this.nStepCycles -= this.cycleCounts.nEACyclesDisp;
|
|
break;
|
|
case 0x07:
|
|
src = this.getEALongData(this.regEBX);
|
|
this.nStepCycles -= this.cycleCounts.nEACyclesBase;
|
|
break;
|
|
case 0x40:
|
|
src = this.getEALongData(this.regEBX + this.regESI + this.getIPDisp());
|
|
this.nStepCycles -= this.cycleCounts.nEACyclesBaseIndexDisp;
|
|
break;
|
|
case 0x41:
|
|
src = this.getEALongData(this.regEBX + this.regEDI + this.getIPDisp());
|
|
this.nStepCycles -= this.cycleCounts.nEACyclesBaseIndexDispExtra;
|
|
break;
|
|
case 0x42:
|
|
src = this.getEALongStack(this.regEBP + this.regESI + this.getIPDisp());
|
|
this.nStepCycles -= this.cycleCounts.nEACyclesBaseIndexDispExtra;
|
|
break;
|
|
case 0x43:
|
|
src = this.getEALongStack(this.regEBP + this.regEDI + this.getIPDisp());
|
|
this.nStepCycles -= this.cycleCounts.nEACyclesBaseIndexDisp;
|
|
break;
|
|
case 0x44:
|
|
src = this.getEALongData(this.regESI + this.getIPDisp());
|
|
this.nStepCycles -= this.cycleCounts.nEACyclesBaseDisp;
|
|
break;
|
|
case 0x45:
|
|
src = this.getEALongData(this.regEDI + this.getIPDisp());
|
|
this.nStepCycles -= this.cycleCounts.nEACyclesBaseDisp;
|
|
break;
|
|
case 0x46:
|
|
src = this.getEALongStack(this.regEBP + this.getIPDisp());
|
|
this.nStepCycles -= this.cycleCounts.nEACyclesBaseDisp;
|
|
break;
|
|
case 0x47:
|
|
src = this.getEALongData(this.regEBX + this.getIPDisp());
|
|
this.nStepCycles -= this.cycleCounts.nEACyclesBaseDisp;
|
|
break;
|
|
case 0x80:
|
|
src = this.getEALongData(this.regEBX + this.regESI + this.getIPAddr());
|
|
this.nStepCycles -= this.cycleCounts.nEACyclesBaseIndexDisp;
|
|
break;
|
|
case 0x81:
|
|
src = this.getEALongData(this.regEBX + this.regEDI + this.getIPAddr());
|
|
this.nStepCycles -= this.cycleCounts.nEACyclesBaseIndexDispExtra;
|
|
break;
|
|
case 0x82:
|
|
src = this.getEALongStack(this.regEBP + this.regESI + this.getIPAddr());
|
|
this.nStepCycles -= this.cycleCounts.nEACyclesBaseIndexDispExtra;
|
|
break;
|
|
case 0x83:
|
|
src = this.getEALongStack(this.regEBP + this.regEDI + this.getIPAddr());
|
|
this.nStepCycles -= this.cycleCounts.nEACyclesBaseIndexDisp;
|
|
break;
|
|
case 0x84:
|
|
src = this.getEALongData(this.regESI + this.getIPAddr());
|
|
this.nStepCycles -= this.cycleCounts.nEACyclesBaseDisp;
|
|
break;
|
|
case 0x85:
|
|
src = this.getEALongData(this.regEDI + this.getIPAddr());
|
|
this.nStepCycles -= this.cycleCounts.nEACyclesBaseDisp;
|
|
break;
|
|
case 0x86:
|
|
src = this.getEALongStack(this.regEBP + this.getIPAddr());
|
|
this.nStepCycles -= this.cycleCounts.nEACyclesBaseDisp;
|
|
break;
|
|
case 0x87:
|
|
src = this.getEALongData(this.regEBX + this.getIPAddr());
|
|
this.nStepCycles -= this.cycleCounts.nEACyclesBaseDisp;
|
|
break;
|
|
case 0xC0:
|
|
src = this.regEAX;
|
|
if (BACKTRACK) {
|
|
this.backTrack.btiEALo = this.backTrack.btiAL; this.backTrack.btiEAHi = this.backTrack.btiAH;
|
|
}
|
|
break;
|
|
case 0xC1:
|
|
src = this.regECX;
|
|
if (BACKTRACK) {
|
|
this.backTrack.btiEALo = this.backTrack.btiCL; this.backTrack.btiEAHi = this.backTrack.btiCH;
|
|
}
|
|
break;
|
|
case 0xC2:
|
|
src = this.regEDX;
|
|
if (BACKTRACK) {
|
|
this.backTrack.btiEALo = this.backTrack.btiDL; this.backTrack.btiEAHi = this.backTrack.btiDH;
|
|
}
|
|
break;
|
|
case 0xC3:
|
|
src = this.regEBX;
|
|
if (BACKTRACK) {
|
|
this.backTrack.btiEALo = this.backTrack.btiBL; this.backTrack.btiEAHi = this.backTrack.btiBH;
|
|
}
|
|
break;
|
|
case 0xC4:
|
|
src = this.getSP();
|
|
if (BACKTRACK) {
|
|
this.backTrack.btiEALo = X86.BTINFO.SP_LO; this.backTrack.btiEAHi = X86.BTINFO.SP_HI;
|
|
}
|
|
break;
|
|
case 0xC5:
|
|
src = this.regEBP;
|
|
if (BACKTRACK) {
|
|
this.backTrack.btiEALo = this.backTrack.btiBPLo; this.backTrack.btiEAHi = this.backTrack.btiBPHi;
|
|
}
|
|
break;
|
|
case 0xC6:
|
|
src = this.regESI;
|
|
if (BACKTRACK) {
|
|
this.backTrack.btiEALo = this.backTrack.btiSILo; this.backTrack.btiEAHi = this.backTrack.btiSIHi;
|
|
}
|
|
break;
|
|
case 0xC7:
|
|
src = this.regEDI;
|
|
if (BACKTRACK) {
|
|
this.backTrack.btiEALo = this.backTrack.btiDILo; this.backTrack.btiEAHi = this.backTrack.btiDIHi;
|
|
}
|
|
break;
|
|
default:
|
|
src = 0;
|
|
this.assert(false, "modRegLong16(): unrecognized modrm byte " + str.toHexByte(bModRM));
|
|
break;
|
|
}
|
|
|
|
var reg = (this.bModRM >> 3) & 0x7;
|
|
|
|
switch(reg) {
|
|
case 0x0:
|
|
dst = this.regEAX;
|
|
break;
|
|
case 0x1:
|
|
dst = this.regECX;
|
|
break;
|
|
case 0x2:
|
|
dst = this.regEDX;
|
|
break;
|
|
case 0x3:
|
|
dst = this.regEBX;
|
|
break;
|
|
case 0x4:
|
|
dst = this.getSP();
|
|
break;
|
|
case 0x5:
|
|
dst = this.regEBP;
|
|
break;
|
|
case 0x6:
|
|
dst = this.regESI;
|
|
break;
|
|
case 0x7:
|
|
dst = this.regEDI;
|
|
break;
|
|
default:
|
|
dst = 0;
|
|
break;
|
|
}
|
|
|
|
var l = fn.call(this, dst, src);
|
|
|
|
switch(reg) {
|
|
case 0x0:
|
|
this.regEAX = l;
|
|
if (BACKTRACK) {
|
|
this.backTrack.btiAL = this.backTrack.btiEALo; this.backTrack.btiAH = this.backTrack.btiEAHi;
|
|
}
|
|
break;
|
|
case 0x1:
|
|
this.regECX = l;
|
|
if (BACKTRACK) {
|
|
this.backTrack.btiCL = this.backTrack.btiEALo; this.backTrack.btiCH = this.backTrack.btiEAHi;
|
|
}
|
|
break;
|
|
case 0x2:
|
|
this.regEDX = l;
|
|
if (BACKTRACK) {
|
|
this.backTrack.btiDL = this.backTrack.btiEALo; this.backTrack.btiDH = this.backTrack.btiEAHi;
|
|
}
|
|
break;
|
|
case 0x3:
|
|
this.regEBX = l;
|
|
if (BACKTRACK) {
|
|
this.backTrack.btiBL = this.backTrack.btiEALo; this.backTrack.btiBH = this.backTrack.btiEAHi;
|
|
}
|
|
break;
|
|
case 0x4:
|
|
this.setSP(l);
|
|
break;
|
|
case 0x5:
|
|
this.regEBP = l;
|
|
if (BACKTRACK) {
|
|
this.backTrack.btiBPLo = this.backTrack.btiEALo; this.backTrack.btiBPHi = this.backTrack.btiEAHi;
|
|
}
|
|
break;
|
|
case 0x6:
|
|
this.regESI = l;
|
|
if (BACKTRACK) {
|
|
this.backTrack.btiSILo = this.backTrack.btiEALo; this.backTrack.btiSIHi = this.backTrack.btiEAHi;
|
|
}
|
|
break;
|
|
case 0x7:
|
|
this.regEDI = l;
|
|
if (BACKTRACK) {
|
|
this.backTrack.btiDILo = this.backTrack.btiEALo; this.backTrack.btiDIHi = this.backTrack.btiEAHi;
|
|
}
|
|
break;
|
|
}
|
|
};
|
|
|
|
/**
|
|
* modMemLong16(fn)
|
|
*
|
|
* @this {X86CPU}
|
|
* @param {function(number,number)} fn (dst,src)
|
|
*/
|
|
X86.modMemLong16 = function(fn)
|
|
{
|
|
var dst, src;
|
|
var bModRM = (this.bModRM = this.getIPByte()) & 0xC7;
|
|
|
|
switch(bModRM) {
|
|
case 0x00:
|
|
dst = this.getEALongData(this.regEBX + this.regESI);
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x01:
|
|
dst = this.getEALongData(this.regEBX + this.regEDI);
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x02:
|
|
dst = this.getEALongStack(this.regEBP + this.regESI);
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x03:
|
|
dst = this.getEALongStack(this.regEBP + this.regEDI);
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x04:
|
|
dst = this.getEALongData(this.regESI);
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x05:
|
|
dst = this.getEALongData(this.regEDI);
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x06:
|
|
dst = this.getEALongData(this.getIPAddr());
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x07:
|
|
dst = this.getEALongData(this.regEBX);
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x40:
|
|
dst = this.getEALongData(this.regEBX + this.regESI + this.getIPDisp());
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x41:
|
|
dst = this.getEALongData(this.regEBX + this.regEDI + this.getIPDisp());
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x42:
|
|
dst = this.getEALongStack(this.regEBP + this.regESI + this.getIPDisp());
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x43:
|
|
dst = this.getEALongStack(this.regEBP + this.regEDI + this.getIPDisp());
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x44:
|
|
dst = this.getEALongData(this.regESI + this.getIPDisp());
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x45:
|
|
dst = this.getEALongData(this.regEDI + this.getIPDisp());
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x46:
|
|
dst = this.getEALongStack(this.regEBP + this.getIPDisp());
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x47:
|
|
dst = this.getEALongData(this.regEBX + this.getIPDisp());
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x80:
|
|
dst = this.getEALongData(this.regEBX + this.regESI + this.getIPAddr());
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x81:
|
|
dst = this.getEALongData(this.regEBX + this.regEDI + this.getIPAddr());
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x82:
|
|
dst = this.getEALongStack(this.regEBP + this.regESI + this.getIPAddr());
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x83:
|
|
dst = this.getEALongStack(this.regEBP + this.regEDI + this.getIPAddr());
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x84:
|
|
dst = this.getEALongData(this.regESI + this.getIPAddr());
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x85:
|
|
dst = this.getEALongData(this.regEDI + this.getIPAddr());
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x86:
|
|
dst = this.getEALongStack(this.regEBP + this.getIPAddr());
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x87:
|
|
dst = this.getEALongData(this.regEBX + this.getIPAddr());
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0xC0:
|
|
dst = this.regEAX;
|
|
break;
|
|
case 0xC1:
|
|
dst = this.regECX;
|
|
break;
|
|
case 0xC2:
|
|
dst = this.regEDX;
|
|
break;
|
|
case 0xC3:
|
|
dst = this.regEBX;
|
|
break;
|
|
case 0xC4:
|
|
dst = this.getSP();
|
|
break;
|
|
case 0xC5:
|
|
dst = this.regEBP;
|
|
break;
|
|
case 0xC6:
|
|
dst = this.regESI;
|
|
break;
|
|
case 0xC7:
|
|
dst = this.regEDI;
|
|
break;
|
|
default:
|
|
dst = 0;
|
|
this.assert(false, "modMemLong16(): unrecognized modrm byte " + str.toHexByte(bModRM));
|
|
break;
|
|
}
|
|
|
|
var reg = (this.bModRM >> 3) & 0x7;
|
|
|
|
switch(reg) {
|
|
case 0x0:
|
|
src = this.regEAX;
|
|
if (BACKTRACK) {
|
|
this.backTrack.btiEALo = this.backTrack.btiAL; this.backTrack.btiEAHi = this.backTrack.btiAH;
|
|
}
|
|
break;
|
|
case 0x1:
|
|
src = this.regECX;
|
|
if (BACKTRACK) {
|
|
this.backTrack.btiEALo = this.backTrack.btiCL; this.backTrack.btiEAHi = this.backTrack.btiCH;
|
|
}
|
|
break;
|
|
case 0x2:
|
|
src = this.regEDX;
|
|
if (BACKTRACK) {
|
|
this.backTrack.btiEALo = this.backTrack.btiDL; this.backTrack.btiEAHi = this.backTrack.btiDH;
|
|
}
|
|
break;
|
|
case 0x3:
|
|
src = this.regEBX;
|
|
if (BACKTRACK) {
|
|
this.backTrack.btiEALo = this.backTrack.btiBL; this.backTrack.btiEAHi = this.backTrack.btiBH;
|
|
}
|
|
break;
|
|
case 0x4:
|
|
src = this.getSP();
|
|
if (BACKTRACK) {
|
|
this.backTrack.btiEALo = X86.BTINFO.SP_LO; this.backTrack.btiEAHi = X86.BTINFO.SP_HI;
|
|
}
|
|
break;
|
|
case 0x5:
|
|
src = this.regEBP;
|
|
if (BACKTRACK) {
|
|
this.backTrack.btiEALo = this.backTrack.btiBPLo; this.backTrack.btiEAHi = this.backTrack.btiBPHi;
|
|
}
|
|
break;
|
|
case 0x6:
|
|
src = this.regESI;
|
|
if (BACKTRACK) {
|
|
this.backTrack.btiEALo = this.backTrack.btiSILo; this.backTrack.btiEAHi = this.backTrack.btiSIHi;
|
|
}
|
|
break;
|
|
case 0x7:
|
|
src = this.regEDI;
|
|
if (BACKTRACK) {
|
|
this.backTrack.btiEALo = this.backTrack.btiDILo; this.backTrack.btiEAHi = this.backTrack.btiDIHi;
|
|
}
|
|
break;
|
|
default:
|
|
src = 0;
|
|
break;
|
|
}
|
|
|
|
var l = fn.call(this, dst, src);
|
|
|
|
switch(bModRM) {
|
|
case 0x00:
|
|
case 0x03:
|
|
this.setEALong(l);
|
|
this.nStepCycles -= this.cycleCounts.nEACyclesBaseIndex;
|
|
break;
|
|
case 0x01:
|
|
case 0x02:
|
|
this.setEALong(l);
|
|
this.nStepCycles -= this.cycleCounts.nEACyclesBaseIndexExtra;
|
|
break;
|
|
case 0x04:
|
|
case 0x05:
|
|
case 0x07:
|
|
this.setEALong(l);
|
|
this.nStepCycles -= this.cycleCounts.nEACyclesBase;
|
|
break;
|
|
case 0x06:
|
|
this.setEALong(l);
|
|
this.nStepCycles -= this.cycleCounts.nEACyclesDisp;
|
|
break;
|
|
case 0x40:
|
|
case 0x43:
|
|
case 0x80:
|
|
case 0x83:
|
|
this.setEALong(l);
|
|
this.nStepCycles -= this.cycleCounts.nEACyclesBaseIndexDisp;
|
|
break;
|
|
case 0x41:
|
|
case 0x42:
|
|
case 0x81:
|
|
case 0x82:
|
|
this.setEALong(l);
|
|
this.nStepCycles -= this.cycleCounts.nEACyclesBaseIndexDispExtra;
|
|
break;
|
|
case 0x44:
|
|
case 0x45:
|
|
case 0x46:
|
|
case 0x47:
|
|
case 0x84:
|
|
case 0x85:
|
|
case 0x86:
|
|
case 0x87:
|
|
this.setEALong(l);
|
|
this.nStepCycles -= this.cycleCounts.nEACyclesBaseDisp;
|
|
break;
|
|
case 0xC0:
|
|
this.regEAX = l;
|
|
if (BACKTRACK) {
|
|
this.backTrack.btiAL = this.backTrack.btiEALo; this.backTrack.btiAH = this.backTrack.btiEAHi;
|
|
}
|
|
break;
|
|
case 0xC1:
|
|
this.regECX = l;
|
|
if (BACKTRACK) {
|
|
this.backTrack.btiCL = this.backTrack.btiEALo; this.backTrack.btiCH = this.backTrack.btiEAHi;
|
|
}
|
|
break;
|
|
case 0xC2:
|
|
this.regEDX = l;
|
|
if (BACKTRACK) {
|
|
this.backTrack.btiDL = this.backTrack.btiEALo; this.backTrack.btiDH = this.backTrack.btiEAHi;
|
|
}
|
|
break;
|
|
case 0xC3:
|
|
this.regEBX = l;
|
|
if (BACKTRACK) {
|
|
this.backTrack.btiBL = this.backTrack.btiEALo; this.backTrack.btiBH = this.backTrack.btiEAHi;
|
|
}
|
|
break;
|
|
case 0xC4:
|
|
this.setSP(l);
|
|
break;
|
|
case 0xC5:
|
|
this.regEBP = l;
|
|
if (BACKTRACK) {
|
|
this.backTrack.btiBPLo = this.backTrack.btiEALo; this.backTrack.btiBPHi = this.backTrack.btiEAHi;
|
|
}
|
|
break;
|
|
case 0xC6:
|
|
this.regESI = l;
|
|
if (BACKTRACK) {
|
|
this.backTrack.btiSILo = this.backTrack.btiEALo; this.backTrack.btiSIHi = this.backTrack.btiEAHi;
|
|
}
|
|
break;
|
|
case 0xC7:
|
|
this.regEDI = l;
|
|
if (BACKTRACK) {
|
|
this.backTrack.btiDILo = this.backTrack.btiEALo; this.backTrack.btiDIHi = this.backTrack.btiEAHi;
|
|
}
|
|
break;
|
|
default:
|
|
this.assert(false, "modMemLong16(): unrecognized modrm byte " + str.toHexByte(bModRM));
|
|
break;
|
|
}
|
|
};
|
|
|
|
/**
|
|
* modGrpLong16(afnGrp, fnSrc)
|
|
*
|
|
* @this {X86CPU}
|
|
* @param {Array.<function(number,number)>} afnGrp
|
|
* @param {function()} fnSrc
|
|
*/
|
|
X86.modGrpLong16 = function(afnGrp, fnSrc) {
|
|
var dst;
|
|
var bModRM = (this.bModRM = this.getIPByte()) & 0xC7;
|
|
|
|
switch(bModRM) {
|
|
case 0x00:
|
|
dst = this.getEALongData(this.regEBX + this.regESI);
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x01:
|
|
dst = this.getEALongData(this.regEBX + this.regEDI);
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x02:
|
|
dst = this.getEALongStack(this.regEBP + this.regESI);
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x03:
|
|
dst = this.getEALongStack(this.regEBP + this.regEDI);
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x04:
|
|
dst = this.getEALongData(this.regESI);
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x05:
|
|
dst = this.getEALongData(this.regEDI);
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x06:
|
|
dst = this.getEALongData(this.getIPAddr());
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x07:
|
|
dst = this.getEALongData(this.regEBX);
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x40:
|
|
dst = this.getEALongData(this.regEBX + this.regESI + this.getIPDisp());
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x41:
|
|
dst = this.getEALongData(this.regEBX + this.regEDI + this.getIPDisp());
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x42:
|
|
dst = this.getEALongStack(this.regEBP + this.regESI + this.getIPDisp());
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x43:
|
|
dst = this.getEALongStack(this.regEBP + this.regEDI + this.getIPDisp());
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x44:
|
|
dst = this.getEALongData(this.regESI + this.getIPDisp());
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x45:
|
|
dst = this.getEALongData(this.regEDI + this.getIPDisp());
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x46:
|
|
dst = this.getEALongStack(this.regEBP + this.getIPDisp());
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x47:
|
|
dst = this.getEALongData(this.regEBX + this.getIPDisp());
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x80:
|
|
dst = this.getEALongData(this.regEBX + this.regESI + this.getIPAddr());
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x81:
|
|
dst = this.getEALongData(this.regEBX + this.regEDI + this.getIPAddr());
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x82:
|
|
dst = this.getEALongStack(this.regEBP + this.regESI + this.getIPAddr());
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x83:
|
|
dst = this.getEALongStack(this.regEBP + this.regEDI + this.getIPAddr());
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x84:
|
|
dst = this.getEALongData(this.regESI + this.getIPAddr());
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x85:
|
|
dst = this.getEALongData(this.regEDI + this.getIPAddr());
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x86:
|
|
dst = this.getEALongStack(this.regEBP + this.getIPAddr());
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x87:
|
|
dst = this.getEALongData(this.regEBX + this.getIPAddr());
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0xC0:
|
|
dst = this.regEAX;
|
|
break;
|
|
case 0xC1:
|
|
dst = this.regECX;
|
|
break;
|
|
case 0xC2:
|
|
dst = this.regEDX;
|
|
break;
|
|
case 0xC3:
|
|
dst = this.regEBX;
|
|
break;
|
|
case 0xC4:
|
|
dst = this.getSP();
|
|
break;
|
|
case 0xC5:
|
|
dst = this.regEBP;
|
|
break;
|
|
case 0xC6:
|
|
dst = this.regESI;
|
|
break;
|
|
case 0xC7:
|
|
dst = this.regEDI;
|
|
break;
|
|
default:
|
|
this.assert(false, "modGrpLong16(): unrecognized modrm byte " + str.toHexByte(bModRM));
|
|
break;
|
|
}
|
|
|
|
var reg = (this.bModRM >> 3) & 0x7;
|
|
|
|
var l = afnGrp[reg].call(this, dst, fnSrc.call(this));
|
|
|
|
switch(bModRM) {
|
|
case 0x00:
|
|
case 0x03:
|
|
this.setEALong(l);
|
|
this.nStepCycles -= this.cycleCounts.nEACyclesBaseIndex;
|
|
break;
|
|
case 0x01:
|
|
case 0x02:
|
|
this.setEALong(l);
|
|
this.nStepCycles -= this.cycleCounts.nEACyclesBaseIndexExtra;
|
|
break;
|
|
case 0x04:
|
|
case 0x05:
|
|
case 0x07:
|
|
this.setEALong(l);
|
|
this.nStepCycles -= this.cycleCounts.nEACyclesBase;
|
|
break;
|
|
case 0x06:
|
|
this.setEALong(l);
|
|
this.nStepCycles -= this.cycleCounts.nEACyclesDisp;
|
|
break;
|
|
case 0x40:
|
|
case 0x43:
|
|
case 0x80:
|
|
case 0x83:
|
|
this.setEALong(l);
|
|
this.nStepCycles -= this.cycleCounts.nEACyclesBaseIndexDisp;
|
|
break;
|
|
case 0x41:
|
|
case 0x42:
|
|
case 0x81:
|
|
case 0x82:
|
|
this.setEALong(l);
|
|
this.nStepCycles -= this.cycleCounts.nEACyclesBaseIndexDispExtra;
|
|
break;
|
|
case 0x44:
|
|
case 0x45:
|
|
case 0x46:
|
|
case 0x47:
|
|
case 0x84:
|
|
case 0x85:
|
|
case 0x86:
|
|
case 0x87:
|
|
this.setEALong(l);
|
|
this.nStepCycles -= this.cycleCounts.nEACyclesBaseDisp;
|
|
break;
|
|
case 0xC0:
|
|
this.regEAX = l;
|
|
break;
|
|
case 0xC1:
|
|
this.regECX = l;
|
|
break;
|
|
case 0xC2:
|
|
this.regEDX = l;
|
|
break;
|
|
case 0xC3:
|
|
this.regEBX = l;
|
|
break;
|
|
case 0xC4:
|
|
this.setSP(l);
|
|
break;
|
|
case 0xC5:
|
|
this.regEBP = l;
|
|
break;
|
|
case 0xC6:
|
|
this.regESI = l;
|
|
break;
|
|
case 0xC7:
|
|
this.regEDI = l;
|
|
break;
|
|
}
|
|
};
|
|
|
|
/**
|
|
* modRegByte32(fn)
|
|
*
|
|
* @this {X86CPU}
|
|
* @param {function(number,number)} fn (dst,src)
|
|
*/
|
|
X86.modRegByte32 = function(fn)
|
|
{
|
|
var dst, src;
|
|
var bModRM = (this.bModRM = this.getIPByte()) & 0xC7;
|
|
|
|
switch(bModRM) {
|
|
case 0x00:
|
|
src = this.getEAByteData(this.regEAX);
|
|
break;
|
|
case 0x01:
|
|
src = this.getEAByteData(this.regECX);
|
|
break;
|
|
case 0x02:
|
|
src = this.getEAByteData(this.regEDX);
|
|
break;
|
|
case 0x03:
|
|
src = this.getEAByteData(this.regEBX);
|
|
break;
|
|
case 0x04:
|
|
src = this.getEAByteData(X86.modSIB.call(this, 0));
|
|
break;
|
|
case 0x05:
|
|
src = this.getEAByteData(this.getIPAddr());
|
|
break;
|
|
case 0x06:
|
|
src = this.getEAByteData(this.regESI);
|
|
break;
|
|
case 0x07:
|
|
src = this.getEAByteData(this.regEDI);
|
|
break;
|
|
case 0x40:
|
|
src = this.getEAByteData(this.regEAX + this.getIPDisp());
|
|
break;
|
|
case 0x41:
|
|
src = this.getEAByteData(this.regECX + this.getIPDisp());
|
|
break;
|
|
case 0x42:
|
|
src = this.getEAByteData(this.regEDX + this.getIPDisp());
|
|
break;
|
|
case 0x43:
|
|
src = this.getEAByteData(this.regEBX + this.getIPDisp());
|
|
break;
|
|
case 0x44:
|
|
src = this.getEAByteData(X86.modSIB.call(this, 1) + this.getIPDisp());
|
|
break;
|
|
case 0x45:
|
|
src = this.getEAByteStack(this.regEBP + this.getIPDisp());
|
|
break;
|
|
case 0x46:
|
|
src = this.getEAByteData(this.regESI + this.getIPDisp());
|
|
break;
|
|
case 0x47:
|
|
src = this.getEAByteData(this.regEDI + this.getIPDisp());
|
|
break;
|
|
case 0x80:
|
|
src = this.getEAByteData(this.regEAX + this.getIPAddr());
|
|
break;
|
|
case 0x81:
|
|
src = this.getEAByteData(this.regECX + this.getIPAddr());
|
|
break;
|
|
case 0x82:
|
|
src = this.getEAByteData(this.regEDX + this.getIPAddr());
|
|
break;
|
|
case 0x83:
|
|
src = this.getEAByteData(this.regEBX + this.getIPAddr());
|
|
break;
|
|
case 0x84:
|
|
src = this.getEAByteData(X86.modSIB.call(this, 2) + this.getIPAddr());
|
|
break;
|
|
case 0x85:
|
|
src = this.getEAByteStack(this.regEBP + this.getIPAddr());
|
|
break;
|
|
case 0x86:
|
|
src = this.getEAByteData(this.regESI + this.getIPAddr());
|
|
break;
|
|
case 0x87:
|
|
src = this.getEAByteData(this.regEDI + this.getIPAddr());
|
|
break;
|
|
case 0xC0:
|
|
src = this.regEAX & 0xff;
|
|
if (BACKTRACK) this.backTrack.btiEALo = this.backTrack.btiAL;
|
|
break;
|
|
case 0xC1:
|
|
src = this.regECX & 0xff;
|
|
if (BACKTRACK) this.backTrack.btiEALo = this.backTrack.btiCL;
|
|
break;
|
|
case 0xC2:
|
|
src = this.regEDX & 0xff;
|
|
if (BACKTRACK) this.backTrack.btiEALo = this.backTrack.btiDL;
|
|
break;
|
|
case 0xC3:
|
|
src = this.regEBX & 0xff;
|
|
if (BACKTRACK) this.backTrack.btiEALo = this.backTrack.btiBL;
|
|
break;
|
|
case 0xC4:
|
|
src = (this.regEAX >> 8) & 0xff;
|
|
if (BACKTRACK) this.backTrack.btiEALo = this.backTrack.btiAH;
|
|
break;
|
|
case 0xC5:
|
|
src = (this.regECX >> 8) & 0xff;
|
|
if (BACKTRACK) this.backTrack.btiEALo = this.backTrack.btiCH;
|
|
break;
|
|
case 0xC6:
|
|
src = (this.regEDX >> 8) & 0xff;
|
|
if (BACKTRACK) this.backTrack.btiEALo = this.backTrack.btiDH;
|
|
break;
|
|
case 0xC7:
|
|
src = (this.regEBX >> 8) & 0xff;
|
|
if (BACKTRACK) this.backTrack.btiEALo = this.backTrack.btiBH;
|
|
break;
|
|
default:
|
|
src = 0;
|
|
this.assert(false, "modRegByte32(): unrecognized modrm byte " + str.toHexByte(bModRM));
|
|
break;
|
|
}
|
|
|
|
var reg = (this.bModRM >> 3) & 0x7;
|
|
|
|
switch(reg) {
|
|
case 0x0:
|
|
dst = this.regEAX & 0xff;
|
|
break;
|
|
case 0x1:
|
|
dst = this.regECX & 0xff;
|
|
break;
|
|
case 0x2:
|
|
dst = this.regEDX & 0xff;
|
|
break;
|
|
case 0x3:
|
|
dst = this.regEBX & 0xff;
|
|
break;
|
|
case 0x4:
|
|
dst = (this.regEAX >> 8) & 0xff;
|
|
break;
|
|
case 0x5:
|
|
dst = (this.regECX >> 8) & 0xff;
|
|
break;
|
|
case 0x6:
|
|
dst = (this.regEDX >> 8) & 0xff;
|
|
break;
|
|
case 0x7:
|
|
dst = (this.regEBX >> 8) & 0xff;
|
|
break;
|
|
default:
|
|
dst = 0;
|
|
break;
|
|
}
|
|
|
|
var b = fn.call(this, dst, src);
|
|
|
|
switch(reg) {
|
|
case 0x0:
|
|
this.regEAX = (this.regEAX & ~0xff) | b;
|
|
if (BACKTRACK) this.backTrack.btiAL = this.backTrack.btiEALo;
|
|
break;
|
|
case 0x1:
|
|
this.regECX = (this.regECX & ~0xff) | b;
|
|
if (BACKTRACK) this.backTrack.btiCL = this.backTrack.btiEALo;
|
|
break;
|
|
case 0x2:
|
|
this.regEDX = (this.regEDX & ~0xff) | b;
|
|
if (BACKTRACK) this.backTrack.btiDL = this.backTrack.btiEALo;
|
|
break;
|
|
case 0x3:
|
|
this.regEBX = (this.regEBX & ~0xff) | b;
|
|
if (BACKTRACK) this.backTrack.btiBL = this.backTrack.btiEALo;
|
|
break;
|
|
case 0x4:
|
|
this.regEAX = (this.regEAX & ~0xff00) | (b << 8);
|
|
if (BACKTRACK) this.backTrack.btiAH = this.backTrack.btiEALo;
|
|
break;
|
|
case 0x5:
|
|
this.regECX = (this.regECX & ~0xff00) | (b << 8);
|
|
if (BACKTRACK) this.backTrack.btiCH = this.backTrack.btiEALo;
|
|
break;
|
|
case 0x6:
|
|
this.regEDX = (this.regEDX & ~0xff00) | (b << 8);
|
|
if (BACKTRACK) this.backTrack.btiDH = this.backTrack.btiEALo;
|
|
break;
|
|
case 0x7:
|
|
this.regEBX = (this.regEBX & ~0xff00) | (b << 8);
|
|
if (BACKTRACK) this.backTrack.btiBH = this.backTrack.btiEALo;
|
|
break;
|
|
}
|
|
};
|
|
|
|
/**
|
|
* modMemByte32(fn)
|
|
*
|
|
* @this {X86CPU}
|
|
* @param {function(number,number)} fn (dst,src)
|
|
*/
|
|
X86.modMemByte32 = function(fn)
|
|
{
|
|
var dst, src;
|
|
var bModRM = (this.bModRM = this.getIPByte()) & 0xC7;
|
|
|
|
switch(bModRM) {
|
|
case 0x00:
|
|
dst = this.getEAByteData(this.regEAX);
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x01:
|
|
dst = this.getEAByteData(this.regECX);
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x02:
|
|
dst = this.getEAByteData(this.regEDX);
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x03:
|
|
dst = this.getEAByteData(this.regEBX);
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x04:
|
|
dst = this.getEAByteData(X86.modSIB.call(this, 0));
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x05:
|
|
dst = this.getEAByteData(this.getIPAddr());
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x06:
|
|
dst = this.getEAByteData(this.regESI);
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x07:
|
|
dst = this.getEAByteData(this.regEDI);
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x40:
|
|
dst = this.getEAByteData(this.regEAX + this.getIPDisp());
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x41:
|
|
dst = this.getEAByteData(this.regECX + this.getIPDisp());
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x42:
|
|
dst = this.getEAByteData(this.regEDX + this.getIPDisp());
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x43:
|
|
dst = this.getEAByteData(this.regEBX + this.getIPDisp());
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x44:
|
|
dst = this.getEAByteData(X86.modSIB.call(this, 1) + this.getIPDisp());
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x45:
|
|
dst = this.getEAByteStack(this.regEBP + this.getIPDisp());
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x46:
|
|
dst = this.getEAByteData(this.regESI + this.getIPDisp());
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x47:
|
|
dst = this.getEAByteData(this.regEDI + this.getIPDisp());
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x80:
|
|
dst = this.getEAByteData(this.regEAX + this.getIPAddr());
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x81:
|
|
dst = this.getEAByteData(this.regECX + this.getIPAddr());
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x82:
|
|
dst = this.getEAByteData(this.regEDX + this.getIPAddr());
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x83:
|
|
dst = this.getEAByteData(this.regEBX + this.getIPAddr());
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x84:
|
|
dst = this.getEAByteData(X86.modSIB.call(this, 2) + this.getIPAddr());
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x85:
|
|
dst = this.getEAByteStack(this.regEBP + this.getIPAddr());
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x86:
|
|
dst = this.getEAByteData(this.regESI + this.getIPAddr());
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x87:
|
|
dst = this.getEAByteData(this.regEDI + this.getIPAddr());
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0xC0:
|
|
dst = this.regEAX & 0xff;
|
|
break;
|
|
case 0xC1:
|
|
dst = this.regECX & 0xff;
|
|
break;
|
|
case 0xC2:
|
|
dst = this.regEDX & 0xff;
|
|
break;
|
|
case 0xC3:
|
|
dst = this.regEBX & 0xff;
|
|
break;
|
|
case 0xC4:
|
|
dst = (this.regEAX >> 8) & 0xff;
|
|
break;
|
|
case 0xC5:
|
|
dst = (this.regECX >> 8) & 0xff;
|
|
break;
|
|
case 0xC6:
|
|
dst = (this.regEDX >> 8) & 0xff;
|
|
break;
|
|
case 0xC7:
|
|
dst = (this.regEBX >> 8) & 0xff;
|
|
break;
|
|
default:
|
|
dst = 0;
|
|
this.assert(false, "modMemByte32(): unrecognized modrm byte " + str.toHexByte(bModRM));
|
|
break;
|
|
}
|
|
|
|
var reg = (this.bModRM >> 3) & 0x7;
|
|
|
|
switch(reg) {
|
|
case 0x0:
|
|
src = this.regEAX & 0xff;
|
|
if (BACKTRACK) this.backTrack.btiEALo = this.backTrack.btiAL;
|
|
break;
|
|
case 0x1:
|
|
src = this.regECX & 0xff;
|
|
if (BACKTRACK) this.backTrack.btiEALo = this.backTrack.btiCL;
|
|
break;
|
|
case 0x2:
|
|
src = this.regEDX & 0xff;
|
|
if (BACKTRACK) this.backTrack.btiEALo = this.backTrack.btiDL;
|
|
break;
|
|
case 0x3:
|
|
src = this.regEBX & 0xff;
|
|
if (BACKTRACK) this.backTrack.btiEALo = this.backTrack.btiBL;
|
|
break;
|
|
case 0x4:
|
|
src = (this.regEAX >> 8) & 0xff;
|
|
if (BACKTRACK) this.backTrack.btiEALo = this.backTrack.btiAH;
|
|
break;
|
|
case 0x5:
|
|
src = (this.regECX >> 8) & 0xff;
|
|
if (BACKTRACK) this.backTrack.btiEALo = this.backTrack.btiCH;
|
|
break;
|
|
case 0x6:
|
|
src = (this.regEDX >> 8) & 0xff;
|
|
if (BACKTRACK) this.backTrack.btiEALo = this.backTrack.btiDH;
|
|
break;
|
|
case 0x7:
|
|
src = (this.regEBX >> 8) & 0xff;
|
|
if (BACKTRACK) this.backTrack.btiEALo = this.backTrack.btiBH;
|
|
break;
|
|
default:
|
|
src = 0;
|
|
break;
|
|
}
|
|
|
|
var b = fn.call(this, dst, src);
|
|
|
|
switch(bModRM) {
|
|
case 0xC0:
|
|
this.regEAX = (this.regEAX & ~0xff) | b;
|
|
if (BACKTRACK) this.backTrack.btiAL = this.backTrack.btiEALo;
|
|
break;
|
|
case 0xC1:
|
|
this.regECX = (this.regECX & ~0xff) | b;
|
|
if (BACKTRACK) this.backTrack.btiCL = this.backTrack.btiEALo;
|
|
break;
|
|
case 0xC2:
|
|
this.regEDX = (this.regEDX & ~0xff) | b;
|
|
if (BACKTRACK) this.backTrack.btiDL = this.backTrack.btiEALo;
|
|
break;
|
|
case 0xC3:
|
|
this.regEBX = (this.regEBX & ~0xff) | b;
|
|
if (BACKTRACK) this.backTrack.btiBL = this.backTrack.btiEALo;
|
|
break;
|
|
case 0xC4:
|
|
this.regEAX = (this.regEAX & ~0xff00) | (b << 8);
|
|
if (BACKTRACK) this.backTrack.btiAH = this.backTrack.btiEALo;
|
|
break;
|
|
case 0xC5:
|
|
this.regECX = (this.regECX & ~0xff00) | (b << 8);
|
|
if (BACKTRACK) this.backTrack.btiCH = this.backTrack.btiEALo;
|
|
break;
|
|
case 0xC6:
|
|
this.regEDX = (this.regEDX & ~0xff00) | (b << 8);
|
|
if (BACKTRACK) this.backTrack.btiDH = this.backTrack.btiEALo;
|
|
break;
|
|
case 0xC7:
|
|
this.regEBX = (this.regEBX & ~0xff00) | (b << 8);
|
|
if (BACKTRACK) this.backTrack.btiBH = this.backTrack.btiEALo;
|
|
break;
|
|
default:
|
|
this.setEAByte(b);
|
|
break;
|
|
}
|
|
};
|
|
|
|
/**
|
|
* modGrpByte32(afnGrp, fnSrc)
|
|
*
|
|
* @this {X86CPU}
|
|
* @param {Array.<function(number,number)>} afnGrp
|
|
* @param {function()} fnSrc
|
|
*/
|
|
X86.modGrpByte32 = function(afnGrp, fnSrc) {
|
|
var dst;
|
|
var bModRM = (this.bModRM = this.getIPByte()) & 0xC7;
|
|
|
|
switch(bModRM) {
|
|
case 0x00:
|
|
dst = this.getEAByteData(this.regEAX);
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x01:
|
|
dst = this.getEAByteData(this.regECX);
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x02:
|
|
dst = this.getEAByteData(this.regEDX);
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x03:
|
|
dst = this.getEAByteData(this.regEBX);
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x04:
|
|
dst = this.getEAByteData(X86.modSIB.call(this, 0));
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x05:
|
|
dst = this.getEAByteData(this.getIPAddr());
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x06:
|
|
dst = this.getEAByteData(this.regESI);
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x07:
|
|
dst = this.getEAByteData(this.regEDI);
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x40:
|
|
dst = this.getEAByteData(this.regEAX + this.getIPDisp());
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x41:
|
|
dst = this.getEAByteData(this.regECX + this.getIPDisp());
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x42:
|
|
dst = this.getEAByteData(this.regEDX + this.getIPDisp());
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x43:
|
|
dst = this.getEAByteData(this.regEBX + this.getIPDisp());
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x44:
|
|
dst = this.getEAByteData(X86.modSIB.call(this, 1) + this.getIPDisp());
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x45:
|
|
dst = this.getEAByteStack(this.regEBP + this.getIPDisp());
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x46:
|
|
dst = this.getEAByteData(this.regESI + this.getIPDisp());
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x47:
|
|
dst = this.getEAByteData(this.regEDI + this.getIPDisp());
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x80:
|
|
dst = this.getEAByteData(this.regEAX + this.getIPAddr());
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x81:
|
|
dst = this.getEAByteData(this.regECX + this.getIPAddr());
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x82:
|
|
dst = this.getEAByteData(this.regEDX + this.getIPAddr());
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x83:
|
|
dst = this.getEAByteData(this.regEBX + this.getIPAddr());
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x84:
|
|
dst = this.getEAByteData(X86.modSIB.call(this, 2) + this.getIPAddr());
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x85:
|
|
dst = this.getEAByteStack(this.regEBP + this.getIPAddr());
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x86:
|
|
dst = this.getEAByteData(this.regESI + this.getIPAddr());
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x87:
|
|
dst = this.getEAByteData(this.regEDI + this.getIPAddr());
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0xC0:
|
|
dst = this.regEAX & 0xff;
|
|
break;
|
|
case 0xC1:
|
|
dst = this.regECX & 0xff;
|
|
break;
|
|
case 0xC2:
|
|
dst = this.regEDX & 0xff;
|
|
break;
|
|
case 0xC3:
|
|
dst = this.regEBX & 0xff;
|
|
break;
|
|
case 0xC4:
|
|
dst = (this.regEAX >> 8) & 0xff;
|
|
break;
|
|
case 0xC5:
|
|
dst = (this.regECX >> 8) & 0xff;
|
|
break;
|
|
case 0xC6:
|
|
dst = (this.regEDX >> 8) & 0xff;
|
|
break;
|
|
case 0xC7:
|
|
dst = (this.regEBX >> 8) & 0xff;
|
|
break;
|
|
default:
|
|
dst = 0;
|
|
this.assert(false, "modGrpByte32(): unrecognized modrm byte " + str.toHexByte(bModRM));
|
|
break;
|
|
}
|
|
|
|
var reg = (this.bModRM >> 3) & 0x7;
|
|
|
|
var b = afnGrp[reg].call(this, dst, fnSrc.call(this));
|
|
|
|
switch(bModRM) {
|
|
case 0xC0:
|
|
this.regEAX = (this.regEAX & ~0xff) | b;
|
|
break;
|
|
case 0xC1:
|
|
this.regECX = (this.regECX & ~0xff) | b;
|
|
break;
|
|
case 0xC2:
|
|
this.regEDX = (this.regEDX & ~0xff) | b;
|
|
break;
|
|
case 0xC3:
|
|
this.regEBX = (this.regEBX & ~0xff) | b;
|
|
break;
|
|
case 0xC4:
|
|
this.regEAX = (this.regEAX & ~0xff00) | (b << 8);
|
|
break;
|
|
case 0xC5:
|
|
this.regECX = (this.regECX & ~0xff00) | (b << 8);
|
|
break;
|
|
case 0xC6:
|
|
this.regEDX = (this.regEDX & ~0xff00) | (b << 8);
|
|
break;
|
|
case 0xC7:
|
|
this.regEBX = (this.regEBX & ~0xff00) | (b << 8);
|
|
break;
|
|
default:
|
|
this.setEAByte(b);
|
|
break;
|
|
}
|
|
};
|
|
|
|
/**
|
|
* modRegShort32(fn)
|
|
*
|
|
* @this {X86CPU}
|
|
* @param {function(number,number)} fn (dst,src)
|
|
*/
|
|
X86.modRegShort32 = function(fn)
|
|
{
|
|
var dst, src;
|
|
var bModRM = (this.bModRM = this.getIPByte()) & 0xC7;
|
|
|
|
switch(bModRM) {
|
|
case 0x00:
|
|
src = this.getEAShortData(this.regEAX);
|
|
break;
|
|
case 0x01:
|
|
src = this.getEAShortData(this.regECX);
|
|
break;
|
|
case 0x02:
|
|
src = this.getEAShortData(this.regEDX);
|
|
break;
|
|
case 0x03:
|
|
src = this.getEAShortData(this.regEBX);
|
|
break;
|
|
case 0x04:
|
|
src = this.getEAShortData(X86.modSIB.call(this, 0));
|
|
break;
|
|
case 0x05:
|
|
src = this.getEAShortData(this.getIPAddr());
|
|
break;
|
|
case 0x06:
|
|
src = this.getEAShortData(this.regESI);
|
|
break;
|
|
case 0x07:
|
|
src = this.getEAShortData(this.regEDI);
|
|
break;
|
|
case 0x40:
|
|
src = this.getEAShortData(this.regEAX + this.getIPDisp());
|
|
break;
|
|
case 0x41:
|
|
src = this.getEAShortData(this.regECX + this.getIPDisp());
|
|
break;
|
|
case 0x42:
|
|
src = this.getEAShortData(this.regEDX + this.getIPDisp());
|
|
break;
|
|
case 0x43:
|
|
src = this.getEAShortData(this.regEBX + this.getIPDisp());
|
|
break;
|
|
case 0x44:
|
|
src = this.getEAShortData(X86.modSIB.call(this, 1) + this.getIPDisp());
|
|
break;
|
|
case 0x45:
|
|
src = this.getEAShortStack(this.regEBP + this.getIPDisp());
|
|
break;
|
|
case 0x46:
|
|
src = this.getEAShortData(this.regESI + this.getIPDisp());
|
|
break;
|
|
case 0x47:
|
|
src = this.getEAShortData(this.regEDI + this.getIPDisp());
|
|
break;
|
|
case 0x80:
|
|
src = this.getEAShortData(this.regEAX + this.getIPAddr());
|
|
break;
|
|
case 0x81:
|
|
src = this.getEAShortData(this.regECX + this.getIPAddr());
|
|
break;
|
|
case 0x82:
|
|
src = this.getEAShortData(this.regEDX + this.getIPAddr());
|
|
break;
|
|
case 0x83:
|
|
src = this.getEAShortData(this.regEBX + this.getIPAddr());
|
|
break;
|
|
case 0x84:
|
|
src = this.getEAShortData(X86.modSIB.call(this, 2) + this.getIPAddr());
|
|
break;
|
|
case 0x85:
|
|
src = this.getEAShortStack(this.regEBP + this.getIPAddr());
|
|
break;
|
|
case 0x86:
|
|
src = this.getEAShortData(this.regESI + this.getIPAddr());
|
|
break;
|
|
case 0x87:
|
|
src = this.getEAShortData(this.regEDI + this.getIPAddr());
|
|
break;
|
|
case 0xC0:
|
|
src = this.regEAX & 0xffff;
|
|
if (BACKTRACK) {
|
|
this.backTrack.btiEALo = this.backTrack.btiAL; this.backTrack.btiEAHi = this.backTrack.btiAH;
|
|
}
|
|
break;
|
|
case 0xC1:
|
|
src = this.regECX & 0xffff;
|
|
if (BACKTRACK) {
|
|
this.backTrack.btiEALo = this.backTrack.btiCL; this.backTrack.btiEAHi = this.backTrack.btiCH;
|
|
}
|
|
break;
|
|
case 0xC2:
|
|
src = this.regEDX & 0xffff;
|
|
if (BACKTRACK) {
|
|
this.backTrack.btiEALo = this.backTrack.btiDL; this.backTrack.btiEAHi = this.backTrack.btiDH;
|
|
}
|
|
break;
|
|
case 0xC3:
|
|
src = this.regEBX & 0xffff;
|
|
if (BACKTRACK) {
|
|
this.backTrack.btiEALo = this.backTrack.btiBL; this.backTrack.btiEAHi = this.backTrack.btiBH;
|
|
}
|
|
break;
|
|
case 0xC4:
|
|
src = this.getSP() & 0xffff;
|
|
if (BACKTRACK) {
|
|
this.backTrack.btiEALo = X86.BTINFO.SP_LO; this.backTrack.btiEAHi = X86.BTINFO.SP_HI;
|
|
}
|
|
break;
|
|
case 0xC5:
|
|
src = this.regEBP & 0xffff;
|
|
if (BACKTRACK) {
|
|
this.backTrack.btiEALo = this.backTrack.btiBPLo; this.backTrack.btiEAHi = this.backTrack.btiBPHi;
|
|
}
|
|
break;
|
|
case 0xC6:
|
|
src = this.regESI & 0xffff;
|
|
if (BACKTRACK) {
|
|
this.backTrack.btiEALo = this.backTrack.btiSILo; this.backTrack.btiEAHi = this.backTrack.btiSIHi;
|
|
}
|
|
break;
|
|
case 0xC7:
|
|
src = this.regEDI & 0xffff;
|
|
if (BACKTRACK) {
|
|
this.backTrack.btiEALo = this.backTrack.btiDILo; this.backTrack.btiEAHi = this.backTrack.btiDIHi;
|
|
}
|
|
break;
|
|
default:
|
|
src = 0;
|
|
this.assert(false, "modRegShort32(): unrecognized modrm byte " + str.toHexByte(bModRM));
|
|
break;
|
|
}
|
|
|
|
var reg = (this.bModRM >> 3) & 0x7;
|
|
|
|
switch(reg) {
|
|
case 0x0:
|
|
dst = this.regEAX & 0xffff;
|
|
break;
|
|
case 0x1:
|
|
dst = this.regECX & 0xffff;
|
|
break;
|
|
case 0x2:
|
|
dst = this.regEDX & 0xffff;
|
|
break;
|
|
case 0x3:
|
|
dst = this.regEBX & 0xffff;
|
|
break;
|
|
case 0x4:
|
|
dst = this.getSP() & 0xffff;
|
|
break;
|
|
case 0x5:
|
|
dst = this.regEBP & 0xffff;
|
|
break;
|
|
case 0x6:
|
|
dst = this.regESI & 0xffff;
|
|
break;
|
|
case 0x7:
|
|
dst = this.regEDI & 0xffff;
|
|
break;
|
|
default:
|
|
dst = 0;
|
|
break;
|
|
}
|
|
|
|
var w = fn.call(this, dst, src);
|
|
|
|
switch(reg) {
|
|
case 0x0:
|
|
this.regEAX = (this.regEAX & ~0xffff) | w;
|
|
if (BACKTRACK) {
|
|
this.backTrack.btiAL = this.backTrack.btiEALo; this.backTrack.btiAH = this.backTrack.btiEAHi;
|
|
}
|
|
break;
|
|
case 0x1:
|
|
this.regECX = (this.regECX & ~0xffff) | w;
|
|
if (BACKTRACK) {
|
|
this.backTrack.btiCL = this.backTrack.btiEALo; this.backTrack.btiCH = this.backTrack.btiEAHi;
|
|
}
|
|
break;
|
|
case 0x2:
|
|
this.regEDX = (this.regEDX & ~0xffff) | w;
|
|
if (BACKTRACK) {
|
|
this.backTrack.btiDL = this.backTrack.btiEALo; this.backTrack.btiDH = this.backTrack.btiEAHi;
|
|
}
|
|
break;
|
|
case 0x3:
|
|
this.regEBX = (this.regEBX & ~0xffff) | w;
|
|
if (BACKTRACK) {
|
|
this.backTrack.btiBL = this.backTrack.btiEALo; this.backTrack.btiBH = this.backTrack.btiEAHi;
|
|
}
|
|
break;
|
|
case 0x4:
|
|
this.setSP((this.getSP() & ~0xffff) | w);
|
|
break;
|
|
case 0x5:
|
|
this.regEBP = (this.regEBP & ~0xffff) | w;
|
|
if (BACKTRACK) {
|
|
this.backTrack.btiBPLo = this.backTrack.btiEALo; this.backTrack.btiBPHi = this.backTrack.btiEAHi;
|
|
}
|
|
break;
|
|
case 0x6:
|
|
this.regESI = (this.regESI & ~0xffff) | w;
|
|
if (BACKTRACK) {
|
|
this.backTrack.btiSILo = this.backTrack.btiEALo; this.backTrack.btiSIHi = this.backTrack.btiEAHi;
|
|
}
|
|
break;
|
|
case 0x7:
|
|
this.regEDI = (this.regEDI & ~0xffff) | w;
|
|
if (BACKTRACK) {
|
|
this.backTrack.btiDILo = this.backTrack.btiEALo; this.backTrack.btiDIHi = this.backTrack.btiEAHi;
|
|
}
|
|
break;
|
|
}
|
|
};
|
|
|
|
/**
|
|
* modMemShort32(fn)
|
|
*
|
|
* @this {X86CPU}
|
|
* @param {function(number,number)} fn (dst,src)
|
|
*/
|
|
X86.modMemShort32 = function(fn)
|
|
{
|
|
var dst, src;
|
|
var bModRM = (this.bModRM = this.getIPByte()) & 0xC7;
|
|
|
|
switch(bModRM) {
|
|
case 0x00:
|
|
dst = this.getEAShortData(this.regEAX);
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x01:
|
|
dst = this.getEAShortData(this.regECX);
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x02:
|
|
dst = this.getEAShortData(this.regEDX);
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x03:
|
|
dst = this.getEAShortData(this.regEBX);
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x04:
|
|
dst = this.getEAShortData(X86.modSIB.call(this, 0));
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x05:
|
|
dst = this.getEAShortData(this.getIPAddr());
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x06:
|
|
dst = this.getEAShortData(this.regESI);
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x07:
|
|
dst = this.getEAShortData(this.regEDI);
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x40:
|
|
dst = this.getEAShortData(this.regEAX + this.getIPDisp());
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x41:
|
|
dst = this.getEAShortData(this.regECX + this.getIPDisp());
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x42:
|
|
dst = this.getEAShortData(this.regEDX + this.getIPDisp());
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x43:
|
|
dst = this.getEAShortData(this.regEBX + this.getIPDisp());
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x44:
|
|
dst = this.getEAShortData(X86.modSIB.call(this, 1) + this.getIPDisp());
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x45:
|
|
dst = this.getEAShortStack(this.regEBP + this.getIPDisp());
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x46:
|
|
dst = this.getEAShortData(this.regESI + this.getIPDisp());
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x47:
|
|
dst = this.getEAShortData(this.regEDI + this.getIPDisp());
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x80:
|
|
dst = this.getEAShortData(this.regEAX + this.getIPAddr());
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x81:
|
|
dst = this.getEAShortData(this.regECX + this.getIPAddr());
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x82:
|
|
dst = this.getEAShortData(this.regEDX + this.getIPAddr());
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x83:
|
|
dst = this.getEAShortData(this.regEBX + this.getIPAddr());
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x84:
|
|
dst = this.getEAShortData(X86.modSIB.call(this, 2) + this.getIPAddr());
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x85:
|
|
dst = this.getEAShortStack(this.regEBP + this.getIPAddr());
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x86:
|
|
dst = this.getEAShortData(this.regESI + this.getIPAddr());
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x87:
|
|
dst = this.getEAShortData(this.regEDI + this.getIPAddr());
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0xC0:
|
|
dst = this.regEAX & 0xffff;
|
|
break;
|
|
case 0xC1:
|
|
dst = this.regECX & 0xffff;
|
|
break;
|
|
case 0xC2:
|
|
dst = this.regEDX & 0xffff;
|
|
break;
|
|
case 0xC3:
|
|
dst = this.regEBX & 0xffff;
|
|
break;
|
|
case 0xC4:
|
|
dst = this.getSP() & 0xffff;
|
|
break;
|
|
case 0xC5:
|
|
dst = this.regEBP & 0xffff;
|
|
break;
|
|
case 0xC6:
|
|
dst = this.regESI & 0xffff;
|
|
break;
|
|
case 0xC7:
|
|
dst = this.regEDI & 0xffff;
|
|
break;
|
|
default:
|
|
dst = 0;
|
|
this.assert(false, "modMemShort32(): unrecognized modrm byte " + str.toHexByte(bModRM));
|
|
break;
|
|
}
|
|
|
|
var reg = (this.bModRM >> 3) & 0x7;
|
|
|
|
switch(reg) {
|
|
case 0x0:
|
|
src = this.regEAX & 0xffff;
|
|
if (BACKTRACK) {
|
|
this.backTrack.btiEALo = this.backTrack.btiAL; this.backTrack.btiEAHi = this.backTrack.btiAH;
|
|
}
|
|
break;
|
|
case 0x1:
|
|
src = this.regECX & 0xffff;
|
|
if (BACKTRACK) {
|
|
this.backTrack.btiEALo = this.backTrack.btiCL; this.backTrack.btiEAHi = this.backTrack.btiCH;
|
|
}
|
|
break;
|
|
case 0x2:
|
|
src = this.regEDX & 0xffff;
|
|
if (BACKTRACK) {
|
|
this.backTrack.btiEALo = this.backTrack.btiDL; this.backTrack.btiEAHi = this.backTrack.btiDH;
|
|
}
|
|
break;
|
|
case 0x3:
|
|
src = this.regEBX & 0xffff;
|
|
if (BACKTRACK) {
|
|
this.backTrack.btiEALo = this.backTrack.btiBL; this.backTrack.btiEAHi = this.backTrack.btiBH;
|
|
}
|
|
break;
|
|
case 0x4:
|
|
src = this.getSP() & 0xffff;
|
|
if (BACKTRACK) {
|
|
this.backTrack.btiEALo = X86.BTINFO.SP_LO; this.backTrack.btiEAHi = X86.BTINFO.SP_HI;
|
|
}
|
|
break;
|
|
case 0x5:
|
|
src = this.regEBP & 0xffff;
|
|
if (BACKTRACK) {
|
|
this.backTrack.btiEALo = this.backTrack.btiBPLo; this.backTrack.btiEAHi = this.backTrack.btiBPHi;
|
|
}
|
|
break;
|
|
case 0x6:
|
|
src = this.regESI & 0xffff;
|
|
if (BACKTRACK) {
|
|
this.backTrack.btiEALo = this.backTrack.btiSILo; this.backTrack.btiEAHi = this.backTrack.btiSIHi;
|
|
}
|
|
break;
|
|
case 0x7:
|
|
src = this.regEDI & 0xffff;
|
|
if (BACKTRACK) {
|
|
this.backTrack.btiEALo = this.backTrack.btiDILo; this.backTrack.btiEAHi = this.backTrack.btiDIHi;
|
|
}
|
|
break;
|
|
default:
|
|
src = 0;
|
|
break;
|
|
}
|
|
|
|
var w = fn.call(this, dst, src);
|
|
|
|
switch(bModRM) {
|
|
case 0xC0:
|
|
this.regEAX = (this.regEAX & ~0xffff) | w;
|
|
if (BACKTRACK) {
|
|
this.backTrack.btiAL = this.backTrack.btiEALo; this.backTrack.btiAH = this.backTrack.btiEAHi;
|
|
}
|
|
break;
|
|
case 0xC1:
|
|
this.regECX = (this.regECX & ~0xffff) | w;
|
|
if (BACKTRACK) {
|
|
this.backTrack.btiCL = this.backTrack.btiEALo; this.backTrack.btiCH = this.backTrack.btiEAHi;
|
|
}
|
|
break;
|
|
case 0xC2:
|
|
this.regEDX = (this.regEDX & ~0xffff) | w;
|
|
if (BACKTRACK) {
|
|
this.backTrack.btiDL = this.backTrack.btiEALo; this.backTrack.btiDH = this.backTrack.btiEAHi;
|
|
}
|
|
break;
|
|
case 0xC3:
|
|
this.regEBX = (this.regEBX & ~0xffff) | w;
|
|
if (BACKTRACK) {
|
|
this.backTrack.btiBL = this.backTrack.btiEALo; this.backTrack.btiBH = this.backTrack.btiEAHi;
|
|
}
|
|
break;
|
|
case 0xC4:
|
|
this.setSP((this.getSP() & ~0xffff) | w);
|
|
break;
|
|
case 0xC5:
|
|
this.regEBP = (this.regEBP & ~0xffff) | w;
|
|
if (BACKTRACK) {
|
|
this.backTrack.btiBPLo = this.backTrack.btiEALo; this.backTrack.btiBPHi = this.backTrack.btiEAHi;
|
|
}
|
|
break;
|
|
case 0xC6:
|
|
this.regESI = (this.regESI & ~0xffff) | w;
|
|
if (BACKTRACK) {
|
|
this.backTrack.btiSILo = this.backTrack.btiEALo; this.backTrack.btiSIHi = this.backTrack.btiEAHi;
|
|
}
|
|
break;
|
|
case 0xC7:
|
|
this.regEDI = (this.regEDI & ~0xffff) | w;
|
|
if (BACKTRACK) {
|
|
this.backTrack.btiDILo = this.backTrack.btiEALo; this.backTrack.btiDIHi = this.backTrack.btiEAHi;
|
|
}
|
|
break;
|
|
default:
|
|
this.setEAShort(w);
|
|
break;
|
|
}
|
|
};
|
|
|
|
/**
|
|
* modGrpShort32(afnGrp, fnSrc)
|
|
*
|
|
* @this {X86CPU}
|
|
* @param {Array.<function(number,number)>} afnGrp
|
|
* @param {function()} fnSrc
|
|
*/
|
|
X86.modGrpShort32 = function(afnGrp, fnSrc) {
|
|
var dst;
|
|
var bModRM = (this.bModRM = this.getIPByte()) & 0xC7;
|
|
|
|
switch(bModRM) {
|
|
case 0x00:
|
|
dst = this.getEAShortData(this.regEAX);
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x01:
|
|
dst = this.getEAShortData(this.regECX);
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x02:
|
|
dst = this.getEAShortData(this.regEDX);
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x03:
|
|
dst = this.getEAShortData(this.regEBX);
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x04:
|
|
dst = this.getEAShortData(X86.modSIB.call(this, 0));
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x05:
|
|
dst = this.getEAShortData(this.getIPAddr());
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x06:
|
|
dst = this.getEAShortData(this.regESI);
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x07:
|
|
dst = this.getEAShortData(this.regEDI);
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x40:
|
|
dst = this.getEAShortData(this.regEAX + this.getIPDisp());
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x41:
|
|
dst = this.getEAShortData(this.regECX + this.getIPDisp());
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x42:
|
|
dst = this.getEAShortData(this.regEDX + this.getIPDisp());
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x43:
|
|
dst = this.getEAShortData(this.regEBX + this.getIPDisp());
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x44:
|
|
dst = this.getEAShortData(X86.modSIB.call(this, 1) + this.getIPDisp());
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x45:
|
|
dst = this.getEAShortStack(this.regEBP + this.getIPDisp());
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x46:
|
|
dst = this.getEAShortData(this.regESI + this.getIPDisp());
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x47:
|
|
dst = this.getEAShortData(this.regEDI + this.getIPDisp());
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x80:
|
|
dst = this.getEAShortData(this.regEAX + this.getIPAddr());
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x81:
|
|
dst = this.getEAShortData(this.regECX + this.getIPAddr());
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x82:
|
|
dst = this.getEAShortData(this.regEDX + this.getIPAddr());
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x83:
|
|
dst = this.getEAShortData(this.regEBX + this.getIPAddr());
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x84:
|
|
dst = this.getEAShortData(X86.modSIB.call(this, 2) + this.getIPAddr());
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x85:
|
|
dst = this.getEAShortStack(this.regEBP + this.getIPAddr());
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x86:
|
|
dst = this.getEAShortData(this.regESI + this.getIPAddr());
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x87:
|
|
dst = this.getEAShortData(this.regEDI + this.getIPAddr());
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0xC0:
|
|
dst = this.regEAX & 0xffff;
|
|
break;
|
|
case 0xC1:
|
|
dst = this.regECX & 0xffff;
|
|
break;
|
|
case 0xC2:
|
|
dst = this.regEDX & 0xffff;
|
|
break;
|
|
case 0xC3:
|
|
dst = this.regEBX & 0xffff;
|
|
break;
|
|
case 0xC4:
|
|
dst = this.getSP() & 0xffff;
|
|
break;
|
|
case 0xC5:
|
|
dst = this.regEBP & 0xffff;
|
|
break;
|
|
case 0xC6:
|
|
dst = this.regESI & 0xffff;
|
|
break;
|
|
case 0xC7:
|
|
dst = this.regEDI & 0xffff;
|
|
break;
|
|
default:
|
|
dst = 0;
|
|
this.assert(false, "modGrpShort32(): unrecognized modrm byte " + str.toHexByte(bModRM));
|
|
break;
|
|
}
|
|
|
|
var reg = (this.bModRM >> 3) & 0x7;
|
|
|
|
var w = afnGrp[reg].call(this, dst, fnSrc.call(this));
|
|
|
|
switch(bModRM) {
|
|
case 0xC0:
|
|
this.regEAX = (this.regEAX & ~0xffff) | w;
|
|
break;
|
|
case 0xC1:
|
|
this.regECX = (this.regECX & ~0xffff) | w;
|
|
break;
|
|
case 0xC2:
|
|
this.regEDX = (this.regEDX & ~0xffff) | w;
|
|
break;
|
|
case 0xC3:
|
|
this.regEBX = (this.regEBX & ~0xffff) | w;
|
|
break;
|
|
case 0xC4:
|
|
this.setSP((this.getSP() & ~0xffff) | w);
|
|
break;
|
|
case 0xC5:
|
|
this.regEBP = (this.regEBP & ~0xffff) | w;
|
|
break;
|
|
case 0xC6:
|
|
this.regESI = (this.regESI & ~0xffff) | w;
|
|
break;
|
|
case 0xC7:
|
|
this.regEDI = (this.regEDI & ~0xffff) | w;
|
|
break;
|
|
default:
|
|
this.setEAShort(w);
|
|
break;
|
|
}
|
|
};
|
|
|
|
/**
|
|
* modRegLong32(fn)
|
|
*
|
|
* @this {X86CPU}
|
|
* @param {function(number,number)} fn (dst,src)
|
|
*/
|
|
X86.modRegLong32 = function(fn)
|
|
{
|
|
var dst, src;
|
|
var bModRM = (this.bModRM = this.getIPByte()) & 0xC7;
|
|
|
|
switch(bModRM) {
|
|
case 0x00:
|
|
src = this.getEALongData(this.regEAX);
|
|
break;
|
|
case 0x01:
|
|
src = this.getEALongData(this.regECX);
|
|
break;
|
|
case 0x02:
|
|
src = this.getEALongData(this.regEDX);
|
|
break;
|
|
case 0x03:
|
|
src = this.getEALongData(this.regEBX);
|
|
break;
|
|
case 0x04:
|
|
src = this.getEALongData(X86.modSIB.call(this, 0));
|
|
break;
|
|
case 0x05:
|
|
src = this.getEALongData(this.getIPAddr());
|
|
break;
|
|
case 0x06:
|
|
src = this.getEALongData(this.regESI);
|
|
break;
|
|
case 0x07:
|
|
src = this.getEALongData(this.regEDI);
|
|
break;
|
|
case 0x40:
|
|
src = this.getEALongData(this.regEAX + this.getIPDisp());
|
|
break;
|
|
case 0x41:
|
|
src = this.getEALongData(this.regECX + this.getIPDisp());
|
|
break;
|
|
case 0x42:
|
|
src = this.getEALongData(this.regEDX + this.getIPDisp());
|
|
break;
|
|
case 0x43:
|
|
src = this.getEALongData(this.regEBX + this.getIPDisp());
|
|
break;
|
|
case 0x44:
|
|
src = this.getEALongData(X86.modSIB.call(this, 1) + this.getIPDisp());
|
|
break;
|
|
case 0x45:
|
|
src = this.getEALongStack(this.regEBP + this.getIPDisp());
|
|
break;
|
|
case 0x46:
|
|
src = this.getEALongData(this.regESI + this.getIPDisp());
|
|
break;
|
|
case 0x47:
|
|
src = this.getEALongData(this.regEDI + this.getIPDisp());
|
|
break;
|
|
case 0x80:
|
|
src = this.getEALongData(this.regEAX + this.getIPAddr());
|
|
break;
|
|
case 0x81:
|
|
src = this.getEALongData(this.regECX + this.getIPAddr());
|
|
break;
|
|
case 0x82:
|
|
src = this.getEALongData(this.regEDX + this.getIPAddr());
|
|
break;
|
|
case 0x83:
|
|
src = this.getEALongData(this.regEBX + this.getIPAddr());
|
|
break;
|
|
case 0x84:
|
|
src = this.getEALongData(X86.modSIB.call(this, 2) + this.getIPAddr());
|
|
break;
|
|
case 0x85:
|
|
src = this.getEALongStack(this.regEBP + this.getIPAddr());
|
|
break;
|
|
case 0x86:
|
|
src = this.getEALongData(this.regESI + this.getIPAddr());
|
|
break;
|
|
case 0x87:
|
|
src = this.getEALongData(this.regEDI + this.getIPAddr());
|
|
break;
|
|
case 0xC0:
|
|
src = this.regEAX;
|
|
if (BACKTRACK) {
|
|
this.backTrack.btiEALo = this.backTrack.btiAL; this.backTrack.btiEAHi = this.backTrack.btiAH;
|
|
}
|
|
break;
|
|
case 0xC1:
|
|
src = this.regECX;
|
|
if (BACKTRACK) {
|
|
this.backTrack.btiEALo = this.backTrack.btiCL; this.backTrack.btiEAHi = this.backTrack.btiCH;
|
|
}
|
|
break;
|
|
case 0xC2:
|
|
src = this.regEDX;
|
|
if (BACKTRACK) {
|
|
this.backTrack.btiEALo = this.backTrack.btiDL; this.backTrack.btiEAHi = this.backTrack.btiDH;
|
|
}
|
|
break;
|
|
case 0xC3:
|
|
src = this.regEBX;
|
|
if (BACKTRACK) {
|
|
this.backTrack.btiEALo = this.backTrack.btiBL; this.backTrack.btiEAHi = this.backTrack.btiBH;
|
|
}
|
|
break;
|
|
case 0xC4:
|
|
src = this.getSP();
|
|
if (BACKTRACK) {
|
|
this.backTrack.btiEALo = X86.BTINFO.SP_LO; this.backTrack.btiEAHi = X86.BTINFO.SP_HI;
|
|
}
|
|
break;
|
|
case 0xC5:
|
|
src = this.regEBP;
|
|
if (BACKTRACK) {
|
|
this.backTrack.btiEALo = this.backTrack.btiBPLo; this.backTrack.btiEAHi = this.backTrack.btiBPHi;
|
|
}
|
|
break;
|
|
case 0xC6:
|
|
src = this.regESI;
|
|
if (BACKTRACK) {
|
|
this.backTrack.btiEALo = this.backTrack.btiSILo; this.backTrack.btiEAHi = this.backTrack.btiSIHi;
|
|
}
|
|
break;
|
|
case 0xC7:
|
|
src = this.regEDI;
|
|
if (BACKTRACK) {
|
|
this.backTrack.btiEALo = this.backTrack.btiDILo; this.backTrack.btiEAHi = this.backTrack.btiDIHi;
|
|
}
|
|
break;
|
|
default:
|
|
src = 0;
|
|
this.assert(false, "modRegLong32(): unrecognized modrm byte " + str.toHexByte(bModRM));
|
|
break;
|
|
}
|
|
|
|
var reg = (this.bModRM >> 3) & 0x7;
|
|
|
|
switch(reg) {
|
|
case 0x0:
|
|
dst = this.regEAX;
|
|
break;
|
|
case 0x1:
|
|
dst = this.regECX;
|
|
break;
|
|
case 0x2:
|
|
dst = this.regEDX;
|
|
break;
|
|
case 0x3:
|
|
dst = this.regEBX;
|
|
break;
|
|
case 0x4:
|
|
dst = this.getSP();
|
|
break;
|
|
case 0x5:
|
|
dst = this.regEBP;
|
|
break;
|
|
case 0x6:
|
|
dst = this.regESI;
|
|
break;
|
|
case 0x7:
|
|
dst = this.regEDI;
|
|
break;
|
|
default:
|
|
dst = 0;
|
|
break;
|
|
}
|
|
|
|
var l = fn.call(this, dst, src);
|
|
|
|
switch(reg) {
|
|
case 0x0:
|
|
this.regEAX = l;
|
|
if (BACKTRACK) {
|
|
this.backTrack.btiAL = this.backTrack.btiEALo; this.backTrack.btiAH = this.backTrack.btiEAHi;
|
|
}
|
|
break;
|
|
case 0x1:
|
|
this.regECX = l;
|
|
if (BACKTRACK) {
|
|
this.backTrack.btiCL = this.backTrack.btiEALo; this.backTrack.btiCH = this.backTrack.btiEAHi;
|
|
}
|
|
break;
|
|
case 0x2:
|
|
this.regEDX = l;
|
|
if (BACKTRACK) {
|
|
this.backTrack.btiDL = this.backTrack.btiEALo; this.backTrack.btiDH = this.backTrack.btiEAHi;
|
|
}
|
|
break;
|
|
case 0x3:
|
|
this.regEBX = l;
|
|
if (BACKTRACK) {
|
|
this.backTrack.btiBL = this.backTrack.btiEALo; this.backTrack.btiBH = this.backTrack.btiEAHi;
|
|
}
|
|
break;
|
|
case 0x4:
|
|
this.setSP(l);
|
|
break;
|
|
case 0x5:
|
|
this.regEBP = l;
|
|
if (BACKTRACK) {
|
|
this.backTrack.btiBPLo = this.backTrack.btiEALo; this.backTrack.btiBPHi = this.backTrack.btiEAHi;
|
|
}
|
|
break;
|
|
case 0x6:
|
|
this.regESI = l;
|
|
if (BACKTRACK) {
|
|
this.backTrack.btiSILo = this.backTrack.btiEALo; this.backTrack.btiSIHi = this.backTrack.btiEAHi;
|
|
}
|
|
break;
|
|
case 0x7:
|
|
this.regEDI = l;
|
|
if (BACKTRACK) {
|
|
this.backTrack.btiDILo = this.backTrack.btiEALo; this.backTrack.btiDIHi = this.backTrack.btiEAHi;
|
|
}
|
|
break;
|
|
}
|
|
};
|
|
|
|
/**
|
|
* modMemLong32(fn)
|
|
*
|
|
* @this {X86CPU}
|
|
* @param {function(number,number)} fn (dst,src)
|
|
*/
|
|
X86.modMemLong32 = function(fn)
|
|
{
|
|
var dst, src;
|
|
var bModRM = (this.bModRM = this.getIPByte()) & 0xC7;
|
|
|
|
switch(bModRM) {
|
|
case 0x00:
|
|
dst = this.getEALongData(this.regEAX);
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x01:
|
|
dst = this.getEALongData(this.regECX);
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x02:
|
|
dst = this.getEALongData(this.regEDX);
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x03:
|
|
dst = this.getEALongData(this.regEBX);
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x04:
|
|
dst = this.getEALongData(X86.modSIB.call(this, 0));
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x05:
|
|
dst = this.getEALongData(this.getIPAddr());
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x06:
|
|
dst = this.getEALongData(this.regESI);
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x07:
|
|
dst = this.getEALongData(this.regEDI);
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x40:
|
|
dst = this.getEALongData(this.regEAX + this.getIPDisp());
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x41:
|
|
dst = this.getEALongData(this.regECX + this.getIPDisp());
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x42:
|
|
dst = this.getEALongData(this.regEDX + this.getIPDisp());
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x43:
|
|
dst = this.getEALongData(this.regEBX + this.getIPDisp());
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x44:
|
|
dst = this.getEALongData(X86.modSIB.call(this, 1) + this.getIPDisp());
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x45:
|
|
dst = this.getEALongStack(this.regEBP + this.getIPDisp());
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x46:
|
|
dst = this.getEALongData(this.regESI + this.getIPDisp());
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x47:
|
|
dst = this.getEALongData(this.regEDI + this.getIPDisp());
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x80:
|
|
dst = this.getEALongData(this.regEAX + this.getIPAddr());
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x81:
|
|
dst = this.getEALongData(this.regECX + this.getIPAddr());
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x82:
|
|
dst = this.getEALongData(this.regEDX + this.getIPAddr());
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x83:
|
|
dst = this.getEALongData(this.regEBX + this.getIPAddr());
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x84:
|
|
dst = this.getEALongData(X86.modSIB.call(this, 2) + this.getIPAddr());
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x85:
|
|
dst = this.getEALongStack(this.regEBP + this.getIPAddr());
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x86:
|
|
dst = this.getEALongData(this.regESI + this.getIPAddr());
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x87:
|
|
dst = this.getEALongData(this.regEDI + this.getIPAddr());
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0xC0:
|
|
dst = this.regEAX;
|
|
break;
|
|
case 0xC1:
|
|
dst = this.regECX;
|
|
break;
|
|
case 0xC2:
|
|
dst = this.regEDX;
|
|
break;
|
|
case 0xC3:
|
|
dst = this.regEBX;
|
|
break;
|
|
case 0xC4:
|
|
dst = this.getSP();
|
|
break;
|
|
case 0xC5:
|
|
dst = this.regEBP;
|
|
break;
|
|
case 0xC6:
|
|
dst = this.regESI;
|
|
break;
|
|
case 0xC7:
|
|
dst = this.regEDI;
|
|
break;
|
|
default:
|
|
dst = 0;
|
|
this.assert(false, "modMemLong32(): unrecognized modrm byte " + str.toHexByte(bModRM));
|
|
break;
|
|
}
|
|
|
|
var reg = (this.bModRM >> 3) & 0x7;
|
|
|
|
switch(reg) {
|
|
case 0x0:
|
|
src = this.regEAX;
|
|
if (BACKTRACK) {
|
|
this.backTrack.btiEALo = this.backTrack.btiAL; this.backTrack.btiEAHi = this.backTrack.btiAH;
|
|
}
|
|
break;
|
|
case 0x1:
|
|
src = this.regECX;
|
|
if (BACKTRACK) {
|
|
this.backTrack.btiEALo = this.backTrack.btiCL; this.backTrack.btiEAHi = this.backTrack.btiCH;
|
|
}
|
|
break;
|
|
case 0x2:
|
|
src = this.regEDX;
|
|
if (BACKTRACK) {
|
|
this.backTrack.btiEALo = this.backTrack.btiDL; this.backTrack.btiEAHi = this.backTrack.btiDH;
|
|
}
|
|
break;
|
|
case 0x3:
|
|
src = this.regEBX;
|
|
if (BACKTRACK) {
|
|
this.backTrack.btiEALo = this.backTrack.btiBL; this.backTrack.btiEAHi = this.backTrack.btiBH;
|
|
}
|
|
break;
|
|
case 0x4:
|
|
src = this.getSP();
|
|
if (BACKTRACK) {
|
|
this.backTrack.btiEALo = X86.BTINFO.SP_LO; this.backTrack.btiEAHi = X86.BTINFO.SP_HI;
|
|
}
|
|
break;
|
|
case 0x5:
|
|
src = this.regEBP;
|
|
if (BACKTRACK) {
|
|
this.backTrack.btiEALo = this.backTrack.btiBPLo; this.backTrack.btiEAHi = this.backTrack.btiBPHi;
|
|
}
|
|
break;
|
|
case 0x6:
|
|
src = this.regESI;
|
|
if (BACKTRACK) {
|
|
this.backTrack.btiEALo = this.backTrack.btiSILo; this.backTrack.btiEAHi = this.backTrack.btiSIHi;
|
|
}
|
|
break;
|
|
case 0x7:
|
|
src = this.regEDI;
|
|
if (BACKTRACK) {
|
|
this.backTrack.btiEALo = this.backTrack.btiDILo; this.backTrack.btiEAHi = this.backTrack.btiDIHi;
|
|
}
|
|
break;
|
|
default:
|
|
src = 0;
|
|
break;
|
|
}
|
|
|
|
var l = fn.call(this, dst, src);
|
|
|
|
switch(bModRM) {
|
|
case 0xC0:
|
|
this.regEAX = l;
|
|
if (BACKTRACK) {
|
|
this.backTrack.btiAL = this.backTrack.btiEALo; this.backTrack.btiAH = this.backTrack.btiEAHi;
|
|
}
|
|
break;
|
|
case 0xC1:
|
|
this.regECX = l;
|
|
if (BACKTRACK) {
|
|
this.backTrack.btiCL = this.backTrack.btiEALo; this.backTrack.btiCH = this.backTrack.btiEAHi;
|
|
}
|
|
break;
|
|
case 0xC2:
|
|
this.regEDX = l;
|
|
if (BACKTRACK) {
|
|
this.backTrack.btiDL = this.backTrack.btiEALo; this.backTrack.btiDH = this.backTrack.btiEAHi;
|
|
}
|
|
break;
|
|
case 0xC3:
|
|
this.regEBX = l;
|
|
if (BACKTRACK) {
|
|
this.backTrack.btiBL = this.backTrack.btiEALo; this.backTrack.btiBH = this.backTrack.btiEAHi;
|
|
}
|
|
break;
|
|
case 0xC4:
|
|
this.setSP(l);
|
|
break;
|
|
case 0xC5:
|
|
this.regEBP = l;
|
|
if (BACKTRACK) {
|
|
this.backTrack.btiBPLo = this.backTrack.btiEALo; this.backTrack.btiBPHi = this.backTrack.btiEAHi;
|
|
}
|
|
break;
|
|
case 0xC6:
|
|
this.regESI = l;
|
|
if (BACKTRACK) {
|
|
this.backTrack.btiSILo = this.backTrack.btiEALo; this.backTrack.btiSIHi = this.backTrack.btiEAHi;
|
|
}
|
|
break;
|
|
case 0xC7:
|
|
this.regEDI = l;
|
|
if (BACKTRACK) {
|
|
this.backTrack.btiDILo = this.backTrack.btiEALo; this.backTrack.btiDIHi = this.backTrack.btiEAHi;
|
|
}
|
|
break;
|
|
default:
|
|
this.setEALong(l);
|
|
break;
|
|
}
|
|
};
|
|
|
|
/**
|
|
* modGrpLong32(afnGrp, fnSrc)
|
|
*
|
|
* @this {X86CPU}
|
|
* @param {Array.<function(number,number)>} afnGrp
|
|
* @param {function()} fnSrc
|
|
*/
|
|
X86.modGrpLong32 = function(afnGrp, fnSrc) {
|
|
var dst;
|
|
var bModRM = (this.bModRM = this.getIPByte()) & 0xC7;
|
|
|
|
switch(bModRM) {
|
|
case 0x00:
|
|
dst = this.getEALongData(this.regEAX);
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x01:
|
|
dst = this.getEALongData(this.regECX);
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x02:
|
|
dst = this.getEALongData(this.regEDX);
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x03:
|
|
dst = this.getEALongData(this.regEBX);
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x04:
|
|
dst = this.getEALongData(X86.modSIB.call(this, 0));
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x05:
|
|
dst = this.getEALongData(this.getIPAddr());
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x06:
|
|
dst = this.getEALongData(this.regESI);
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x07:
|
|
dst = this.getEALongData(this.regEDI);
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x40:
|
|
dst = this.getEALongData(this.regEAX + this.getIPDisp());
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x41:
|
|
dst = this.getEALongData(this.regECX + this.getIPDisp());
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x42:
|
|
dst = this.getEALongData(this.regEDX + this.getIPDisp());
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x43:
|
|
dst = this.getEALongData(this.regEBX + this.getIPDisp());
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x44:
|
|
dst = this.getEALongData(X86.modSIB.call(this, 1) + this.getIPDisp());
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x45:
|
|
dst = this.getEALongStack(this.regEBP + this.getIPDisp());
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x46:
|
|
dst = this.getEALongData(this.regESI + this.getIPDisp());
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x47:
|
|
dst = this.getEALongData(this.regEDI + this.getIPDisp());
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x80:
|
|
dst = this.getEALongData(this.regEAX + this.getIPAddr());
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x81:
|
|
dst = this.getEALongData(this.regECX + this.getIPAddr());
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x82:
|
|
dst = this.getEALongData(this.regEDX + this.getIPAddr());
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x83:
|
|
dst = this.getEALongData(this.regEBX + this.getIPAddr());
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x84:
|
|
dst = this.getEALongData(X86.modSIB.call(this, 2) + this.getIPAddr());
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x85:
|
|
dst = this.getEALongStack(this.regEBP + this.getIPAddr());
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x86:
|
|
dst = this.getEALongData(this.regESI + this.getIPAddr());
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0x87:
|
|
dst = this.getEALongData(this.regEDI + this.getIPAddr());
|
|
this.regEAWrite = this.regEA;
|
|
break;
|
|
case 0xC0:
|
|
dst = this.regEAX;
|
|
break;
|
|
case 0xC1:
|
|
dst = this.regECX;
|
|
break;
|
|
case 0xC2:
|
|
dst = this.regEDX;
|
|
break;
|
|
case 0xC3:
|
|
dst = this.regEBX;
|
|
break;
|
|
case 0xC4:
|
|
dst = this.getSP();
|
|
break;
|
|
case 0xC5:
|
|
dst = this.regEBP;
|
|
break;
|
|
case 0xC6:
|
|
dst = this.regESI;
|
|
break;
|
|
case 0xC7:
|
|
dst = this.regEDI;
|
|
break;
|
|
default:
|
|
dst = 0;
|
|
this.assert(false, "modGrpLong32(): unrecognized modrm byte " + str.toHexByte(bModRM));
|
|
break;
|
|
}
|
|
|
|
var reg = (this.bModRM >> 3) & 0x7;
|
|
|
|
var l = afnGrp[reg].call(this, dst, fnSrc.call(this));
|
|
|
|
switch(bModRM) {
|
|
case 0xC0:
|
|
this.regEAX = l;
|
|
break;
|
|
case 0xC1:
|
|
this.regECX = l;
|
|
break;
|
|
case 0xC2:
|
|
this.regEDX = l;
|
|
break;
|
|
case 0xC3:
|
|
this.regEBX = l;
|
|
break;
|
|
case 0xC4:
|
|
this.setSP(l);
|
|
break;
|
|
case 0xC5:
|
|
this.regEBP = l;
|
|
break;
|
|
case 0xC6:
|
|
this.regESI = l;
|
|
break;
|
|
case 0xC7:
|
|
this.regEDI = l;
|
|
break;
|
|
default:
|
|
this.setEALong(l);
|
|
break;
|
|
}
|
|
};
|
|
|
|
/**
|
|
* modSIB(mod)
|
|
*
|
|
* @this {X86CPU}
|
|
* @param {number} mod
|
|
* @return {number}
|
|
*/
|
|
X86.modSIB = function(mod)
|
|
{
|
|
var bSIB = this.getIPByte();
|
|
var scale = bSIB >> 6, index, base;
|
|
|
|
switch((bSIB >> 3) & 0x7) {
|
|
case 0:
|
|
index = this.regEAX;
|
|
break;
|
|
case 1:
|
|
index = this.regECX;
|
|
break;
|
|
case 2:
|
|
index = this.regEDX;
|
|
break;
|
|
case 3:
|
|
index = this.regEBX;
|
|
break;
|
|
case 4:
|
|
index = 0;
|
|
break;
|
|
case 5:
|
|
index = this.regEBP;
|
|
break;
|
|
case 6:
|
|
index = this.regESI;
|
|
break;
|
|
case 7:
|
|
index = this.regEDI;
|
|
break;
|
|
}
|
|
|
|
switch(bSIB & 0x07) {
|
|
case 0:
|
|
base = this.regEAX;
|
|
break;
|
|
case 1:
|
|
base = this.regECX;
|
|
break;
|
|
case 2:
|
|
base = this.regEDX;
|
|
break;
|
|
case 3:
|
|
base = this.regEBX;
|
|
break;
|
|
case 4:
|
|
base = this.getSP();
|
|
this.segData = this.segStack;
|
|
break;
|
|
case 5:
|
|
if (mod) {
|
|
base = this.regEBP;
|
|
this.segData = this.segStack;
|
|
} else {
|
|
base = this.getIPAddr();
|
|
}
|
|
break;
|
|
case 6:
|
|
base = this.regESI;
|
|
break;
|
|
case 7:
|
|
base = this.regEDI;
|
|
break;
|
|
}
|
|
|
|
return ((index << scale) + base)|0;
|
|
};
|