fix: align interrupt data with minix src

This commit is contained in:
2025-06-10 09:44:34 +09:00
parent 232b73aad8
commit 2b37884a60
3 changed files with 92 additions and 53 deletions

View File

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

View 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)
}
}

View File

@@ -1,5 +1,6 @@
mod computer;
mod flags;
pub mod interpreter;
mod interrupt;
mod memory;
mod register;