Fixed some problems with the IO bus
This commit is contained in:
parent
9240dc669f
commit
81fe7ad9ca
|
@ -1560,92 +1560,6 @@ function handle_irqs()
|
|||
}
|
||||
}
|
||||
|
||||
// any two consecutive 8-bit ports can be treated as a 16-bit port;
|
||||
// and four consecutive 8-bit ports can be treated as a 32-bit port
|
||||
//
|
||||
// http://css.csail.mit.edu/6.858/2012/readings/i386/s08_01.htm
|
||||
|
||||
function out8(port_addr, out_byte)
|
||||
{
|
||||
if(privileges_for_io())
|
||||
{
|
||||
io.port_write(port_addr, out_byte);
|
||||
}
|
||||
else
|
||||
{
|
||||
trigger_gp(0);
|
||||
}
|
||||
}
|
||||
|
||||
function out16(port_addr, out_word)
|
||||
{
|
||||
if(privileges_for_io())
|
||||
{
|
||||
io.port_write(port_addr, out_word & 0xFF);
|
||||
io.port_write(port_addr + 1, out_word >> 8 & 0xFF);
|
||||
}
|
||||
else
|
||||
{
|
||||
trigger_gp(0);
|
||||
}
|
||||
}
|
||||
|
||||
function out32(port_addr, out_dword)
|
||||
{
|
||||
if(privileges_for_io())
|
||||
{
|
||||
io.port_write(port_addr, out_dword & 0xFF);
|
||||
io.port_write(port_addr + 1, out_dword >> 8 & 0xFF);
|
||||
io.port_write(port_addr + 2, out_dword >> 16 & 0xFF);
|
||||
io.port_write(port_addr + 3, out_dword >> 24 & 0xFF);
|
||||
}
|
||||
else
|
||||
{
|
||||
trigger_gp(0);
|
||||
}
|
||||
}
|
||||
|
||||
function in8(port_addr)
|
||||
{
|
||||
if(privileges_for_io())
|
||||
{
|
||||
return io.port_read(port_addr);
|
||||
}
|
||||
else
|
||||
{
|
||||
trigger_gp(0);
|
||||
}
|
||||
}
|
||||
|
||||
function in16(port_addr)
|
||||
{
|
||||
if(privileges_for_io())
|
||||
{
|
||||
return io.port_read(port_addr) |
|
||||
io.port_read(port_addr + 1) << 8;
|
||||
}
|
||||
else
|
||||
{
|
||||
trigger_gp(0);
|
||||
}
|
||||
}
|
||||
|
||||
function in32(port_addr)
|
||||
{
|
||||
if(privileges_for_io())
|
||||
{
|
||||
return io.port_read(port_addr) |
|
||||
io.port_read(port_addr + 1) << 8 |
|
||||
io.port_read(port_addr + 2) << 16 |
|
||||
io.port_read(port_addr + 3) << 24;
|
||||
}
|
||||
else
|
||||
{
|
||||
trigger_gp(0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* returns the current iopl from the eflags register
|
||||
*/
|
||||
|
@ -1654,9 +1568,12 @@ function getiopl()
|
|||
return flags >> 12 & 3;
|
||||
}
|
||||
|
||||
function privileges_for_io()
|
||||
function test_privileges_for_io()
|
||||
{
|
||||
return !protected_mode || cpl <= getiopl();
|
||||
if(protected_mode && cpl > getiopl())
|
||||
{
|
||||
trigger_gp(0);
|
||||
}
|
||||
}
|
||||
|
||||
function cpuid()
|
||||
|
|
|
@ -1103,10 +1103,28 @@ op(0xE1, { loope(); });
|
|||
op(0xE2, { loop(); });
|
||||
op(0xE3, { jcxz(); });
|
||||
|
||||
op(0xE4, { reg8[reg_al] = in8(read_imm8()); });
|
||||
op2(0xE5, { reg16[reg_ax] = in16(read_imm8()); }, { reg32[reg_eax] = in32(read_imm8()); });
|
||||
op(0xE6, { out8(read_imm8(), reg8[reg_al]); });
|
||||
op2(0xE7, { out16(read_imm8(), reg16[reg_ax]); }, { out32(read_imm8(), reg32s[reg_eax]); });
|
||||
op(0xE4, {
|
||||
test_privileges_for_io();
|
||||
reg8[reg_al] = io.port_read8(read_imm8());
|
||||
});
|
||||
op2(0xE5, {
|
||||
test_privileges_for_io();
|
||||
reg16[reg_ax] = io.port_read16(read_imm8());
|
||||
}, {
|
||||
test_privileges_for_io();
|
||||
reg32[reg_eax] = io.port_read32(read_imm8());
|
||||
});
|
||||
op(0xE6, {
|
||||
test_privileges_for_io();
|
||||
io.port_write8(read_imm8(), reg8[reg_al]);
|
||||
});
|
||||
op2(0xE7, {
|
||||
test_privileges_for_io();
|
||||
io.port_write16(read_imm8(), reg16[reg_ax]);
|
||||
}, {
|
||||
test_privileges_for_io();
|
||||
io.port_write32(read_imm8(), reg32s[reg_eax]);
|
||||
});
|
||||
|
||||
op2(0xE8, {
|
||||
// call
|
||||
|
@ -1149,10 +1167,28 @@ op(0xEB, {
|
|||
instruction_pointer = instruction_pointer + imm8 | 0;
|
||||
});
|
||||
|
||||
op(0xEC, { reg8[reg_al] = in8(reg16[reg_dx]); });
|
||||
op2(0xED, { reg16[reg_ax] = in16(reg16[reg_dx]); }, { reg32[reg_eax] = in32(reg16[reg_dx]); });
|
||||
op(0xEE, { out8(reg16[reg_dx], reg8[reg_al]); });
|
||||
op2(0xEF, { out16(reg16[reg_dx], reg16[reg_ax]); }, { out32(reg16[reg_dx], reg32s[reg_eax]); });
|
||||
op(0xEC, {
|
||||
test_privileges_for_io();
|
||||
reg8[reg_al] = io.port_read8(reg16[reg_dx]);
|
||||
});
|
||||
op2(0xED, {
|
||||
test_privileges_for_io();
|
||||
reg16[reg_ax] = io.port_read16(reg16[reg_dx]);
|
||||
}, {
|
||||
test_privileges_for_io();
|
||||
reg32[reg_eax] = io.port_read32(reg16[reg_dx]);
|
||||
});
|
||||
op(0xEE, {
|
||||
test_privileges_for_io();
|
||||
io.port_write8(reg16[reg_dx], reg8[reg_al]);
|
||||
});
|
||||
op2(0xEF, {
|
||||
test_privileges_for_io();
|
||||
io.port_write16(reg16[reg_dx], reg16[reg_ax]);
|
||||
}, {
|
||||
test_privileges_for_io();
|
||||
io.port_write32(reg16[reg_dx], reg32s[reg_eax]);
|
||||
});
|
||||
|
||||
op(0xF0, {
|
||||
// lock
|
||||
|
@ -1264,27 +1300,15 @@ op(0xF9, {
|
|||
op(0xFA, {
|
||||
// cli
|
||||
//dbg_log("interrupts off");
|
||||
if(!privileges_for_io())
|
||||
{
|
||||
trigger_gp(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
flags &= ~flag_interrupt;
|
||||
}
|
||||
test_privileges_for_io();
|
||||
flags &= ~flag_interrupt;
|
||||
});
|
||||
op(0xFB, {
|
||||
// sti
|
||||
//dbg_log("interrupts on");
|
||||
if(!privileges_for_io())
|
||||
{
|
||||
trigger_gp(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
flags |= flag_interrupt;
|
||||
handle_irqs();
|
||||
}
|
||||
test_privileges_for_io();
|
||||
flags |= flag_interrupt;
|
||||
handle_irqs();
|
||||
|
||||
});
|
||||
|
||||
|
|
96
src/io.js
96
src/io.js
|
@ -164,15 +164,103 @@ function IO()
|
|||
});
|
||||
}
|
||||
|
||||
this.port_write = function(port_addr, out_byte)
|
||||
|
||||
// any two consecutive 8-bit ports can be treated as a 16-bit port;
|
||||
// and four consecutive 8-bit ports can be treated as a 32-bit port
|
||||
//
|
||||
// http://css.csail.mit.edu/6.858/2012/readings/i386/s08_01.htm
|
||||
//
|
||||
// This info seems to be incorrect, at least some multibyte ports are next
|
||||
// to each other, such as 1CE and 1CF (VBE dispi) or the 170 (ATA data port).
|
||||
//
|
||||
// As a workaround, we pass the original port to the callback as the last argument.
|
||||
|
||||
|
||||
this.port_write8 = function(port_addr, out_byte)
|
||||
{
|
||||
write_callbacks[port_addr](out_byte);
|
||||
write_callbacks[port_addr](out_byte, port_addr);
|
||||
};
|
||||
|
||||
this.port_write16 = function(port_addr, out_byte)
|
||||
{
|
||||
dbg_log(
|
||||
"write port16 #" + h(port_addr, 3) + " <- " + h(out_byte, 2) + get_port_description(port_addr),
|
||||
LOG_IO
|
||||
);
|
||||
|
||||
if(port_addr <= 0xFFFE)
|
||||
{
|
||||
write_callbacks[port_addr](out_byte & 0xFF, port_addr);
|
||||
write_callbacks[port_addr + 1](out_byte >> 8, port_addr);
|
||||
}
|
||||
else
|
||||
{
|
||||
dbg_log("Ignored 2 byte write to port " + h(port_addr), LOG_IO);
|
||||
}
|
||||
};
|
||||
|
||||
this.port_write32 = function(port_addr, out_byte)
|
||||
{
|
||||
dbg_log(
|
||||
"write port32 #" + h(port_addr, 3) + " <- " + h(out_byte, 2) + get_port_description(port_addr),
|
||||
LOG_IO
|
||||
);
|
||||
|
||||
if(port_addr <= 0xFFFC)
|
||||
{
|
||||
write_callbacks[port_addr](out_byte & 0xFF, port_addr);
|
||||
write_callbacks[port_addr + 1](out_byte >> 8 & 0xFF, port_addr);
|
||||
write_callbacks[port_addr + 2](out_byte >> 16 & 0xFF, port_addr);
|
||||
write_callbacks[port_addr + 3](out_byte >>> 24, port_addr);
|
||||
}
|
||||
else
|
||||
{
|
||||
dbg_log("Ignored 4 byte write to port " + h(port_addr), LOG_IO);
|
||||
}
|
||||
};
|
||||
|
||||
// read byte from port
|
||||
this.port_read = function(port_addr)
|
||||
this.port_read8 = function(port_addr)
|
||||
{
|
||||
return read_callbacks[port_addr]();
|
||||
return read_callbacks[port_addr](port_addr);
|
||||
};
|
||||
|
||||
this.port_read16 = function(port_addr)
|
||||
{
|
||||
dbg_log(
|
||||
"read port16 #" + h(port_addr, 3) + get_port_description(port_addr),
|
||||
LOG_IO
|
||||
);
|
||||
|
||||
if(port_addr <= 0xFFFE)
|
||||
{
|
||||
return read_callbacks[port_addr](port_addr) |
|
||||
read_callbacks[port_addr + 1](port_addr) << 8;
|
||||
}
|
||||
else
|
||||
{
|
||||
dbg_log("Ignored 2 byte read from port " + h(port_addr), LOG_IO);
|
||||
}
|
||||
};
|
||||
|
||||
this.port_read32 = function(port_addr)
|
||||
{
|
||||
dbg_log(
|
||||
"read port32 #" + h(port_addr, 3) + get_port_description(port_addr),
|
||||
LOG_IO
|
||||
);
|
||||
|
||||
if(port_addr <= 0xFFFC)
|
||||
{
|
||||
return read_callbacks[port_addr](port_addr) |
|
||||
read_callbacks[port_addr + 1](port_addr) << 8 |
|
||||
read_callbacks[port_addr + 2](port_addr) << 16 |
|
||||
read_callbacks[port_addr + 3](port_addr) << 24;
|
||||
}
|
||||
else
|
||||
{
|
||||
dbg_log("Ignored 4 byte read from port " + h(port_addr), LOG_IO);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue