Merge pull request #10 from danluu/master
More documentation for obscure functions
This commit is contained in:
commit
1fa83c912a
64
cpux86-ta.js
64
cpux86-ta.js
@ -3715,7 +3715,7 @@ CPU_X86.prototype.exec_internal = function(N_cycles, interrupt) {
|
|||||||
ke = ld16_mem8_kernel_read();
|
ke = ld16_mem8_kernel_read();
|
||||||
return [ke, le];
|
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 descriptor_table, qe, descriptor_type, he, selector, re, cpl_var;
|
||||||
var te, ue, is_32_bit;
|
var te, ue, is_32_bit;
|
||||||
var e, descriptor_low4bytes, descriptor_high4bytes, ve, ke, le, we, xe;
|
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);
|
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;
|
var descriptor_table, qe, selector, ve, le, ye;
|
||||||
descriptor_table = cpu.idt;
|
descriptor_table = cpu.idt;
|
||||||
if (intno * 4 + 3 > descriptor_table.limit)
|
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)) {
|
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 {
|
} 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
|
//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) {
|
function Pe(register, cpl_var) {
|
||||||
var dpl, descriptor_high4bytes;
|
var dpl, descriptor_high4bytes;
|
||||||
if ((register == 4 || register == 5) && (cpu.segs[register].selector & 0xfffc) == 0)
|
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;
|
var le;
|
||||||
le = regs[4];
|
le = regs[4];
|
||||||
if (is_32_bit) {
|
if (is_32_bit) {
|
||||||
@ -4234,7 +4234,7 @@ CPU_X86.prototype.exec_internal = function(N_cycles, interrupt) {
|
|||||||
cpu.segs[1].base = (selector << 4);
|
cpu.segs[1].base = (selector << 4);
|
||||||
init_segment_local_vars();
|
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 ue, i, e;
|
||||||
var descriptor_low4bytes, descriptor_high4bytes, cpl_var, dpl, rpl, selector, ve, Se;
|
var descriptor_low4bytes, descriptor_high4bytes, cpl_var, dpl, rpl, selector, ve, Se;
|
||||||
var ke, we, xe, esp, descriptor_type, re, SS_mask;
|
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) {
|
function op_CALLF(is_32_bit, selector, Le, oe) {
|
||||||
if (!(cpu.cr0 & (1 << 0)) || (cpu.eflags & 0x00020000)) {
|
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 {
|
} 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;
|
var esp, selector, stack_eip, stack_eflags, SS_mask, qe, ef;
|
||||||
SS_mask = 0xffff;
|
SS_mask = 0xffff;
|
||||||
esp = regs[4];
|
esp = regs[4];
|
||||||
@ -4503,7 +4503,7 @@ CPU_X86.prototype.exec_internal = function(N_cycles, interrupt) {
|
|||||||
}
|
}
|
||||||
init_segment_local_vars();
|
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 selector, stack_eflags, gf;
|
||||||
var hf, jf, kf, lf;
|
var hf, jf, kf, lf;
|
||||||
var e, descriptor_low4bytes, descriptor_high4bytes, we, xe;
|
var e, descriptor_low4bytes, descriptor_high4bytes, we, xe;
|
||||||
@ -4695,20 +4695,20 @@ CPU_X86.prototype.exec_internal = function(N_cycles, interrupt) {
|
|||||||
if (iopl != 3)
|
if (iopl != 3)
|
||||||
abort(13);
|
abort(13);
|
||||||
}
|
}
|
||||||
do_return_not_paged_mode(is_32_bit, 1, 0);
|
do_return_not_protected_mode(is_32_bit, 1, 0);
|
||||||
} else {
|
} else {
|
||||||
if (cpu.eflags & 0x00004000) {
|
if (cpu.eflags & 0x00004000) {
|
||||||
throw "unsupported task gate";
|
throw "unsupported task gate";
|
||||||
} else {
|
} 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) {
|
function op_RETF(is_32_bit, imm16) {
|
||||||
if (!(cpu.cr0 & (1 << 0)) || (cpu.eflags & 0x00020000)) {
|
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 {
|
} 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
|
//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;
|
var e, descriptor_low4bytes, descriptor_high4bytes, rpl, dpl, cpl_var;
|
||||||
if ((selector & 0xfffc) == 0)
|
if ((selector & 0xfffc) == 0)
|
||||||
return 0;
|
return 0;
|
||||||
@ -4796,13 +4796,13 @@ CPU_X86.prototype.exec_internal = function(N_cycles, interrupt) {
|
|||||||
return 0;
|
return 0;
|
||||||
descriptor_low4bytes = e[0];
|
descriptor_low4bytes = e[0];
|
||||||
descriptor_high4bytes = e[1];
|
descriptor_high4bytes = e[1];
|
||||||
if (!(descriptor_high4bytes & (1 << 12)))
|
if (!(descriptor_high4bytes & (1 << 12))) // s bit (system == 0)
|
||||||
return 0;
|
return 0;
|
||||||
rpl = selector & 3;
|
rpl = selector & 3;
|
||||||
dpl = (descriptor_high4bytes >> 13) & 3;
|
dpl = (descriptor_high4bytes >> 13) & 3;
|
||||||
cpl_var = cpu.cpl;
|
cpl_var = cpu.cpl;
|
||||||
if (descriptor_high4bytes & (1 << 11)) {
|
if (descriptor_high4bytes & (1 << 11)) { // code == 1, data == 0
|
||||||
if (ud) {
|
if (is_verw) { // code segments are never writable
|
||||||
return 0;
|
return 0;
|
||||||
} else {
|
} else {
|
||||||
if (!(descriptor_high4bytes & (1 << 9)))
|
if (!(descriptor_high4bytes & (1 << 9)))
|
||||||
@ -4813,17 +4813,19 @@ CPU_X86.prototype.exec_internal = function(N_cycles, interrupt) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (dpl < cpl_var || dpl < rpl)
|
if (dpl < cpl_var || dpl < rpl) // data segments are always readable, if privilege is sufficient
|
||||||
return 0;
|
return 0;
|
||||||
if (ud && !(descriptor_high4bytes & (1 << 9)))
|
if (is_verw && !(descriptor_high4bytes & (1 << 9))) //writable data segment
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
function op_VERR_VERW(selector, ud) {
|
function op_VERR_VERW(selector, is_verw) {
|
||||||
var z;
|
var z;
|
||||||
z = rf(selector, ud);
|
z = segment_isnt_accessible(selector, is_verw);
|
||||||
_src = get_conditional_flags();
|
_src = get_conditional_flags();
|
||||||
|
|
||||||
|
// clear eflags.zf if selector is accessible and (readable (for VERR) or writable (for VERW))
|
||||||
if (z)
|
if (z)
|
||||||
_src |= 0x0040;
|
_src |= 0x0040;
|
||||||
else
|
else
|
||||||
@ -4860,21 +4862,21 @@ CPU_X86.prototype.exec_internal = function(N_cycles, interrupt) {
|
|||||||
_op = 24;
|
_op = 24;
|
||||||
}
|
}
|
||||||
function op_CPUID() {
|
function op_CPUID() {
|
||||||
var Rb;
|
var eax;
|
||||||
Rb = regs[0];
|
eax = regs[0];
|
||||||
switch (Rb) {
|
switch (eax) {
|
||||||
case 0:
|
case 0: // eax == 0: vendor ID
|
||||||
regs[0] = 1;
|
regs[0] = 1;
|
||||||
regs[3] = 0x756e6547 & -1;
|
regs[3] = 0x756e6547 & -1;
|
||||||
regs[2] = 0x49656e69 & -1;
|
regs[2] = 0x49656e69 & -1;
|
||||||
regs[1] = 0x6c65746e & -1;
|
regs[1] = 0x6c65746e & -1;
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1: // eax == 1: processor info and feature flags
|
||||||
default:
|
default:
|
||||||
regs[0] = (5 << 8) | (4 << 4) | 3;
|
regs[0] = (5 << 8) | (4 << 4) | 3; // family | model | stepping
|
||||||
regs[3] = 8 << 8;
|
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[1] = 0;
|
||||||
regs[2] = (1 << 4);
|
regs[2] = (1 << 4); // rdtsc support
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -25,6 +25,8 @@ have been added.
|
|||||||
The core opcode execution loop has been autocommented to indicate what
|
The core opcode execution loop has been autocommented to indicate what
|
||||||
instruction operation the opcode refers to.
|
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
|
### 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.
|
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.
|
||||||
|
Loading…
Reference in New Issue
Block a user