2011-12-21 13:34:38 +08:00
|
|
|
/*
|
2013-03-29 10:43:44 +08:00
|
|
|
JSLinux-deobfuscated - An annotated version of the original JSLinux.
|
|
|
|
|
|
|
|
Original is Copyright (c) 2011-2012 Fabrice Bellard
|
|
|
|
Redistribution or commercial use is prohibited without the author's permission.
|
2011-12-21 13:34:38 +08:00
|
|
|
|
|
|
|
Main PC Emulator Routine
|
|
|
|
*/
|
|
|
|
|
2013-09-16 11:17:04 +08:00
|
|
|
// used as callback wrappers for emulated PIT and PIC chips
|
2011-12-21 13:34:38 +08:00
|
|
|
function set_hard_irq_wrapper(irq) { this.hard_irq = irq;}
|
|
|
|
function return_cycle_count() { return this.cycle_count; }
|
|
|
|
|
2013-09-16 11:17:04 +08:00
|
|
|
function PCEmulator(params) {
|
2011-12-21 13:34:38 +08:00
|
|
|
var cpu;
|
|
|
|
cpu = new CPU_X86();
|
|
|
|
this.cpu = cpu;
|
2013-09-16 11:17:04 +08:00
|
|
|
cpu.phys_mem_resize(params.mem_size);
|
2011-12-21 13:34:38 +08:00
|
|
|
this.init_ioports();
|
|
|
|
this.register_ioport_write(0x80, 1, 1, this.ioport80_write);
|
|
|
|
this.pic = new PIC_Controller(this, 0x20, 0xa0, set_hard_irq_wrapper.bind(cpu));
|
|
|
|
this.pit = new PIT(this, this.pic.set_irq.bind(this.pic, 0), return_cycle_count.bind(cpu));
|
|
|
|
this.cmos = new CMOS(this);
|
2013-09-16 11:17:04 +08:00
|
|
|
this.serial = new Serial(this, 0x3f8, this.pic.set_irq.bind(this.pic, 4), params.serial_write);
|
2011-12-21 13:34:38 +08:00
|
|
|
this.kbd = new KBD(this, this.reset.bind(this));
|
|
|
|
this.reset_request = 0;
|
2013-09-16 11:17:04 +08:00
|
|
|
if (params.clipboard_get && params.clipboard_set) {
|
|
|
|
this.jsclipboard = new clipboard_device(this, 0x3c0, params.clipboard_get, params.clipboard_set, params.get_boot_time);
|
2011-12-21 13:34:38 +08:00
|
|
|
}
|
|
|
|
cpu.ld8_port = this.ld8_port.bind(this);
|
|
|
|
cpu.ld16_port = this.ld16_port.bind(this);
|
|
|
|
cpu.ld32_port = this.ld32_port.bind(this);
|
|
|
|
cpu.st8_port = this.st8_port.bind(this);
|
|
|
|
cpu.st16_port = this.st16_port.bind(this);
|
|
|
|
cpu.st32_port = this.st32_port.bind(this);
|
|
|
|
cpu.get_hard_intno = this.pic.get_hard_intno.bind(this.pic);
|
|
|
|
}
|
|
|
|
|
2014-10-20 06:24:09 +08:00
|
|
|
PCEmulator.prototype.load_binary = function(binary_array, mem8_loc) { return this.cpu.load_binary(binary_array, mem8_loc); };
|
2011-12-21 13:34:38 +08:00
|
|
|
|
|
|
|
PCEmulator.prototype.start = function() { setTimeout(this.timer_func.bind(this), 10); };
|
|
|
|
|
|
|
|
PCEmulator.prototype.timer_func = function() {
|
2011-12-24 11:28:34 +08:00
|
|
|
var exit_status, Ncycles, do_reset, err_on_exit, PC, cpu;
|
|
|
|
PC = this;
|
|
|
|
cpu = PC.cpu;
|
|
|
|
Ncycles = cpu.cycle_count + 100000;
|
|
|
|
|
|
|
|
do_reset = false;
|
|
|
|
err_on_exit = false;
|
|
|
|
|
|
|
|
exec_loop: while (cpu.cycle_count < Ncycles) {
|
|
|
|
PC.pit.update_irq();
|
|
|
|
exit_status = cpu.exec(Ncycles - cpu.cycle_count);
|
|
|
|
if (exit_status == 256) {
|
|
|
|
if (PC.reset_request) {
|
|
|
|
do_reset = true;
|
2011-12-21 13:34:38 +08:00
|
|
|
break;
|
|
|
|
}
|
2011-12-24 11:28:34 +08:00
|
|
|
} else if (exit_status == 257) {
|
|
|
|
err_on_exit = true;
|
2011-12-21 13:34:38 +08:00
|
|
|
break;
|
|
|
|
} else {
|
2011-12-24 11:28:34 +08:00
|
|
|
do_reset = true;
|
2011-12-21 13:34:38 +08:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2011-12-24 11:28:34 +08:00
|
|
|
if (!do_reset) {
|
|
|
|
if (err_on_exit) {
|
2011-12-21 13:34:38 +08:00
|
|
|
setTimeout(this.timer_func.bind(this), 10);
|
|
|
|
} else {
|
|
|
|
setTimeout(this.timer_func.bind(this), 0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
PCEmulator.prototype.init_ioports = function() {
|
2011-12-24 11:28:34 +08:00
|
|
|
var i, readw, writew;
|
2011-12-21 13:34:38 +08:00
|
|
|
this.ioport_readb_table = new Array();
|
|
|
|
this.ioport_writeb_table = new Array();
|
|
|
|
this.ioport_readw_table = new Array();
|
|
|
|
this.ioport_writew_table = new Array();
|
|
|
|
this.ioport_readl_table = new Array();
|
|
|
|
this.ioport_writel_table = new Array();
|
2011-12-24 11:28:34 +08:00
|
|
|
readw = this.default_ioport_readw.bind(this);
|
|
|
|
writew = this.default_ioport_writew.bind(this);
|
2011-12-21 13:34:38 +08:00
|
|
|
for (i = 0; i < 1024; i++) {
|
|
|
|
this.ioport_readb_table[i] = this.default_ioport_readb;
|
|
|
|
this.ioport_writeb_table[i] = this.default_ioport_writeb;
|
2011-12-24 11:28:34 +08:00
|
|
|
this.ioport_readw_table[i] = readw;
|
|
|
|
this.ioport_writew_table[i] = writew;
|
2011-12-21 13:34:38 +08:00
|
|
|
this.ioport_readl_table[i] = this.default_ioport_readl;
|
|
|
|
this.ioport_writel_table[i] = this.default_ioport_writel;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2011-12-24 11:28:34 +08:00
|
|
|
PCEmulator.prototype.default_ioport_readb = function(port_num) {
|
2011-12-21 13:34:38 +08:00
|
|
|
var x;
|
|
|
|
x = 0xff;
|
|
|
|
return x;
|
|
|
|
};
|
|
|
|
|
2011-12-24 11:28:34 +08:00
|
|
|
PCEmulator.prototype.default_ioport_readw = function(port_num) {
|
2011-12-21 13:34:38 +08:00
|
|
|
var x;
|
2011-12-24 11:28:34 +08:00
|
|
|
x = this.ioport_readb_table[port_num](port_num);
|
|
|
|
port_num = (port_num + 1) & (1024 - 1);
|
|
|
|
x |= this.ioport_readb_table[port_num](port_num) << 8;
|
2011-12-21 13:34:38 +08:00
|
|
|
return x;
|
|
|
|
};
|
|
|
|
|
2011-12-24 11:28:34 +08:00
|
|
|
PCEmulator.prototype.default_ioport_readl = function(port_num) {
|
2011-12-21 13:34:38 +08:00
|
|
|
var x;
|
|
|
|
x = -1;
|
|
|
|
return x;
|
|
|
|
};
|
|
|
|
|
2011-12-24 11:28:34 +08:00
|
|
|
PCEmulator.prototype.default_ioport_writeb = function(port_num, x) {};
|
2011-12-21 13:34:38 +08:00
|
|
|
|
2011-12-24 11:28:34 +08:00
|
|
|
PCEmulator.prototype.default_ioport_writew = function(port_num, x) {
|
|
|
|
this.ioport_writeb_table[port_num](port_num, x & 0xff);
|
|
|
|
port_num = (port_num + 1) & (1024 - 1);
|
|
|
|
this.ioport_writeb_table[port_num](port_num, (x >> 8) & 0xff);
|
2011-12-21 13:34:38 +08:00
|
|
|
};
|
|
|
|
|
2011-12-24 11:28:34 +08:00
|
|
|
PCEmulator.prototype.default_ioport_writel = function(port_num, x) {};
|
2011-12-21 13:34:38 +08:00
|
|
|
|
2011-12-24 11:28:34 +08:00
|
|
|
PCEmulator.prototype.ld8_port = function(port_num) {
|
2011-12-21 13:34:38 +08:00
|
|
|
var x;
|
2011-12-24 11:28:34 +08:00
|
|
|
x = this.ioport_readb_table[port_num & (1024 - 1)](port_num);
|
2011-12-21 13:34:38 +08:00
|
|
|
return x;
|
|
|
|
};
|
|
|
|
|
2011-12-24 11:28:34 +08:00
|
|
|
PCEmulator.prototype.ld16_port = function(port_num) {
|
2011-12-21 13:34:38 +08:00
|
|
|
var x;
|
2011-12-24 11:28:34 +08:00
|
|
|
x = this.ioport_readw_table[port_num & (1024 - 1)](port_num);
|
2011-12-21 13:34:38 +08:00
|
|
|
return x;
|
|
|
|
};
|
|
|
|
|
2011-12-24 11:28:34 +08:00
|
|
|
PCEmulator.prototype.ld32_port = function(port_num) {
|
2011-12-21 13:34:38 +08:00
|
|
|
var x;
|
2011-12-24 11:28:34 +08:00
|
|
|
x = this.ioport_readl_table[port_num & (1024 - 1)](port_num);
|
2011-12-21 13:34:38 +08:00
|
|
|
return x;
|
|
|
|
};
|
|
|
|
|
2011-12-24 11:28:34 +08:00
|
|
|
PCEmulator.prototype.st8_port = function(port_num, x) { this.ioport_writeb_table[port_num & (1024 - 1)](port_num, x); };
|
|
|
|
PCEmulator.prototype.st16_port = function(port_num, x) { this.ioport_writew_table[port_num & (1024 - 1)](port_num, x); };
|
|
|
|
PCEmulator.prototype.st32_port = function(port_num, x) { this.ioport_writel_table[port_num & (1024 - 1)](port_num, x); };
|
2011-12-21 13:34:38 +08:00
|
|
|
|
2011-12-24 11:28:34 +08:00
|
|
|
PCEmulator.prototype.register_ioport_read = function(start, len, iotype, io_callback) {
|
2011-12-21 13:34:38 +08:00
|
|
|
var i;
|
2011-12-24 11:28:34 +08:00
|
|
|
switch (iotype) {
|
2011-12-21 13:34:38 +08:00
|
|
|
case 1:
|
2011-12-24 11:28:34 +08:00
|
|
|
for (i = start; i < start + len; i++) {
|
|
|
|
this.ioport_readb_table[i] = io_callback;
|
2011-12-21 13:34:38 +08:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 2:
|
2011-12-24 11:28:34 +08:00
|
|
|
for (i = start; i < start + len; i += 2) {
|
|
|
|
this.ioport_readw_table[i] = io_callback;
|
2011-12-21 13:34:38 +08:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 4:
|
2011-12-24 11:28:34 +08:00
|
|
|
for (i = start; i < start + len; i += 4) {
|
|
|
|
this.ioport_readl_table[i] = io_callback;
|
2011-12-21 13:34:38 +08:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2011-12-24 11:28:34 +08:00
|
|
|
PCEmulator.prototype.register_ioport_write = function(start, len, iotype, io_callback) {
|
2011-12-21 13:34:38 +08:00
|
|
|
var i;
|
2011-12-24 11:28:34 +08:00
|
|
|
switch (iotype) {
|
2011-12-21 13:34:38 +08:00
|
|
|
case 1:
|
2011-12-24 11:28:34 +08:00
|
|
|
for (i = start; i < start + len; i++) {
|
|
|
|
this.ioport_writeb_table[i] = io_callback;
|
2011-12-21 13:34:38 +08:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 2:
|
2011-12-24 11:28:34 +08:00
|
|
|
for (i = start; i < start + len; i += 2) {
|
|
|
|
this.ioport_writew_table[i] = io_callback;
|
2011-12-21 13:34:38 +08:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 4:
|
2011-12-24 11:28:34 +08:00
|
|
|
for (i = start; i < start + len; i += 4) {
|
|
|
|
this.ioport_writel_table[i] = io_callback;
|
2011-12-21 13:34:38 +08:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2013-03-23 12:32:41 +08:00
|
|
|
PCEmulator.prototype.ioport80_write = function(mem8_loc, data) {}; //POST codes! Seem to be ignored?
|
2011-12-21 13:34:38 +08:00
|
|
|
PCEmulator.prototype.reset = function() { this.request_request = 1; };
|
|
|
|
|
|
|
|
|
|
|
|
|
2011-12-24 11:28:34 +08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|