diff options
author | Ashelyn Rose <git@ashen.earth> | 2024-12-21 17:23:24 -0700 |
---|---|---|
committer | Ashelyn Rose <git@ashen.earth> | 2024-12-21 17:23:24 -0700 |
commit | 9a2c2bc2d9ff45b9bd96c570b8c5fc0b03067ccc (patch) | |
tree | 12f65bfca6e285911713c6699b4d2a534df88cd4 /src/instructions.rs | |
parent | fbbeed8c10dc9c9bdb34f946d5b844b537ebad7a (diff) |
Implement setiosys
Diffstat (limited to 'src/instructions.rs')
-rw-r--r-- | src/instructions.rs | 431 |
1 files changed, 46 insertions, 385 deletions
diff --git a/src/instructions.rs b/src/instructions.rs index 59efd47..55bc5b9 100644 --- a/src/instructions.rs +++ b/src/instructions.rs @@ -1,11 +1,13 @@ use core::panic; use crate::interpreter::{MemAddress, StackAddress}; +use crate::opcodes::OpCode; #[derive(Debug)] pub struct Instruction { - pub operation: OpCode, - pub operands: Vec<Operand> + pub opcode: OpCode, + pub in_operands: Vec<Operand>, + pub out_operands: Vec<Operand>, } enum Nybble { @@ -13,7 +15,7 @@ enum Nybble { Low, } -#[derive(PartialEq, Debug)] +#[derive(PartialEq, Debug, Clone)] pub enum Operand { Constant(i32), PopStack, @@ -23,17 +25,44 @@ pub enum Operand { } impl Instruction { - pub fn read<'a, I>(bytes: &mut I) -> (Instruction, u32) + pub fn read<'a, I>(bytes: &mut I) -> Result<(Instruction, u32), u32> where I: IntoIterator<Item = &'a u8> + Copy { let mut bytes = bytes.into_iter().enumerate().peekable(); - let instruction_length = OpCode::get_length(*bytes.peek().unwrap().1); - let mut bytes = bytes.into_iter(); - let instruction_bytes = (0..instruction_length).into_iter().map(|_n| *bytes.next().unwrap().1).collect(); - let operation = OpCode::from_bytes(instruction_bytes); - let operand_count = operation.get_operand_count(); + let instruction_length = { + let first_byte = *bytes.peek().unwrap().1; + match first_byte >> 6 { + 0b00 | 0b01 => 1, + 0b10 => 2, + 0b11 => 4, + _ => unreachable!() + } + }; + + let mask = match instruction_length { + 1 => 0, + 2 => 0x8000, + 4 => 0xC0000000, + _ => panic!("Invalid opcode byte array"), + }; + + let instruction_bytes = (0..4-instruction_length).into_iter().map(|_n| 0).chain( + (0..instruction_length).into_iter().map(|_n| *bytes.next().unwrap().1) + ).collect::<Vec<_>>(); + + let opcode_num = u32::from_be_bytes(instruction_bytes.clone().try_into().unwrap()) & !mask; + println!("instruction length: {instruction_length}, number: 0x{opcode_num:x}, bytes: {instruction_bytes:?}"); + let opcode = OpCode::get_from_code(opcode_num); + if let None = opcode { + return Err(opcode_num); + } + let opcode = opcode.unwrap(); + let input_operand_count = OpCode::get_input_arg_count(opcode.clone()); + let output_operand_count = OpCode::get_output_arg_count(opcode.clone()); + + let operand_count = input_operand_count + output_operand_count; let operand_bytes = (operand_count + 1) / 2; let skip_last_half = operand_bytes != operand_count / 2; let operand_bytes = (0..operand_bytes).into_iter().map(|_n| *bytes.next().unwrap().1); @@ -76,382 +105,14 @@ impl Instruction { operands.remove(operands.len() - 1); } - // Return instruction along with the number of bytes we've read - (Instruction { - operation, - operands, - }, data_bytes.peek().unwrap().0 as u32) - } -} - -impl OpCode { - fn get_length(first_byte: u8) -> usize { - let length = match first_byte >> 6 { - 0b00 | 0b01 => 1, - 0b10 => 2, - 0b11 => 4, - _ => unreachable!() - }; - return length - } - - fn from_bytes(bytes: Vec<u8>) -> Self { - let (padded_bytes, mask) = match bytes.len() { - 1 => ([0,0,0,bytes[0]], 0), - 2 => ([0,0,bytes[0],bytes[1]], 0x8000), - 4 => ([bytes[0],bytes[1],bytes[2],bytes[3]], 0xC0000000), - _ => panic!("Invalid opcode byte array") - }; - - let instruction = u32::from_be_bytes(padded_bytes) & !mask; - return unsafe { std::mem::transmute(instruction) } - } - - fn get_operand_count(&self) -> usize { - match *self { - // Misc - OpCode::Nop => 0, - OpCode::Gestalt => 3, - OpCode::Debugtrap => 1, - OpCode::Glk => 3, - - // Integer math - OpCode::Add => 3, - OpCode::Sub => 3, - OpCode::Mul => 3, - OpCode::Div => 3, - OpCode::Mod => 3, - OpCode::Neg => 2, - OpCode::Bitand => 3, - OpCode::Bitor => 3, - OpCode::Bitxor => 3, - OpCode::Bitnot => 3, - OpCode::Shiftl => 3, - OpCode::Sshiftr => 3, - OpCode::Ushiftr => 3, - - // Branches - OpCode::Jump => 1, - OpCode::Jz => 2, - OpCode::Jnz => 2, - OpCode::Jeq => 3, - OpCode::Jne => 3, - OpCode::Jlt => 3, - OpCode::Jge => 3, - OpCode::Jgt => 3, - OpCode::Jle => 3, - OpCode::Jltu => 3, - OpCode::Jgeu => 3, - OpCode::Jgtu => 3, - OpCode::Jleu => 3, - OpCode::Jumpabs => 1, + let in_operands = operands[0..input_operand_count].try_into().unwrap(); + let out_operands = operands[input_operand_count..].try_into().unwrap(); - // Moving data - OpCode::Copy => 2, - OpCode::Copys => 2, - OpCode::Copyb => 2, - OpCode::Sexs => 2, - OpCode::Sexb => 2, - - // Array data - OpCode::Aload => 3, - OpCode::Aloads => 3, - OpCode::Aloadb => 3, - OpCode::Aloadbit => 3, - OpCode::Astore => 3, - OpCode::Astores => 3, - OpCode::Astoreb => 3, - OpCode::Astorebit => 3, - - // Stack operations - OpCode::Stkcount => 1, - OpCode::Stkpeek => 2, - OpCode::Stkswap => 0, - OpCode::Stkroll => 2, - OpCode::Stkcopy => 1, - - // Functions - OpCode::Call => 3, - OpCode::Callf => 2, - OpCode::Callfi => 3, - OpCode::Callfii => 4, - OpCode::Callfiii => 5, - OpCode::Return => 1, - OpCode::Tailcall => 2, - - // Continuations - OpCode::Catch => 2, - OpCode::Throw => 2, - - // Memory - OpCode::Getmemsize => 1, - OpCode::Setmemsize => 2, - OpCode::Malloc => 2, - OpCode::Mfree => 1, - - // Game state - OpCode::Quit => 0, - OpCode::Restart => 0, - OpCode::Save => 2, - OpCode::Restore => 2, - OpCode::Saveundo => 1, - OpCode::Restoreundo => 1, - OpCode::Hasundo => 1, - OpCode::Discardundo => 0, - OpCode::Protect => 2, - OpCode::Verify => 1, - - // Output - OpCode::Getiosys => 2, - OpCode::Setiosys => 2, - OpCode::Streamchar => 1, - OpCode::Streamunichar => 1, - OpCode::Streamnum => 1, - OpCode::Streamstr => 1, - OpCode::Getstringtbl => 1, - OpCode::Setstringtbl => 1, - - // Floating point math - OpCode::Numtof => 2, - OpCode::Ftonumz => 2, - OpCode::Ftonumn => 2, - OpCode::Fadd => 3, - OpCode::Fsub => 3, - OpCode::Fmul => 3, - OpCode::Fdiv => 3, - OpCode::Fmod => 4, - OpCode::Ceil => 2, - OpCode::Floor => 2, - OpCode::Sqrt => 2, - OpCode::Exp => 2, - OpCode::Log => 2, - OpCode::Pow => 3, - OpCode::Sin => 2, - OpCode::Cos => 2, - OpCode::Tan => 2, - OpCode::Asin => 2, - OpCode::Acos => 2, - OpCode::Atan => 2, - OpCode::Atan2 => 3, - - // Double precision math - OpCode::Numtod => 3, - OpCode::Dtonumz => 3, - OpCode::Dtonumn => 3, - OpCode::Ftod => 3, - OpCode::Dtof => 3, - OpCode::Dadd => 6, - OpCode::Dsub => 6, - OpCode::Dmul => 6, - OpCode::Ddiv => 6, - OpCode::Dmodr => 6, - OpCode::Dmodq => 6, - OpCode::Dceil => 4, - OpCode::Dfloor => 4, - OpCode::Dsqrt => 4, - OpCode::Dexp => 4, - OpCode::Dlog => 4, - OpCode::Dpow => 6, - OpCode::Dsin => 4, - OpCode::Dcos => 4, - OpCode::Dtan => 4, - OpCode::Dasin => 4, - OpCode::Dacos => 4, - OpCode::Datan => 4, - OpCode::Datan2 => 4, - - // Floating point comparisons - OpCode::Jisnan => 2, - OpCode::Jisinf => 2, - OpCode::Jfeq => 4, - OpCode::Jfne => 4, - OpCode::Jflt => 3, - OpCode::Jfle => 3, - OpCode::Jfgt => 3, - OpCode::Jfge => 3, - - // Double precision comparisons - OpCode::Jdisnan => 3, - OpCode::Jdisinf => 3, - OpCode::Jdeq => 7, - OpCode::Jdne => 7, - OpCode::Jdlt => 5, - OpCode::Jdle => 5, - OpCode::Jdgt => 5, - OpCode::Jdge => 5, - - // RNG - OpCode::Random => 2, - OpCode::Setrandom => 1, - - // Block copy and clear - OpCode::Mzero => 2, - OpCode::Mcopy => 3, - - // Searching - OpCode::Linearsearch => 8, - OpCode::Binarysearch => 8, - OpCode::Linkedsearch => 7, - - // Accelerated functions - OpCode::Accelfunc => 2, - OpCode::Accelparam => 2, - } + // Return instruction along with the number of bytes we've read + Ok((Instruction { + opcode, + in_operands, + out_operands, + }, data_bytes.peek().unwrap().0 as u32)) } } - - -#[repr(u32)] -#[derive(Debug)] -pub enum OpCode { - Nop = 0x00, - Add = 0x10, - Sub = 0x11, - Mul = 0x12, - Div = 0x13, - Mod = 0x14, - Neg = 0x15, - Bitand = 0x18, - Bitor = 0x19, - Bitxor = 0x1A, - Bitnot = 0x1B, - Shiftl = 0x1C, - Sshiftr = 0x1D, - Ushiftr = 0x1E, - Jump = 0x20, - Jz = 0x22, - Jnz = 0x23, - Jeq = 0x24, - Jne = 0x25, - Jlt = 0x26, - Jge = 0x27, - Jgt = 0x28, - Jle = 0x29, - Jltu = 0x2A, - Jgeu = 0x2B, - Jgtu = 0x2C, - Jleu = 0x2D, - Call = 0x30, - Return = 0x31, - Catch = 0x32, - Throw = 0x33, - Tailcall = 0x34, - Copy = 0x40, - Copys = 0x41, - Copyb = 0x42, - Sexs = 0x44, - Sexb = 0x45, - Aload = 0x48, - Aloads = 0x49, - Aloadb = 0x4A, - Aloadbit = 0x4B, - Astore = 0x4C, - Astores = 0x4D, - Astoreb = 0x4E, - Astorebit = 0x4F, - Stkcount = 0x50, - Stkpeek = 0x51, - Stkswap = 0x52, - Stkroll = 0x53, - Stkcopy = 0x54, - Streamchar = 0x70, - Streamnum = 0x71, - Streamstr = 0x72, - Streamunichar = 0x73, - Gestalt = 0x100, - Debugtrap = 0x101, - Getmemsize = 0x102, - Setmemsize = 0x103, - Jumpabs = 0x104, - Random = 0x110, - Setrandom = 0x111, - Quit = 0x120, - Verify = 0x121, - Restart = 0x122, - Save = 0x123, - Restore = 0x124, - Saveundo = 0x125, - Restoreundo = 0x126, - Protect = 0x127, - Hasundo = 0x128, - Discardundo = 0x129, - Glk = 0x130, - Getstringtbl = 0x140, - Setstringtbl = 0x141, - Getiosys = 0x148, - Setiosys = 0x149, - Linearsearch = 0x150, - Binarysearch = 0x151, - Linkedsearch = 0x152, - Callf = 0x160, - Callfi = 0x161, - Callfii = 0x162, - Callfiii = 0x163, - Mzero = 0x170, - Mcopy = 0x171, - Malloc = 0x178, - Mfree = 0x179, - Accelfunc = 0x180, - Accelparam = 0x181, - Numtof = 0x190, - Ftonumz = 0x191, - Ftonumn = 0x192, - Ceil = 0x198, - Floor = 0x199, - Fadd = 0x1A0, - Fsub = 0x1A1, - Fmul = 0x1A2, - Fdiv = 0x1A3, - Fmod = 0x1A4, - Sqrt = 0x1A8, - Exp = 0x1A9, - Log = 0x1AA, - Pow = 0x1AB, - Sin = 0x1B0, - Cos = 0x1B1, - Tan = 0x1B2, - Asin = 0x1B3, - Acos = 0x1B4, - Atan = 0x1B5, - Atan2 = 0x1B6, - Jfeq = 0x1C0, - Jfne = 0x1C1, - Jflt = 0x1C2, - Jfle = 0x1C3, - Jfgt = 0x1C4, - Jfge = 0x1C5, - Jisnan = 0x1C8, - Jisinf = 0x1C9, - Numtod = 0x200, - Dtonumz = 0x201, - Dtonumn = 0x202, - Ftod = 0x203, - Dtof = 0x204, - Dceil = 0x208, - Dfloor = 0x209, - Dadd = 0x210, - Dsub = 0x211, - Dmul = 0x212, - Ddiv = 0x213, - Dmodr = 0x214, - Dmodq = 0x215, - Dsqrt = 0x218, - Dexp = 0x219, - Dlog = 0x21A, - Dpow = 0x21B, - Dsin = 0x220, - Dcos = 0x221, - Dtan = 0x222, - Dasin = 0x223, - Dacos = 0x224, - Datan = 0x225, - Datan2 = 0x226, - Jdeq = 0x230, - Jdne = 0x231, - Jdlt = 0x232, - Jdle = 0x233, - Jdgt = 0x234, - Jdge = 0x235, - Jdisnan = 0x238, - Jdisinf = 0x239, -} |