fix: align interrupt data with minix src
This commit is contained in:
@@ -3,10 +3,14 @@ use std::{fmt::Debug, process::exit};
|
||||
|
||||
use crate::{
|
||||
instructions::{Instruction, Mnemonic},
|
||||
operands::{Byte, ImmediateOperand, ModRmTarget, Word},
|
||||
interpreter::interrupt::Mess1,
|
||||
operands::{Byte, ImmediateOperand, ModRmTarget},
|
||||
};
|
||||
|
||||
use super::computer::{Computer, Operand};
|
||||
use super::{
|
||||
computer::{Computer, Operand},
|
||||
interrupt::InterruptMessage,
|
||||
};
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum InterpreterError {
|
||||
@@ -79,7 +83,7 @@ impl Interpreter {
|
||||
* MOV
|
||||
*/
|
||||
Mnemonic::MOV_BXIv(word) => self.computer.regs.bx.write(word),
|
||||
Mnemonic::INT(id) => self.handle_int(id)?,
|
||||
Mnemonic::INT(id) => self.interpret_interrupt(id)?,
|
||||
_ => log::info!("no action done"),
|
||||
}
|
||||
}
|
||||
@@ -87,7 +91,7 @@ impl Interpreter {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn handle_int(&self, id: u8) -> Result<(), InterpreterError> {
|
||||
fn interpret_interrupt(&self, id: u8) -> Result<(), InterpreterError> {
|
||||
let bx = self.computer.regs.bx.read() as usize;
|
||||
// a message is always 8 words aligned
|
||||
let len = 2 * 8;
|
||||
@@ -96,17 +100,28 @@ impl Interpreter {
|
||||
.get(bx..bx + len)
|
||||
.ok_or(InterpreterError::EndOfData)?
|
||||
.to_owned();
|
||||
let interrupt_data = InterruptData::new(data);
|
||||
|
||||
let msg = InterruptMessage::new(&data);
|
||||
|
||||
// simulate interrupt handler code of MINIX
|
||||
match id {
|
||||
// sofware interrupts
|
||||
0x20 => {
|
||||
match interrupt_data.interrupt_id {
|
||||
log::debug!("Software interrupt with raw data {:?}", data);
|
||||
match msg.m_type {
|
||||
// EXIT()
|
||||
0x01 => {
|
||||
let data = Mess1::new(&data);
|
||||
let status = data.i1;
|
||||
log::info!("executing exit({})", status);
|
||||
exit(status.into())
|
||||
}
|
||||
// WRITE()
|
||||
0x04 => {
|
||||
let fd = interrupt_data.m_type;
|
||||
let location = interrupt_data.data_position;
|
||||
let len = interrupt_data.count;
|
||||
let data = Mess1::new(&data);
|
||||
let fd = data.i1;
|
||||
let len = data.i2;
|
||||
let location = data.p1;
|
||||
log::info!("executing write({}, {}, {})", fd, location, len);
|
||||
for byte in &self.data[location as usize..] {
|
||||
if *byte == 0x00 {
|
||||
@@ -116,11 +131,6 @@ impl Interpreter {
|
||||
}
|
||||
}
|
||||
}
|
||||
0x01 => {
|
||||
let exit_code = interrupt_data.data_position;
|
||||
log::info!("executing exit({})", exit_code);
|
||||
exit(exit_code.into())
|
||||
}
|
||||
_ => todo!(),
|
||||
};
|
||||
}
|
||||
@@ -130,42 +140,3 @@ impl Interpreter {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
// https://cse.unl.edu/~goddard/Courses/CSCE351/Lectures/Lecture8.pdf
|
||||
pub struct InterruptData {
|
||||
pub m_type: Word, // Operation requested
|
||||
pub interrupt_id: Word, // Minor device to use
|
||||
pub proc_nr: Word, // Process requesting the I/O
|
||||
pub count: Word, // Word count or ioctl code
|
||||
pub position: Word, // Position on device
|
||||
pub data_position: Word, // Minor device to use
|
||||
}
|
||||
|
||||
impl InterruptData {
|
||||
pub fn new(data: Vec<u8>) -> Self {
|
||||
Self {
|
||||
m_type: Word::from_le_bytes([data[0], data[1]]),
|
||||
interrupt_id: Word::from_le_bytes([data[2], data[3]]),
|
||||
proc_nr: Word::from_le_bytes([data[4], data[5]]),
|
||||
count: Word::from_le_bytes([data[6], data[7]]),
|
||||
position: Word::from_le_bytes([data[8], data[9]]),
|
||||
data_position: Word::from_le_bytes([data[10], data[11]]),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for InterruptData {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(
|
||||
f,
|
||||
"Interrupt({}, {}, {}, {}, {}, {})",
|
||||
self.m_type,
|
||||
self.interrupt_id,
|
||||
self.proc_nr,
|
||||
self.count,
|
||||
self.position,
|
||||
self.data_position
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
67
src/interpreter/interrupt.rs
Normal file
67
src/interpreter/interrupt.rs
Normal file
@@ -0,0 +1,67 @@
|
||||
use core::fmt;
|
||||
|
||||
use crate::operands::Word;
|
||||
|
||||
// TODO:
|
||||
// typedef struct {int m2i1, m2i2, m2i3; long m2l1, m2l2; char *m2p1;} mess_2;
|
||||
// typedef struct {int m3i1, m3i2; char *m3p1; char m3ca1[M3_STRING];} mess_3;
|
||||
// typedef struct {long m4l1, m4l2, m4l3, m4l4, m4l5;} mess_4;
|
||||
// typedef struct {char m5c1, m5c2; int m5i1, m5i2; long m5l1, m5l2, m5l3;}mess_5;
|
||||
// typedef struct {int m6i1, m6i2, m6i3; long m6l1; sighandler_t m6f1;} mess_6;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
// typedef struct {int m1i1, m1i2, m1i3; char *m1p1, *m1p2, *m1p3;} mess_1;
|
||||
pub struct Mess1 {
|
||||
pub i1: Word,
|
||||
pub i2: Word,
|
||||
pub i3: Word,
|
||||
pub p1: Word,
|
||||
pub p2: Word,
|
||||
pub p3: Word,
|
||||
}
|
||||
|
||||
impl Mess1 {
|
||||
pub fn new(data: &Vec<u8>) -> Self {
|
||||
Self {
|
||||
i1: Word::from_le_bytes([data[4], data[5]]),
|
||||
i2: Word::from_le_bytes([data[6], data[7]]),
|
||||
i3: Word::from_le_bytes([data[8], data[9]]),
|
||||
p1: Word::from_le_bytes([data[10], data[11]]),
|
||||
p2: Word::from_le_bytes([data[12], data[13]]),
|
||||
p3: Word::from_le_bytes([data[14], data[15]]),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for Mess1 {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(
|
||||
f,
|
||||
"Mess1({} {} {} {} {} {})",
|
||||
self.i1, self.i2, self.i3, self.p1, self.p2, self.p3
|
||||
)
|
||||
}
|
||||
}
|
||||
#[derive(Debug, Clone)]
|
||||
/// First part of: include/minix/type.h:struct message
|
||||
/// The union-type will be handled differently, where I the data of each
|
||||
/// MessX type will be parsed, when needed for each specific interrupt.
|
||||
pub struct InterruptMessage {
|
||||
pub m_source: Word,
|
||||
pub m_type: Word,
|
||||
}
|
||||
|
||||
impl InterruptMessage {
|
||||
pub fn new(data: &Vec<u8>) -> Self {
|
||||
Self {
|
||||
m_source: Word::from_le_bytes([data[0], data[1]]),
|
||||
m_type: Word::from_le_bytes([data[2], data[3]]),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for InterruptMessage {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "Interrupt({}, {})", self.m_source, self.m_type)
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
mod computer;
|
||||
mod flags;
|
||||
pub mod interpreter;
|
||||
mod interrupt;
|
||||
mod memory;
|
||||
mod register;
|
||||
|
||||
Reference in New Issue
Block a user