summary refs log tree commit diff
path: root/src/instructions.rs
diff options
context:
space:
mode:
authorAshelyn Rose <git@ashen.earth>2024-12-21 17:23:24 -0700
committerAshelyn Rose <git@ashen.earth>2024-12-21 17:23:24 -0700
commit9a2c2bc2d9ff45b9bd96c570b8c5fc0b03067ccc (patch)
tree12f65bfca6e285911713c6699b4d2a534df88cd4 /src/instructions.rs
parentfbbeed8c10dc9c9bdb34f946d5b844b537ebad7a (diff)
Implement setiosys
Diffstat (limited to 'src/instructions.rs')
-rw-r--r--src/instructions.rs431
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,
-}