This commit is contained in:
parent
13989eeaa5
commit
a485494f6f
91
src/cpu.js
91
src/cpu.js
|
@ -76,6 +76,8 @@ function CPU()
|
|||
/** @type {number} */
|
||||
this.gdtr_offset = 0;
|
||||
|
||||
this.tss_size_32 = false;
|
||||
|
||||
/*
|
||||
* whether or not a page fault occured
|
||||
*/
|
||||
|
@ -318,6 +320,8 @@ CPU.prototype.get_state = function()
|
|||
|
||||
state[63] = this.devices.ioapic;
|
||||
|
||||
state[64] = this.tss_size_32;
|
||||
|
||||
return state;
|
||||
};
|
||||
|
||||
|
@ -389,6 +393,8 @@ CPU.prototype.set_state = function(state)
|
|||
|
||||
this.devices.ioapic = state[63];
|
||||
|
||||
this.tss_size_32 = state[64];
|
||||
|
||||
this.mem16 = new Uint16Array(this.mem8.buffer, this.mem8.byteOffset, this.mem8.length >> 1);
|
||||
this.mem32s = new Int32Array(this.mem8.buffer, this.mem8.byteOffset, this.mem8.length >> 2);
|
||||
|
||||
|
@ -1734,8 +1740,16 @@ CPU.prototype.call_interrupt_vector = function(interrupt_nr, is_software_int, er
|
|||
//this.debug.dump_regs();
|
||||
var tss_stack_addr = this.get_tss_stack_addr(info.dpl);
|
||||
|
||||
var new_esp = this.read32s(tss_stack_addr);
|
||||
var new_ss = this.read16(tss_stack_addr + 4 | 0);
|
||||
if(this.tss_size_32)
|
||||
{
|
||||
var new_esp = this.read32s(tss_stack_addr);
|
||||
var new_ss = this.read16(tss_stack_addr + 4 | 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
var new_esp = this.read16(tss_stack_addr);
|
||||
var new_ss = this.read16(tss_stack_addr + 2 | 0);
|
||||
}
|
||||
var ss_info = this.lookup_segment_selector(new_ss);
|
||||
|
||||
// Disabled: Incorrect handling of direction bit
|
||||
|
@ -2402,7 +2416,7 @@ CPU.prototype.far_jump = function(eip, selector, is_call)
|
|||
|
||||
if(info.is_system)
|
||||
{
|
||||
dbg_assert(is_call, "TODO: Jump")
|
||||
dbg_assert(is_call, "TODO: Jump");
|
||||
|
||||
dbg_log("system type cs: " + h(selector), LOG_CPU);
|
||||
|
||||
|
@ -2461,8 +2475,16 @@ CPU.prototype.far_jump = function(eip, selector, is_call)
|
|||
dbg_log("more privilege call gate is_16=" + is_16 + " from=" + this.cpl + " to=" + cs_info.dpl);
|
||||
var tss_stack_addr = this.get_tss_stack_addr(cs_info.dpl);
|
||||
|
||||
var new_esp = this.read32s(tss_stack_addr);
|
||||
var new_ss = this.read16(tss_stack_addr + 4 | 0);
|
||||
if(this.tss_size_32)
|
||||
{
|
||||
var new_esp = this.read32s(tss_stack_addr);
|
||||
var new_ss = this.read16(tss_stack_addr + 4 | 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
var new_esp = this.read16(tss_stack_addr);
|
||||
var new_ss = this.read16(tss_stack_addr + 2 | 0);
|
||||
}
|
||||
var ss_info = this.lookup_segment_selector(new_ss);
|
||||
|
||||
// Disabled: Incorrect handling of direction bit
|
||||
|
@ -2686,27 +2708,44 @@ CPU.prototype.far_jump = function(eip, selector, is_call)
|
|||
|
||||
CPU.prototype.get_tss_stack_addr = function(dpl)
|
||||
{
|
||||
var tss_stack_addr = (dpl << 3) + 4 | 0;
|
||||
|
||||
if((tss_stack_addr + 5 | 0) > this.segment_limits[reg_tr])
|
||||
if(this.tss_size_32)
|
||||
{
|
||||
throw this.debug.unimpl("#TS handler");
|
||||
}
|
||||
var tss_stack_addr = (dpl << 3) + 4 | 0;
|
||||
|
||||
tss_stack_addr = tss_stack_addr + this.segment_offsets[reg_tr] | 0;
|
||||
if((tss_stack_addr + 5 | 0) > this.segment_limits[reg_tr])
|
||||
{
|
||||
throw this.debug.unimpl("#TS handler");
|
||||
}
|
||||
|
||||
tss_stack_addr = tss_stack_addr + this.segment_offsets[reg_tr] | 0;
|
||||
|
||||
dbg_assert((tss_stack_addr & 0xFFF) <= 0x1000 - 6);
|
||||
}
|
||||
else
|
||||
{
|
||||
var tss_stack_addr = (dpl << 2) + 2 | 0;
|
||||
|
||||
if((tss_stack_addr + 5 | 0) > this.segment_limits[reg_tr])
|
||||
{
|
||||
throw this.debug.unimpl("#TS handler");
|
||||
}
|
||||
|
||||
tss_stack_addr = tss_stack_addr + this.segment_offsets[reg_tr] | 0;
|
||||
dbg_assert((tss_stack_addr & 0xFFF) <= 0x1000 - 4);
|
||||
}
|
||||
|
||||
if(this.paging)
|
||||
{
|
||||
tss_stack_addr = this.translate_address_system_read(tss_stack_addr);
|
||||
}
|
||||
|
||||
dbg_assert((tss_stack_addr & 0xFFF) <= 0x1000 - 6);
|
||||
|
||||
return tss_stack_addr;
|
||||
};
|
||||
|
||||
CPU.prototype.do_task_switch = function(selector, error_code)
|
||||
{
|
||||
dbg_assert(!this.tss_size_32, "TODO");
|
||||
|
||||
dbg_log("do_task_switch sel=" + h(selector), LOG_CPU);
|
||||
var descriptor = this.lookup_segment_selector(selector);
|
||||
|
||||
|
@ -3283,12 +3322,12 @@ CPU.prototype.write_e32 = function(value)
|
|||
CPU.prototype.read_reg_e16 = function()
|
||||
{
|
||||
return this.reg16[this.modrm_byte << 1 & 14];
|
||||
}
|
||||
};
|
||||
|
||||
CPU.prototype.write_reg_e16 = function(value)
|
||||
{
|
||||
this.reg16[this.modrm_byte << 1 & 14] = value;
|
||||
}
|
||||
};
|
||||
|
||||
CPU.prototype.read_reg_e32s = function()
|
||||
{
|
||||
|
@ -3399,8 +3438,15 @@ CPU.prototype.test_privileges_for_io = function(port, size)
|
|||
{
|
||||
if(this.protected_mode && (this.cpl > this.getiopl() || (this.flags & flag_vm)))
|
||||
{
|
||||
var tsr_size = this.segment_limits[reg_tr],
|
||||
tsr_offset = this.segment_offsets[reg_tr];
|
||||
if(!this.tss_size_32)
|
||||
{
|
||||
dbg_log("#GP for port io, 16-bit TSS port=" + h(port) + " size=" + size, LOG_CPU);
|
||||
CPU_LOG_VERBOSE && this.debug.dump_state();
|
||||
this.trigger_gp(0);
|
||||
}
|
||||
|
||||
var tsr_size = this.segment_limits[reg_tr];
|
||||
var tsr_offset = this.segment_offsets[reg_tr];
|
||||
|
||||
if(tsr_size >= 0x67)
|
||||
{
|
||||
|
@ -3627,8 +3673,8 @@ CPU.prototype.lookup_segment_selector = function(selector)
|
|||
// limit is the number of entries in the table minus one
|
||||
if((selector | 7) > table_limit)
|
||||
{
|
||||
dbg_log("Selector " + h(selector, 4) + " is outside of the "
|
||||
+ (is_gdt ? "g" : "l") + "dt limits", LOG_CPU)
|
||||
dbg_log("Selector " + h(selector, 4) + " is outside of the " +
|
||||
(is_gdt ? "g" : "l") + "dt limits", LOG_CPU);
|
||||
info.is_valid = false;
|
||||
return info;
|
||||
}
|
||||
|
@ -3825,12 +3871,7 @@ CPU.prototype.load_tr = function(selector)
|
|||
throw this.debug.unimpl("#NT handler");
|
||||
}
|
||||
|
||||
if(info.type === 1)
|
||||
{
|
||||
// 286 tss: Load 16 bit values from tss in call_interrupt_vector
|
||||
throw this.debug.unimpl("286 tss");
|
||||
}
|
||||
|
||||
this.tss_size_32 = info.type === 9;
|
||||
this.segment_offsets[reg_tr] = info.base;
|
||||
this.segment_limits[reg_tr] = info.effective_limit;
|
||||
this.sreg[reg_tr] = selector;
|
||||
|
|
Loading…
Reference in a new issue