Port lsl/lar/verr/verw to rust
This commit is contained in:
parent
39eb650ff3
commit
d34817d45b
|
@ -134,11 +134,6 @@ function V86Starter(options)
|
|||
cpu.mmap_write128(addr, value0, value1, value2, value3);
|
||||
},
|
||||
|
||||
"lar": function() { return cpu.lar.apply(cpu, arguments); },
|
||||
"lsl": function() { return cpu.lsl.apply(cpu, arguments); },
|
||||
"verw": function() { return cpu.verw.apply(cpu, arguments); },
|
||||
"verr": function() { return cpu.verr.apply(cpu, arguments); },
|
||||
|
||||
"cpuid": function() { return cpu.cpuid.apply(cpu, arguments); },
|
||||
|
||||
"load_ldt": function() { return cpu.load_ldt.apply(cpu, arguments); },
|
||||
|
|
100
src/cpu.js
100
src/cpu.js
|
@ -2321,106 +2321,6 @@ CPU.prototype.load_ldt = function(selector)
|
|||
//dbg_log("ldt at " + h(info.base >>> 0) + "; (" + info.effective_limit + " bytes)", LOG_CPU);
|
||||
};
|
||||
|
||||
CPU.prototype.lar = function(selector, original)
|
||||
{
|
||||
if(CPU_LOG_VERBOSE)
|
||||
{
|
||||
dbg_log("lar sel=" + h(selector, 4), LOG_CPU);
|
||||
}
|
||||
|
||||
/** @const */
|
||||
var LAR_INVALID_TYPE = 1 << 0 | 1 << 6 | 1 << 7 | 1 << 8 | 1 << 0xA |
|
||||
1 << 0xD | 1 << 0xE | 1 << 0xF;
|
||||
|
||||
var info = this.lookup_segment_selector(selector);
|
||||
this.flags_changed[0] &= ~flag_zero;
|
||||
|
||||
var dpl_bad = info.dpl < this.cpl[0] || info.dpl < info.rpl;
|
||||
|
||||
if(info.is_null || !info.is_valid ||
|
||||
(info.is_system ? (LAR_INVALID_TYPE >> info.type & 1) || dpl_bad :
|
||||
!info.is_conforming_executable && dpl_bad)
|
||||
) {
|
||||
this.flags[0] &= ~flag_zero;
|
||||
dbg_log("lar: invalid selector=" + h(selector, 4) + " is_null=" + info.is_null, LOG_CPU);
|
||||
return original;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.flags[0] |= flag_zero;
|
||||
return info.raw1 & 0x00FFFF00;
|
||||
}
|
||||
};
|
||||
|
||||
CPU.prototype.lsl = function(selector, original)
|
||||
{
|
||||
if(CPU_LOG_VERBOSE)
|
||||
{
|
||||
dbg_log("lsl sel=" + h(selector, 4), LOG_CPU);
|
||||
}
|
||||
|
||||
/** @const */
|
||||
var LSL_INVALID_TYPE = 1 << 0 | 1 << 4 | 1 << 5 | 1 << 6 | 1 << 7 | 1 << 8 |
|
||||
1 << 0xA | 1 << 0xC | 1 << 0xD | 1 << 0xE | 1 << 0xF;
|
||||
|
||||
var info = this.lookup_segment_selector(selector);
|
||||
this.flags_changed[0] &= ~flag_zero;
|
||||
|
||||
var dpl_bad = info.dpl < this.cpl[0] || info.dpl < info.rpl;
|
||||
|
||||
if(info.is_null || !info.is_valid ||
|
||||
(info.is_system ? (LSL_INVALID_TYPE >> info.type & 1) || dpl_bad :
|
||||
!info.is_conforming_executable && dpl_bad)
|
||||
) {
|
||||
this.flags[0] &= ~flag_zero;
|
||||
dbg_log("lsl: invalid selector=" + h(selector, 4) + " is_null=" + info.is_null, LOG_CPU);
|
||||
return original;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.flags[0] |= flag_zero;
|
||||
return info.effective_limit | 0;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
CPU.prototype.verr = function(selector)
|
||||
{
|
||||
var info = this.lookup_segment_selector(selector);
|
||||
this.flags_changed[0] &= ~flag_zero;
|
||||
|
||||
if(info.is_null || !info.is_valid || info.is_system || !info.is_readable ||
|
||||
(!info.is_conforming_executable && (info.dpl < this.cpl[0] || info.dpl < info.rpl)))
|
||||
{
|
||||
dbg_log("verr -> invalid. selector=" + h(selector, 4), LOG_CPU);
|
||||
this.flags[0] &= ~flag_zero;
|
||||
}
|
||||
else
|
||||
{
|
||||
dbg_log("verr -> valid. selector=" + h(selector, 4), LOG_CPU);
|
||||
this.flags[0] |= flag_zero;
|
||||
}
|
||||
};
|
||||
|
||||
CPU.prototype.verw = function(selector)
|
||||
{
|
||||
var info = this.lookup_segment_selector(selector);
|
||||
this.flags_changed[0] &= ~flag_zero;
|
||||
|
||||
if(info.is_null || !info.is_valid || info.is_system || !info.is_writable ||
|
||||
info.dpl < this.cpl[0] || info.dpl < info.rpl)
|
||||
{
|
||||
dbg_log("verw invalid " + " " + h(selector) + " " + info.is_null + " " +
|
||||
!info.is_valid + " " + info.is_system + " " + !info.is_writable + " " +
|
||||
(info.dpl < this.cpl[0]) + " " + (info.dpl < info.rpl) + " " + LOG_CPU);
|
||||
this.flags[0] &= ~flag_zero;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.flags[0] |= flag_zero;
|
||||
}
|
||||
};
|
||||
|
||||
// Closure Compiler's way of exporting
|
||||
if(typeof window !== "undefined")
|
||||
{
|
||||
|
|
|
@ -316,7 +316,7 @@ pub enum SelectorNullOrInvalid {
|
|||
}
|
||||
|
||||
pub struct SegmentDescriptor {
|
||||
raw: u64,
|
||||
pub raw: u64,
|
||||
}
|
||||
|
||||
impl SegmentDescriptor {
|
||||
|
|
|
@ -3,10 +3,6 @@
|
|||
extern "C" {
|
||||
fn get_rand_int() -> i32;
|
||||
fn cpuid();
|
||||
fn lsl(r: i32, v: i32) -> i32;
|
||||
fn lar(r: i32, v: i32) -> i32;
|
||||
fn verw(r: i32);
|
||||
fn verr(r: i32);
|
||||
fn load_tr(v: i32);
|
||||
fn load_ldt(v: i32);
|
||||
}
|
||||
|
@ -37,6 +33,7 @@ use cpu::misc_instr::{
|
|||
jmpcc32, push16, push32, setcc_mem, setcc_reg, test_b, test_be, test_l, test_le, test_o,
|
||||
test_p, test_s, test_z,
|
||||
};
|
||||
use cpu::misc_instr::{lar, lsl, verr, verw};
|
||||
use cpu::misc_instr::{lss16, lss32};
|
||||
use cpu::sse_instr::*;
|
||||
|
||||
|
|
|
@ -459,3 +459,156 @@ pub unsafe fn xchg32r(r32: i32) {
|
|||
|
||||
#[no_mangle]
|
||||
pub unsafe fn bswap(r: i32) { write_reg32(r, read_reg32(r).swap_bytes()) }
|
||||
|
||||
pub unsafe fn lar(selector: i32, original: i32) -> i32 {
|
||||
if false {
|
||||
dbg_log!("lar sel={:x}", selector);
|
||||
}
|
||||
|
||||
const LAR_INVALID_TYPE: u32 =
|
||||
1 << 0 | 1 << 6 | 1 << 7 | 1 << 8 | 1 << 0xA | 1 << 0xD | 1 << 0xE | 1 << 0xF;
|
||||
|
||||
match lookup_segment_selector(selector) {
|
||||
Err(()) => {
|
||||
// pagefault
|
||||
return original;
|
||||
},
|
||||
Ok(Err(_)) => {
|
||||
*flags_changed &= !FLAG_ZERO;
|
||||
*flags &= !FLAG_ZERO;
|
||||
dbg_log!("lar: invalid selector={:x}: null or invalid", selector);
|
||||
return original;
|
||||
},
|
||||
Ok(Ok((desc, sel))) => {
|
||||
*flags_changed &= !FLAG_ZERO;
|
||||
let dpl_bad = desc.dpl() < *cpl || desc.dpl() < sel.rpl();
|
||||
|
||||
if if desc.is_system() {
|
||||
(LAR_INVALID_TYPE >> desc.system_type() & 1 == 1) || dpl_bad
|
||||
}
|
||||
else {
|
||||
!desc.is_conforming_executable() && dpl_bad
|
||||
} {
|
||||
dbg_log!(
|
||||
"lar: invalid selector={:x} is_null={} is_system={}",
|
||||
selector,
|
||||
false,
|
||||
desc.is_system()
|
||||
);
|
||||
*flags &= !FLAG_ZERO;
|
||||
return original;
|
||||
}
|
||||
else {
|
||||
*flags |= FLAG_ZERO;
|
||||
return (desc.raw >> 32) as i32 & 0x00FFFF00;
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
pub unsafe fn lsl(selector: i32, original: i32) -> i32 {
|
||||
if false {
|
||||
dbg_log!("lsl sel={:x}", selector);
|
||||
}
|
||||
|
||||
const LSL_INVALID_TYPE: i32 = 1 << 0
|
||||
| 1 << 4
|
||||
| 1 << 5
|
||||
| 1 << 6
|
||||
| 1 << 7
|
||||
| 1 << 8
|
||||
| 1 << 0xA
|
||||
| 1 << 0xC
|
||||
| 1 << 0xD
|
||||
| 1 << 0xE
|
||||
| 1 << 0xF;
|
||||
|
||||
match lookup_segment_selector(selector) {
|
||||
Err(()) => {
|
||||
// pagefault
|
||||
return original;
|
||||
},
|
||||
Ok(Err(_)) => {
|
||||
*flags_changed &= !FLAG_ZERO;
|
||||
*flags &= !FLAG_ZERO;
|
||||
dbg_log!("lsl: invalid selector={:x}: null or invalid", selector);
|
||||
return original;
|
||||
},
|
||||
Ok(Ok((desc, sel))) => {
|
||||
*flags_changed &= !FLAG_ZERO;
|
||||
let dpl_bad = desc.dpl() < *cpl || desc.dpl() < sel.rpl();
|
||||
|
||||
if if desc.is_system() {
|
||||
(LSL_INVALID_TYPE >> desc.system_type() & 1 == 1) || dpl_bad
|
||||
}
|
||||
else {
|
||||
!desc.is_conforming_executable() && dpl_bad
|
||||
} {
|
||||
dbg_log!(
|
||||
"lsl: invalid selector={:x} is_null={} is_system={}",
|
||||
selector,
|
||||
false,
|
||||
desc.is_system(),
|
||||
);
|
||||
*flags &= !FLAG_ZERO;
|
||||
return original;
|
||||
}
|
||||
else {
|
||||
*flags |= FLAG_ZERO;
|
||||
return desc.effective_limit() as i32;
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
pub unsafe fn verr(selector: i32) {
|
||||
*flags_changed &= !FLAG_ZERO;
|
||||
match return_on_pagefault!(lookup_segment_selector(selector)) {
|
||||
Err(_) => {
|
||||
*flags &= !FLAG_ZERO;
|
||||
dbg_log!("verr -> invalid. selector={:x}", selector);
|
||||
},
|
||||
Ok((desc, sel)) => {
|
||||
if desc.is_system()
|
||||
|| !desc.is_readable()
|
||||
|| (!desc.is_conforming_executable()
|
||||
&& (desc.dpl() < *cpl || desc.dpl() < sel.rpl()))
|
||||
{
|
||||
dbg_log!("verr -> invalid. selector={:x}", selector);
|
||||
*flags &= !FLAG_ZERO;
|
||||
}
|
||||
else {
|
||||
dbg_log!("verr -> valid. selector={:x}", selector);
|
||||
*flags |= FLAG_ZERO;
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
pub unsafe fn verw(selector: i32) {
|
||||
*flags_changed &= !FLAG_ZERO;
|
||||
match return_on_pagefault!(lookup_segment_selector(selector)) {
|
||||
Err(_) => {
|
||||
*flags &= !FLAG_ZERO;
|
||||
dbg_log!("verw -> invalid. selector={:x}", selector);
|
||||
},
|
||||
Ok((desc, sel)) => {
|
||||
if desc.is_system()
|
||||
|| !desc.is_writable()
|
||||
|| desc.dpl() < *cpl
|
||||
|| desc.dpl() < sel.rpl()
|
||||
{
|
||||
dbg_log!(
|
||||
"verw invalid selector={:x} is_system={} is_writable={}",
|
||||
selector,
|
||||
desc.is_system(),
|
||||
desc.is_writable(),
|
||||
);
|
||||
*flags &= !FLAG_ZERO;
|
||||
}
|
||||
else {
|
||||
*flags |= FLAG_ZERO;
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue