Merge pull request #10 from danluu/master

More documentation for obscure functions
This commit is contained in:
Anselm Levskaya 2013-03-20 20:32:06 -07:00
commit 1fa83c912a
2 changed files with 35 additions and 31 deletions

View File

@ -3715,7 +3715,7 @@ CPU_X86.prototype.exec_internal = function(N_cycles, interrupt) {
ke = ld16_mem8_kernel_read();
return [ke, le];
}
function do_interrupt_paged_mode(intno, ne, error_code, oe, pe) {
function do_interrupt_protected_mode(intno, ne, error_code, oe, pe) {
var descriptor_table, qe, descriptor_type, he, selector, re, cpl_var;
var te, ue, is_32_bit;
var e, descriptor_low4bytes, descriptor_high4bytes, ve, ke, le, we, xe;
@ -3954,7 +3954,7 @@ CPU_X86.prototype.exec_internal = function(N_cycles, interrupt) {
}
cpu.eflags &= ~(0x00000100 | 0x00020000 | 0x00010000 | 0x00004000);
}
function do_interrupt_not_paged_mode(intno, ne, error_code, oe, pe) {
function do_interrupt_not_protected_mode(intno, ne, error_code, oe, pe) {
var descriptor_table, qe, selector, ve, le, ye;
descriptor_table = cpu.idt;
if (intno * 4 + 3 > descriptor_table.limit)
@ -4015,9 +4015,9 @@ CPU_X86.prototype.exec_internal = function(N_cycles, interrupt) {
}
}
if (cpu.cr0 & (1 << 0)) {
do_interrupt_paged_mode(intno, ne, error_code, oe, pe);
do_interrupt_protected_mode(intno, ne, error_code, oe, pe);
} else {
do_interrupt_not_paged_mode(intno, ne, error_code, oe, pe);
do_interrupt_not_protected_mode(intno, ne, error_code, oe, pe);
}
}
//SLDT routines
@ -4188,7 +4188,7 @@ CPU_X86.prototype.exec_internal = function(N_cycles, interrupt) {
}
}
/* used only in do_return_paged_mode */
/* used only in do_return_protected_mode */
function Pe(register, cpl_var) {
var dpl, descriptor_high4bytes;
if ((register == 4 || register == 5) && (cpu.segs[register].selector & 0xfffc) == 0)
@ -4202,7 +4202,7 @@ CPU_X86.prototype.exec_internal = function(N_cycles, interrupt) {
}
}
function op_CALLF_not_paged_mode(is_32_bit, selector, Le, oe) {
function op_CALLF_not_protected_mode(is_32_bit, selector, Le, oe) {
var le;
le = regs[4];
if (is_32_bit) {
@ -4234,7 +4234,7 @@ CPU_X86.prototype.exec_internal = function(N_cycles, interrupt) {
cpu.segs[1].base = (selector << 4);
init_segment_local_vars();
}
function op_CALLF_paged_mode(is_32_bit, selector, Le, oe) {
function op_CALLF_protected_mode(is_32_bit, selector, Le, oe) {
var ue, i, e;
var descriptor_low4bytes, descriptor_high4bytes, cpl_var, dpl, rpl, selector, ve, Se;
var ke, we, xe, esp, descriptor_type, re, SS_mask;
@ -4444,12 +4444,12 @@ CPU_X86.prototype.exec_internal = function(N_cycles, interrupt) {
}
function op_CALLF(is_32_bit, selector, Le, oe) {
if (!(cpu.cr0 & (1 << 0)) || (cpu.eflags & 0x00020000)) {
op_CALLF_not_paged_mode(is_32_bit, selector, Le, oe);
op_CALLF_not_protected_mode(is_32_bit, selector, Le, oe);
} else {
op_CALLF_paged_mode(is_32_bit, selector, Le, oe);
op_CALLF_protected_mode(is_32_bit, selector, Le, oe);
}
}
function do_return_not_paged_mode(is_32_bit, is_iret, imm16) {
function do_return_not_protected_mode(is_32_bit, is_iret, imm16) {
var esp, selector, stack_eip, stack_eflags, SS_mask, qe, ef;
SS_mask = 0xffff;
esp = regs[4];
@ -4503,7 +4503,7 @@ CPU_X86.prototype.exec_internal = function(N_cycles, interrupt) {
}
init_segment_local_vars();
}
function do_return_paged_mode(is_32_bit, is_iret, imm16) {
function do_return_protected_mode(is_32_bit, is_iret, imm16) {
var selector, stack_eflags, gf;
var hf, jf, kf, lf;
var e, descriptor_low4bytes, descriptor_high4bytes, we, xe;
@ -4695,20 +4695,20 @@ CPU_X86.prototype.exec_internal = function(N_cycles, interrupt) {
if (iopl != 3)
abort(13);
}
do_return_not_paged_mode(is_32_bit, 1, 0);
do_return_not_protected_mode(is_32_bit, 1, 0);
} else {
if (cpu.eflags & 0x00004000) {
throw "unsupported task gate";
} else {
do_return_paged_mode(is_32_bit, 1, 0);
do_return_protected_mode(is_32_bit, 1, 0);
}
}
}
function op_RETF(is_32_bit, imm16) {
if (!(cpu.cr0 & (1 << 0)) || (cpu.eflags & 0x00020000)) {
do_return_not_paged_mode(is_32_bit, 0, imm16);
do_return_not_protected_mode(is_32_bit, 0, imm16);
} else {
do_return_paged_mode(is_32_bit, 0, imm16);
do_return_protected_mode(is_32_bit, 0, imm16);
}
}
@ -4787,7 +4787,7 @@ CPU_X86.prototype.exec_internal = function(N_cycles, interrupt) {
}
//utility function for op_VERR_VERW
function rf(selector, ud) {
function segment_isnt_accessible(selector, is_verw) {
var e, descriptor_low4bytes, descriptor_high4bytes, rpl, dpl, cpl_var;
if ((selector & 0xfffc) == 0)
return 0;
@ -4796,13 +4796,13 @@ CPU_X86.prototype.exec_internal = function(N_cycles, interrupt) {
return 0;
descriptor_low4bytes = e[0];
descriptor_high4bytes = e[1];
if (!(descriptor_high4bytes & (1 << 12)))
if (!(descriptor_high4bytes & (1 << 12))) // s bit (system == 0)
return 0;
rpl = selector & 3;
dpl = (descriptor_high4bytes >> 13) & 3;
cpl_var = cpu.cpl;
if (descriptor_high4bytes & (1 << 11)) {
if (ud) {
if (descriptor_high4bytes & (1 << 11)) { // code == 1, data == 0
if (is_verw) { // code segments are never writable
return 0;
} else {
if (!(descriptor_high4bytes & (1 << 9)))
@ -4813,17 +4813,19 @@ CPU_X86.prototype.exec_internal = function(N_cycles, interrupt) {
}
}
} else {
if (dpl < cpl_var || dpl < rpl)
if (dpl < cpl_var || dpl < rpl) // data segments are always readable, if privilege is sufficient
return 0;
if (ud && !(descriptor_high4bytes & (1 << 9)))
if (is_verw && !(descriptor_high4bytes & (1 << 9))) //writable data segment
return 0;
}
return 1;
}
function op_VERR_VERW(selector, ud) {
function op_VERR_VERW(selector, is_verw) {
var z;
z = rf(selector, ud);
z = segment_isnt_accessible(selector, is_verw);
_src = get_conditional_flags();
// clear eflags.zf if selector is accessible and (readable (for VERR) or writable (for VERW))
if (z)
_src |= 0x0040;
else
@ -4860,21 +4862,21 @@ CPU_X86.prototype.exec_internal = function(N_cycles, interrupt) {
_op = 24;
}
function op_CPUID() {
var Rb;
Rb = regs[0];
switch (Rb) {
case 0:
var eax;
eax = regs[0];
switch (eax) {
case 0: // eax == 0: vendor ID
regs[0] = 1;
regs[3] = 0x756e6547 & -1;
regs[2] = 0x49656e69 & -1;
regs[1] = 0x6c65746e & -1;
break;
case 1:
case 1: // eax == 1: processor info and feature flags
default:
regs[0] = (5 << 8) | (4 << 4) | 3;
regs[3] = 8 << 8;
regs[0] = (5 << 8) | (4 << 4) | 3; // family | model | stepping
regs[3] = 8 << 8; // danluu: This is a mystery to me. This bit now indicates clflush line size, but must have meant something else in the past.
regs[1] = 0;
regs[2] = (1 << 4);
regs[2] = (1 << 4); // rdtsc support
break;
}
}

View File

@ -25,6 +25,8 @@ have been added.
The core opcode execution loop has been autocommented to indicate what
instruction operation the opcode refers to.
One mystery is, why does CPUID(1) return 8 << 8 in EBX? EBX[15:8] is now used to indicate CLFLUSH line size, but that field must have been used for something else in the past.
### ETC
I highly recommend, by the way, the excellent [JSShaper][2] library for transforming large javascript code bases. The hacks I made from it are in this repo: a little symbol-name-transformer node.js script and an emacs function for doing this in live buffers.