Fix small problems in CPU, cleanup

This commit is contained in:
copy 2013-12-28 23:21:43 +01:00
parent 0a401c7a4f
commit 64da166901
7 changed files with 207 additions and 129 deletions

View file

@ -14,7 +14,7 @@ VGA_MEMORY_SIZE = 128 * 64 * 1024,
* @const
* @type {number}
*/
memory_size = 1024 * 1024 * 64;
memory_size = 1024 * 1024 * 128;
var
@ -52,7 +52,7 @@ var
///** @const */ LOG_LEVEL = LOG_FPU | LOG_OTHER;
///** @const */ LOG_LEVEL = LOG_DMA | LOG_DISK | LOG_IO | LOG_PCI;
//** @const */ LOG_LEVEL = LOG_DMA | LOG_DISK | LOG_PCI | LOG_CD | LOG_BIOS;
/** @const */ LOG_LEVEL = LOG_ALL & ~LOG_DMA & ~LOG_PS2 & ~LOG_PIT;
/** @const */ LOG_LEVEL = LOG_ALL & ~LOG_DMA & ~LOG_PS2 & ~LOG_DISK & ~LOG_PIT;
///** @const */ LOG_LEVEL = LOG_SERIAL | LOG_IO;
///** @const */ LOG_LEVEL = LOG_PIT | LOG_RTC;
///** @const */ LOG_LEVEL = 0;

View file

@ -702,7 +702,7 @@ function cpu_init(settings)
};
// 00:07.0 Bridge: Intel Corporation 82371AB/EB/MB PIIX4 ACPI (rev 08)
io.register_device(acpi);
pci.register_device(acpi);
var elcr = 0;
@ -716,21 +716,25 @@ function cpu_init(settings)
elcr = elcr & 0xFF | data << 8;
});
io.register_read(0xb3, function()
{
return 0;
});
// ACPI, pmtimer
io.register_read(0xb008, function(data)
io.register_read(0xb008, function()
{
return 0;
});
io.register_read(0xb009, function(data)
io.register_read(0xb009, function()
{
return 0;
});
io.register_read(0xb00a, function(data)
io.register_read(0xb00a, function()
{
return 0;
});
io.register_read(0xb00b, function(data)
io.register_read(0xb00b, function()
{
return 0;
});
@ -800,6 +804,8 @@ function do_run()
{
now = Date.now();
previous_ip = instruction_pointer;
if(ENABLE_HPET)
{
timer.timer(now, hpet.legacy_mode);
@ -838,6 +844,7 @@ function do_run()
loop_counter++;
}
previous_ip = instruction_pointer;
next_tick();
}
@ -1222,11 +1229,11 @@ function get_esp_npe(mod)
{
if(stack_size_32)
{
return get_seg(reg_ss) + stack_reg[reg_vsp] + mod;
return get_seg(reg_ss) + stack_reg[reg_vsp] + mod | 0;
}
else
{
return get_seg(reg_ss) + (stack_reg[reg_vsp] + mod & 0xFFFF);
return get_seg(reg_ss) + (stack_reg[reg_vsp] + mod & 0xFFFF) | 0;
}
}
@ -1235,12 +1242,12 @@ function get_esp_pe_read(mod)
// UNSAFE: stack_reg[reg_vsp]+mod needs to be masked in 16 bit mode
// (only if paging is enabled and in 16 bit mode)
return translate_address_read(get_seg(reg_ss) + stack_reg[reg_vsp] + mod);
return get_seg(reg_ss) + stack_reg[reg_vsp] + mod | 0;
}
function get_esp_pe_write(mod)
{
return translate_address_write(get_seg(reg_ss) + stack_reg[reg_vsp] + mod);
return get_seg(reg_ss) + stack_reg[reg_vsp] + mod | 0;
}
@ -1257,7 +1264,7 @@ function call_interrupt_vector(interrupt_nr, is_software_int, error_code)
{
if(DEBUG)
{
ops.add(instruction_pointer);
ops.add(instruction_pointer >>> 0);
ops.add("-- INT " + h(interrupt_nr));
ops.add(1);
}
@ -1269,7 +1276,6 @@ function call_interrupt_vector(interrupt_nr, is_software_int, error_code)
// dbg_log("=> ", h(memory.read16(es) * 16 + memory.read16(bx)));
//}
//if(interrupt_nr == 0x10)
//{
// dbg_log("int10 ax=" + h(reg16[reg_ax], 4) + " '" + String.fromCharCode(reg8[reg_al]) + "'");
@ -1277,8 +1283,6 @@ function call_interrupt_vector(interrupt_nr, is_software_int, error_code)
// if(reg8[reg_ah] == 0xe) vga.tt_write(reg8[reg_al]);
//}
//dbg_log("int " + h(interrupt_nr));
//if(interrupt_nr === 0x13)
//{
// dump_regs_short();
@ -1314,7 +1318,7 @@ function call_interrupt_vector(interrupt_nr, is_software_int, error_code)
if((interrupt_nr << 3 | 7) > idtr_size)
{
dbg_log(interrupt_nr, LOG_CPU);
dbg_trace();
dbg_trace(LOG_CPU);
throw unimpl("#GP handler");
}
@ -1369,7 +1373,7 @@ function call_interrupt_vector(interrupt_nr, is_software_int, error_code)
else
{
// invalid type
dbg_trace();
dbg_trace(LOG_CPU);
dbg_log("invalid type: " + h(type));
dbg_log(h(addr) + " " + h(base) + " " + h(selector));
throw unimpl("#GP handler");
@ -1444,19 +1448,25 @@ function call_interrupt_vector(interrupt_nr, is_software_int, error_code)
var old_esp = reg32s[reg_esp],
old_ss = sreg[reg_ss];
reg32[reg_esp] = new_esp;
sreg[reg_ss] = new_ss;
cpl = info.dpl;
//dbg_log("int" + h(interrupt_nr, 2) +" from=" + h(instruction_pointer, 8)
// + " cpl=" + cpl + " old ss:esp=" + h(old_ss,4) + ":" + h(old_esp,8), LOG_CPU);
//dbg_log("int" + h(interrupt_nr, 2) +" from=" + h(instruction_pointer >>> 0, 8)
// + " cpl=" + cpl + " old ss:esp=" + h(old_ss, 4) + ":" + h(old_esp >>> 0, 8), LOG_CPU);
cpl_changed();
if(flags & flag_vm)
is_32 = operand_size_32 = address_size_32 = info.size;
flags &= ~flag_vm & ~flag_rf;
update_operand_size();
update_address_size();
reg32[reg_esp] = new_esp;
switch_seg(reg_ss, new_ss);
if(old_flags & flag_vm)
{
dbg_log("return from vm86 mode", LOG_CPU);
flags &= ~flag_vm & ~flag_rf;
push32(sreg[reg_gs]);
push32(sreg[reg_fs]);
@ -1477,6 +1487,10 @@ function call_interrupt_vector(interrupt_nr, is_software_int, error_code)
//dbg_log("int" + h(interrupt_nr, 2) +" from=" + h(instruction_pointer, 8), LOG_CPU);
}
else
{
dbg_assert(false);
}
push32(old_flags);
@ -1511,7 +1525,11 @@ function call_interrupt_vector(interrupt_nr, is_software_int, error_code)
segment_offsets[reg_cs] = info.base;
//dbg_log("current esp: " + h(reg32[reg_esp]), LOG_CPU);
//dbg_log("call int " + h(interrupt_nr) + " from " + h(instruction_pointer) + " to " + h(base) + " with error_code=" + error_code, LOG_CPU);
//dbg_log("call int " + h(interrupt_nr >>> 0, 8) +
// " from " + h(instruction_pointer >>> 0, 8) +
// " to " + h(base >>> 0) +
// " if=" + +!!(is_trap && flags & flag_interrupt) +
// " error_code=" + error_code, LOG_CPU);
instruction_pointer = get_seg(reg_cs) + base | 0;
@ -1554,7 +1572,7 @@ function raise_exception(interrupt_nr)
{
// warn about error
dbg_log("Exception " + h(interrupt_nr), LOG_CPU);
dbg_trace();
dbg_trace(LOG_CPU);
//throw "exception: " + interrupt_nr;
}
@ -1570,7 +1588,7 @@ function raise_exception_with_code(interrupt_nr, error_code)
if(DEBUG)
{
dbg_log("Exception " + h(interrupt_nr) + " err=" + h(error_code), LOG_CPU);
dbg_trace();
dbg_trace(LOG_CPU);
//throw "exception: " + interrupt_nr;
}
@ -1689,6 +1707,8 @@ function handle_irqs()
{
if(pic)
{
dbg_assert(!page_fault);
if((flags & flag_interrupt) && !page_fault)
{
pic.handle_irqs();
@ -2457,14 +2477,21 @@ function trigger_pagefault(write, user, present)
{
if(LOG_LEVEL & LOG_CPU)
{
//dbg_log("page fault", LOG_CPU);
dbg_trace();
//throw "stop";
dbg_log("page fault w=" + write + " u=" + user + " p=" + present +
" eip=" + h(previous_ip >>> 0, 8) +
" cr2=" + h(cr2 >>> 0, 8), LOG_CPU);
dbg_trace(LOG_CPU);
}
// likely invalid pointer reference
//if((cr2 >>> 0) < 0x100)
//{
// throw "stop";
//}
if(page_fault)
{
dbg_trace();
dbg_trace(LOG_CPU);
throw unimpl("Double fault");
}

View file

@ -88,7 +88,7 @@ function logop(_ip, op)
}
if(!step_mode)
{
//return;
return;
}

View file

@ -133,10 +133,25 @@ var table16 = [],
case 7: i7; break;\
}
// equivalent to switch(modrm_byte >> 3 & 7)
#define sub_op_expr(i0, i1, i2, i3, i4, i5, i6, i7) \
((modrm_byte & 0x20) ? sub_op_expr1(i4, i5, i6, i7) :\
sub_op_expr1(i0, i1, i2, i3))
#define sub_op_expr1(i0, i1, i2, i3)\
((modrm_byte & 0x10) ? sub_op_expr2(i2, i3) :\
sub_op_expr2(i0, i1))
#define sub_op_expr2(i0, i1)\
((modrm_byte & 0x08) ? (i1) :\
(i0))
#define pop_sreg_op(n, reg)\
op2(n, \
{ switch_seg(reg, memory.read16(get_esp_read(0))); stack_reg[reg_vsp] += 2; }, \
{ switch_seg(reg, memory.read16(get_esp_read(0))); stack_reg[reg_vsp] += 4; });
{ switch_seg(reg, safe_read16(get_esp_read(0))); stack_reg[reg_vsp] += 2; }, \
{ switch_seg(reg, safe_read16(get_esp_read(0))); stack_reg[reg_vsp] += 4; });
#define reg_e8 reg8[modrm_byte << 2 & 0xC | modrm_byte >> 2 & 1]
@ -556,18 +571,18 @@ opm(0x8F, {
if(operand_size_32)
{
// change esp first, then resolve modrm address
var sp = get_esp_read(0);
var sp = safe_read32s(get_esp_read(0));
// TODO unsafe
stack_reg[reg_vsp] += 4;
set_ev32(memory.read32s(sp));
set_ev32(sp);
}
else
{
var sp = get_esp_read(0);
var sp = safe_read16(get_esp_read(0));
stack_reg[reg_vsp] += 2;
set_ev16(memory.read16(sp));
set_ev16(sp);
}
});
@ -717,38 +732,47 @@ each_reg(groupB8);
opm(0xC0, {
sub_op(
{ write_e8(rol8(data, read_imm8() & 31)); },
{ write_e8(ror8(data, read_imm8() & 31)); },
{ write_e8(rcl8(data, read_imm8() & 31)); },
{ write_e8(rcr8(data, read_imm8() & 31)); },
{ write_e8(shl8(data, read_imm8() & 31)); },
{ write_e8(shr8(data, read_imm8() & 31)); },
{ write_e8(shl8(data, read_imm8() & 31)); },
{ write_e8(sar8(data, read_imm8() & 31)); }
write_e8(
sub_op_expr(
rol8,
ror8,
rcl8,
rcr8,
shl8,
shr8,
shl8,
sar8
)
(data, read_imm8() & 31)
)
});
opm2(0xC1, {
sub_op(
{ write_ev16(rol16(data, read_imm8() & 31)); },
{ write_ev16(ror16(data, read_imm8() & 31)); },
{ write_ev16(rcl16(data, read_imm8() & 31)); },
{ write_ev16(rcr16(data, read_imm8() & 31)); },
{ write_ev16(shl16(data, read_imm8() & 31)); },
{ write_ev16(shr16(data, read_imm8() & 31)); },
{ write_ev16(shl16(data, read_imm8() & 31)); },
{ write_ev16(sar16(data, read_imm8() & 31)); }
write_ev16(
sub_op_expr(
rol16,
ror16,
rcl16,
rcr16,
shl16,
shr16,
shl16,
sar16
)
(data, read_imm8() & 31)
)
}, {
sub_op(
{ write_ev32(rol32(data, read_imm8() & 31)); },
{ write_ev32(ror32(data, read_imm8() & 31)); },
{ write_ev32(rcl32(data, read_imm8() & 31)); },
{ write_ev32(rcr32(data, read_imm8() & 31)); },
{ write_ev32(shl32(data, read_imm8() & 31)); },
{ write_ev32(shr32(data, read_imm8() & 31)); },
{ write_ev32(shl32(data, read_imm8() & 31)); },
{ write_ev32(sar32(data, read_imm8() & 31)); }
write_ev32(
sub_op_expr(
rol32,
ror32,
rcl32,
rcr32,
shl32,
shr32,
shl32,
sar32
)
(data, read_imm8() & 31)
)
});
@ -1002,7 +1026,7 @@ op2(0xCF, {
//dbg_log("iret to " + h(instruction_pointer));
}
//dbg_log("iret if=" + (flags & flag_interrupt) + " cpl=" + cpl);
//dbg_log("iret if=" + (flags & flag_interrupt) + " cpl=" + cpl + " eip=" + h(instruction_pointer >>> 0, 8), LOG_CPU);
dbg_assert(!page_fault);
handle_irqs();
@ -1010,77 +1034,92 @@ op2(0xCF, {
});
opm(0xD0, {
sub_op(
{ write_e8(rol8(data, 1)); },
{ write_e8(ror8(data, 1)); },
{ write_e8(rcl8(data, 1)); },
{ write_e8(rcr8(data, 1)); },
{ write_e8(shl8(data, 1)); },
{ write_e8(shr8(data, 1)); },
{ write_e8(shl8(data, 1)); },
{ write_e8(sar8(data, 1)); }
write_e8(
sub_op_expr(
rol8,
ror8,
rcl8,
rcr8,
shl8,
shr8,
shl8,
sar8
)
(data, 1)
)
});
opm2(0xD1, {
sub_op(
{ write_ev16(rol16(data, 1)); },
{ write_ev16(ror16(data, 1)); },
{ write_ev16(rcl16(data, 1)); },
{ write_ev16(rcr16(data, 1)); },
{ write_ev16(shl16(data, 1)); },
{ write_ev16(shr16(data, 1)); },
{ write_ev16(shl16(data, 1)); },
{ write_ev16(sar16(data, 1)); }
write_ev16(
sub_op_expr(
rol16,
ror16,
rcl16,
rcr16,
shl16,
shr16,
shl16,
sar16
)
(data, 1)
)
}, {
sub_op(
{ write_ev32(rol32(data, 1)); },
{ write_ev32(ror32(data, 1)); },
{ write_ev32(rcl32(data, 1)); },
{ write_ev32(rcr32(data, 1)); },
{ write_ev32(shl32(data, 1)); },
{ write_ev32(shr32(data, 1)); },
{ write_ev32(shl32(data, 1)); },
{ write_ev32(sar32(data, 1)); }
write_ev32(
sub_op_expr(
rol32,
ror32,
rcl32,
rcr32,
shl32,
shr32,
shl32,
sar32
)
(data, 1)
)
});
opm(0xD2, {
var shift = reg8[reg_cl] & 31;
sub_op(
{ write_e8(rol8(data, shift)); },
{ write_e8(ror8(data, shift)); },
{ write_e8(rcl8(data, shift)); },
{ write_e8(rcr8(data, shift)); },
{ write_e8(shl8(data, shift)); },
{ write_e8(shr8(data, shift)); },
{ write_e8(shl8(data, shift)); },
{ write_e8(sar8(data, shift)); }
write_e8(
sub_op_expr(
rol8,
ror8,
rcl8,
rcr8,
shl8,
shr8,
shl8,
sar8
)
(data, reg8[reg_cl] & 31)
)
});
opm2(0xD3, {
var shift = reg8[reg_cl] & 31;
sub_op(
{ write_ev16(rol16(data, shift)); },
{ write_ev16(ror16(data, shift)); },
{ write_ev16(rcl16(data, shift)); },
{ write_ev16(rcr16(data, shift)); },
{ write_ev16(shl16(data, shift)); },
{ write_ev16(shr16(data, shift)); },
{ write_ev16(shl16(data, shift)); },
{ write_ev16(sar16(data, shift)); }
write_ev16(
sub_op_expr(
rol16,
ror16,
rcl16,
rcr16,
shl16,
shr16,
shl16,
sar16
)
(data, reg8[reg_cl] & 31)
)
}, {
var shift = reg8[reg_cl] & 31;
sub_op(
{ write_ev32(rol32(data, shift)); },
{ write_ev32(ror32(data, shift)); },
{ write_ev32(rcl32(data, shift)); },
{ write_ev32(rcr32(data, shift)); },
{ write_ev32(shl32(data, shift)); },
{ write_ev32(shr32(data, shift)); },
{ write_ev32(shl32(data, shift)); },
{ write_ev32(sar32(data, shift)); }
write_ev32(
sub_op_expr(
rol32,
ror32,
rcl32,
rcr32,
shl32,
shr32,
shl32,
sar32
)
(data, reg8[reg_cl] & 31)
)
});
@ -1360,6 +1399,7 @@ op(0xFB, {
getiopl() === 3 : getiopl() >= cpl))
{
flags |= flag_interrupt;
table[read_imm8()]();
handle_irqs();
}
else
@ -2098,7 +2138,9 @@ opm(0xB1, {
var data = safe_read32(virt_addr);
}
else
{
data = reg_e32;
}
cmp32(data, reg32[reg_eax]);

View file

@ -85,6 +85,9 @@ function dbg_log(stuff, level)
}
}
/**
* @param {number=} level
*/
function dbg_trace(level)
{
if(!DEBUG) return;
@ -95,8 +98,9 @@ function dbg_trace(level)
/**
* console.assert is fucking slow
* @param {string=} msg
* @param {number=} level
*/
function dbg_assert(cond, msg)
function dbg_assert(cond, msg, level)
{
if(!DEBUG) return;

View file

@ -222,32 +222,34 @@ function push16(imm16)
{
var sp = get_esp_write(-2);
safe_write16(sp, imm16);
stack_reg[reg_vsp] -= 2;
memory.write16(sp, imm16);
}
function push32(imm32)
{
var sp = get_esp_write(-4);
safe_write32(sp, imm32);
stack_reg[reg_vsp] -= 4;
memory.write32(sp, imm32);
}
function pop16()
{
var sp = get_esp_read(0);
var sp = get_esp_read(0),
result = safe_read16(sp);
stack_reg[reg_vsp] += 2;
return memory.read16(sp);
return result;
}
function pop32s()
{
var sp = get_esp_read(0);
var sp = get_esp_read(0),
result = safe_read32s(sp);
stack_reg[reg_vsp] += 4;
return memory.read32s(sp);
return result;
}
function pusha16()

View file

@ -83,6 +83,8 @@ function PIC(dev, call_interrupt_vector, handle_irqs, master)
isr |= irq;
}
//dbg_log("master handling irq " + irq_number, LOG_PIC);
//dbg_trace(LOG_PIC);
call_interrupt_vector(irq_map | irq_number, false, false);
return true;
@ -114,6 +116,7 @@ function PIC(dev, call_interrupt_vector, handle_irqs, master)
irr &= ~irq;
isr |= irq;
//dbg_log("slave handling irq " + irq_number, LOG_PIC);
call_interrupt_vector(irq_map | irq_number, false, false);
if(irr)