Port lsl/lar/verr/verw to rust

This commit is contained in:
Fabian 2020-12-31 19:14:33 -06:00
parent 39eb650ff3
commit d34817d45b
5 changed files with 155 additions and 110 deletions

View file

@ -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); },

View file

@ -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")
{

View file

@ -316,7 +316,7 @@ pub enum SelectorNullOrInvalid {
}
pub struct SegmentDescriptor {
raw: u64,
pub raw: u64,
}
impl SegmentDescriptor {

View file

@ -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::*;

View file

@ -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;
}
},
}
}