Improved prefix handling, preparation for faster emulation
This commit is contained in:
parent
b6056f8589
commit
b23b070a8d
17
src/const.js
17
src/const.js
|
@ -269,7 +269,7 @@ var
|
|||
SEG_PREFIX_NONE = -1,
|
||||
|
||||
/** @const */
|
||||
SEG_PREFIX_ZERO = 9;
|
||||
SEG_PREFIX_ZERO = 7;
|
||||
|
||||
|
||||
var
|
||||
|
@ -340,3 +340,18 @@ var TSC_RATE = 8 * 1024;
|
|||
/** @const */ var TSR_LDT = 0x60;
|
||||
|
||||
|
||||
|
||||
/** @const */
|
||||
var PREFIX_MASK_REP = 0b11000;
|
||||
/** @const */
|
||||
var PREFIX_REPZ = 0b01000;
|
||||
/** @const */
|
||||
var PREFIX_REPNZ = 0b10000;
|
||||
|
||||
/** @const */
|
||||
var PREFIX_MASK_SEGMENT = 0b111;
|
||||
|
||||
/** @const */
|
||||
var PREFIX_MASK_OPSIZE = 0b100000;
|
||||
/** @const */
|
||||
var PREFIX_MASK_ADDRSIZE = 0b1000000;
|
||||
|
|
300
src/cpu.js
300
src/cpu.js
|
@ -98,13 +98,8 @@ function CPU()
|
|||
/** @type {boolean} */
|
||||
this.is_32 = false;
|
||||
/** @type {boolean} */
|
||||
this.operand_size_32 = false;
|
||||
/** @type {boolean} */
|
||||
this.stack_size_32 = false;
|
||||
|
||||
/** @type {boolean} */
|
||||
this.address_size_32 = false;
|
||||
|
||||
/**
|
||||
* Was the last instruction a hlt?
|
||||
* @type {boolean}
|
||||
|
@ -145,9 +140,8 @@ function CPU()
|
|||
/** @type {number} */
|
||||
this.sysenter_eip = 0;
|
||||
|
||||
|
||||
/** @type {number} */
|
||||
this.repeat_string_prefix = REPEAT_STRING_PREFIX_NONE;
|
||||
this.prefixes = 0;
|
||||
|
||||
/** @type {number} */
|
||||
this.flags = 0;
|
||||
|
@ -189,13 +183,6 @@ function CPU()
|
|||
/** @type {number} */
|
||||
this.phys_addr_high = 0;
|
||||
|
||||
|
||||
// cpu.reg16 or cpu.reg32s, depending on address size attribute
|
||||
this.regv = this.reg16;
|
||||
this.reg_vcx = 0;
|
||||
this.reg_vsi = 0;
|
||||
this.reg_vdi = 0;
|
||||
|
||||
this.table = [];
|
||||
|
||||
// paging enabled
|
||||
|
@ -243,9 +230,6 @@ function CPU()
|
|||
// debug registers
|
||||
this.dreg = new Int32Array(8);
|
||||
|
||||
// current state of prefixes
|
||||
this.segment_prefix = SEG_PREFIX_NONE;
|
||||
|
||||
// dynamic instruction translator
|
||||
this.translator = undefined;
|
||||
|
||||
|
@ -255,13 +239,14 @@ function CPU()
|
|||
dbg_assert(this.table16 && this.table32);
|
||||
dbg_assert(this.table0F_16 && this.table0F_32);
|
||||
|
||||
this.update_address_size();
|
||||
this.update_operand_size();
|
||||
|
||||
this.tsc_offset = v86.microtick();
|
||||
|
||||
this.debug_init();
|
||||
|
||||
this.init2();
|
||||
|
||||
//Object.seal(this);
|
||||
}
|
||||
|
||||
|
@ -283,8 +268,7 @@ CPU.prototype.get_state = function()
|
|||
state[11] = this.cpl;
|
||||
state[12] = this.page_size_extensions;
|
||||
state[13] = this.is_32;
|
||||
state[14] = this.operand_size_32;
|
||||
state[15] = this.address_size_32;
|
||||
|
||||
state[16] = this.stack_size_32;
|
||||
state[17] = this.in_hlt;
|
||||
state[18] = this.last_virt_eip;
|
||||
|
@ -294,7 +278,7 @@ CPU.prototype.get_state = function()
|
|||
state[22] = this.sysenter_cs;
|
||||
state[23] = this.sysenter_eip;
|
||||
state[24] = this.sysenter_esp;
|
||||
state[25] = this.repeat_string_prefix;
|
||||
state[25] = this.prefixes;
|
||||
state[26] = this.flags;
|
||||
state[27] = this.flags_changed;
|
||||
state[28] = this.last_op1;
|
||||
|
@ -350,9 +334,9 @@ CPU.prototype.set_state = function(state)
|
|||
this.cpl = state[11];
|
||||
this.page_size_extensions = state[12];
|
||||
this.is_32 = state[13];
|
||||
this.operand_size_32 = state[14];
|
||||
this.address_size_32 = state[15];
|
||||
|
||||
this.stack_size_32 = state[16];
|
||||
|
||||
this.in_hlt = state[17];
|
||||
this.last_virt_eip = state[18];
|
||||
this.eip_phys = state[19];
|
||||
|
@ -361,7 +345,8 @@ CPU.prototype.set_state = function(state)
|
|||
this.sysenter_cs = state[22];
|
||||
this.sysenter_eip = state[23];
|
||||
this.sysenter_esp = state[24];
|
||||
this.repeat_string_prefix = state[25];
|
||||
this.prefixes = state[25];
|
||||
|
||||
this.flags = state[26];
|
||||
this.flags_changed = state[27];
|
||||
this.last_op1 = state[28];
|
||||
|
@ -411,7 +396,6 @@ CPU.prototype.set_state = function(state)
|
|||
this.reg8s = new Int8Array(this.reg32s.buffer);
|
||||
this.reg8 = new Uint8Array(this.reg32s.buffer);
|
||||
|
||||
this.update_address_size();
|
||||
this.update_operand_size();
|
||||
};
|
||||
|
||||
|
@ -440,6 +424,7 @@ CPU.prototype.main_run = function()
|
|||
}
|
||||
|
||||
this.do_run();
|
||||
|
||||
return 0;
|
||||
};
|
||||
|
||||
|
@ -464,7 +449,7 @@ CPU.prototype.exception_cleanup = function(e)
|
|||
//Error.captureStackTrace && Error.captureStackTrace(e);
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
CPU.prototype.reboot_internal = function()
|
||||
{
|
||||
|
@ -513,14 +498,11 @@ CPU.prototype.reset = function()
|
|||
this.paging = false;
|
||||
this.page_size_extensions = 0;
|
||||
this.is_32 = false;
|
||||
this.operand_size_32 = false;
|
||||
this.stack_size_32 = false;
|
||||
this.address_size_32 = false;
|
||||
|
||||
this.paging_changed();
|
||||
|
||||
this.update_operand_size();
|
||||
this.update_address_size();
|
||||
|
||||
this.timestamp_counter = 0;
|
||||
this.previous_ip = 0;
|
||||
|
@ -530,8 +512,6 @@ CPU.prototype.reset = function()
|
|||
this.sysenter_esp = 0;
|
||||
this.sysenter_eip = 0;
|
||||
|
||||
this.segment_prefix = SEG_PREFIX_NONE;
|
||||
this.repeat_string_prefix = REPEAT_STRING_PREFIX_NONE;
|
||||
this.flags = flags_default;
|
||||
this.flags_changed = 0;
|
||||
|
||||
|
@ -573,9 +553,6 @@ CPU.prototype.create_memory = function(size)
|
|||
|
||||
this.memory_size = size;
|
||||
|
||||
// use by dynamic translator
|
||||
//if(OP_TRANSLATION) this.mem_page_infos = new Uint8Array(1 << 20);
|
||||
|
||||
var buffer = new ArrayBuffer(size);
|
||||
|
||||
this.mem8 = new Uint8Array(buffer);
|
||||
|
@ -585,15 +562,11 @@ CPU.prototype.create_memory = function(size)
|
|||
|
||||
CPU.prototype.init = function(settings, device_bus)
|
||||
{
|
||||
this.create_memory(settings.memory_size || 1024 * 1024 * 64);
|
||||
this.create_memory(typeof settings.memory_size === "number" ?
|
||||
settings.memory_size : 1024 * 1024 * 64);
|
||||
|
||||
this.reset();
|
||||
|
||||
if(OP_TRANSLATION)
|
||||
{
|
||||
this.translator = new DynamicTranslator(this);
|
||||
}
|
||||
|
||||
var io = new IO(this);
|
||||
this.io = io;
|
||||
|
||||
|
@ -830,7 +803,6 @@ CPU.prototype.do_run = function()
|
|||
|
||||
if(this.in_hlt)
|
||||
{
|
||||
this.hlt_loop();
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -857,7 +829,7 @@ CPU.prototype.do_many_cycles_unsafe = function()
|
|||
{
|
||||
this.cycle_internal();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Some functions must not be inlined, because then more code is in the
|
||||
// deoptimized try-catch block.
|
||||
|
@ -869,7 +841,7 @@ if(typeof window !== "undefined")
|
|||
CPU.prototype.do_many_cycles_unsafe,
|
||||
CPU.prototype.do_many_cycles,
|
||||
];
|
||||
};
|
||||
}
|
||||
|
||||
/** @const */
|
||||
var PROFILING = false;
|
||||
|
@ -887,7 +859,7 @@ if(PROFILING)
|
|||
total: instruction_total[i],
|
||||
count: instruction_count[i],
|
||||
per: (instruction_total[i] / instruction_count[i]) || 0,
|
||||
}
|
||||
};
|
||||
|
||||
console.log("count:");
|
||||
console.table(prof_instructions.sort((p0, p1) => p1.count - p0.count));
|
||||
|
@ -897,7 +869,7 @@ if(PROFILING)
|
|||
|
||||
console.log("time/count:");
|
||||
console.table(prof_instructions.sort((p0, p1) => p1.per - p0.per));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -953,9 +925,24 @@ CPU.prototype.cycle = function()
|
|||
}
|
||||
};
|
||||
|
||||
CPU.prototype.segment_prefix_op = function(sreg)
|
||||
{
|
||||
dbg_assert(sreg <= 5);
|
||||
this.prefixes |= sreg + 1;
|
||||
this.run_prefix_instruction();
|
||||
this.prefixes = 0;
|
||||
};
|
||||
|
||||
CPU.prototype.run_prefix_instruction = function()
|
||||
{
|
||||
this.table[this.read_imm8()](this);
|
||||
if(this.is_osize_32())
|
||||
{
|
||||
this.table32[this.read_imm8()](this);
|
||||
}
|
||||
else
|
||||
{
|
||||
this.table16[this.read_imm8()](this);
|
||||
}
|
||||
};
|
||||
|
||||
CPU.prototype.hlt_loop = function()
|
||||
|
@ -987,20 +974,7 @@ CPU.prototype.hlt_loop = function()
|
|||
|
||||
CPU.prototype.clear_prefixes = function()
|
||||
{
|
||||
this.repeat_string_prefix = REPEAT_STRING_PREFIX_NONE;
|
||||
this.segment_prefix = SEG_PREFIX_NONE;
|
||||
|
||||
if(this.address_size_32 !== this.is_32)
|
||||
{
|
||||
this.address_size_32 = this.is_32;
|
||||
this.update_address_size();
|
||||
}
|
||||
|
||||
if(this.operand_size_32 !== this.is_32)
|
||||
{
|
||||
this.operand_size_32 = this.is_32;
|
||||
this.update_operand_size();
|
||||
}
|
||||
this.prefixes = 0;
|
||||
};
|
||||
|
||||
CPU.prototype.cr0_changed = function(old_cr0)
|
||||
|
@ -1024,11 +998,6 @@ CPU.prototype.cr0_changed = function(old_cr0)
|
|||
this.paging = new_paging;
|
||||
this.full_clear_tlb();
|
||||
}
|
||||
|
||||
if(OP_TRANSLATION && (this.cr[0] ^ old_cr0) & 1)
|
||||
{
|
||||
this.translator.clear_cache();
|
||||
}
|
||||
};
|
||||
|
||||
CPU.prototype.paging_changed = function()
|
||||
|
@ -1097,17 +1066,36 @@ CPU.prototype.read_modrm_byte = function()
|
|||
this.modrm_byte = this.read_imm8();
|
||||
};
|
||||
|
||||
CPU.prototype.read_op0F = CPU.prototype.read_imm8;
|
||||
CPU.prototype.read_sib = CPU.prototype.read_imm8;
|
||||
CPU.prototype.read_op8 = CPU.prototype.read_imm8;
|
||||
CPU.prototype.read_op8s = CPU.prototype.read_imm8s;
|
||||
CPU.prototype.read_op16 = CPU.prototype.read_imm16;
|
||||
CPU.prototype.read_op32s = CPU.prototype.read_imm32s;
|
||||
CPU.prototype.read_second_op8 = CPU.prototype.read_imm8;
|
||||
CPU.prototype.read_second_op16 = CPU.prototype.read_imm16;
|
||||
CPU.prototype.read_disp8 = CPU.prototype.read_imm8;
|
||||
CPU.prototype.read_disp8s = CPU.prototype.read_imm8s;
|
||||
CPU.prototype.read_disp16 = CPU.prototype.read_imm16;
|
||||
CPU.prototype.read_disp32s = CPU.prototype.read_imm32s;
|
||||
|
||||
CPU.prototype.init2 = function () {};
|
||||
CPU.prototype.branch_taken = function () {};
|
||||
CPU.prototype.branch_not_taken = function () {};
|
||||
CPU.prototype.diverged = function () {};
|
||||
|
||||
CPU.prototype.modrm_resolve = function(modrm_byte)
|
||||
{
|
||||
dbg_assert(modrm_byte < 0xC0);
|
||||
|
||||
return (this.is_asize_32() ? this.modrm_table32 : this.modrm_table16)[modrm_byte](this);
|
||||
};
|
||||
|
||||
CPU.prototype.sib_resolve = function(mod)
|
||||
{
|
||||
return this.sib_table[this.read_sib()](this, mod);
|
||||
};
|
||||
|
||||
CPU.prototype.clear_instruction_cache = function() {};
|
||||
|
||||
// read word from a page boundary, given 2 physical addresses
|
||||
CPU.prototype.virt_boundary_read16 = function(low, high)
|
||||
{
|
||||
|
@ -1144,7 +1132,7 @@ CPU.prototype.virt_boundary_read32s = function(low, high)
|
|||
mid = this.virt_boundary_read16(low + 1 | 0, high - 1 | 0);
|
||||
}
|
||||
|
||||
return this.read8(low) | mid << 8 | this.read8(high) << 24;;
|
||||
return this.read8(low) | mid << 8 | this.read8(high) << 24;
|
||||
};
|
||||
|
||||
CPU.prototype.virt_boundary_write16 = function(low, high, value)
|
||||
|
@ -1247,7 +1235,8 @@ CPU.prototype.safe_write32 = function(addr, value)
|
|||
|
||||
if((addr & 0xFFF) >= 0xFFD)
|
||||
{
|
||||
this.virt_boundary_write32(phys_low, this.translate_address_write(addr + 3 | 0), value);
|
||||
// XXX
|
||||
this.virt_boundary_write32(phys_low, this.translate_address_write(addr + 3 & ~3) | (addr + 3) & 3, value);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1258,7 +1247,7 @@ CPU.prototype.safe_write32 = function(addr, value)
|
|||
// read 2 or 4 byte from ip, depending on address size attribute
|
||||
CPU.prototype.read_moffs = function()
|
||||
{
|
||||
if(this.address_size_32)
|
||||
if(this.is_asize_32())
|
||||
{
|
||||
return this.get_seg_prefix(reg_ds) + this.read_op32s() | 0;
|
||||
}
|
||||
|
@ -1392,7 +1381,7 @@ CPU.prototype.get_real_eip = function()
|
|||
CPU.prototype.call_interrupt_vector = function(interrupt_nr, is_software_int, error_code)
|
||||
{
|
||||
//dbg_log("int " + h(interrupt_nr, 2) + " (" + (is_software_int ? "soft" : "hard") + "ware)", LOG_CPU);
|
||||
CPU_LOG_VERBOSE && this.debug.dump_state("int start");
|
||||
CPU_LOG_VERBOSE && this.debug.dump_state("int " + h(interrupt_nr) + " start");
|
||||
//this.debug.dump_regs_short();
|
||||
|
||||
this.debug.debug_interrupt(interrupt_nr);
|
||||
|
@ -1730,9 +1719,16 @@ CPU.prototype.iret32 = function()
|
|||
CPU.prototype.iret = function(is_16)
|
||||
{
|
||||
//dbg_log("iret is_16=" + is_16, LOG_CPU);
|
||||
CPU_LOG_VERBOSE && this.debug.dump_state("iret start");
|
||||
CPU_LOG_VERBOSE && this.debug.dump_state("iret" + (is_16 ? "16" : "32") + " start");
|
||||
//this.debug.dump_regs_short();
|
||||
|
||||
if(this.vm86_mode() && this.getiopl() < 3)
|
||||
{
|
||||
// vm86 mode, iopl != 3
|
||||
dbg_log("#gp iret vm86 mode, iopl != 3", LOG_CPU);
|
||||
this.trigger_gp(0);
|
||||
}
|
||||
|
||||
if(is_16)
|
||||
{
|
||||
var new_eip = this.safe_read16(this.get_stack_pointer(0));
|
||||
|
@ -1774,12 +1770,7 @@ CPU.prototype.iret = function(is_16)
|
|||
return;
|
||||
}
|
||||
|
||||
if(this.vm86_mode())
|
||||
{
|
||||
// vm86 mode, iopl != 3
|
||||
dbg_log("#gp iret vm86 mode, iopl != 3", LOG_CPU)
|
||||
this.trigger_gp(0);
|
||||
}
|
||||
dbg_assert(!this.vm86_mode());
|
||||
|
||||
if(this.flags & flag_nt)
|
||||
{
|
||||
|
@ -1912,7 +1903,6 @@ CPU.prototype.iret = function(is_16)
|
|||
ss_info.dpl !== new_cpl)
|
||||
{
|
||||
dbg_log("#GP for loading invalid in SS sel=" + h(temp_ss, 4), LOG_CPU);
|
||||
debugger;
|
||||
dbg_trace(LOG_CPU);
|
||||
this.trigger_gp(temp_ss & ~3);
|
||||
}
|
||||
|
@ -1996,8 +1986,7 @@ CPU.prototype.iret = function(is_16)
|
|||
|
||||
this.instruction_pointer = new_eip + this.get_seg(reg_cs) | 0;
|
||||
|
||||
//dbg_log("iret is_16=" + is_16 + " to:", LOG_CPU);
|
||||
CPU_LOG_VERBOSE && this.debug.dump_state("iret end");
|
||||
CPU_LOG_VERBOSE && this.debug.dump_state("iret" + (is_16 ? "16" : "32") + " end");
|
||||
|
||||
this.handle_irqs();
|
||||
};
|
||||
|
@ -2030,7 +2019,7 @@ CPU.prototype.far_return = function(eip, selector, stack_adjust)
|
|||
{
|
||||
this.switch_cs_real_mode(selector);
|
||||
this.instruction_pointer = this.get_seg(reg_cs) + eip | 0;
|
||||
this.adjust_stack_reg(2 * (this.operand_size_32 ? 4 : 2) + stack_adjust);
|
||||
this.adjust_stack_reg(2 * (this.is_osize_32() ? 4 : 2) + stack_adjust);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -2087,20 +2076,20 @@ CPU.prototype.far_return = function(eip, selector, stack_adjust)
|
|||
|
||||
if(info.rpl > this.cpl)
|
||||
{
|
||||
dbg_log("far return privilege change cs: " + h(selector) + " from=" + this.cpl + " to=" + info.rpl + " is_16=" + this.operand_size_32, LOG_CPU);
|
||||
dbg_log("far return privilege change cs: " + h(selector) + " from=" + this.cpl + " to=" + info.rpl + " is_16=" + this.is_osize_32(), LOG_CPU);
|
||||
|
||||
if(this.operand_size_32)
|
||||
if(this.is_osize_32())
|
||||
{
|
||||
dbg_log("esp read from " + h(this.translate_address_system_read(this.get_stack_pointer(stack_adjust + 8))))
|
||||
//dbg_log("esp read from " + h(this.translate_address_system_read(this.get_stack_pointer(stack_adjust + 8))))
|
||||
var temp_esp = this.safe_read32s(this.get_stack_pointer(stack_adjust + 8));
|
||||
dbg_log("esp=" + h(temp_esp));
|
||||
//dbg_log("esp=" + h(temp_esp));
|
||||
var temp_ss = this.safe_read16(this.get_stack_pointer(stack_adjust + 12));
|
||||
}
|
||||
else
|
||||
{
|
||||
dbg_log("esp read from " + h(this.translate_address_system_read(this.get_stack_pointer(stack_adjust + 4))));
|
||||
//dbg_log("esp read from " + h(this.translate_address_system_read(this.get_stack_pointer(stack_adjust + 4))));
|
||||
var temp_esp = this.safe_read16(this.get_stack_pointer(stack_adjust + 4));
|
||||
dbg_log("esp=" + h(temp_esp));
|
||||
//dbg_log("esp=" + h(temp_esp));
|
||||
var temp_ss = this.safe_read16(this.get_stack_pointer(stack_adjust + 6));
|
||||
}
|
||||
|
||||
|
@ -2111,7 +2100,7 @@ CPU.prototype.far_return = function(eip, selector, stack_adjust)
|
|||
this.switch_seg(reg_ss, temp_ss);
|
||||
this.set_stack_reg(temp_esp + stack_adjust);
|
||||
|
||||
//if(this.operand_size_32)
|
||||
//if(this.is_osize_32())
|
||||
//{
|
||||
// this.adjust_stack_reg(2 * 4);
|
||||
//}
|
||||
|
@ -2126,7 +2115,7 @@ CPU.prototype.far_return = function(eip, selector, stack_adjust)
|
|||
}
|
||||
else
|
||||
{
|
||||
if(this.operand_size_32)
|
||||
if(this.is_osize_32())
|
||||
{
|
||||
this.adjust_stack_reg(2 * 4 + stack_adjust);
|
||||
}
|
||||
|
@ -2171,7 +2160,7 @@ CPU.prototype.far_jump = function(eip, selector, is_call)
|
|||
{
|
||||
if(is_call)
|
||||
{
|
||||
if(this.operand_size_32)
|
||||
if(this.is_osize_32())
|
||||
{
|
||||
this.writable_or_pagefault(this.get_stack_pointer(-8), 8);
|
||||
this.push32(this.sreg[reg_cs]);
|
||||
|
@ -2461,7 +2450,7 @@ CPU.prototype.far_jump = function(eip, selector, is_call)
|
|||
|
||||
if(is_call)
|
||||
{
|
||||
if(this.operand_size_32)
|
||||
if(this.is_osize_32())
|
||||
{
|
||||
this.writable_or_pagefault(this.get_stack_pointer(-8), 8);
|
||||
this.push32(this.sreg[reg_cs]);
|
||||
|
@ -2648,7 +2637,6 @@ CPU.prototype.hlt_op = function()
|
|||
this.trigger_gp(0);
|
||||
}
|
||||
|
||||
// hlt
|
||||
if((this.flags & flag_interrupt) === 0)
|
||||
{
|
||||
this.debug.show("cpu halted");
|
||||
|
@ -2659,7 +2647,21 @@ CPU.prototype.hlt_op = function()
|
|||
{
|
||||
// get out of here and into hlt_loop
|
||||
this.in_hlt = true;
|
||||
throw MAGIC_CPU_EXCEPTION;
|
||||
|
||||
if(false) // possibly unsafe, test in safari
|
||||
{
|
||||
this.hlt_loop();
|
||||
this.diverged();
|
||||
|
||||
if(this.in_hlt)
|
||||
{
|
||||
throw MAGIC_CPU_EXCEPTION;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
throw MAGIC_CPU_EXCEPTION;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -2681,6 +2683,8 @@ CPU.prototype.raise_exception = function(interrupt_nr)
|
|||
|
||||
CPU.prototype.raise_exception_with_code = function(interrupt_nr, error_code)
|
||||
{
|
||||
dbg_assert(typeof error_code === "number");
|
||||
|
||||
//if(DEBUG)
|
||||
//{
|
||||
// dbg_log("Exception " + h(interrupt_nr) + " err=" + h(error_code) + " at " + h(this.previous_ip >>> 0, 8) + " (cs=" + h(this.sreg[reg_cs], 4) + ")", LOG_CPU);
|
||||
|
@ -2791,17 +2795,22 @@ CPU.prototype.get_seg_prefix_cs = function()
|
|||
*/
|
||||
CPU.prototype.get_seg_prefix = function(default_segment /*, offset*/)
|
||||
{
|
||||
if(this.segment_prefix === SEG_PREFIX_NONE)
|
||||
var prefix = this.prefixes & PREFIX_MASK_SEGMENT;
|
||||
|
||||
if(prefix)
|
||||
{
|
||||
return this.get_seg(default_segment /*, offset*/);
|
||||
}
|
||||
else if(this.segment_prefix === SEG_PREFIX_ZERO)
|
||||
{
|
||||
return 0;
|
||||
if(prefix === SEG_PREFIX_ZERO)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
return this.get_seg(prefix - 1 /*, offset*/);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return this.get_seg(this.segment_prefix /*, offset*/);
|
||||
return this.get_seg(default_segment /*, offset*/);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -2962,7 +2971,8 @@ CPU.prototype.read_write_e32 = function()
|
|||
var virt_addr = this.modrm_resolve(this.modrm_byte);
|
||||
this.phys_addr = this.translate_address_write(virt_addr);
|
||||
if(this.paging && (virt_addr & 0xFFF) >= 0xFFD) {
|
||||
this.phys_addr_high = this.translate_address_write(virt_addr + 3 | 0);
|
||||
//this.phys_addr_high = this.translate_address_write(virt_addr + 3 | 0);
|
||||
this.phys_addr_high = this.translate_address_write(virt_addr + 3 & ~3) | (virt_addr + 3) & 3;
|
||||
dbg_assert(this.phys_addr_high);
|
||||
return this.virt_boundary_read32s(this.phys_addr, this.phys_addr_high);
|
||||
} else {
|
||||
|
@ -3059,6 +3069,8 @@ CPU.prototype.handle_irqs = function()
|
|||
{
|
||||
dbg_assert(!this.page_fault);
|
||||
|
||||
this.diverged();
|
||||
|
||||
if((this.flags & flag_interrupt) && !this.page_fault)
|
||||
{
|
||||
if(this.devices.pic)
|
||||
|
@ -3238,20 +3250,16 @@ CPU.prototype.cpuid = function()
|
|||
|
||||
CPU.prototype.update_cs_size = function(new_size)
|
||||
{
|
||||
this.is_32 = this.operand_size_32 = this.address_size_32 = new_size;
|
||||
this.clear_instruction_cache();
|
||||
|
||||
this.is_32 = new_size;
|
||||
|
||||
this.update_operand_size();
|
||||
this.update_address_size();
|
||||
|
||||
if(OP_TRANSLATION)
|
||||
{
|
||||
this.translator.clear_cache();
|
||||
}
|
||||
};
|
||||
|
||||
CPU.prototype.update_operand_size = function()
|
||||
{
|
||||
if(this.operand_size_32)
|
||||
if(this.is_32)
|
||||
{
|
||||
this.table = this.table32;
|
||||
}
|
||||
|
@ -3261,24 +3269,6 @@ CPU.prototype.update_operand_size = function()
|
|||
}
|
||||
};
|
||||
|
||||
CPU.prototype.update_address_size = function()
|
||||
{
|
||||
if(this.address_size_32)
|
||||
{
|
||||
this.regv = this.reg32s;
|
||||
this.reg_vcx = reg_ecx;
|
||||
this.reg_vsi = reg_esi;
|
||||
this.reg_vdi = reg_edi;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.regv = this.reg16;
|
||||
this.reg_vcx = reg_cx;
|
||||
this.reg_vsi = reg_si;
|
||||
this.reg_vdi = reg_di;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {number} selector
|
||||
*/
|
||||
|
@ -4061,6 +4051,60 @@ CPU.prototype.trigger_pagefault = function(write, user, present)
|
|||
throw MAGIC_CPU_EXCEPTION;
|
||||
};
|
||||
|
||||
CPU.prototype.is_osize_32 = function()
|
||||
{
|
||||
return this.is_32 !== ((this.prefixes & PREFIX_MASK_OPSIZE) === PREFIX_MASK_OPSIZE);
|
||||
};
|
||||
|
||||
CPU.prototype.is_asize_32 = function()
|
||||
{
|
||||
return this.is_32 !== ((this.prefixes & PREFIX_MASK_ADDRSIZE) === PREFIX_MASK_ADDRSIZE);
|
||||
};
|
||||
|
||||
CPU.prototype.get_reg_asize = function(reg)
|
||||
{
|
||||
dbg_assert(reg === reg_ecx || reg === reg_esi || reg === reg_edi);
|
||||
var r = this.reg32s[reg];
|
||||
|
||||
if(this.is_asize_32())
|
||||
{
|
||||
return r;
|
||||
}
|
||||
else
|
||||
{
|
||||
return r & 0xFFFF;
|
||||
}
|
||||
};
|
||||
|
||||
CPU.prototype.set_ecx_asize = function(value)
|
||||
{
|
||||
if(this.is_asize_32())
|
||||
{
|
||||
this.reg32s[reg_ecx] = value;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.reg16[reg_cx] = value;
|
||||
}
|
||||
};
|
||||
|
||||
CPU.prototype.add_reg_asize = function(reg, value)
|
||||
{
|
||||
dbg_assert(reg === reg_ecx || reg === reg_esi || reg === reg_edi);
|
||||
if(this.is_asize_32())
|
||||
{
|
||||
this.reg32s[reg] += value;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.reg16[reg << 1] += value;
|
||||
}
|
||||
};
|
||||
|
||||
CPU.prototype.decr_ecx_asize = function()
|
||||
{
|
||||
return this.is_asize_32() ? --this.reg32s[reg_ecx] : --this.reg16[reg_cx];
|
||||
}
|
||||
|
||||
// Closure Compiler's way of exporting
|
||||
if(typeof window !== "undefined")
|
||||
|
|
|
@ -322,7 +322,7 @@ FPU.prototype.safe_tag_word = function(tag_word)
|
|||
|
||||
FPU.prototype.fstenv = function(addr)
|
||||
{
|
||||
if(this.cpu.operand_size_32)
|
||||
if(this.cpu.is_osize_32())
|
||||
{
|
||||
this.cpu.writable_or_pagefault(addr, 26);
|
||||
|
||||
|
@ -345,7 +345,7 @@ FPU.prototype.fstenv = function(addr)
|
|||
|
||||
FPU.prototype.fldenv = function(addr)
|
||||
{
|
||||
if(this.cpu.operand_size_32)
|
||||
if(this.cpu.is_osize_32())
|
||||
{
|
||||
this.control_word = this.cpu.safe_read16(addr);
|
||||
|
||||
|
|
|
@ -6,13 +6,13 @@ var t32 = [];
|
|||
|
||||
t[0x00] = cpu => { cpu.read_modrm_byte(); cpu.write_e8(cpu.add8(cpu.read_write_e8(), cpu.read_g8())); };
|
||||
t16[0x01] = cpu => { cpu.read_modrm_byte(); cpu.write_e16(cpu.add16(cpu.read_write_e16(), cpu.read_g16())); };
|
||||
t32[0x01] = cpu => { cpu.read_modrm_byte(); cpu.write_e32(cpu.add32(cpu.read_write_e32(), cpu.read_g32s())); }
|
||||
t32[0x01] = cpu => { cpu.read_modrm_byte(); cpu.write_e32(cpu.add32(cpu.read_write_e32(), cpu.read_g32s())); };
|
||||
t[0x02] = cpu => { cpu.read_modrm_byte(); cpu.write_g8(cpu.add8(cpu.read_g8(), cpu.read_e8())); };
|
||||
t16[0x03] = cpu => { cpu.read_modrm_byte(); cpu.write_g16(cpu.add16(cpu.read_g16(), cpu.read_e16())); };
|
||||
t32[0x03] = cpu => { cpu.read_modrm_byte(); cpu.write_g32(cpu.add32(cpu.read_g32s(), cpu.read_e32s())); }
|
||||
t32[0x03] = cpu => { cpu.read_modrm_byte(); cpu.write_g32(cpu.add32(cpu.read_g32s(), cpu.read_e32s())); };
|
||||
t[0x04] = cpu => { cpu.reg8[reg_al] = cpu.add8(cpu.reg8[reg_al], cpu.read_op8()); };
|
||||
t16[0x05] = cpu => { cpu.reg16[reg_ax] = cpu.add16(cpu.reg16[reg_ax], cpu.read_op16()); };
|
||||
t32[0x05] = cpu => { cpu.reg32s[reg_eax] = cpu.add32(cpu.reg32s[reg_eax], cpu.read_op32s()); }
|
||||
t32[0x05] = cpu => { cpu.reg32s[reg_eax] = cpu.add32(cpu.reg32s[reg_eax], cpu.read_op32s()); };
|
||||
|
||||
t16[0x06] = cpu => { cpu.push16(cpu.sreg[reg_es]); };
|
||||
t32[0x06] = cpu => { cpu.push32(cpu.sreg[reg_es]); };
|
||||
|
@ -27,7 +27,7 @@ t32[0x07] = cpu => {
|
|||
|
||||
t[0x08] = cpu => { cpu.read_modrm_byte(); cpu.write_e8(cpu.or8(cpu.read_write_e8(), cpu.read_g8())); };
|
||||
t16[0x09] = cpu => { cpu.read_modrm_byte(); cpu.write_e16(cpu.or16(cpu.read_write_e16(), cpu.read_g16())); };
|
||||
t32[0x09] = cpu => { cpu.read_modrm_byte(); cpu.write_e32(cpu.or32(cpu.read_write_e32(), cpu.read_g32s())); }
|
||||
t32[0x09] = cpu => { cpu.read_modrm_byte(); cpu.write_e32(cpu.or32(cpu.read_write_e32(), cpu.read_g32s())); };
|
||||
t[0x0a] = cpu => { cpu.read_modrm_byte(); cpu.write_g8(cpu.or8(cpu.read_g8(), cpu.read_e8())); };
|
||||
t16[0x0b] = cpu => { cpu.read_modrm_byte(); cpu.write_g16(cpu.or16(cpu.read_g16(), cpu.read_e16())); };
|
||||
t32[0x0b] = cpu => { cpu.read_modrm_byte(); cpu.write_g32(cpu.or32(cpu.read_g32s(), cpu.read_e32s())); }
|
||||
|
@ -39,10 +39,10 @@ t32[0x0d] = cpu => { cpu.reg32s[reg_eax] = cpu.or32(cpu.reg32s[reg_eax], cpu.rea
|
|||
t16[0x0E] = cpu => { cpu.push16(cpu.sreg[reg_cs]); };
|
||||
t32[0x0E] = cpu => { cpu.push32(cpu.sreg[reg_cs]); };
|
||||
t16[0x0F] = cpu => {
|
||||
cpu.table0F_16[cpu.read_op8()](cpu);
|
||||
cpu.table0F_16[cpu.read_op0F()](cpu);
|
||||
};
|
||||
t32[0x0F] = cpu => {
|
||||
cpu.table0F_32[cpu.read_op8()](cpu);
|
||||
cpu.table0F_32[cpu.read_op0F()](cpu);
|
||||
};
|
||||
|
||||
t[0x10] = cpu => { cpu.read_modrm_byte(); cpu.write_e8(cpu.adc8(cpu.read_write_e8(), cpu.read_g8())); };
|
||||
|
@ -103,7 +103,7 @@ t16[0x25] = cpu => { cpu.reg16[reg_ax] = cpu.and16(cpu.reg16[reg_ax], cpu.read_o
|
|||
t32[0x25] = cpu => { cpu.reg32s[reg_eax] = cpu.and32(cpu.reg32s[reg_eax], cpu.read_op32s()); }
|
||||
|
||||
|
||||
t[0x26] = cpu => { cpu.segment_prefix = reg_es; cpu.run_prefix_instruction(); cpu.segment_prefix = SEG_PREFIX_NONE; };
|
||||
t[0x26] = cpu => { cpu.segment_prefix_op(reg_es); };
|
||||
t[0x27] = cpu => { cpu.bcd_daa(); };
|
||||
|
||||
t[0x28] = cpu => { cpu.read_modrm_byte(); cpu.write_e8(cpu.sub8(cpu.read_write_e8(), cpu.read_g8())); };
|
||||
|
@ -116,7 +116,7 @@ t[0x2c] = cpu => { cpu.reg8[reg_al] = cpu.sub8(cpu.reg8[reg_al], cpu.read_op8())
|
|||
t16[0x2d] = cpu => { cpu.reg16[reg_ax] = cpu.sub16(cpu.reg16[reg_ax], cpu.read_op16()); };
|
||||
t32[0x2d] = cpu => { cpu.reg32s[reg_eax] = cpu.sub32(cpu.reg32s[reg_eax], cpu.read_op32s()); }
|
||||
|
||||
t[0x2E] = cpu => { cpu.segment_prefix = reg_cs; cpu.run_prefix_instruction(); cpu.segment_prefix = SEG_PREFIX_NONE; };
|
||||
t[0x2E] = cpu => { cpu.segment_prefix_op(reg_cs); };
|
||||
t[0x2F] = cpu => { cpu.bcd_das(); };
|
||||
|
||||
t[0x30] = cpu => { cpu.read_modrm_byte(); cpu.write_e8(cpu.xor8(cpu.read_write_e8(), cpu.read_g8())); };
|
||||
|
@ -129,7 +129,7 @@ t[0x34] = cpu => { cpu.reg8[reg_al] = cpu.xor8(cpu.reg8[reg_al], cpu.read_op8())
|
|||
t16[0x35] = cpu => { cpu.reg16[reg_ax] = cpu.xor16(cpu.reg16[reg_ax], cpu.read_op16()); };
|
||||
t32[0x35] = cpu => { cpu.reg32s[reg_eax] = cpu.xor32(cpu.reg32s[reg_eax], cpu.read_op32s()); }
|
||||
|
||||
t[0x36] = cpu => { cpu.segment_prefix = reg_ss; cpu.run_prefix_instruction(); cpu.segment_prefix = SEG_PREFIX_NONE; };
|
||||
t[0x36] = cpu => { cpu.segment_prefix_op(reg_ss); };
|
||||
t[0x37] = cpu => { cpu.bcd_aaa(); };
|
||||
|
||||
t[0x38] = cpu => { cpu.read_modrm_byte(); cpu.cmp8(cpu.read_e8(), cpu.read_g8()); };
|
||||
|
@ -142,7 +142,7 @@ t[0x3C] = cpu => { cpu.cmp8(cpu.reg8[reg_al], cpu.read_op8()); };
|
|||
t16[0x3D] = cpu => { cpu.cmp16(cpu.reg16[reg_ax], cpu.read_op16()); };
|
||||
t32[0x3D] = cpu => { cpu.cmp32(cpu.reg32s[reg_eax], cpu.read_op32s()); }
|
||||
|
||||
t[0x3E] = cpu => { cpu.segment_prefix = reg_ds; cpu.run_prefix_instruction(); cpu.segment_prefix = SEG_PREFIX_NONE; };
|
||||
t[0x3E] = cpu => { cpu.segment_prefix_op(reg_ds); };
|
||||
t[0x3F] = cpu => { cpu.bcd_aas(); };
|
||||
|
||||
|
||||
|
@ -241,31 +241,23 @@ t[0x63] = cpu => { cpu.read_modrm_byte();
|
|||
}
|
||||
};
|
||||
|
||||
t[0x64] = cpu => { cpu.segment_prefix = reg_fs; cpu.run_prefix_instruction(); cpu.segment_prefix = SEG_PREFIX_NONE; };
|
||||
t[0x65] = cpu => { cpu.segment_prefix = reg_gs; cpu.run_prefix_instruction(); cpu.segment_prefix = SEG_PREFIX_NONE; };
|
||||
t[0x64] = cpu => { cpu.segment_prefix_op(reg_fs); };
|
||||
t[0x65] = cpu => { cpu.segment_prefix_op(reg_gs); };
|
||||
|
||||
t[0x66] = cpu => {
|
||||
// Operand-size override prefix
|
||||
cpu.operand_size_32 = !cpu.is_32;
|
||||
cpu.update_operand_size();
|
||||
|
||||
cpu.prefixes |= PREFIX_MASK_OPSIZE;
|
||||
cpu.run_prefix_instruction();
|
||||
|
||||
cpu.operand_size_32 = cpu.is_32;
|
||||
cpu.update_operand_size();
|
||||
cpu.prefixes = 0;
|
||||
};
|
||||
|
||||
t[0x67] = cpu => {
|
||||
// Address-size override prefix
|
||||
dbg_assert(cpu.address_size_32 === cpu.is_32);
|
||||
|
||||
cpu.address_size_32 = !cpu.is_32;
|
||||
cpu.update_address_size();
|
||||
dbg_assert(cpu.is_asize_32() === cpu.is_32);
|
||||
|
||||
cpu.prefixes |= PREFIX_MASK_ADDRSIZE;
|
||||
cpu.run_prefix_instruction();
|
||||
|
||||
cpu.address_size_32 = cpu.is_32;
|
||||
cpu.update_address_size();
|
||||
cpu.prefixes = 0;
|
||||
};
|
||||
|
||||
t16[0x68] = cpu => { cpu.push16(cpu.read_op16()); };
|
||||
|
@ -351,9 +343,7 @@ t32[0x81] = cpu => { cpu.read_modrm_byte();
|
|||
case 7: cpu.cmp32(cpu.read_e32s(), cpu.read_op32s()); break;
|
||||
}
|
||||
};
|
||||
t[0x82] = cpu => {
|
||||
cpu.table[0x80](cpu); // alias
|
||||
};
|
||||
t[0x82] = t[0x80]; // alias
|
||||
t16[0x83] = cpu => { cpu.read_modrm_byte();
|
||||
switch(cpu.modrm_byte >> 3 & 7)
|
||||
{
|
||||
|
@ -428,9 +418,9 @@ t16[0x8D] = cpu => { cpu.read_modrm_byte();
|
|||
var mod = cpu.modrm_byte >> 3 & 7;
|
||||
|
||||
// override prefix, so modrm_resolve does not return the segment part
|
||||
cpu.segment_prefix = SEG_PREFIX_ZERO;
|
||||
cpu.prefixes |= SEG_PREFIX_ZERO;
|
||||
cpu.reg16[mod << 1] = cpu.modrm_resolve(cpu.modrm_byte);
|
||||
cpu.segment_prefix = SEG_PREFIX_NONE;
|
||||
cpu.prefixes = 0;
|
||||
};
|
||||
t32[0x8D] = cpu => { cpu.read_modrm_byte();
|
||||
if(cpu.modrm_byte >= 0xC0)
|
||||
|
@ -440,9 +430,9 @@ t32[0x8D] = cpu => { cpu.read_modrm_byte();
|
|||
}
|
||||
var mod = cpu.modrm_byte >> 3 & 7;
|
||||
|
||||
cpu.segment_prefix = SEG_PREFIX_ZERO;
|
||||
cpu.prefixes |= SEG_PREFIX_ZERO;
|
||||
cpu.reg32s[mod] = cpu.modrm_resolve(cpu.modrm_byte);
|
||||
cpu.segment_prefix = SEG_PREFIX_NONE;
|
||||
cpu.prefixes = 0;
|
||||
};
|
||||
|
||||
t[0x8E] = cpu => { cpu.read_modrm_byte();
|
||||
|
@ -516,14 +506,15 @@ t32[0x99] = cpu => { /* cdq */ cpu.reg32s[reg_edx] = cpu.reg32s[reg_eax] >> 31;
|
|||
t16[0x9A] = cpu => {
|
||||
// callf
|
||||
var new_ip = cpu.read_op16();
|
||||
var new_cs = cpu.read_second_op16();
|
||||
var new_cs = cpu.read_disp16();
|
||||
|
||||
cpu.far_jump(new_ip, new_cs, true);
|
||||
dbg_assert(cpu.address_size_32 || cpu.get_real_eip() < 0x10000);
|
||||
dbg_assert(cpu.is_asize_32() || cpu.get_real_eip() < 0x10000);
|
||||
cpu.diverged();
|
||||
};
|
||||
t32[0x9A] = cpu => {
|
||||
var new_ip = cpu.read_op32s();
|
||||
var new_cs = cpu.read_second_op16();
|
||||
var new_cs = cpu.read_disp16();
|
||||
|
||||
if(!cpu.protected_mode || cpu.vm86_mode())
|
||||
{
|
||||
|
@ -534,7 +525,8 @@ t32[0x9A] = cpu => {
|
|||
}
|
||||
|
||||
cpu.far_jump(new_ip, new_cs, true);
|
||||
dbg_assert(cpu.address_size_32 || cpu.get_real_eip() < 0x10000);
|
||||
dbg_assert(cpu.is_asize_32() || cpu.get_real_eip() < 0x10000);
|
||||
cpu.diverged();
|
||||
};
|
||||
|
||||
t[0x9B] = cpu => {
|
||||
|
@ -606,7 +598,7 @@ t16[0x9D] = cpu => {
|
|||
//cpu.instruction_pointer = cpu.previous_ip;
|
||||
//cpu.raise_exception(1);
|
||||
}
|
||||
else // XXX
|
||||
else
|
||||
{
|
||||
cpu.handle_irqs();
|
||||
}
|
||||
|
@ -660,9 +652,9 @@ t32[0xA3] = cpu => {
|
|||
cpu.safe_write32(cpu.read_moffs(), cpu.reg32s[reg_eax]);
|
||||
};
|
||||
|
||||
t[0xA4] = cpu => { movsb(cpu); };
|
||||
t16[0xA5] = cpu => { movsw(cpu); };
|
||||
t32[0xA5] = cpu => { movsd(cpu); };
|
||||
t[0xA4] = cpu => { cpu.movsb(); };
|
||||
t16[0xA5] = cpu => { cpu.movsw(); };
|
||||
t32[0xA5] = cpu => { cpu.movsd(); };
|
||||
t[0xA6] = cpu => { cmpsb(cpu); };
|
||||
t16[0xA7] = cpu => { cmpsw(cpu); };
|
||||
t32[0xA7] = cpu => { cmpsd(cpu); };
|
||||
|
@ -772,27 +764,31 @@ t16[0xC2] = cpu => {
|
|||
var imm16 = cpu.read_op16();
|
||||
|
||||
cpu.instruction_pointer = cpu.get_seg(reg_cs) + cpu.pop16() | 0;
|
||||
dbg_assert(cpu.address_size_32 || cpu.get_real_eip() < 0x10000);
|
||||
dbg_assert(cpu.is_asize_32() || cpu.get_real_eip() < 0x10000);
|
||||
cpu.adjust_stack_reg(imm16);
|
||||
cpu.diverged();
|
||||
};
|
||||
t32[0xC2] = cpu => {
|
||||
// retn
|
||||
var imm16 = cpu.read_op16();
|
||||
var ip = cpu.pop32s();
|
||||
|
||||
dbg_assert(cpu.address_size_32 || ip < 0x10000);
|
||||
dbg_assert(cpu.is_asize_32() || ip < 0x10000);
|
||||
cpu.instruction_pointer = cpu.get_seg(reg_cs) + ip | 0;
|
||||
cpu.adjust_stack_reg(imm16);
|
||||
cpu.diverged();
|
||||
};
|
||||
t16[0xC3] = cpu => {
|
||||
// retn
|
||||
cpu.instruction_pointer = cpu.get_seg(reg_cs) + cpu.pop16() | 0;
|
||||
cpu.diverged();
|
||||
};
|
||||
t32[0xC3] = cpu => {
|
||||
// retn
|
||||
var ip = cpu.pop32s();
|
||||
dbg_assert(cpu.address_size_32 || ip < 0x10000);
|
||||
dbg_assert(cpu.is_asize_32() || ip < 0x10000);
|
||||
cpu.instruction_pointer = cpu.get_seg(reg_cs) + ip | 0;
|
||||
cpu.diverged();
|
||||
};
|
||||
|
||||
t16[0xC4] = cpu => { cpu.read_modrm_byte();
|
||||
|
@ -830,8 +826,8 @@ t32[0xC7] = cpu => { cpu.read_modrm_byte();
|
|||
}
|
||||
}
|
||||
|
||||
t16[0xC8] = cpu => { cpu.enter16(cpu.read_op16(), cpu.read_second_op8()); };
|
||||
t32[0xC8] = cpu => { cpu.enter32(cpu.read_op16(), cpu.read_second_op8()); };
|
||||
t16[0xC8] = cpu => { cpu.enter16(cpu.read_op16(), cpu.read_disp8()); };
|
||||
t32[0xC8] = cpu => { cpu.enter32(cpu.read_op16(), cpu.read_disp8()); };
|
||||
t16[0xC9] = cpu => {
|
||||
// leave
|
||||
var old_vbp = cpu.stack_size_32 ? cpu.reg32s[reg_ebp] : cpu.reg16[reg_bp];
|
||||
|
@ -852,6 +848,7 @@ t16[0xCA] = cpu => {
|
|||
var cs = cpu.safe_read16(cpu.get_stack_pointer(2));
|
||||
|
||||
cpu.far_return(ip, cs, imm16);
|
||||
cpu.diverged();
|
||||
};
|
||||
t32[0xCA] = cpu => {
|
||||
// retf
|
||||
|
@ -860,7 +857,8 @@ t32[0xCA] = cpu => {
|
|||
var cs = cpu.safe_read32s(cpu.get_stack_pointer(4)) & 0xFFFF;
|
||||
|
||||
cpu.far_return(ip, cs, imm16);
|
||||
dbg_assert(cpu.address_size_32 || cpu.get_real_eip() < 0x10000);
|
||||
dbg_assert(cpu.is_asize_32() || cpu.get_real_eip() < 0x10000);
|
||||
cpu.diverged();
|
||||
};
|
||||
t16[0xCB] = cpu => {
|
||||
// retf
|
||||
|
@ -868,7 +866,8 @@ t16[0xCB] = cpu => {
|
|||
var cs = cpu.safe_read16(cpu.get_stack_pointer(2));
|
||||
|
||||
cpu.far_return(ip, cs, 0);
|
||||
dbg_assert(cpu.address_size_32 || cpu.get_real_eip() < 0x10000);
|
||||
dbg_assert(cpu.is_asize_32() || cpu.get_real_eip() < 0x10000);
|
||||
cpu.diverged();
|
||||
};
|
||||
t32[0xCB] = cpu => {
|
||||
// retf
|
||||
|
@ -876,7 +875,8 @@ t32[0xCB] = cpu => {
|
|||
var cs = cpu.safe_read32s(cpu.get_stack_pointer(4)) & 0xFFFF;
|
||||
|
||||
cpu.far_return(ip, cs, 0);
|
||||
dbg_assert(cpu.address_size_32 || cpu.get_real_eip() < 0x10000);
|
||||
dbg_assert(cpu.is_asize_32() || cpu.get_real_eip() < 0x10000);
|
||||
cpu.diverged();
|
||||
};
|
||||
|
||||
t[0xCC] = cpu => {
|
||||
|
@ -884,11 +884,13 @@ t[0xCC] = cpu => {
|
|||
// TODO: inhibit iopl checks
|
||||
dbg_log("INT3", LOG_CPU);
|
||||
cpu.call_interrupt_vector(3, true, false);
|
||||
cpu.diverged();
|
||||
};
|
||||
t[0xCD] = cpu => {
|
||||
// INT
|
||||
var imm8 = cpu.read_op8();
|
||||
cpu.call_interrupt_vector(imm8, true, false);
|
||||
cpu.diverged();
|
||||
};
|
||||
t[0xCE] = cpu => {
|
||||
// INTO
|
||||
|
@ -898,14 +900,17 @@ t[0xCE] = cpu => {
|
|||
// TODO: inhibit iopl checks
|
||||
cpu.call_interrupt_vector(4, true, false);
|
||||
}
|
||||
cpu.diverged();
|
||||
};
|
||||
|
||||
t16[0xCF] = cpu => {
|
||||
// iret
|
||||
cpu.iret16();
|
||||
cpu.diverged();
|
||||
};
|
||||
t32[0xCF] = cpu => {
|
||||
cpu.iret32();
|
||||
cpu.diverged();
|
||||
};
|
||||
|
||||
t[0xD0] = cpu => { cpu.read_modrm_byte();
|
||||
|
@ -1022,13 +1027,13 @@ t[0xD6] = cpu => {
|
|||
};
|
||||
t[0xD7] = cpu => {
|
||||
// xlat
|
||||
if(cpu.address_size_32)
|
||||
if(cpu.is_asize_32())
|
||||
{
|
||||
cpu.reg8[reg_al] = cpu.safe_read8(cpu.get_seg_prefix(reg_ds) + cpu.reg32s[reg_ebx] + cpu.reg8[reg_al]);
|
||||
cpu.reg8[reg_al] = cpu.safe_read8(cpu.get_seg_prefix(reg_ds) + cpu.reg32s[reg_ebx] + cpu.reg8[reg_al] | 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
cpu.reg8[reg_al] = cpu.safe_read8(cpu.get_seg_prefix(reg_ds) + cpu.reg16[reg_bx] + cpu.reg8[reg_al]);
|
||||
cpu.reg8[reg_al] = cpu.safe_read8(cpu.get_seg_prefix(reg_ds) + (cpu.reg16[reg_bx] + cpu.reg8[reg_al] & 0xFFFF) | 0);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -1098,31 +1103,37 @@ t[0xE4] = cpu => {
|
|||
var port = cpu.read_op8();
|
||||
cpu.test_privileges_for_io(port, 1);
|
||||
cpu.reg8[reg_al] = cpu.io.port_read8(port);
|
||||
cpu.diverged();
|
||||
};
|
||||
t16[0xE5] = cpu => {
|
||||
var port = cpu.read_op8();
|
||||
cpu.test_privileges_for_io(port, 2);
|
||||
cpu.reg16[reg_ax] = cpu.io.port_read16(port);
|
||||
cpu.diverged();
|
||||
};
|
||||
t32[0xE5] = cpu => {
|
||||
var port = cpu.read_op8();
|
||||
cpu.test_privileges_for_io(port, 4);
|
||||
cpu.reg32s[reg_eax] = cpu.io.port_read32(port);
|
||||
cpu.diverged();
|
||||
};
|
||||
t[0xE6] = cpu => {
|
||||
var port = cpu.read_op8();
|
||||
cpu.test_privileges_for_io(port, 1);
|
||||
cpu.io.port_write8(port, cpu.reg8[reg_al]);
|
||||
cpu.diverged();
|
||||
};
|
||||
t16[0xE7] = cpu => {
|
||||
var port = cpu.read_op8();
|
||||
cpu.test_privileges_for_io(port, 2);
|
||||
cpu.io.port_write16(port, cpu.reg16[reg_ax]);
|
||||
cpu.diverged();
|
||||
};
|
||||
t32[0xE7] = cpu => {
|
||||
var port = cpu.read_op8();
|
||||
cpu.test_privileges_for_io(port, 4);
|
||||
cpu.io.port_write32(port, cpu.reg32s[reg_eax]);
|
||||
cpu.diverged();
|
||||
};
|
||||
|
||||
t16[0xE8] = cpu => {
|
||||
|
@ -1131,6 +1142,7 @@ t16[0xE8] = cpu => {
|
|||
cpu.push16(cpu.get_real_eip());
|
||||
|
||||
cpu.jmp_rel16(imm16);
|
||||
cpu.diverged();
|
||||
};
|
||||
t32[0xE8] = cpu => {
|
||||
// call
|
||||
|
@ -1138,71 +1150,83 @@ t32[0xE8] = cpu => {
|
|||
cpu.push32(cpu.get_real_eip());
|
||||
|
||||
cpu.instruction_pointer = cpu.instruction_pointer + imm32s | 0;
|
||||
dbg_assert(cpu.address_size_32 || cpu.get_real_eip() < 0x10000);
|
||||
dbg_assert(cpu.is_asize_32() || cpu.get_real_eip() < 0x10000);
|
||||
cpu.diverged();
|
||||
};
|
||||
t16[0xE9] = cpu => {
|
||||
// jmp
|
||||
var imm16 = cpu.read_op16();
|
||||
cpu.jmp_rel16(imm16);
|
||||
cpu.diverged();
|
||||
};
|
||||
t32[0xE9] = cpu => {
|
||||
// jmp
|
||||
var imm32s = cpu.read_op32s();
|
||||
cpu.instruction_pointer = cpu.instruction_pointer + imm32s | 0;
|
||||
dbg_assert(cpu.address_size_32 || cpu.get_real_eip() < 0x10000);
|
||||
dbg_assert(cpu.is_asize_32() || cpu.get_real_eip() < 0x10000);
|
||||
cpu.diverged();
|
||||
};
|
||||
t16[0xEA] = cpu => {
|
||||
// jmpf
|
||||
var ip = cpu.read_op16();
|
||||
var cs = cpu.read_second_op16();
|
||||
var cs = cpu.read_disp16();
|
||||
cpu.far_jump(ip, cs, false);
|
||||
dbg_assert(cpu.address_size_32 || cpu.get_real_eip() < 0x10000);
|
||||
dbg_assert(cpu.is_asize_32() || cpu.get_real_eip() < 0x10000);
|
||||
cpu.diverged();
|
||||
};
|
||||
t32[0xEA] = cpu => {
|
||||
// jmpf
|
||||
var new_ip = cpu.read_op32s();
|
||||
var cs = cpu.read_second_op16();
|
||||
var cs = cpu.read_disp16();
|
||||
cpu.far_jump(new_ip, cs, false);
|
||||
dbg_assert(cpu.address_size_32 || cpu.get_real_eip() < 0x10000);
|
||||
dbg_assert(cpu.is_asize_32() || cpu.get_real_eip() < 0x10000);
|
||||
cpu.diverged();
|
||||
};
|
||||
t[0xEB] = cpu => {
|
||||
// jmp near
|
||||
var imm8 = cpu.read_op8s();
|
||||
cpu.instruction_pointer = cpu.instruction_pointer + imm8 | 0;
|
||||
dbg_assert(cpu.address_size_32 || cpu.get_real_eip() < 0x10000);
|
||||
dbg_assert(cpu.is_asize_32() || cpu.get_real_eip() < 0x10000);
|
||||
|
||||
cpu.protected_mode = (cpu.cr[0] & CR0_PE) === CR0_PE;
|
||||
cpu.diverged();
|
||||
};
|
||||
|
||||
t[0xEC] = cpu => {
|
||||
var port = cpu.reg16[reg_dx];
|
||||
cpu.test_privileges_for_io(port, 1);
|
||||
cpu.reg8[reg_al] = cpu.io.port_read8(port);
|
||||
cpu.diverged();
|
||||
};
|
||||
t16[0xED] = cpu => {
|
||||
var port = cpu.reg16[reg_dx];
|
||||
cpu.test_privileges_for_io(port, 2);
|
||||
cpu.reg16[reg_ax] = cpu.io.port_read16(port);
|
||||
cpu.diverged();
|
||||
};
|
||||
t32[0xED] = cpu => {
|
||||
var port = cpu.reg16[reg_dx];
|
||||
cpu.test_privileges_for_io(port, 4);
|
||||
cpu.reg32s[reg_eax] = cpu.io.port_read32(port);
|
||||
cpu.diverged();
|
||||
};
|
||||
t[0xEE] = cpu => {
|
||||
var port = cpu.reg16[reg_dx];
|
||||
cpu.test_privileges_for_io(port, 1);
|
||||
cpu.io.port_write8(port, cpu.reg8[reg_al]);
|
||||
cpu.diverged();
|
||||
};
|
||||
t16[0xEF] = cpu => {
|
||||
var port = cpu.reg16[reg_dx];
|
||||
cpu.test_privileges_for_io(port, 2);
|
||||
cpu.io.port_write16(port, cpu.reg16[reg_ax]);
|
||||
cpu.diverged();
|
||||
};
|
||||
t32[0xEF] = cpu => {
|
||||
var port = cpu.reg16[reg_dx];
|
||||
cpu.test_privileges_for_io(port, 4);
|
||||
cpu.io.port_write32(port, cpu.reg32s[reg_eax]);
|
||||
cpu.diverged();
|
||||
};
|
||||
|
||||
t[0xF0] = cpu => {
|
||||
|
@ -1222,17 +1246,17 @@ t[0xF1] = cpu => {
|
|||
|
||||
t[0xF2] = cpu => {
|
||||
// repnz
|
||||
dbg_assert(cpu.repeat_string_prefix === REPEAT_STRING_PREFIX_NONE);
|
||||
cpu.repeat_string_prefix = REPEAT_STRING_PREFIX_NZ;
|
||||
dbg_assert((cpu.prefixes & PREFIX_MASK_REP) === 0);
|
||||
cpu.prefixes |= PREFIX_REPNZ;
|
||||
cpu.run_prefix_instruction();
|
||||
cpu.repeat_string_prefix = REPEAT_STRING_PREFIX_NONE;
|
||||
cpu.prefixes = 0;
|
||||
};
|
||||
t[0xF3] = cpu => {
|
||||
// repz
|
||||
dbg_assert(cpu.repeat_string_prefix === REPEAT_STRING_PREFIX_NONE);
|
||||
cpu.repeat_string_prefix = REPEAT_STRING_PREFIX_Z;
|
||||
dbg_assert((cpu.prefixes & PREFIX_MASK_REP) === 0);
|
||||
cpu.prefixes |= PREFIX_REPZ;
|
||||
cpu.run_prefix_instruction();
|
||||
cpu.repeat_string_prefix = REPEAT_STRING_PREFIX_NONE;
|
||||
cpu.prefixes = 0;
|
||||
};
|
||||
|
||||
t[0xF4] = cpu => {
|
||||
|
@ -1439,7 +1463,8 @@ t16[0xFF] = cpu => { cpu.read_modrm_byte();
|
|||
var data = cpu.read_e16();
|
||||
cpu.push16(cpu.get_real_eip());
|
||||
cpu.instruction_pointer = cpu.get_seg(reg_cs) + data | 0;
|
||||
dbg_assert(cpu.address_size_32 || cpu.get_real_eip() < 0x10000);
|
||||
dbg_assert(cpu.is_asize_32() || cpu.get_real_eip() < 0x10000);
|
||||
cpu.diverged();
|
||||
break;
|
||||
case 3:
|
||||
// 3, callf
|
||||
|
@ -1455,13 +1480,15 @@ t16[0xFF] = cpu => { cpu.read_modrm_byte();
|
|||
var new_cs = cpu.safe_read16(virt_addr + 2 | 0);
|
||||
|
||||
cpu.far_jump(new_ip, new_cs, true);
|
||||
dbg_assert(cpu.address_size_32 || cpu.get_real_eip() < 0x10000);
|
||||
dbg_assert(cpu.is_asize_32() || cpu.get_real_eip() < 0x10000);
|
||||
cpu.diverged();
|
||||
break;
|
||||
case 4:
|
||||
// 4, jmp near
|
||||
var data = cpu.read_e16();
|
||||
cpu.instruction_pointer = cpu.get_seg(reg_cs) + data | 0;
|
||||
dbg_assert(cpu.address_size_32 || cpu.get_real_eip() < 0x10000);
|
||||
dbg_assert(cpu.is_asize_32() || cpu.get_real_eip() < 0x10000);
|
||||
cpu.diverged();
|
||||
break;
|
||||
case 5:
|
||||
// 5, jmpf
|
||||
|
@ -1477,7 +1504,8 @@ t16[0xFF] = cpu => { cpu.read_modrm_byte();
|
|||
var new_cs = cpu.safe_read16(virt_addr + 2 | 0);
|
||||
|
||||
cpu.far_jump(new_ip, new_cs, false);
|
||||
dbg_assert(cpu.address_size_32 || cpu.get_real_eip() < 0x10000);
|
||||
dbg_assert(cpu.is_asize_32() || cpu.get_real_eip() < 0x10000);
|
||||
cpu.diverged();
|
||||
break;
|
||||
case 6:
|
||||
// 6, push
|
||||
|
@ -1502,8 +1530,9 @@ t32[0xFF] = cpu => { cpu.read_modrm_byte();
|
|||
var data = cpu.read_e32s();
|
||||
cpu.push32(cpu.get_real_eip());
|
||||
|
||||
dbg_assert(cpu.address_size_32 || data < 0x10000);
|
||||
dbg_assert(cpu.is_asize_32() || data < 0x10000);
|
||||
cpu.instruction_pointer = cpu.get_seg(reg_cs) + data | 0;
|
||||
cpu.diverged();
|
||||
break;
|
||||
case 3:
|
||||
// 3, callf
|
||||
|
@ -1527,13 +1556,15 @@ t32[0xFF] = cpu => { cpu.read_modrm_byte();
|
|||
}
|
||||
|
||||
cpu.far_jump(new_ip, new_cs, true);
|
||||
dbg_assert(cpu.address_size_32 || new_ip < 0x10000);
|
||||
dbg_assert(cpu.is_asize_32() || new_ip < 0x10000);
|
||||
cpu.diverged();
|
||||
break;
|
||||
case 4:
|
||||
// 4, jmp near
|
||||
var data = cpu.read_e32s();
|
||||
dbg_assert(cpu.address_size_32 || data < 0x10000);
|
||||
dbg_assert(cpu.is_asize_32() || data < 0x10000);
|
||||
cpu.instruction_pointer = cpu.get_seg(reg_cs) + data | 0;
|
||||
cpu.diverged();
|
||||
break;
|
||||
case 5:
|
||||
// 5, jmpf
|
||||
|
@ -1557,7 +1588,8 @@ t32[0xFF] = cpu => { cpu.read_modrm_byte();
|
|||
}
|
||||
|
||||
cpu.far_jump(new_ip, new_cs, false);
|
||||
dbg_assert(cpu.address_size_32 || new_ip < 0x10000);
|
||||
dbg_assert(cpu.is_asize_32() || new_ip < 0x10000);
|
||||
cpu.diverged();
|
||||
break;
|
||||
case 6:
|
||||
// push
|
||||
|
@ -1610,7 +1642,7 @@ t[0x00] = cpu => { cpu.read_modrm_byte();
|
|||
case 0:
|
||||
// sldt
|
||||
cpu.set_e16(cpu.sreg[reg_ldtr]);
|
||||
if(cpu.modrm_byte >= 0xC0)
|
||||
if(cpu.is_osize_32() && cpu.modrm_byte >= 0xC0)
|
||||
{
|
||||
cpu.reg32s[cpu.modrm_byte & 7] &= 0xFFFF;
|
||||
}
|
||||
|
@ -1618,7 +1650,7 @@ t[0x00] = cpu => { cpu.read_modrm_byte();
|
|||
case 1:
|
||||
// str
|
||||
cpu.set_e16(cpu.sreg[reg_tr]);
|
||||
if(cpu.modrm_byte >= 0xC0)
|
||||
if(cpu.is_osize_32() && cpu.modrm_byte >= 0xC0)
|
||||
{
|
||||
cpu.reg32s[cpu.modrm_byte & 7] &= 0xFFFF;
|
||||
}
|
||||
|
@ -1662,7 +1694,14 @@ t[0x01] = cpu => { cpu.read_modrm_byte();
|
|||
if(mod === 4)
|
||||
{
|
||||
// smsw
|
||||
cpu.set_e16(cpu.cr[0]);
|
||||
if(cpu.modrm_byte >= 0xC0 && cpu.is_osize_32())
|
||||
{
|
||||
cpu.set_e32(cpu.cr[0]);
|
||||
}
|
||||
else
|
||||
{
|
||||
cpu.set_e16(cpu.cr[0]);
|
||||
}
|
||||
return;
|
||||
}
|
||||
else if(mod === 6)
|
||||
|
@ -1704,14 +1743,14 @@ t[0x01] = cpu => { cpu.read_modrm_byte();
|
|||
// sgdt
|
||||
cpu.writable_or_pagefault(addr, 6);
|
||||
cpu.safe_write16(addr, cpu.gdtr_size);
|
||||
var mask = cpu.operand_size_32 ? -1 : 0x00FFFFFF;
|
||||
var mask = cpu.is_osize_32() ? -1 : 0x00FFFFFF;
|
||||
cpu.safe_write32(addr + 2, cpu.gdtr_offset & mask);
|
||||
break;
|
||||
case 1:
|
||||
// sidt
|
||||
cpu.writable_or_pagefault(addr, 6);
|
||||
cpu.safe_write16(addr, cpu.idtr_size);
|
||||
var mask = cpu.operand_size_32 ? -1 : 0x00FFFFFF;
|
||||
var mask = cpu.is_osize_32() ? -1 : 0x00FFFFFF;
|
||||
cpu.safe_write32(addr + 2, cpu.idtr_offset & mask);
|
||||
break;
|
||||
case 2:
|
||||
|
@ -1727,7 +1766,7 @@ t[0x01] = cpu => { cpu.read_modrm_byte();
|
|||
cpu.gdtr_size = size;
|
||||
cpu.gdtr_offset = offset;
|
||||
|
||||
if(!cpu.operand_size_32)
|
||||
if(!cpu.is_osize_32())
|
||||
{
|
||||
cpu.gdtr_offset &= 0xFFFFFF;
|
||||
}
|
||||
|
@ -1750,7 +1789,7 @@ t[0x01] = cpu => { cpu.read_modrm_byte();
|
|||
cpu.idtr_size = size;
|
||||
cpu.idtr_offset = offset;
|
||||
|
||||
if(!cpu.operand_size_32)
|
||||
if(!cpu.is_osize_32())
|
||||
{
|
||||
cpu.idtr_offset &= 0xFFFFFF;
|
||||
}
|
||||
|
@ -1968,7 +2007,7 @@ t[0x22] = cpu => { cpu.read_modrm_byte();
|
|||
case 3:
|
||||
//dbg_log("cr3=" + h(data >>> 0), LOG_CPU);
|
||||
cpu.cr[3] = data;
|
||||
dbg_assert((cpu.cr[3] & 0xFFF) === 0);
|
||||
dbg_assert((cpu.cr[3] & 0xFFF) === 0); // os2 v4
|
||||
cpu.clear_tlb();
|
||||
|
||||
//dump_page_directory();
|
||||
|
@ -2053,8 +2092,11 @@ t[0x30] = cpu => {
|
|||
var low = cpu.reg32s[reg_eax];
|
||||
var high = cpu.reg32s[reg_edx];
|
||||
|
||||
dbg_log("wrmsr ecx=" + h(index >>> 0, 8) +
|
||||
" data=" + h(high >>> 0, 8) + ":" + h(low >>> 0, 8), LOG_CPU);
|
||||
if(index !== IA32_SYSENTER_ESP)
|
||||
{
|
||||
dbg_log("wrmsr ecx=" + h(index >>> 0, 8) +
|
||||
" data=" + h(high >>> 0, 8) + ":" + h(low >>> 0, 8), LOG_CPU);
|
||||
}
|
||||
|
||||
switch(index)
|
||||
{
|
||||
|
@ -2199,8 +2241,8 @@ t[0x34] = cpu => {
|
|||
cpu.trigger_gp(0);
|
||||
}
|
||||
|
||||
//dbg_log("sysenter cs:eip=" + h(seg , 4) + ":" + h(cpu.sysenter_eip >>> 0, 8) +
|
||||
// " ss:esp=" + h(seg + 8, 4) + ":" + h(cpu.sysenter_esp >>> 0, 8), LOG_CPU);
|
||||
dbg_log("sysenter cs:eip=" + h(seg , 4) + ":" + h(cpu.sysenter_eip >>> 0, 8) +
|
||||
" ss:esp=" + h(seg + 8, 4) + ":" + h(cpu.sysenter_esp >>> 0, 8), LOG_CPU);
|
||||
|
||||
cpu.flags &= ~flag_vm & ~flag_interrupt;
|
||||
|
||||
|
@ -2224,6 +2266,7 @@ t[0x34] = cpu => {
|
|||
cpu.segment_offsets[reg_ss] = 0;
|
||||
|
||||
cpu.stack_size_32 = true;
|
||||
cpu.diverged();
|
||||
};
|
||||
|
||||
t[0x35] = cpu => {
|
||||
|
@ -2235,8 +2278,8 @@ t[0x35] = cpu => {
|
|||
cpu.trigger_gp(0);
|
||||
}
|
||||
|
||||
//dbg_log("sysexit cs:eip=" + h(seg + 16, 4) + ":" + h(cpu.reg32s[reg_edx] >>> 0, 8) +
|
||||
// " ss:esp=" + h(seg + 24, 4) + ":" + h(cpu.reg32s[reg_ecx] >>> 0, 8), LOG_CPU);
|
||||
dbg_log("sysexit cs:eip=" + h(seg + 16, 4) + ":" + h(cpu.reg32s[reg_edx] >>> 0, 8) +
|
||||
" ss:esp=" + h(seg + 24, 4) + ":" + h(cpu.reg32s[reg_ecx] >>> 0, 8), LOG_CPU);
|
||||
|
||||
cpu.instruction_pointer = cpu.reg32s[reg_edx];
|
||||
cpu.reg32s[reg_esp] = cpu.reg32s[reg_ecx];
|
||||
|
@ -2259,6 +2302,7 @@ t[0x35] = cpu => {
|
|||
cpu.segment_offsets[reg_ss] = 0;
|
||||
|
||||
cpu.stack_size_32 = true;
|
||||
cpu.diverged();
|
||||
};
|
||||
|
||||
t[0x36] = cpu => { cpu.undefined_instruction(); };
|
||||
|
@ -2571,6 +2615,9 @@ t[0xB0] = cpu => { cpu.read_modrm_byte();
|
|||
}
|
||||
else
|
||||
{
|
||||
if(cpu.modrm_byte < 0xC0)
|
||||
cpu.safe_write8(virt_addr, data);
|
||||
|
||||
cpu.reg8[reg_al] = data;
|
||||
}
|
||||
};
|
||||
|
@ -2597,6 +2644,9 @@ t16[0xB1] = cpu => { cpu.read_modrm_byte();
|
|||
}
|
||||
else
|
||||
{
|
||||
if(cpu.modrm_byte < 0xC0)
|
||||
cpu.safe_write16(virt_addr, data);
|
||||
|
||||
cpu.reg16[reg_ax] = data;
|
||||
}
|
||||
};
|
||||
|
@ -2624,6 +2674,9 @@ t32[0xB1] = cpu => { cpu.read_modrm_byte();
|
|||
}
|
||||
else
|
||||
{
|
||||
if(cpu.modrm_byte < 0xC0)
|
||||
cpu.safe_write32(virt_addr, data);
|
||||
|
||||
cpu.reg32s[reg_eax] = data;
|
||||
}
|
||||
};
|
||||
|
@ -2847,10 +2900,10 @@ t[0xC6] = cpu => { cpu.unimplemented_sse(); };
|
|||
t[0xC7] = cpu => {
|
||||
cpu.read_modrm_byte();
|
||||
|
||||
// cmpxchg8b
|
||||
switch(cpu.modrm_byte >> 3 & 7)
|
||||
{
|
||||
case 1:
|
||||
// cmpxchg8b
|
||||
if(cpu.modrm_byte >= 0xC0)
|
||||
{
|
||||
cpu.trigger_ud();
|
||||
|
@ -2876,6 +2929,9 @@ t[0xC7] = cpu => {
|
|||
|
||||
cpu.reg32s[reg_eax] = m64_low;
|
||||
cpu.reg32s[reg_edx] = m64_high;
|
||||
|
||||
cpu.safe_write32(addr, m64_low);
|
||||
cpu.safe_write32(addr + 4 | 0, m64_high);
|
||||
}
|
||||
|
||||
cpu.flags_changed &= ~flag_zero;
|
||||
|
@ -2894,7 +2950,7 @@ t[0xC7] = cpu => {
|
|||
}
|
||||
//dbg_log("rdrand -> " + h(rand >>> 0, 8), LOG_CPU);
|
||||
|
||||
if(cpu.operand_size_32)
|
||||
if(cpu.is_osize_32())
|
||||
{
|
||||
cpu.set_e32(rand);
|
||||
}
|
||||
|
|
|
@ -10,7 +10,8 @@ var A20_MASK32 = ~(1 << 20 - 2);
|
|||
/** @const */
|
||||
var USE_A20 = false;
|
||||
|
||||
// called by all memory reads and writes
|
||||
|
||||
// called by all memory writes
|
||||
CPU.prototype.debug_write = function(addr, size, value)
|
||||
{
|
||||
if(!DEBUG)
|
||||
|
@ -80,7 +81,7 @@ CPU.prototype.mmap_write32 = function(addr, value)
|
|||
|
||||
CPU.prototype.in_mapped_range = function(addr)
|
||||
{
|
||||
return addr < 0 || addr >= 0xA0000 && addr < 0xC0000 || addr >= this.memory_size;
|
||||
return (addr | 0) >= 0xA0000 && (addr | 0) < 0xC0000 || (addr >>> 0) >= (this.memory_size >>> 0);
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -185,10 +186,6 @@ CPU.prototype.write8 = function(addr, value)
|
|||
this.debug_write(addr, 1, value);
|
||||
if(USE_A20 && !this.a20_enabled) addr &= A20_MASK;
|
||||
|
||||
var page = addr >>> MMAP_BLOCK_BITS;
|
||||
|
||||
//if(OP_TRANSLATION) this.mem_page_infos[page] |= MEM_PAGE_WRITTEN;
|
||||
|
||||
if(this.in_mapped_range(addr))
|
||||
{
|
||||
this.mmap_write8(addr, value);
|
||||
|
@ -206,16 +203,9 @@ CPU.prototype.write8 = function(addr, value)
|
|||
CPU.prototype.write16 = function(addr, value)
|
||||
{
|
||||
this.debug_write(addr, 2, value);
|
||||
this.check_write2(addr, 2);
|
||||
if(USE_A20 && !this.a20_enabled) addr &= A20_MASK;
|
||||
|
||||
var page = addr >>> MMAP_BLOCK_BITS;
|
||||
|
||||
//if(OP_TRANSLATION)
|
||||
//{
|
||||
// this.mem_page_infos[page] |= MEM_PAGE_WRITTEN;
|
||||
// this.mem_page_infos[addr + 1 >>> MMAP_BLOCK_BITS] |= MEM_PAGE_WRITTEN;
|
||||
//}
|
||||
|
||||
if(this.in_mapped_range(addr))
|
||||
{
|
||||
this.mmap_write16(addr, value);
|
||||
|
@ -237,10 +227,6 @@ CPU.prototype.write_aligned16 = function(addr, value)
|
|||
this.debug_write(addr << 1, 2, value);
|
||||
if(USE_A20 && !this.a20_enabled) addr &= A20_MASK16;
|
||||
|
||||
var page = addr >>> MMAP_BLOCK_BITS - 1;
|
||||
|
||||
//if(OP_TRANSLATION) this.mem_page_infos[page] |= MEM_PAGE_WRITTEN;
|
||||
|
||||
if(this.in_mapped_range(addr << 1))
|
||||
{
|
||||
this.mmap_write16(addr << 1, value);
|
||||
|
@ -258,16 +244,9 @@ CPU.prototype.write_aligned16 = function(addr, value)
|
|||
CPU.prototype.write32 = function(addr, value)
|
||||
{
|
||||
this.debug_write(addr, 4, value);
|
||||
this.check_write2(addr, 4);
|
||||
if(USE_A20 && !this.a20_enabled) addr &= A20_MASK;
|
||||
|
||||
var page = addr >>> MMAP_BLOCK_BITS;
|
||||
|
||||
//if(OP_TRANSLATION)
|
||||
//{
|
||||
// this.mem_page_infos[page] |= MEM_PAGE_WRITTEN;
|
||||
// this.mem_page_infos[addr + 3 >>> MMAP_BLOCK_BITS] |= MEM_PAGE_WRITTEN;
|
||||
//}
|
||||
|
||||
if(this.in_mapped_range(addr))
|
||||
{
|
||||
this.mmap_write32(addr, value);
|
||||
|
@ -287,10 +266,6 @@ CPU.prototype.write_aligned32 = function(addr, value)
|
|||
this.debug_write(addr << 2, 4, value);
|
||||
if(USE_A20 && !this.a20_enabled) addr &= A20_MASK32;
|
||||
|
||||
var page = addr >>> MMAP_BLOCK_BITS - 2;
|
||||
|
||||
//if(OP_TRANSLATION) this.mem_page_infos[page] |= MEM_PAGE_WRITTEN;
|
||||
|
||||
if(this.in_mapped_range(addr << 2))
|
||||
{
|
||||
this.mmap_write32(addr << 2, value);
|
||||
|
@ -307,20 +282,10 @@ CPU.prototype.write_aligned32 = function(addr, value)
|
|||
*/
|
||||
CPU.prototype.write_blob = function(blob, offset)
|
||||
{
|
||||
dbg_assert(blob && blob.length);
|
||||
this.debug_write(offset, blob.length, 0)
|
||||
dbg_assert(blob && blob.length >= 0);
|
||||
|
||||
this.mem8.set(blob, offset);
|
||||
|
||||
//var page = offset >>> 12;
|
||||
//var end = (offset + blob) >>> 12;
|
||||
|
||||
//if(OP_TRANSLATION)
|
||||
//{
|
||||
// for(; page <= end; page++)
|
||||
// {
|
||||
// this.mem_page_infos[page] |= MEM_PAGE_WRITTEN;
|
||||
// }
|
||||
//}
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -330,5 +295,6 @@ CPU.prototype.write_blob = function(blob, offset)
|
|||
CPU.prototype.write_blob32 = function(blob, offset)
|
||||
{
|
||||
dbg_assert(blob && blob.length);
|
||||
this.debug_write(offset, blob.length << 2, 0);
|
||||
this.mem32s.set(blob, offset);
|
||||
};
|
||||
|
|
|
@ -20,6 +20,11 @@ CPU.prototype.jmpcc8 = function(condition)
|
|||
if(condition)
|
||||
{
|
||||
this.instruction_pointer = this.instruction_pointer + imm8 | 0;
|
||||
this.branch_taken();
|
||||
}
|
||||
else
|
||||
{
|
||||
this.branch_not_taken();
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -40,6 +45,11 @@ CPU.prototype.jmpcc16 = function(condition)
|
|||
if(condition)
|
||||
{
|
||||
this.jmp_rel16(imm16);
|
||||
this.branch_taken();
|
||||
}
|
||||
else
|
||||
{
|
||||
this.branch_not_taken();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -53,6 +63,11 @@ CPU.prototype.jmpcc32 = function(condition)
|
|||
// since read_op32s modifies instruction_pointer
|
||||
|
||||
this.instruction_pointer = this.instruction_pointer + imm32s | 0;
|
||||
this.branch_taken();
|
||||
}
|
||||
else
|
||||
{
|
||||
this.branch_not_taken();
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -81,37 +96,53 @@ CPU.prototype.setcc = function(condition)
|
|||
|
||||
CPU.prototype.loopne = function(imm8s)
|
||||
{
|
||||
if(--this.regv[this.reg_vcx] && !this.getzf())
|
||||
if(this.decr_ecx_asize() && !this.getzf())
|
||||
{
|
||||
this.instruction_pointer = this.instruction_pointer + imm8s | 0;
|
||||
if(!this.operand_size_32) dbg_assert(this.get_real_eip() <= 0xffff);
|
||||
this.branch_taken();
|
||||
}
|
||||
else
|
||||
{
|
||||
this.branch_not_taken();
|
||||
}
|
||||
}
|
||||
|
||||
CPU.prototype.loope = function(imm8s)
|
||||
{
|
||||
if(--this.regv[this.reg_vcx] && this.getzf())
|
||||
if(this.decr_ecx_asize() && this.getzf())
|
||||
{
|
||||
this.instruction_pointer = this.instruction_pointer + imm8s | 0;
|
||||
if(!this.operand_size_32) dbg_assert(this.get_real_eip() <= 0xffff);
|
||||
this.branch_taken();
|
||||
}
|
||||
else
|
||||
{
|
||||
this.branch_not_taken();
|
||||
}
|
||||
}
|
||||
|
||||
CPU.prototype.loop = function(imm8s)
|
||||
{
|
||||
if(--this.regv[this.reg_vcx])
|
||||
if(this.decr_ecx_asize())
|
||||
{
|
||||
this.instruction_pointer = this.instruction_pointer + imm8s | 0;
|
||||
if(!this.operand_size_32) dbg_assert(this.get_real_eip() <= 0xffff);
|
||||
this.branch_taken();
|
||||
}
|
||||
else
|
||||
{
|
||||
this.branch_not_taken();
|
||||
}
|
||||
}
|
||||
|
||||
CPU.prototype.jcxz = function(imm8s)
|
||||
{
|
||||
if(this.regv[this.reg_vcx] === 0)
|
||||
if(this.get_reg_asize(reg_ecx) === 0)
|
||||
{
|
||||
this.instruction_pointer = this.instruction_pointer + imm8s | 0;
|
||||
if(!this.operand_size_32) dbg_assert(this.get_real_eip() <= 0xffff);
|
||||
this.branch_taken();
|
||||
}
|
||||
else
|
||||
{
|
||||
this.branch_not_taken();
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -266,7 +297,7 @@ CPU.prototype.pusha16 = function()
|
|||
|
||||
// make sure we don't get a pagefault after having
|
||||
// pushed several registers already
|
||||
this.translate_address_write(this.get_stack_pointer(-15));
|
||||
this.writable_or_pagefault(this.get_stack_pointer(-16), 16);
|
||||
|
||||
this.push16(this.reg16[reg_ax]);
|
||||
this.push16(this.reg16[reg_cx]);
|
||||
|
@ -282,7 +313,7 @@ CPU.prototype.pusha32 = function()
|
|||
{
|
||||
var temp = this.reg32s[reg_esp];
|
||||
|
||||
this.translate_address_write(this.get_stack_pointer(-31));
|
||||
this.writable_or_pagefault(this.get_stack_pointer(-32), 32);
|
||||
|
||||
this.push32(this.reg32s[reg_eax]);
|
||||
this.push32(this.reg32s[reg_ecx]);
|
||||
|
@ -296,6 +327,7 @@ CPU.prototype.pusha32 = function()
|
|||
|
||||
CPU.prototype.popa16 = function()
|
||||
{
|
||||
this.translate_address_read(this.get_stack_pointer(0));
|
||||
this.translate_address_read(this.get_stack_pointer(15));
|
||||
|
||||
this.reg16[reg_di] = this.pop16();
|
||||
|
@ -310,6 +342,7 @@ CPU.prototype.popa16 = function()
|
|||
|
||||
CPU.prototype.popa32 = function()
|
||||
{
|
||||
this.translate_address_read(this.get_stack_pointer(0));
|
||||
this.translate_address_read(this.get_stack_pointer(31));
|
||||
|
||||
this.reg32s[reg_edi] = this.pop32s();
|
||||
|
@ -419,7 +452,7 @@ CPU.prototype.enter16 = function(size, nesting_level)
|
|||
this.push16(frame_temp);
|
||||
}
|
||||
this.reg16[reg_bp] = frame_temp;
|
||||
this.reg16[reg_sp] -= size;
|
||||
this.adjust_stack_reg(-size);
|
||||
};
|
||||
|
||||
CPU.prototype.enter32 = function(size, nesting_level)
|
||||
|
@ -441,7 +474,7 @@ CPU.prototype.enter32 = function(size, nesting_level)
|
|||
this.push32(frame_temp);
|
||||
}
|
||||
this.reg32s[reg_ebp] = frame_temp;
|
||||
this.reg32s[reg_esp] -= size;
|
||||
this.adjust_stack_reg(-size);
|
||||
};
|
||||
|
||||
CPU.prototype.bswap = function(reg)
|
||||
|
|
18
src/modrm.js
18
src/modrm.js
|
@ -203,15 +203,15 @@
|
|||
};
|
||||
CPU.prototype.modrm_table32[0x00 | 4] = function(cpu)
|
||||
{
|
||||
return cpu.sib_table[cpu.read_sib()](cpu, false) | 0;
|
||||
return cpu.sib_resolve(false) | 0;
|
||||
};
|
||||
CPU.prototype.modrm_table32[0x40 | 4] = function(cpu)
|
||||
{
|
||||
return cpu.sib_table[cpu.read_sib()](cpu, true) + cpu.read_disp8s() | 0;
|
||||
return cpu.sib_resolve(true) + cpu.read_disp8s() | 0;
|
||||
};
|
||||
CPU.prototype.modrm_table32[0x80 | 4] = function(cpu)
|
||||
{
|
||||
return cpu.sib_table[cpu.read_sib()](cpu, true) + cpu.read_disp32s() | 0;
|
||||
return cpu.sib_resolve(true) + cpu.read_disp32s() | 0;
|
||||
};
|
||||
for(var low = 0; low < 8; low++)
|
||||
{
|
||||
|
@ -1250,16 +1250,4 @@
|
|||
{
|
||||
return(cpu.reg32s[reg_edi] << 3) + cpu.get_seg_prefix_ds() + cpu.reg32s[reg_edi] | 0;
|
||||
};
|
||||
|
||||
CPU.prototype.modrm_resolve = function(modrm_byte)
|
||||
{
|
||||
if(modrm_byte < 0xC0)
|
||||
{
|
||||
return(this.address_size_32 ? this.modrm_table32 : this.modrm_table16)[modrm_byte](this);
|
||||
}
|
||||
else
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
};
|
||||
})();
|
||||
|
|
413
src/string.js
413
src/string.js
|
@ -41,15 +41,16 @@ function string_get_cycle_count2(size, addr1, addr2)
|
|||
}
|
||||
|
||||
|
||||
function movsb(cpu)
|
||||
CPU.prototype.movsb = function()
|
||||
{
|
||||
var src = cpu.get_seg_prefix(reg_ds) + cpu.regv[cpu.reg_vsi] | 0;
|
||||
var dest = cpu.get_seg(reg_es) + cpu.regv[cpu.reg_vdi] | 0;
|
||||
var cpu = this;
|
||||
var src = cpu.get_seg_prefix(reg_ds) + cpu.get_reg_asize(reg_esi) | 0;
|
||||
var dest = cpu.get_seg(reg_es) + cpu.get_reg_asize(reg_edi) | 0;
|
||||
var size = cpu.flags & flag_direction ? -1 : 1;
|
||||
|
||||
if(cpu.repeat_string_prefix !== REPEAT_STRING_PREFIX_NONE)
|
||||
if(cpu.prefixes & PREFIX_MASK_REP)
|
||||
{
|
||||
var count = cpu.regv[cpu.reg_vcx] >>> 0;
|
||||
var count = cpu.get_reg_asize(reg_ecx) >>> 0;
|
||||
if(count === 0) return;
|
||||
var cont = false;
|
||||
var start_count = count;
|
||||
|
@ -69,32 +70,35 @@ function movsb(cpu)
|
|||
}
|
||||
while(cont && cycle_counter--);
|
||||
var diff = size * (start_count - count) | 0;
|
||||
cpu.regv[cpu.reg_vdi] += diff;
|
||||
cpu.regv[cpu.reg_vsi] += diff;
|
||||
cpu.regv[cpu.reg_vcx] = count;
|
||||
cpu.add_reg_asize(reg_edi, diff);
|
||||
cpu.add_reg_asize(reg_esi, diff);
|
||||
cpu.set_ecx_asize(count);
|
||||
cpu.timestamp_counter += start_count - count;
|
||||
if(cont)
|
||||
{
|
||||
cpu.instruction_pointer = cpu.previous_ip;
|
||||
//cpu.instruction_pointer = cpu.previous_ip;
|
||||
this.movsb();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
cpu.safe_write8(dest, cpu.safe_read8(src));
|
||||
cpu.regv[cpu.reg_vdi] += size;
|
||||
cpu.regv[cpu.reg_vsi] += size;
|
||||
cpu.add_reg_asize(reg_edi, size);
|
||||
cpu.add_reg_asize(reg_esi, size);
|
||||
}
|
||||
cpu.diverged();
|
||||
}
|
||||
|
||||
function movsw(cpu)
|
||||
CPU.prototype.movsw = function()
|
||||
{
|
||||
var src = cpu.get_seg_prefix(reg_ds) + cpu.regv[cpu.reg_vsi] | 0;
|
||||
var dest = cpu.get_seg(reg_es) + cpu.regv[cpu.reg_vdi] | 0;
|
||||
var cpu = this;
|
||||
var src = cpu.get_seg_prefix(reg_ds) + cpu.get_reg_asize(reg_esi) | 0;
|
||||
var dest = cpu.get_seg(reg_es) + cpu.get_reg_asize(reg_edi) | 0;
|
||||
var size = cpu.flags & flag_direction ? -2 : 2;
|
||||
|
||||
if(cpu.repeat_string_prefix !== REPEAT_STRING_PREFIX_NONE)
|
||||
if(cpu.prefixes & PREFIX_MASK_REP)
|
||||
{
|
||||
var count = cpu.regv[cpu.reg_vcx] >>> 0;
|
||||
var count = cpu.get_reg_asize(reg_ecx) >>> 0;
|
||||
if(count === 0) return;
|
||||
var cont = false;
|
||||
var start_count = count;
|
||||
|
@ -117,9 +121,9 @@ function movsw(cpu)
|
|||
}
|
||||
while(cont && cycle_counter--);
|
||||
var diff = size * (start_count - count) | 0;
|
||||
cpu.regv[cpu.reg_vdi] += diff;
|
||||
cpu.regv[cpu.reg_vsi] += diff;
|
||||
cpu.regv[cpu.reg_vcx] = count;
|
||||
cpu.add_reg_asize(reg_edi, diff);
|
||||
cpu.add_reg_asize(reg_esi, diff);
|
||||
cpu.set_ecx_asize(count);
|
||||
cpu.timestamp_counter += start_count - count;
|
||||
}
|
||||
else
|
||||
|
@ -128,37 +132,41 @@ function movsw(cpu)
|
|||
{
|
||||
cpu.safe_write16(dest, cpu.safe_read16(src));
|
||||
dest += size;
|
||||
cpu.regv[cpu.reg_vdi] += size;
|
||||
cpu.add_reg_asize(reg_edi, size);
|
||||
src += size;
|
||||
cpu.regv[cpu.reg_vsi] += size;
|
||||
cont = --cpu.regv[cpu.reg_vcx] !== 0;
|
||||
cpu.add_reg_asize(reg_esi, size);
|
||||
cont = cpu.decr_ecx_asize() !== 0;
|
||||
}
|
||||
while(cont && cycle_counter--);
|
||||
}
|
||||
if(cont)
|
||||
{
|
||||
cpu.instruction_pointer = cpu.previous_ip;
|
||||
//cpu.instruction_pointer = cpu.previous_ip;
|
||||
this.movsw();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
cpu.safe_write16(dest, cpu.safe_read16(src));
|
||||
cpu.regv[cpu.reg_vdi] += size;
|
||||
cpu.regv[cpu.reg_vsi] += size;
|
||||
cpu.add_reg_asize(reg_edi, size);
|
||||
cpu.add_reg_asize(reg_esi, size);
|
||||
}
|
||||
cpu.diverged();
|
||||
}
|
||||
|
||||
function movsd(cpu)
|
||||
CPU.prototype.movsd = function()
|
||||
{
|
||||
if(cpu.repeat_string_prefix !== REPEAT_STRING_PREFIX_NONE)
|
||||
var cpu = this;
|
||||
//if(cpu.prefixes & PREFIX_MASK_REP)
|
||||
if(false)
|
||||
{
|
||||
// often used by memcpy, well worth optimizing
|
||||
// using cpu.mem32s.set
|
||||
var ds = cpu.get_seg_prefix(reg_ds),
|
||||
src = ds + cpu.regv[cpu.reg_vsi] | 0,
|
||||
src = ds + cpu.get_reg_asize(reg_esi) | 0,
|
||||
es = cpu.get_seg(reg_es),
|
||||
dest = es + cpu.regv[cpu.reg_vdi] | 0,
|
||||
count = cpu.regv[cpu.reg_vcx] >>> 0;
|
||||
dest = es + cpu.get_reg_asize(reg_edi) | 0,
|
||||
count = cpu.get_reg_asize(reg_ecx) >>> 0;
|
||||
|
||||
if(!count)
|
||||
{
|
||||
|
@ -192,9 +200,9 @@ function movsd(cpu)
|
|||
!cpu.io.in_mmap_range(dest, count))
|
||||
{
|
||||
var diff = count << 2;
|
||||
cpu.regv[cpu.reg_vcx] -= count;
|
||||
cpu.regv[cpu.reg_vdi] += diff;
|
||||
cpu.regv[cpu.reg_vsi] += diff;
|
||||
cpu.add_reg_asize(reg_ecx, -count);
|
||||
cpu.add_reg_asize(reg_edi, diff);
|
||||
cpu.add_reg_asize(reg_esi, diff);
|
||||
|
||||
dest >>= 2;
|
||||
src >>= 2;
|
||||
|
@ -202,7 +210,8 @@ function movsd(cpu)
|
|||
|
||||
if(cont)
|
||||
{
|
||||
cpu.instruction_pointer = cpu.previous_ip;
|
||||
//cpu.instruction_pointer = cpu.previous_ip;
|
||||
this.movsd();
|
||||
}
|
||||
|
||||
return;
|
||||
|
@ -210,13 +219,13 @@ function movsd(cpu)
|
|||
}
|
||||
}
|
||||
|
||||
var src = cpu.get_seg_prefix(reg_ds) + cpu.regv[cpu.reg_vsi] | 0;
|
||||
var dest = cpu.get_seg(reg_es) + cpu.regv[cpu.reg_vdi] | 0;
|
||||
var src = cpu.get_seg_prefix(reg_ds) + cpu.get_reg_asize(reg_esi) | 0;
|
||||
var dest = cpu.get_seg(reg_es) + cpu.get_reg_asize(reg_edi) | 0;
|
||||
var size = cpu.flags & flag_direction ? -4 : 4;
|
||||
|
||||
if(cpu.repeat_string_prefix !== REPEAT_STRING_PREFIX_NONE)
|
||||
if(cpu.prefixes & PREFIX_MASK_REP)
|
||||
{
|
||||
var count = cpu.regv[cpu.reg_vcx] >>> 0;
|
||||
var count = cpu.get_reg_asize(reg_ecx) >>> 0;
|
||||
if(count === 0) return;
|
||||
var cont = false;
|
||||
var start_count = count;
|
||||
|
@ -239,9 +248,9 @@ function movsd(cpu)
|
|||
}
|
||||
while(cont && cycle_counter--);
|
||||
var diff = size * (start_count - count) | 0;
|
||||
cpu.regv[cpu.reg_vdi] += diff;
|
||||
cpu.regv[cpu.reg_vsi] += diff;
|
||||
cpu.regv[cpu.reg_vcx] = count;
|
||||
cpu.add_reg_asize(reg_edi, diff);
|
||||
cpu.add_reg_asize(reg_esi, diff);
|
||||
cpu.set_ecx_asize(count);
|
||||
cpu.timestamp_counter += start_count - count;
|
||||
}
|
||||
else
|
||||
|
@ -250,40 +259,42 @@ function movsd(cpu)
|
|||
{
|
||||
cpu.safe_write32(dest, cpu.safe_read32s(src));
|
||||
dest += size;
|
||||
cpu.regv[cpu.reg_vdi] += size;
|
||||
cpu.add_reg_asize(reg_edi, size);
|
||||
src += size;
|
||||
cpu.regv[cpu.reg_vsi] += size;
|
||||
cont = --cpu.regv[cpu.reg_vcx] !== 0;
|
||||
cpu.add_reg_asize(reg_esi, size);
|
||||
cont = cpu.decr_ecx_asize() !== 0;
|
||||
}
|
||||
while(cont && cycle_counter--);
|
||||
}
|
||||
if(cont)
|
||||
{
|
||||
cpu.instruction_pointer = cpu.previous_ip;
|
||||
this.instruction_pointer = this.previous_ip;
|
||||
//this.movsd();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
cpu.safe_write32(dest, cpu.safe_read32s(src));
|
||||
cpu.regv[cpu.reg_vdi] += size;
|
||||
cpu.regv[cpu.reg_vsi] += size;
|
||||
cpu.add_reg_asize(reg_edi, size);
|
||||
cpu.add_reg_asize(reg_esi, size);
|
||||
}
|
||||
cpu.diverged();
|
||||
}
|
||||
|
||||
function cmpsb(cpu)
|
||||
{
|
||||
var src = cpu.get_seg_prefix(reg_ds) + cpu.regv[cpu.reg_vsi] | 0;
|
||||
var dest = cpu.get_seg(reg_es) + cpu.regv[cpu.reg_vdi] | 0;
|
||||
var src = cpu.get_seg_prefix(reg_ds) + cpu.get_reg_asize(reg_esi) | 0;
|
||||
var dest = cpu.get_seg(reg_es) + cpu.get_reg_asize(reg_edi) | 0;
|
||||
var data_src, data_dest;
|
||||
var size = cpu.flags & flag_direction ? -1 : 1;
|
||||
|
||||
if(cpu.repeat_string_prefix !== REPEAT_STRING_PREFIX_NONE)
|
||||
if(cpu.prefixes & PREFIX_MASK_REP)
|
||||
{
|
||||
var count = cpu.regv[cpu.reg_vcx] >>> 0;
|
||||
var count = cpu.get_reg_asize(reg_ecx) >>> 0;
|
||||
if(count === 0) return;
|
||||
var cont = false;
|
||||
var start_count = count;
|
||||
var is_repz = cpu.repeat_string_prefix === REPEAT_STRING_PREFIX_Z;
|
||||
var is_repz = (cpu.prefixes & PREFIX_MASK_REP) === PREFIX_REPZ;
|
||||
var cycle_counter = MAX_COUNT_PER_CYCLE;
|
||||
var phys_src = cpu.translate_address_read(src);
|
||||
var phys_dest = cpu.translate_address_read(dest);
|
||||
|
@ -301,9 +312,9 @@ function cmpsb(cpu)
|
|||
}
|
||||
while(cont && cycle_counter--);
|
||||
var diff = size * (start_count - count) | 0;
|
||||
cpu.regv[cpu.reg_vdi] += diff;
|
||||
cpu.regv[cpu.reg_vsi] += diff;
|
||||
cpu.regv[cpu.reg_vcx] = count;
|
||||
cpu.add_reg_asize(reg_edi, diff);
|
||||
cpu.add_reg_asize(reg_esi, diff);
|
||||
cpu.set_ecx_asize(count);
|
||||
cpu.timestamp_counter += start_count - count;
|
||||
if(cont)
|
||||
{
|
||||
|
@ -314,27 +325,28 @@ function cmpsb(cpu)
|
|||
{
|
||||
data_src = cpu.safe_read8(src);
|
||||
data_dest = cpu.safe_read8(dest);
|
||||
cpu.regv[cpu.reg_vdi] += size;
|
||||
cpu.regv[cpu.reg_vsi] += size;
|
||||
cpu.add_reg_asize(reg_edi, size);
|
||||
cpu.add_reg_asize(reg_esi, size);
|
||||
}
|
||||
|
||||
cpu.cmp8(data_src, data_dest);
|
||||
cpu.diverged();
|
||||
}
|
||||
|
||||
function cmpsw(cpu)
|
||||
{
|
||||
var src = cpu.get_seg_prefix(reg_ds) + cpu.regv[cpu.reg_vsi] | 0;
|
||||
var dest = cpu.get_seg(reg_es) + cpu.regv[cpu.reg_vdi] | 0;
|
||||
var src = cpu.get_seg_prefix(reg_ds) + cpu.get_reg_asize(reg_esi) | 0;
|
||||
var dest = cpu.get_seg(reg_es) + cpu.get_reg_asize(reg_edi) | 0;
|
||||
var data_src, data_dest;
|
||||
var size = cpu.flags & flag_direction ? -2 : 2;
|
||||
|
||||
if(cpu.repeat_string_prefix !== REPEAT_STRING_PREFIX_NONE)
|
||||
if(cpu.prefixes & PREFIX_MASK_REP)
|
||||
{
|
||||
var count = cpu.regv[cpu.reg_vcx] >>> 0;
|
||||
var count = cpu.get_reg_asize(reg_ecx) >>> 0;
|
||||
if(count === 0) return;
|
||||
var cont = false;
|
||||
var start_count = count;
|
||||
var is_repz = cpu.repeat_string_prefix === REPEAT_STRING_PREFIX_Z;
|
||||
var is_repz = (cpu.prefixes & PREFIX_MASK_REP) === PREFIX_REPZ;
|
||||
var cycle_counter = MAX_COUNT_PER_CYCLE;
|
||||
if(!(dest & 1) && !(src & 1))
|
||||
{
|
||||
|
@ -355,9 +367,9 @@ function cmpsw(cpu)
|
|||
}
|
||||
while(cont && cycle_counter--);
|
||||
var diff = size * (start_count - count) | 0;
|
||||
cpu.regv[cpu.reg_vdi] += diff;
|
||||
cpu.regv[cpu.reg_vsi] += diff;
|
||||
cpu.regv[cpu.reg_vcx] = count;
|
||||
cpu.add_reg_asize(reg_edi, diff);
|
||||
cpu.add_reg_asize(reg_esi, diff);
|
||||
cpu.set_ecx_asize(count);
|
||||
cpu.timestamp_counter += start_count - count;
|
||||
}
|
||||
else
|
||||
|
@ -367,10 +379,10 @@ function cmpsw(cpu)
|
|||
data_dest = cpu.safe_read16(dest);
|
||||
data_src = cpu.safe_read16(src);
|
||||
dest += size;
|
||||
cpu.regv[cpu.reg_vdi] += size;
|
||||
cpu.add_reg_asize(reg_edi, size);
|
||||
src += size;
|
||||
cpu.regv[cpu.reg_vsi] += size;
|
||||
cont = --cpu.regv[cpu.reg_vcx] !== 0 && (data_src === data_dest) === is_repz;
|
||||
cpu.add_reg_asize(reg_esi, size);
|
||||
cont = cpu.decr_ecx_asize() !== 0 && (data_src === data_dest) === is_repz;
|
||||
}
|
||||
while(cont && cycle_counter--);
|
||||
}
|
||||
|
@ -383,27 +395,28 @@ function cmpsw(cpu)
|
|||
{
|
||||
data_dest = cpu.safe_read16(dest);
|
||||
data_src = cpu.safe_read16(src);
|
||||
cpu.regv[cpu.reg_vdi] += size;
|
||||
cpu.regv[cpu.reg_vsi] += size;
|
||||
cpu.add_reg_asize(reg_edi, size);
|
||||
cpu.add_reg_asize(reg_esi, size);
|
||||
}
|
||||
|
||||
cpu.cmp16(data_src, data_dest);
|
||||
cpu.diverged();
|
||||
}
|
||||
|
||||
function cmpsd(cpu)
|
||||
{
|
||||
var src = cpu.get_seg_prefix(reg_ds) + cpu.regv[cpu.reg_vsi] | 0;
|
||||
var dest = cpu.get_seg(reg_es) + cpu.regv[cpu.reg_vdi] | 0;
|
||||
var src = cpu.get_seg_prefix(reg_ds) + cpu.get_reg_asize(reg_esi) | 0;
|
||||
var dest = cpu.get_seg(reg_es) + cpu.get_reg_asize(reg_edi) | 0;
|
||||
var data_src, data_dest;
|
||||
var size = cpu.flags & flag_direction ? -4 : 4;
|
||||
|
||||
if(cpu.repeat_string_prefix !== REPEAT_STRING_PREFIX_NONE)
|
||||
if(cpu.prefixes & PREFIX_MASK_REP)
|
||||
{
|
||||
var count = cpu.regv[cpu.reg_vcx] >>> 0;
|
||||
var count = cpu.get_reg_asize(reg_ecx) >>> 0;
|
||||
if(count === 0) return;
|
||||
var cont = false;
|
||||
var start_count = count;
|
||||
var is_repz = cpu.repeat_string_prefix === REPEAT_STRING_PREFIX_Z;
|
||||
var is_repz = (cpu.prefixes & PREFIX_MASK_REP) === PREFIX_REPZ;
|
||||
var cycle_counter = MAX_COUNT_PER_CYCLE;
|
||||
if(!(dest & 3) && !(src & 3))
|
||||
{
|
||||
|
@ -424,9 +437,9 @@ function cmpsd(cpu)
|
|||
}
|
||||
while(cont && cycle_counter--);
|
||||
var diff = size * (start_count - count) | 0;
|
||||
cpu.regv[cpu.reg_vdi] += diff;
|
||||
cpu.regv[cpu.reg_vsi] += diff;
|
||||
cpu.regv[cpu.reg_vcx] = count;
|
||||
cpu.add_reg_asize(reg_edi, diff);
|
||||
cpu.add_reg_asize(reg_esi, diff);
|
||||
cpu.set_ecx_asize(count);
|
||||
cpu.timestamp_counter += start_count - count;
|
||||
}
|
||||
else
|
||||
|
@ -436,10 +449,10 @@ function cmpsd(cpu)
|
|||
data_dest = cpu.safe_read32s(dest);
|
||||
data_src = cpu.safe_read32s(src);
|
||||
dest += size;
|
||||
cpu.regv[cpu.reg_vdi] += size;
|
||||
cpu.add_reg_asize(reg_edi, size);
|
||||
src += size;
|
||||
cpu.regv[cpu.reg_vsi] += size;
|
||||
cont = --cpu.regv[cpu.reg_vcx] !== 0 && (data_src === data_dest) === is_repz;
|
||||
cpu.add_reg_asize(reg_esi, size);
|
||||
cont = cpu.decr_ecx_asize() !== 0 && (data_src === data_dest) === is_repz;
|
||||
}
|
||||
while(cont && cycle_counter--);
|
||||
}
|
||||
|
@ -452,22 +465,23 @@ function cmpsd(cpu)
|
|||
{
|
||||
data_dest = cpu.safe_read32s(dest);
|
||||
data_src = cpu.safe_read32s(src);
|
||||
cpu.regv[cpu.reg_vdi] += size;
|
||||
cpu.regv[cpu.reg_vsi] += size;
|
||||
cpu.add_reg_asize(reg_edi, size);
|
||||
cpu.add_reg_asize(reg_esi, size);
|
||||
}
|
||||
|
||||
cpu.cmp32(data_src, data_dest);
|
||||
cpu.diverged();
|
||||
}
|
||||
|
||||
function stosb(cpu)
|
||||
{
|
||||
var data = cpu.reg8[reg_al];
|
||||
var dest = cpu.get_seg(reg_es) + cpu.regv[cpu.reg_vdi] | 0;
|
||||
var dest = cpu.get_seg(reg_es) + cpu.get_reg_asize(reg_edi) | 0;
|
||||
var size = cpu.flags & flag_direction ? -1 : 1;
|
||||
|
||||
if(cpu.repeat_string_prefix !== REPEAT_STRING_PREFIX_NONE)
|
||||
if(cpu.prefixes & PREFIX_MASK_REP)
|
||||
{
|
||||
var count = cpu.regv[cpu.reg_vcx] >>> 0;
|
||||
var count = cpu.get_reg_asize(reg_ecx) >>> 0;
|
||||
if(count === 0) return;
|
||||
var cont = false;
|
||||
var start_count = count;
|
||||
|
@ -485,8 +499,8 @@ function stosb(cpu)
|
|||
}
|
||||
while(cont && cycle_counter--);
|
||||
var diff = size * (start_count - count) | 0;
|
||||
cpu.regv[cpu.reg_vdi] += diff;
|
||||
cpu.regv[cpu.reg_vcx] = count;
|
||||
cpu.add_reg_asize(reg_edi, diff);
|
||||
cpu.set_ecx_asize(count);
|
||||
cpu.timestamp_counter += start_count - count;
|
||||
if(cont)
|
||||
{
|
||||
|
@ -496,19 +510,20 @@ function stosb(cpu)
|
|||
else
|
||||
{
|
||||
cpu.safe_write8(dest, data);
|
||||
cpu.regv[cpu.reg_vdi] += size;
|
||||
cpu.add_reg_asize(reg_edi, size);
|
||||
}
|
||||
cpu.diverged();
|
||||
}
|
||||
|
||||
function stosw(cpu)
|
||||
{
|
||||
var data = cpu.reg16[reg_ax];
|
||||
var dest = cpu.get_seg(reg_es) + cpu.regv[cpu.reg_vdi] | 0;
|
||||
var dest = cpu.get_seg(reg_es) + cpu.get_reg_asize(reg_edi) | 0;
|
||||
var size = cpu.flags & flag_direction ? -2 : 2;
|
||||
|
||||
if(cpu.repeat_string_prefix !== REPEAT_STRING_PREFIX_NONE)
|
||||
if(cpu.prefixes & PREFIX_MASK_REP)
|
||||
{
|
||||
var count = cpu.regv[cpu.reg_vcx] >>> 0;
|
||||
var count = cpu.get_reg_asize(reg_ecx) >>> 0;
|
||||
if(count === 0) return;
|
||||
var cont = false;
|
||||
var start_count = count;
|
||||
|
@ -529,8 +544,8 @@ function stosw(cpu)
|
|||
}
|
||||
while(cont && cycle_counter--);
|
||||
var diff = size * (start_count - count) | 0;
|
||||
cpu.regv[cpu.reg_vdi] += diff;
|
||||
cpu.regv[cpu.reg_vcx] = count;
|
||||
cpu.add_reg_asize(reg_edi, diff);
|
||||
cpu.set_ecx_asize(count);
|
||||
cpu.timestamp_counter += start_count - count;
|
||||
}
|
||||
else
|
||||
|
@ -539,8 +554,8 @@ function stosw(cpu)
|
|||
{
|
||||
cpu.safe_write16(dest, data);
|
||||
dest += size;
|
||||
cpu.regv[cpu.reg_vdi] += size;
|
||||
cont = --cpu.regv[cpu.reg_vcx] !== 0;
|
||||
cpu.add_reg_asize(reg_edi, size);
|
||||
cont = cpu.decr_ecx_asize() !== 0;
|
||||
}
|
||||
while(cont && cycle_counter--);
|
||||
}
|
||||
|
@ -552,19 +567,20 @@ function stosw(cpu)
|
|||
else
|
||||
{
|
||||
cpu.safe_write16(dest, data);
|
||||
cpu.regv[cpu.reg_vdi] += size;
|
||||
cpu.add_reg_asize(reg_edi, size);
|
||||
}
|
||||
cpu.diverged();
|
||||
}
|
||||
|
||||
function stosd(cpu)
|
||||
{
|
||||
var data = cpu.reg32s[reg_eax];
|
||||
var dest = cpu.get_seg(reg_es) + cpu.regv[cpu.reg_vdi] | 0;
|
||||
var dest = cpu.get_seg(reg_es) + cpu.get_reg_asize(reg_edi) | 0;
|
||||
var size = cpu.flags & flag_direction ? -4 : 4;
|
||||
|
||||
if(cpu.repeat_string_prefix !== REPEAT_STRING_PREFIX_NONE)
|
||||
if(cpu.prefixes & PREFIX_MASK_REP)
|
||||
{
|
||||
var count = cpu.regv[cpu.reg_vcx] >>> 0;
|
||||
var count = cpu.get_reg_asize(reg_ecx) >>> 0;
|
||||
if(count === 0) return;
|
||||
var cont = false;
|
||||
var start_count = count;
|
||||
|
@ -585,8 +601,8 @@ function stosd(cpu)
|
|||
}
|
||||
while(cont && cycle_counter--);
|
||||
var diff = size * (start_count - count) | 0;
|
||||
cpu.regv[cpu.reg_vdi] += diff;
|
||||
cpu.regv[cpu.reg_vcx] = count;
|
||||
cpu.add_reg_asize(reg_edi, diff);
|
||||
cpu.set_ecx_asize(count);
|
||||
cpu.timestamp_counter += start_count - count;
|
||||
}
|
||||
else
|
||||
|
@ -595,8 +611,8 @@ function stosd(cpu)
|
|||
{
|
||||
cpu.safe_write32(dest, data);
|
||||
dest += size;
|
||||
cpu.regv[cpu.reg_vdi] += size;
|
||||
cont = --cpu.regv[cpu.reg_vcx] !== 0;
|
||||
cpu.add_reg_asize(reg_edi, size);
|
||||
cont = cpu.decr_ecx_asize() !== 0;
|
||||
}
|
||||
while(cont && cycle_counter--);
|
||||
}
|
||||
|
@ -608,18 +624,19 @@ function stosd(cpu)
|
|||
else
|
||||
{
|
||||
cpu.safe_write32(dest, data);
|
||||
cpu.regv[cpu.reg_vdi] += size;
|
||||
cpu.add_reg_asize(reg_edi, size);
|
||||
}
|
||||
cpu.diverged();
|
||||
}
|
||||
|
||||
function lodsb(cpu)
|
||||
{
|
||||
var src = cpu.get_seg_prefix(reg_ds) + cpu.regv[cpu.reg_vsi] | 0;
|
||||
var src = cpu.get_seg_prefix(reg_ds) + cpu.get_reg_asize(reg_esi) | 0;
|
||||
var size = cpu.flags & flag_direction ? -1 : 1;
|
||||
|
||||
if(cpu.repeat_string_prefix !== REPEAT_STRING_PREFIX_NONE)
|
||||
if(cpu.prefixes & PREFIX_MASK_REP)
|
||||
{
|
||||
var count = cpu.regv[cpu.reg_vcx] >>> 0;
|
||||
var count = cpu.get_reg_asize(reg_ecx) >>> 0;
|
||||
if(count === 0) return;
|
||||
var cont = false;
|
||||
var start_count = count;
|
||||
|
@ -637,8 +654,8 @@ function lodsb(cpu)
|
|||
}
|
||||
while(cont && cycle_counter--);
|
||||
var diff = size * (start_count - count) | 0;
|
||||
cpu.regv[cpu.reg_vsi] += diff;
|
||||
cpu.regv[cpu.reg_vcx] = count;
|
||||
cpu.add_reg_asize(reg_esi, diff);
|
||||
cpu.set_ecx_asize(count);
|
||||
cpu.timestamp_counter += start_count - count;
|
||||
if(cont)
|
||||
{
|
||||
|
@ -648,18 +665,19 @@ function lodsb(cpu)
|
|||
else
|
||||
{
|
||||
cpu.reg8[reg_al] = cpu.safe_read8(src);
|
||||
cpu.regv[cpu.reg_vsi] += size;
|
||||
cpu.add_reg_asize(reg_esi, size);
|
||||
}
|
||||
cpu.diverged();
|
||||
}
|
||||
|
||||
function lodsw(cpu)
|
||||
{
|
||||
var src = cpu.get_seg_prefix(reg_ds) + cpu.regv[cpu.reg_vsi] | 0;
|
||||
var src = cpu.get_seg_prefix(reg_ds) + cpu.get_reg_asize(reg_esi) | 0;
|
||||
var size = cpu.flags & flag_direction ? -2 : 2;
|
||||
|
||||
if(cpu.repeat_string_prefix !== REPEAT_STRING_PREFIX_NONE)
|
||||
if(cpu.prefixes & PREFIX_MASK_REP)
|
||||
{
|
||||
var count = cpu.regv[cpu.reg_vcx] >>> 0;
|
||||
var count = cpu.get_reg_asize(reg_ecx) >>> 0;
|
||||
if(count === 0) return;
|
||||
var cont = false;
|
||||
var cycle_counter = MAX_COUNT_PER_CYCLE;
|
||||
|
@ -667,8 +685,8 @@ function lodsw(cpu)
|
|||
{
|
||||
cpu.reg16[reg_ax] = cpu.safe_read16(src);
|
||||
src += size;
|
||||
cpu.regv[cpu.reg_vsi] += size;
|
||||
cont = --cpu.regv[cpu.reg_vcx] !== 0;
|
||||
cpu.add_reg_asize(reg_esi, size);
|
||||
cont = cpu.decr_ecx_asize() !== 0;
|
||||
}
|
||||
while(cont && cycle_counter--);
|
||||
if(cont)
|
||||
|
@ -679,18 +697,19 @@ function lodsw(cpu)
|
|||
else
|
||||
{
|
||||
cpu.reg16[reg_ax] = cpu.safe_read16(src);
|
||||
cpu.regv[cpu.reg_vsi] += size;
|
||||
cpu.add_reg_asize(reg_esi, size);
|
||||
}
|
||||
cpu.diverged();
|
||||
}
|
||||
|
||||
function lodsd(cpu)
|
||||
{
|
||||
var src = cpu.get_seg_prefix(reg_ds) + cpu.regv[cpu.reg_vsi] | 0;
|
||||
var src = cpu.get_seg_prefix(reg_ds) + cpu.get_reg_asize(reg_esi) | 0;
|
||||
var size = cpu.flags & flag_direction ? -4 : 4;
|
||||
|
||||
if(cpu.repeat_string_prefix !== REPEAT_STRING_PREFIX_NONE)
|
||||
if(cpu.prefixes & PREFIX_MASK_REP)
|
||||
{
|
||||
var count = cpu.regv[cpu.reg_vcx] >>> 0;
|
||||
var count = cpu.get_reg_asize(reg_ecx) >>> 0;
|
||||
if(count === 0) return;
|
||||
var cont = false;
|
||||
var cycle_counter = MAX_COUNT_PER_CYCLE;
|
||||
|
@ -698,8 +717,8 @@ function lodsd(cpu)
|
|||
{
|
||||
cpu.reg32s[reg_eax] = cpu.safe_read32s(src);
|
||||
src += size;
|
||||
cpu.regv[cpu.reg_vsi] += size;
|
||||
cont = --cpu.regv[cpu.reg_vcx] !== 0;
|
||||
cpu.add_reg_asize(reg_esi, size);
|
||||
cont = cpu.decr_ecx_asize() !== 0;
|
||||
}
|
||||
while(cont && cycle_counter--);
|
||||
if(cont)
|
||||
|
@ -710,24 +729,25 @@ function lodsd(cpu)
|
|||
else
|
||||
{
|
||||
cpu.reg32s[reg_eax] = cpu.safe_read32s(src);
|
||||
cpu.regv[cpu.reg_vsi] += size;
|
||||
cpu.add_reg_asize(reg_esi, size);
|
||||
}
|
||||
cpu.diverged();
|
||||
}
|
||||
|
||||
function scasb(cpu)
|
||||
{
|
||||
var dest = cpu.get_seg(reg_es) + cpu.regv[cpu.reg_vdi] | 0;
|
||||
var dest = cpu.get_seg(reg_es) + cpu.get_reg_asize(reg_edi) | 0;
|
||||
var size = cpu.flags & flag_direction ? -1 : 1;
|
||||
var data_dest;
|
||||
var data_src = cpu.reg8[reg_al];
|
||||
|
||||
if(cpu.repeat_string_prefix !== REPEAT_STRING_PREFIX_NONE)
|
||||
if(cpu.prefixes & PREFIX_MASK_REP)
|
||||
{
|
||||
var count = cpu.regv[cpu.reg_vcx] >>> 0;
|
||||
var count = cpu.get_reg_asize(reg_ecx) >>> 0;
|
||||
if(count === 0) return;
|
||||
var cont = false;
|
||||
var start_count = count;
|
||||
var is_repz = cpu.repeat_string_prefix === REPEAT_STRING_PREFIX_Z;
|
||||
var is_repz = (cpu.prefixes & PREFIX_MASK_REP) === PREFIX_REPZ;
|
||||
var cycle_counter = MAX_COUNT_PER_CYCLE;
|
||||
var phys_dest = cpu.translate_address_read(dest);
|
||||
if(cpu.paging)
|
||||
|
@ -742,8 +762,8 @@ function scasb(cpu)
|
|||
}
|
||||
while(cont && cycle_counter--);
|
||||
var diff = size * (start_count - count) | 0;
|
||||
cpu.regv[cpu.reg_vdi] += diff;
|
||||
cpu.regv[cpu.reg_vcx] = count;
|
||||
cpu.add_reg_asize(reg_edi, diff);
|
||||
cpu.set_ecx_asize(count);
|
||||
cpu.timestamp_counter += start_count - count;
|
||||
if(cont)
|
||||
{
|
||||
|
@ -753,26 +773,27 @@ function scasb(cpu)
|
|||
else
|
||||
{
|
||||
data_dest = cpu.safe_read8(dest);
|
||||
cpu.regv[cpu.reg_vdi] += size;
|
||||
cpu.add_reg_asize(reg_edi, size);
|
||||
}
|
||||
|
||||
cpu.cmp8(data_src, data_dest);
|
||||
cpu.diverged();
|
||||
}
|
||||
|
||||
function scasw(cpu)
|
||||
{
|
||||
var dest = cpu.get_seg(reg_es) + cpu.regv[cpu.reg_vdi] | 0;
|
||||
var dest = cpu.get_seg(reg_es) + cpu.get_reg_asize(reg_edi) | 0;
|
||||
var size = cpu.flags & flag_direction ? -2 : 2;
|
||||
var data_dest;
|
||||
var data_src = cpu.reg16[reg_al];
|
||||
|
||||
if(cpu.repeat_string_prefix !== REPEAT_STRING_PREFIX_NONE)
|
||||
if(cpu.prefixes & PREFIX_MASK_REP)
|
||||
{
|
||||
var count = cpu.regv[cpu.reg_vcx] >>> 0;
|
||||
var count = cpu.get_reg_asize(reg_ecx) >>> 0;
|
||||
if(count === 0) return;
|
||||
var cont = false;
|
||||
var start_count = count;
|
||||
var is_repz = cpu.repeat_string_prefix === REPEAT_STRING_PREFIX_Z;
|
||||
var is_repz = (cpu.prefixes & PREFIX_MASK_REP) === PREFIX_REPZ;
|
||||
var cycle_counter = MAX_COUNT_PER_CYCLE;
|
||||
if(!(dest & 1))
|
||||
{
|
||||
|
@ -790,8 +811,8 @@ function scasw(cpu)
|
|||
}
|
||||
while(cont && cycle_counter--);
|
||||
var diff = size * (start_count - count) | 0;
|
||||
cpu.regv[cpu.reg_vdi] += diff;
|
||||
cpu.regv[cpu.reg_vcx] = count;
|
||||
cpu.add_reg_asize(reg_edi, diff);
|
||||
cpu.set_ecx_asize(count);
|
||||
cpu.timestamp_counter += start_count - count;
|
||||
}
|
||||
else
|
||||
|
@ -800,8 +821,8 @@ function scasw(cpu)
|
|||
{
|
||||
data_dest = cpu.safe_read16(dest);
|
||||
dest += size;
|
||||
cpu.regv[cpu.reg_vdi] += size;
|
||||
cont = --cpu.regv[cpu.reg_vcx] !== 0 && (data_src === data_dest) === is_repz;
|
||||
cpu.add_reg_asize(reg_edi, size);
|
||||
cont = cpu.decr_ecx_asize() !== 0 && (data_src === data_dest) === is_repz;
|
||||
}
|
||||
while(cont && cycle_counter--);
|
||||
}
|
||||
|
@ -813,26 +834,27 @@ function scasw(cpu)
|
|||
else
|
||||
{
|
||||
data_dest = cpu.safe_read16(dest);
|
||||
cpu.regv[cpu.reg_vdi] += size;
|
||||
cpu.add_reg_asize(reg_edi, size);
|
||||
}
|
||||
|
||||
cpu.cmp16(data_src, data_dest);
|
||||
cpu.diverged();
|
||||
}
|
||||
|
||||
function scasd(cpu)
|
||||
{
|
||||
var dest = cpu.get_seg(reg_es) + cpu.regv[cpu.reg_vdi] | 0;
|
||||
var dest = cpu.get_seg(reg_es) + cpu.get_reg_asize(reg_edi) | 0;
|
||||
var size = cpu.flags & flag_direction ? -4 : 4;
|
||||
var data_dest;
|
||||
var data_src = cpu.reg32s[reg_eax];
|
||||
|
||||
if(cpu.repeat_string_prefix !== REPEAT_STRING_PREFIX_NONE)
|
||||
if(cpu.prefixes & PREFIX_MASK_REP)
|
||||
{
|
||||
var count = cpu.regv[cpu.reg_vcx] >>> 0;
|
||||
var count = cpu.get_reg_asize(reg_ecx) >>> 0;
|
||||
if(count === 0) return;
|
||||
var cont = false;
|
||||
var start_count = count;
|
||||
var is_repz = cpu.repeat_string_prefix === REPEAT_STRING_PREFIX_Z;
|
||||
var is_repz = (cpu.prefixes & PREFIX_MASK_REP) === PREFIX_REPZ;
|
||||
var cycle_counter = MAX_COUNT_PER_CYCLE;
|
||||
if(!(dest & 3))
|
||||
{
|
||||
|
@ -850,8 +872,8 @@ function scasd(cpu)
|
|||
}
|
||||
while(cont && cycle_counter--);
|
||||
var diff = size * (start_count - count) | 0;
|
||||
cpu.regv[cpu.reg_vdi] += diff;
|
||||
cpu.regv[cpu.reg_vcx] = count;
|
||||
cpu.add_reg_asize(reg_edi, diff);
|
||||
cpu.set_ecx_asize(count);
|
||||
cpu.timestamp_counter += start_count - count;
|
||||
}
|
||||
else
|
||||
|
@ -860,8 +882,8 @@ function scasd(cpu)
|
|||
{
|
||||
data_dest = cpu.safe_read32s(dest);
|
||||
dest += size;
|
||||
cpu.regv[cpu.reg_vdi] += size;
|
||||
cont = --cpu.regv[cpu.reg_vcx] !== 0 && (data_src === data_dest) === is_repz;
|
||||
cpu.add_reg_asize(reg_edi, size);
|
||||
cont = cpu.decr_ecx_asize() !== 0 && (data_src === data_dest) === is_repz;
|
||||
}
|
||||
while(cont && cycle_counter--);
|
||||
}
|
||||
|
@ -873,10 +895,11 @@ function scasd(cpu)
|
|||
else
|
||||
{
|
||||
data_dest = cpu.safe_read32s(dest);
|
||||
cpu.regv[cpu.reg_vdi] += size;
|
||||
cpu.add_reg_asize(reg_edi, size);
|
||||
}
|
||||
|
||||
cpu.cmp32(data_src, data_dest);
|
||||
cpu.diverged();
|
||||
}
|
||||
|
||||
function insb(cpu)
|
||||
|
@ -884,12 +907,12 @@ function insb(cpu)
|
|||
var port = cpu.reg16[reg_dx];
|
||||
cpu.test_privileges_for_io(port, 1);
|
||||
|
||||
var dest = cpu.get_seg(reg_es) + cpu.regv[cpu.reg_vdi] | 0;
|
||||
var dest = cpu.get_seg(reg_es) + cpu.get_reg_asize(reg_edi) | 0;
|
||||
var size = cpu.flags & flag_direction ? -1 : 1;
|
||||
|
||||
if(cpu.repeat_string_prefix !== REPEAT_STRING_PREFIX_NONE)
|
||||
if(cpu.prefixes & PREFIX_MASK_REP)
|
||||
{
|
||||
var count = cpu.regv[cpu.reg_vcx] >>> 0;
|
||||
var count = cpu.get_reg_asize(reg_ecx) >>> 0;
|
||||
if(count === 0) return;
|
||||
var cont = false;
|
||||
var start_count = count;
|
||||
|
@ -907,8 +930,8 @@ function insb(cpu)
|
|||
}
|
||||
while(cont && cycle_counter--);
|
||||
var diff = size * (start_count - count) | 0;
|
||||
cpu.regv[cpu.reg_vdi] += diff;
|
||||
cpu.regv[cpu.reg_vcx] = count;
|
||||
cpu.add_reg_asize(reg_edi, diff);
|
||||
cpu.set_ecx_asize(count);
|
||||
cpu.timestamp_counter += start_count - count;
|
||||
if(cont)
|
||||
{
|
||||
|
@ -919,8 +942,9 @@ function insb(cpu)
|
|||
else
|
||||
{
|
||||
cpu.safe_write8(dest, cpu.io.port_read8(port));
|
||||
cpu.regv[cpu.reg_vdi] += size;
|
||||
cpu.add_reg_asize(reg_edi, size);
|
||||
}
|
||||
cpu.diverged();
|
||||
}
|
||||
|
||||
function insw(cpu)
|
||||
|
@ -928,12 +952,12 @@ function insw(cpu)
|
|||
var port = cpu.reg16[reg_dx];
|
||||
cpu.test_privileges_for_io(port, 2);
|
||||
|
||||
var dest = cpu.get_seg(reg_es) + cpu.regv[cpu.reg_vdi] | 0;
|
||||
var dest = cpu.get_seg(reg_es) + cpu.get_reg_asize(reg_edi) | 0;
|
||||
var size = cpu.flags & flag_direction ? -2 : 2;
|
||||
|
||||
if(cpu.repeat_string_prefix !== REPEAT_STRING_PREFIX_NONE)
|
||||
if(cpu.prefixes & PREFIX_MASK_REP)
|
||||
{
|
||||
var count = cpu.regv[cpu.reg_vcx] >>> 0;
|
||||
var count = cpu.get_reg_asize(reg_ecx) >>> 0;
|
||||
if(count === 0) return;
|
||||
var cont = false;
|
||||
var start_count = count;
|
||||
|
@ -954,8 +978,8 @@ function insw(cpu)
|
|||
}
|
||||
while(cont && cycle_counter--);
|
||||
var diff = size * (start_count - count) | 0;
|
||||
cpu.regv[cpu.reg_vdi] += diff;
|
||||
cpu.regv[cpu.reg_vcx] = count;
|
||||
cpu.add_reg_asize(reg_edi, diff);
|
||||
cpu.set_ecx_asize(count);
|
||||
cpu.timestamp_counter += start_count - count;
|
||||
}
|
||||
else
|
||||
|
@ -964,8 +988,8 @@ function insw(cpu)
|
|||
{
|
||||
cpu.safe_write16(dest, cpu.io.port_read16(port));
|
||||
dest += size;
|
||||
cpu.regv[cpu.reg_vdi] += size;
|
||||
cont = --cpu.regv[cpu.reg_vcx] !== 0;
|
||||
cpu.add_reg_asize(reg_edi, size);
|
||||
cont = cpu.decr_ecx_asize() !== 0;
|
||||
}
|
||||
while(cont && cycle_counter--);
|
||||
}
|
||||
|
@ -978,8 +1002,9 @@ function insw(cpu)
|
|||
else
|
||||
{
|
||||
cpu.safe_write16(dest, cpu.io.port_read16(port));
|
||||
cpu.regv[cpu.reg_vdi] += size;
|
||||
cpu.add_reg_asize(reg_edi, size);
|
||||
}
|
||||
cpu.diverged();
|
||||
}
|
||||
|
||||
function insd(cpu)
|
||||
|
@ -987,12 +1012,12 @@ function insd(cpu)
|
|||
var port = cpu.reg16[reg_dx];
|
||||
cpu.test_privileges_for_io(port, 4);
|
||||
|
||||
var dest = cpu.get_seg(reg_es) + cpu.regv[cpu.reg_vdi] | 0;
|
||||
var dest = cpu.get_seg(reg_es) + cpu.get_reg_asize(reg_edi) | 0;
|
||||
var size = cpu.flags & flag_direction ? -4 : 4;
|
||||
|
||||
if(cpu.repeat_string_prefix !== REPEAT_STRING_PREFIX_NONE)
|
||||
if(cpu.prefixes & PREFIX_MASK_REP)
|
||||
{
|
||||
var count = cpu.regv[cpu.reg_vcx] >>> 0;
|
||||
var count = cpu.get_reg_asize(reg_ecx) >>> 0;
|
||||
if(count === 0) return;
|
||||
var cont = false;
|
||||
var start_count = count;
|
||||
|
@ -1013,8 +1038,8 @@ function insd(cpu)
|
|||
}
|
||||
while(cont && cycle_counter--);
|
||||
var diff = size * (start_count - count) | 0;
|
||||
cpu.regv[cpu.reg_vdi] += diff;
|
||||
cpu.regv[cpu.reg_vcx] = count;
|
||||
cpu.add_reg_asize(reg_edi, diff);
|
||||
cpu.set_ecx_asize(count);
|
||||
cpu.timestamp_counter += start_count - count;
|
||||
}
|
||||
else
|
||||
|
@ -1023,8 +1048,8 @@ function insd(cpu)
|
|||
{
|
||||
cpu.safe_write32(dest, cpu.io.port_read32(port));
|
||||
dest += size;
|
||||
cpu.regv[cpu.reg_vdi] += size;
|
||||
cont = --cpu.regv[cpu.reg_vcx] !== 0;
|
||||
cpu.add_reg_asize(reg_edi, size);
|
||||
cont = cpu.decr_ecx_asize() !== 0;
|
||||
}
|
||||
while(cont && cycle_counter--);
|
||||
}
|
||||
|
@ -1037,8 +1062,9 @@ function insd(cpu)
|
|||
else
|
||||
{
|
||||
cpu.safe_write32(dest, cpu.io.port_read32(port));
|
||||
cpu.regv[cpu.reg_vdi] += size;
|
||||
cpu.add_reg_asize(reg_edi, size);
|
||||
}
|
||||
cpu.diverged();
|
||||
}
|
||||
|
||||
function outsb(cpu)
|
||||
|
@ -1046,12 +1072,12 @@ function outsb(cpu)
|
|||
var port = cpu.reg16[reg_dx];
|
||||
cpu.test_privileges_for_io(port, 1);
|
||||
|
||||
var src = cpu.get_seg_prefix(reg_ds) + cpu.regv[cpu.reg_vsi] | 0;
|
||||
var src = cpu.get_seg_prefix(reg_ds) + cpu.get_reg_asize(reg_esi) | 0;
|
||||
var size = cpu.flags & flag_direction ? -1 : 1;
|
||||
|
||||
if(cpu.repeat_string_prefix !== REPEAT_STRING_PREFIX_NONE)
|
||||
if(cpu.prefixes & PREFIX_MASK_REP)
|
||||
{
|
||||
var count = cpu.regv[cpu.reg_vcx] >>> 0;
|
||||
var count = cpu.get_reg_asize(reg_ecx) >>> 0;
|
||||
if(count === 0) return;
|
||||
var cont = false;
|
||||
var start_count = count;
|
||||
|
@ -1069,8 +1095,8 @@ function outsb(cpu)
|
|||
}
|
||||
while(cont && cycle_counter--);
|
||||
var diff = size * (start_count - count) | 0;
|
||||
cpu.regv[cpu.reg_vsi] += diff;
|
||||
cpu.regv[cpu.reg_vcx] = count;
|
||||
cpu.add_reg_asize(reg_esi, diff);
|
||||
cpu.set_ecx_asize(count);
|
||||
cpu.timestamp_counter += start_count - count;
|
||||
if(cont)
|
||||
{
|
||||
|
@ -1081,8 +1107,9 @@ function outsb(cpu)
|
|||
else
|
||||
{
|
||||
cpu.io.port_write8(port, cpu.safe_read8(src));
|
||||
cpu.regv[cpu.reg_vsi] += size;
|
||||
cpu.add_reg_asize(reg_esi, size);
|
||||
}
|
||||
cpu.diverged();
|
||||
}
|
||||
|
||||
function outsw(cpu)
|
||||
|
@ -1090,12 +1117,12 @@ function outsw(cpu)
|
|||
var port = cpu.reg16[reg_dx];
|
||||
cpu.test_privileges_for_io(port, 2);
|
||||
|
||||
var src = cpu.get_seg_prefix(reg_ds) + cpu.regv[cpu.reg_vsi] | 0;
|
||||
var src = cpu.get_seg_prefix(reg_ds) + cpu.get_reg_asize(reg_esi) | 0;
|
||||
var size = cpu.flags & flag_direction ? -2 : 2;
|
||||
|
||||
if(cpu.repeat_string_prefix !== REPEAT_STRING_PREFIX_NONE)
|
||||
if(cpu.prefixes & PREFIX_MASK_REP)
|
||||
{
|
||||
var count = cpu.regv[cpu.reg_vcx] >>> 0;
|
||||
var count = cpu.get_reg_asize(reg_ecx) >>> 0;
|
||||
if(count === 0) return;
|
||||
var cont = false;
|
||||
var start_count = count;
|
||||
|
@ -1116,8 +1143,8 @@ function outsw(cpu)
|
|||
}
|
||||
while(cont && cycle_counter--);
|
||||
var diff = size * (start_count - count) | 0;
|
||||
cpu.regv[cpu.reg_vsi] += diff;
|
||||
cpu.regv[cpu.reg_vcx] = count;
|
||||
cpu.add_reg_asize(reg_esi, diff);
|
||||
cpu.set_ecx_asize(count);
|
||||
cpu.timestamp_counter += start_count - count;
|
||||
}
|
||||
else
|
||||
|
@ -1126,8 +1153,8 @@ function outsw(cpu)
|
|||
{
|
||||
cpu.io.port_write16(port, cpu.safe_read16(src));
|
||||
src += size;
|
||||
cpu.regv[cpu.reg_vsi] += size;
|
||||
cont = --cpu.regv[cpu.reg_vcx] !== 0;
|
||||
cpu.add_reg_asize(reg_esi, size);
|
||||
cont = cpu.decr_ecx_asize() !== 0;
|
||||
}
|
||||
while(cont && cycle_counter--);
|
||||
}
|
||||
|
@ -1140,8 +1167,9 @@ function outsw(cpu)
|
|||
else
|
||||
{
|
||||
cpu.io.port_write16(port, cpu.safe_read16(src));
|
||||
cpu.regv[cpu.reg_vsi] += size;
|
||||
cpu.add_reg_asize(reg_esi, size);
|
||||
}
|
||||
cpu.diverged();
|
||||
}
|
||||
|
||||
function outsd(cpu)
|
||||
|
@ -1149,12 +1177,12 @@ function outsd(cpu)
|
|||
var port = cpu.reg16[reg_dx];
|
||||
cpu.test_privileges_for_io(port, 4);
|
||||
|
||||
var src = cpu.get_seg_prefix(reg_ds) + cpu.regv[cpu.reg_vsi] | 0;
|
||||
var src = cpu.get_seg_prefix(reg_ds) + cpu.get_reg_asize(reg_esi) | 0;
|
||||
var size = cpu.flags & flag_direction ? -4 : 4;
|
||||
|
||||
if(cpu.repeat_string_prefix !== REPEAT_STRING_PREFIX_NONE)
|
||||
if(cpu.prefixes & PREFIX_MASK_REP)
|
||||
{
|
||||
var count = cpu.regv[cpu.reg_vcx] >>> 0;
|
||||
var count = cpu.get_reg_asize(reg_ecx) >>> 0;
|
||||
if(count === 0) return;
|
||||
var cont = false;
|
||||
var start_count = count;
|
||||
|
@ -1175,8 +1203,8 @@ function outsd(cpu)
|
|||
}
|
||||
while(cont && cycle_counter--);
|
||||
var diff = size * (start_count - count) | 0;
|
||||
cpu.regv[cpu.reg_vsi] += diff;
|
||||
cpu.regv[cpu.reg_vcx] = count;
|
||||
cpu.add_reg_asize(reg_esi, diff);
|
||||
cpu.set_ecx_asize(count);
|
||||
cpu.timestamp_counter += start_count - count;
|
||||
}
|
||||
else
|
||||
|
@ -1185,8 +1213,8 @@ function outsd(cpu)
|
|||
{
|
||||
cpu.io.port_write32(port, cpu.safe_read32s(src));
|
||||
src += size;
|
||||
cpu.regv[cpu.reg_vsi] += size;
|
||||
cont = --cpu.regv[cpu.reg_vcx] !== 0;
|
||||
cpu.add_reg_asize(reg_esi, size);
|
||||
cont = cpu.decr_ecx_asize() !== 0;
|
||||
}
|
||||
while(cont && cycle_counter--);
|
||||
}
|
||||
|
@ -1199,6 +1227,7 @@ function outsd(cpu)
|
|||
else
|
||||
{
|
||||
cpu.io.port_write32(port, cpu.safe_read32s(src));
|
||||
cpu.regv[cpu.reg_vsi] += size;
|
||||
cpu.add_reg_asize(reg_esi, size);
|
||||
}
|
||||
cpu.diverged();
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue