diff options
-rw-r--r-- | opcode_proc/src/lib.rs | 32 | ||||
-rw-r--r-- | src/glk.rs | 1 | ||||
-rw-r--r-- | src/instructions.rs | 431 | ||||
-rw-r--r-- | src/interpreter.rs | 425 | ||||
-rw-r--r-- | src/main.rs | 1 | ||||
-rw-r--r-- | src/opcodes.rs | 780 |
6 files changed, 890 insertions, 780 deletions
diff --git a/opcode_proc/src/lib.rs b/opcode_proc/src/lib.rs index d777214..7c84f9a 100644 --- a/opcode_proc/src/lib.rs +++ b/opcode_proc/src/lib.rs @@ -19,7 +19,7 @@ pub fn generate_opcodes(item: TokenStream) -> TokenStream { let code = &field.byte_code; let variant = &field.name; quote! { - #code => Self::#variant, + #code => Some(Self::#variant), } }).collect::<Vec<_>>(); @@ -39,6 +39,14 @@ pub fn generate_opcodes(item: TokenStream) -> TokenStream { } }); + let gen_stub_arms = ops_def.codes.iter().map(|field| { + let variant = &field.name; + let value = &field.no_store; + quote! { + #enum_name::#variant => #value, + } + }); + let closure_match_arms = ops_def.codes.iter().map(|field| { let variant = &field.name; let closure_expr = &field.func_block; @@ -87,15 +95,16 @@ pub fn generate_opcodes(item: TokenStream) -> TokenStream { }); let tokens = quote! { + #[derive(Debug, Clone)] pub enum #enum_name { #(#field_names),* } impl #enum_name { - pub fn get_from_code(code: u32) -> Self { + pub fn get_from_code(code: u32) -> Option<Self> { match code { #(#getcode_match_arms)* - _ => panic!("Unknown opcode 0x{code:03x}") + _ => None } } @@ -111,6 +120,12 @@ pub fn generate_opcodes(item: TokenStream) -> TokenStream { } } + pub fn should_gen_return_stub(opcode: Self) -> bool { + match opcode { + #(#gen_stub_arms)* + } + } + pub fn call_opcode(interpreter: &mut crate::Interpreter, opcode: Self, input_params: Vec<u32>) -> Vec<u32> { match opcode { #(#closure_match_arms)* @@ -148,6 +163,15 @@ impl Parse for SingleOpcodeDefinition { parenthesized!(code in attr); let byte_code = code.parse::<LitInt>()?; + let mut no_store = false; + if attr.peek(Token![,]) { + attr.parse::<Token![,]>()?; + let extra_attr = attr.parse::<Ident>()?; + if extra_attr == "no_store" { + no_store = true; + } + } + input.parse::<Token![fn]>()?; let name = input.parse::<Ident>()?; @@ -186,6 +210,7 @@ impl Parse for SingleOpcodeDefinition { Ok(SingleOpcodeDefinition { byte_code, + no_store, name, input_params, interpreter_ident, @@ -204,6 +229,7 @@ struct OpcodeBlock { struct SingleOpcodeDefinition { pub byte_code: LitInt, + pub no_store: bool, pub name: Ident, pub interpreter_ident: Option<Ident>, pub input_params: Vec<PatType>, diff --git a/src/glk.rs b/src/glk.rs index 3efb095..ed308f9 100644 --- a/src/glk.rs +++ b/src/glk.rs @@ -1,3 +1,2 @@ pub struct Glk { - } 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, -} diff --git a/src/interpreter.rs b/src/interpreter.rs index b93b05f..9f226ae 100644 --- a/src/interpreter.rs +++ b/src/interpreter.rs @@ -1,6 +1,6 @@ use core::panic; -use crate::{glk::Glk, instructions::{Instruction, Operand}}; +use crate::{glk::Glk, instructions::{Instruction, Operand}, opcodes::OpCode}; pub type MemAddress = u32; pub type StackAddress = u32; @@ -33,7 +33,7 @@ pub struct HeapChunk { pub enum Output { Null, Filter(FunctionPointer), - Glk(Glk), + Glk(Glk, u32), } pub struct Interpreter { @@ -49,6 +49,7 @@ pub struct Interpreter { pub reg_strdec: MemAddress, pub output_mode: Output, + tmp_dest_oper: Option<Operand>, } impl Interpreter { @@ -81,6 +82,7 @@ impl Interpreter { reg_strdec: str_decode, output_mode: Output::Null, + tmp_dest_oper: None, } } @@ -90,406 +92,53 @@ impl Interpreter { loop { let pc = self.reg_program as usize; let mut instruction_slice = &self.memory[pc..pc+100]; - let (instruction, bytes_read) = Instruction::read(&mut instruction_slice); + let instruction_read = Instruction::read(&mut instruction_slice); + if let Err(unknown_opcode) = instruction_read { + panic!("Unknown opcode 0x{unknown_opcode:03x} at 0x{pc:08x}") + } + let (instruction, bytes_read) = instruction_read.unwrap(); self.reg_program += bytes_read; println!("Executing instruction {instruction:?}"); - match instruction.operation { - crate::instructions::OpCode::Nop => (), - crate::instructions::OpCode::Add => { - let op1 = self.eval_source_operand(&instruction.operands[0]); - let op2 = self.eval_source_operand(&instruction.operands[1]); - - self.store_dest_operand(&instruction.operands[2], op1 + op2); - }, - crate::instructions::OpCode::Sub => { - let op1 = self.eval_source_operand(&instruction.operands[0]); - let op2 = self.eval_source_operand(&instruction.operands[1]); - - self.store_dest_operand(&instruction.operands[2], op1 - op2); - }, - crate::instructions::OpCode::Mul => { - let op1 = self.eval_source_operand(&instruction.operands[0]); - let op2 = self.eval_source_operand(&instruction.operands[1]); - - self.store_dest_operand(&instruction.operands[2], op1 * op2); - }, - crate::instructions::OpCode::Div => { - let op1 = self.eval_source_operand(&instruction.operands[0]) as i32; - let op2 = self.eval_source_operand(&instruction.operands[1]) as i32; - let result = (op1 / op2) as u32; - - self.store_dest_operand(&instruction.operands[2], result); - }, - crate::instructions::OpCode::Mod => { - let op1 = self.eval_source_operand(&instruction.operands[0]) as i32; - let op2 = self.eval_source_operand(&instruction.operands[1]) as i32; - let result = (op1 % op2) as u32; - - self.store_dest_operand(&instruction.operands[2], result); - }, - crate::instructions::OpCode::Neg => { - let op1 = self.eval_source_operand(&instruction.operands[0]) as i32; - let result = (-op1) as u32; - - self.store_dest_operand(&instruction.operands[1], result); - }, - crate::instructions::OpCode::Bitand => { - let op1 = self.eval_source_operand(&instruction.operands[0]); - let op2 = self.eval_source_operand(&instruction.operands[1]); - - self.store_dest_operand(&instruction.operands[2], op1 & op2); - }, - crate::instructions::OpCode::Bitor => { - let op1 = self.eval_source_operand(&instruction.operands[0]); - let op2 = self.eval_source_operand(&instruction.operands[1]); - - self.store_dest_operand(&instruction.operands[2], op1 | op2); - }, - crate::instructions::OpCode::Bitxor => { - let op1 = self.eval_source_operand(&instruction.operands[0]); - let op2 = self.eval_source_operand(&instruction.operands[1]); - - self.store_dest_operand(&instruction.operands[2], op1 ^ op2); - }, - crate::instructions::OpCode::Bitnot => { - let op1 = self.eval_source_operand(&instruction.operands[0]); - - self.store_dest_operand(&instruction.operands[1], !op1); - }, - crate::instructions::OpCode::Shiftl => { - let op1 = self.eval_source_operand(&instruction.operands[0]); - let op2 = self.eval_source_operand(&instruction.operands[1]); - - self.store_dest_operand(&instruction.operands[2], op1 << op2); - }, - crate::instructions::OpCode::Sshiftr => { - let op1 = self.eval_source_operand(&instruction.operands[0]); - let op2 = self.eval_source_operand(&instruction.operands[1]); - - self.store_dest_operand(&instruction.operands[2], op1 >> op2); - }, - crate::instructions::OpCode::Ushiftr => { - let op1 = self.eval_source_operand(&instruction.operands[0]); - let op2 = self.eval_source_operand(&instruction.operands[1]); - - self.store_dest_operand(&instruction.operands[2], op1 >> op2); - }, - crate::instructions::OpCode::Jump => { - let op1 = self.eval_source_operand(&instruction.operands[0]); - self.jump_with_offset(op1); - }, - crate::instructions::OpCode::Jz => { - let check = self.eval_source_operand(&instruction.operands[0]); - let destination = self.eval_source_operand(&instruction.operands[1]); - if check == 0 { - self.jump_with_offset(destination); - } - }, - crate::instructions::OpCode::Jnz => { - let check = self.eval_source_operand(&instruction.operands[0]); - let destination = self.eval_source_operand(&instruction.operands[1]); - if check != 0 { - self.jump_with_offset(destination); - } - }, - crate::instructions::OpCode::Jeq => { - let op1 = self.eval_source_operand(&instruction.operands[0]); - let op2 = self.eval_source_operand(&instruction.operands[1]); - let destination = self.eval_source_operand(&instruction.operands[2]); - if op1 == op2 { - self.jump_with_offset(destination); - } - }, - crate::instructions::OpCode::Jne => { - let op1 = self.eval_source_operand(&instruction.operands[0]) as i32; - let op2 = self.eval_source_operand(&instruction.operands[1]) as i32; - let destination = self.eval_source_operand(&instruction.operands[2]); - if op1 != op2 { - self.jump_with_offset(destination); - } - }, - crate::instructions::OpCode::Jlt => { - let op1 = self.eval_source_operand(&instruction.operands[0]) as i32; - let op2 = self.eval_source_operand(&instruction.operands[1]) as i32; - let destination = self.eval_source_operand(&instruction.operands[2]); - if op1 < op2 { - self.jump_with_offset(destination); - } - }, - crate::instructions::OpCode::Jge => { - let op1 = self.eval_source_operand(&instruction.operands[0]) as i32; - let op2 = self.eval_source_operand(&instruction.operands[1]) as i32; - let destination = self.eval_source_operand(&instruction.operands[2]); - if op1 >= op2 { - self.jump_with_offset(destination); - } - }, - crate::instructions::OpCode::Jgt => { - let op1 = self.eval_source_operand(&instruction.operands[0]) as i32; - let op2 = self.eval_source_operand(&instruction.operands[1]) as i32; - let destination = self.eval_source_operand(&instruction.operands[2]); - if op1 > op2 { - self.jump_with_offset(destination); - } - }, - crate::instructions::OpCode::Jle => { - let op1 = self.eval_source_operand(&instruction.operands[0]); - let op2 = self.eval_source_operand(&instruction.operands[1]); - let destination = self.eval_source_operand(&instruction.operands[2]); - if op1 <= op2 { - self.jump_with_offset(destination); - } - }, - crate::instructions::OpCode::Jltu => { - let op1 = self.eval_source_operand(&instruction.operands[0]); - let op2 = self.eval_source_operand(&instruction.operands[1]); - let destination = self.eval_source_operand(&instruction.operands[2]); - if op1 < op2 { - self.jump_with_offset(destination); - } - }, - crate::instructions::OpCode::Jgeu => { - let op1 = self.eval_source_operand(&instruction.operands[0]); - let op2 = self.eval_source_operand(&instruction.operands[1]); - let destination = self.eval_source_operand(&instruction.operands[2]); - if op1 >= op2 { - self.jump_with_offset(destination); - } - }, - crate::instructions::OpCode::Jgtu => { - let op1 = self.eval_source_operand(&instruction.operands[0]); - let op2 = self.eval_source_operand(&instruction.operands[1]); - let destination = self.eval_source_operand(&instruction.operands[2]); - if op1 > op2 { - self.jump_with_offset(destination); - } - }, - crate::instructions::OpCode::Jleu => { - let op1 = self.eval_source_operand(&instruction.operands[0]); - let op2 = self.eval_source_operand(&instruction.operands[1]); - let destination = self.eval_source_operand(&instruction.operands[2]); - if op1 <= op2 { - self.jump_with_offset(destination); - } - }, - crate::instructions::OpCode::Jumpabs => { - let destination = self.eval_source_operand(&instruction.operands[0]); - self.reg_program = destination; - }, - crate::instructions::OpCode::Copy => { - let source = self.eval_source_operand(&instruction.operands[0]); - self.store_dest_operand(&instruction.operands[1], source); - }, - crate::instructions::OpCode::Copys => todo!(), - crate::instructions::OpCode::Copyb => todo!(), - crate::instructions::OpCode::Sexs => { - let source = self.eval_source_operand(&instruction.operands[0]); - let result = source as i16 as i32 as u32; - self.store_dest_operand(&instruction.operands[1], result); - }, - crate::instructions::OpCode::Sexb => { - let source = self.eval_source_operand(&instruction.operands[0]); - let result = source as i8 as i32 as u32; - self.store_dest_operand(&instruction.operands[1], result); - }, - crate::instructions::OpCode::Aload => { - let l1 = self.eval_source_operand(&instruction.operands[0]); - let l2 = self.eval_source_operand(&instruction.operands[1]); - let value = self.get_word(l1.wrapping_add(4 * l2), ReadWriteDest::Memory); - self.store_dest_operand(&instruction.operands[2], value); - }, - crate::instructions::OpCode::Aloads => { - let l1 = self.eval_source_operand(&instruction.operands[0]); - let l2 = self.eval_source_operand(&instruction.operands[1]); - let value = self.get_twobyte(l1.wrapping_add(2 * l2), ReadWriteDest::Memory); - self.store_dest_operand(&instruction.operands[2], value as u32); - }, - crate::instructions::OpCode::Aloadb => { - let l1 = self.eval_source_operand(&instruction.operands[0]); - let l2 = self.eval_source_operand(&instruction.operands[1]); - let value = self.get_twobyte(l1.wrapping_add(l2), ReadWriteDest::Memory); - self.store_dest_operand(&instruction.operands[2], value as u32); - }, - crate::instructions::OpCode::Astore => { - let l1 = self.eval_source_operand(&instruction.operands[0]); - let l2 = self.eval_source_operand(&instruction.operands[1]); - let l3 = self.eval_source_operand(&instruction.operands[2]); - self.write_word(l1.wrapping_add(4 * l2), ReadWriteDest::Memory, l3); - }, - crate::instructions::OpCode::Astores => { - let l1 = self.eval_source_operand(&instruction.operands[0]); - let l2 = self.eval_source_operand(&instruction.operands[1]); - let l3 = self.eval_source_operand(&instruction.operands[2]); - self.write_twobyte(l1.wrapping_add(2 * l2), ReadWriteDest::Memory, l3 as u16); - }, - crate::instructions::OpCode::Astoreb => { - let l1 = self.eval_source_operand(&instruction.operands[0]); - let l2 = self.eval_source_operand(&instruction.operands[1]); - let l3 = self.eval_source_operand(&instruction.operands[2]); - self.write_byte(l1.wrapping_add(l2), ReadWriteDest::Memory, l3 as u8); - }, - crate::instructions::OpCode::Aloadbit => todo!(), - crate::instructions::OpCode::Astorebit => todo!(), - crate::instructions::OpCode::Stkcount => todo!(), - crate::instructions::OpCode::Stkpeek => todo!(), - crate::instructions::OpCode::Stkswap => todo!(), - crate::instructions::OpCode::Stkroll => todo!(), - crate::instructions::OpCode::Stkcopy => todo!(), - crate::instructions::OpCode::Call => { - let func_addr = self.eval_source_operand(&instruction.operands[0]); - let arg_count = self.eval_source_operand(&instruction.operands[1]); - let args = (0..arg_count).map(|_| self.pop_stack()).collect::<Vec<_>>(); - self.call_function(func_addr, args, &instruction.operands[2]); - }, - crate::instructions::OpCode::Callf => { - let func_addr = self.eval_source_operand(&instruction.operands[0]); - self.call_function(func_addr, Vec::new(), &instruction.operands[1]); - }, - crate::instructions::OpCode::Callfi => todo!(), - crate::instructions::OpCode::Callfii => todo!(), - crate::instructions::OpCode::Callfiii => todo!(), - crate::instructions::OpCode::Return => todo!(), - crate::instructions::OpCode::Catch => todo!(), - crate::instructions::OpCode::Throw => todo!(), - crate::instructions::OpCode::Tailcall => todo!(), - crate::instructions::OpCode::Streamchar => todo!(), - crate::instructions::OpCode::Streamnum => todo!(), - crate::instructions::OpCode::Streamstr => todo!(), - crate::instructions::OpCode::Streamunichar => todo!(), - crate::instructions::OpCode::Gestalt => { - let gestalt_num = self.eval_source_operand(&instruction.operands[0]); - let extra_arg = self.eval_source_operand(&instruction.operands[1]); - - if gestalt_num == 4 && extra_arg == 2 { - self.store_dest_operand(&instruction.operands[2], 1); - } else { - self.store_dest_operand(&instruction.operands[2], 0); - } - }, - crate::instructions::OpCode::Debugtrap => todo!(), - crate::instructions::OpCode::Getmemsize => todo!(), - crate::instructions::OpCode::Setmemsize => todo!(), - crate::instructions::OpCode::Random => todo!(), - crate::instructions::OpCode::Setrandom => todo!(), - crate::instructions::OpCode::Quit => { - println!("Quit called"); - return; - }, - crate::instructions::OpCode::Verify => todo!(), - crate::instructions::OpCode::Restart => todo!(), - crate::instructions::OpCode::Save => todo!(), - crate::instructions::OpCode::Restore => todo!(), - crate::instructions::OpCode::Saveundo => todo!(), - crate::instructions::OpCode::Restoreundo => todo!(), - crate::instructions::OpCode::Protect => todo!(), - crate::instructions::OpCode::Hasundo => todo!(), - crate::instructions::OpCode::Discardundo => todo!(), - crate::instructions::OpCode::Glk => todo!(), - crate::instructions::OpCode::Getstringtbl => todo!(), - crate::instructions::OpCode::Setstringtbl => todo!(), - crate::instructions::OpCode::Getiosys => todo!(), - crate::instructions::OpCode::Setiosys => todo!(), - crate::instructions::OpCode::Linearsearch => todo!(), - crate::instructions::OpCode::Binarysearch => todo!(), - crate::instructions::OpCode::Linkedsearch => todo!(), - crate::instructions::OpCode::Mzero => todo!(), - crate::instructions::OpCode::Mcopy => todo!(), - crate::instructions::OpCode::Malloc => todo!(), - crate::instructions::OpCode::Mfree => todo!(), - crate::instructions::OpCode::Accelfunc => todo!(), - crate::instructions::OpCode::Accelparam => todo!(), - crate::instructions::OpCode::Numtof => todo!(), - crate::instructions::OpCode::Ftonumz => todo!(), - crate::instructions::OpCode::Ftonumn => todo!(), - crate::instructions::OpCode::Ceil => todo!(), - crate::instructions::OpCode::Floor => todo!(), - crate::instructions::OpCode::Fadd => todo!(), - crate::instructions::OpCode::Fsub => todo!(), - crate::instructions::OpCode::Fmul => todo!(), - crate::instructions::OpCode::Fdiv => todo!(), - crate::instructions::OpCode::Fmod => todo!(), - crate::instructions::OpCode::Sqrt => todo!(), - crate::instructions::OpCode::Exp => todo!(), - crate::instructions::OpCode::Log => todo!(), - crate::instructions::OpCode::Pow => todo!(), - crate::instructions::OpCode::Sin => todo!(), - crate::instructions::OpCode::Cos => todo!(), - crate::instructions::OpCode::Tan => todo!(), - crate::instructions::OpCode::Asin => todo!(), - crate::instructions::OpCode::Acos => todo!(), - crate::instructions::OpCode::Atan => todo!(), - crate::instructions::OpCode::Atan2 => todo!(), - crate::instructions::OpCode::Jfeq => todo!(), - crate::instructions::OpCode::Jfne => todo!(), - crate::instructions::OpCode::Jflt => todo!(), - crate::instructions::OpCode::Jfle => todo!(), - crate::instructions::OpCode::Jfgt => todo!(), - crate::instructions::OpCode::Jfge => todo!(), - crate::instructions::OpCode::Jisnan => todo!(), - crate::instructions::OpCode::Jisinf => todo!(), - crate::instructions::OpCode::Numtod => todo!(), - crate::instructions::OpCode::Dtonumz => todo!(), - crate::instructions::OpCode::Dtonumn => todo!(), - crate::instructions::OpCode::Ftod => todo!(), - crate::instructions::OpCode::Dtof => todo!(), - crate::instructions::OpCode::Dceil => todo!(), - crate::instructions::OpCode::Dfloor => todo!(), - crate::instructions::OpCode::Dadd => todo!(), - crate::instructions::OpCode::Dsub => todo!(), - crate::instructions::OpCode::Dmul => todo!(), - crate::instructions::OpCode::Ddiv => todo!(), - crate::instructions::OpCode::Dmodr => todo!(), - crate::instructions::OpCode::Dmodq => todo!(), - crate::instructions::OpCode::Dsqrt => todo!(), - crate::instructions::OpCode::Dexp => todo!(), - crate::instructions::OpCode::Dlog => todo!(), - crate::instructions::OpCode::Dpow => todo!(), - crate::instructions::OpCode::Dsin => todo!(), - crate::instructions::OpCode::Dcos => todo!(), - crate::instructions::OpCode::Dtan => todo!(), - crate::instructions::OpCode::Dasin => todo!(), - crate::instructions::OpCode::Dacos => todo!(), - crate::instructions::OpCode::Datan => todo!(), - crate::instructions::OpCode::Datan2 => todo!(), - crate::instructions::OpCode::Jdeq => todo!(), - crate::instructions::OpCode::Jdne => todo!(), - crate::instructions::OpCode::Jdlt => todo!(), - crate::instructions::OpCode::Jdle => todo!(), - crate::instructions::OpCode::Jdgt => todo!(), - crate::instructions::OpCode::Jdge => todo!(), - crate::instructions::OpCode::Jdisnan => todo!(), - crate::instructions::OpCode::Jdisinf => todo!(), + let in_operands = instruction.in_operands.iter().map(|op| self.eval_source_operand(&op)).collect(); + let no_store = OpCode::should_gen_return_stub(instruction.opcode.clone()); + self.tmp_dest_oper = instruction.out_operands.get(0).cloned(); + + let result_values = OpCode::call_opcode(self, instruction.opcode, in_operands); + + if !no_store { + instruction.out_operands.iter().enumerate().for_each(|(index, op)| self.store_dest_operand(&op, result_values[index])); } } } - fn call_function(&mut self, func_addr: FunctionPointer, args: Vec<u32>, dest_oper: &Operand) { - let (dest_type, dest_addr) = match dest_oper { - Operand::Constant(_) => (StubDestType::DoNotStore, 0), - Operand::PopStack => (StubDestType::PushOnStack, 0), - Operand::FrameIndirect(offset) => (StubDestType::LocalVariable, *offset), - Operand::MemIndirect(offset) => (StubDestType::MainMemory, *offset), - Operand::MemRamIndirect(offset) => (StubDestType::MainMemory, self.mem_writeable + *offset), - }; - - self.create_return_stub(dest_type, dest_addr, self.reg_program, self.reg_frame); - + pub fn call_function(&mut self, func_addr: FunctionPointer, args: Vec<u32>) { let new_program_counter = self.create_stack_frame(func_addr, args); println!("Jumping to function at 0x{new_program_counter:04x}"); self.reg_program = new_program_counter; } - fn create_return_stub(&mut self, dest_type: StubDestType, dest_addr: u32, program_counter: MemAddress, frame_pointer: StackAddress) { + pub fn create_return_stub(&mut self) { + let dest_oper = self.tmp_dest_oper.clone(); + + let (dest_type, dest_addr) = match dest_oper { + None => (StubDestType::DoNotStore, 0), + Some(Operand::Constant(_)) => (StubDestType::DoNotStore, 0), + Some(Operand::PopStack) => (StubDestType::PushOnStack, 0), + Some(Operand::FrameIndirect(offset)) => (StubDestType::LocalVariable, offset), + Some(Operand::MemIndirect(offset)) => (StubDestType::MainMemory, offset), + Some(Operand::MemRamIndirect(offset)) => (StubDestType::MainMemory, self.mem_writeable + offset), + }; + self.push_stack(dest_type as u32); self.push_stack(dest_addr); - self.push_stack(program_counter); - self.push_stack(frame_pointer); + self.push_stack(self.reg_program); + self.push_stack(self.reg_frame); } // Returns program counter after parsing all the args - fn create_stack_frame(&mut self, func: FunctionPointer, mut args: Vec<u32>) -> MemAddress { + pub fn create_stack_frame(&mut self, func: FunctionPointer, mut args: Vec<u32>) -> MemAddress { // Reading function signature let func_type = self.get_byte(func, ReadWriteDest::Memory); @@ -572,7 +221,7 @@ impl Interpreter { return opcode_start; } - fn return_from_function(&mut self, value: u32) { + pub fn return_from_function(&mut self, value: u32) { // Discard frame self.reg_stack = self.reg_frame - 4; @@ -600,7 +249,7 @@ impl Interpreter { } } - fn jump_with_offset(&mut self, offset: u32) { + pub fn jump_with_offset(&mut self, offset: u32) { if offset == 1 || offset == 0 { return self.return_from_function(offset); } @@ -616,12 +265,12 @@ impl Interpreter { self.reg_program = destination; } - fn push_stack(&mut self, value: u32) { + pub fn push_stack(&mut self, value: u32) { self.write_word(self.reg_stack, ReadWriteDest::Stack, value); self.reg_stack += 4; } - fn pop_stack(&mut self) -> u32 { + pub fn pop_stack(&mut self) -> u32 { self.reg_stack -= 4; self.get_word(self.reg_stack, ReadWriteDest::Stack) } diff --git a/src/main.rs b/src/main.rs index 4e97cd4..3aeb2e7 100644 --- a/src/main.rs +++ b/src/main.rs @@ -3,7 +3,6 @@ mod interpreter; mod glk; mod instructions; mod opcodes; -use opcodes::OpCodes; use interpreter::Interpreter; use std::{env, fs, process::exit}; diff --git a/src/opcodes.rs b/src/opcodes.rs index e8ef7fe..1fbc80f 100644 --- a/src/opcodes.rs +++ b/src/opcodes.rs @@ -1,7 +1,9 @@ use opcode_proc::generate_opcodes; +use crate::{glk::Glk, interpreter::Output}; + generate_opcodes!( - pub enum OpCodes { + pub enum OpCode { #[code(0x00)] fn Nop() { @@ -17,11 +19,785 @@ generate_opcodes!( a - b }, + #[code(0x12)] + fn Mul(a: u32, b: u32) -> u32 { + a * b + }, + + #[code(0x13)] + fn Div(a: u32, b: u32) -> u32 { + a / b + }, + + #[code(0x14)] + fn Mod(a: u32, b: u32) -> u32 { + a % b + }, + + #[code(0x15)] + fn Neg(a: u32) -> u32 { + -(a as i32) as u32 + }, + + #[code(0x18)] + fn Bitand(a: u32, b: u32) -> u32 { + a & b + }, + + #[code(0x19)] + fn Bitor(a: u32, b: u32) -> u32 { + a | b + }, + + #[code(0x1A)] + fn Bitxor(a: u32, b: u32) -> u32 { + a ^ b + }, + + #[code(0x1B)] + fn Bitnot(a: u32) -> u32 { + !a + }, + + #[code(0x1C)] + fn Shiftl() { + todo!() + }, + + #[code(0x1D)] + fn Sshiftr() { + todo!() + }, + + #[code(0x1E)] + fn Ushiftr() { + todo!() + }, + + #[code(0x20)] + fn Jump() { + todo!() + }, + + #[code(0x22)] + fn Jz() { + todo!() + }, + #[code(0x23)] fn Jnz(&mut interpreter, comparison: u32, offset: u32) { if comparison != 0 { - interpreter.reg_program += offset; + interpreter.reg_program = interpreter.reg_program + offset - 2; + } + }, + + #[code(0x24)] + fn Jeq() { + todo!(); + }, + + #[code(0x25)] + fn Jne() { + todo!(); + }, + + #[code(0x26)] + fn Jlt() { + todo!(); + }, + + #[code(0x27)] + fn Jge() { + todo!(); + }, + + #[code(0x28)] + fn Jgt() { + todo!(); + }, + + #[code(0x29)] + fn Jle() { + todo!(); + }, + + #[code(0x2A)] + fn Jltu() { + todo!(); + }, + + #[code(0x2B)] + fn Jgeu() { + todo!(); + }, + + #[code(0x2C)] + fn Jgtu() { + todo!(); + }, + + #[code(0x2D)] + fn Jleu() { + todo!(); + }, + + #[code(0x30), no_store] + fn Call(&mut interpreter, func_addr: u32, arg_count: u32) -> u32 { + let args = (0..arg_count).map(|_| interpreter.pop_stack()).collect::<Vec<_>>(); + + interpreter.create_return_stub(); + interpreter.call_function(func_addr, args); + + // This gets ignored because of gen_return_stub but it's here for type reasons + return 0; + }, + + #[code(0x31)] + fn Return() { + todo!(); + }, + + #[code(0x32)] + fn Catch() { + todo!(); + }, + + #[code(0x33)] + fn Throw() { + todo!(); + }, + + #[code(0x34)] + fn Tailcall() { + todo!(); + }, + + #[code(0x40)] + fn Copy(param: u32) -> u32 { + return param + }, + + #[code(0x41)] + fn Copys() { + todo!(); + }, + + #[code(0x42)] + fn Copyb() { + todo!(); + }, + + #[code(0x44)] + fn Sexs() { + todo!(); + }, + + #[code(0x45)] + fn Sexb() { + todo!(); + }, + + #[code(0x48)] + fn Aload() { + todo!(); + }, + + #[code(0x49)] + fn Aloads() { + todo!(); + }, + + #[code(0x4A)] + fn Aloadb() { + todo!(); + }, + + #[code(0x4B)] + fn Aloadbit() { + todo!(); + }, + + #[code(0x4C)] + fn Astore() { + todo!(); + }, + + #[code(0x4D)] + fn Astores() { + todo!(); + }, + + #[code(0x4E)] + fn Astoreb() { + todo!(); + }, + + #[code(0x4F)] + fn Astorebit() { + todo!(); + }, + + #[code(0x50)] + fn Stkcount() { + todo!(); + }, + + #[code(0x51)] + fn Stkpeek() { + todo!(); + }, + + #[code(0x52)] + fn Stkswap() { + todo!(); + }, + + #[code(0x53)] + fn Stkroll() { + todo!(); + }, + + #[code(0x54)] + fn Stkcopy() { + todo!(); + }, + + #[code(0x70)] + fn Streamchar() { + todo!(); + }, + + #[code(0x71)] + fn Streamnum() { + todo!(); + }, + + #[code(0x72)] + fn Streamstr() { + todo!(); + }, + + #[code(0x73)] + fn Streamunichar() { + todo!(); + }, + + #[code(0x100)] + fn Gestalt(gestalt_selector: u32, extra_arg: u32) -> u32 { + match gestalt_selector { + // IO System + 4 => { + return match extra_arg { + // Null + 0 => 1, + 1 => 0, + 2 => 1, + 20 => 0, + _ => 0, + } + } + + _ => { + println!("WARN: Unknown gestalt {gestalt_selector}"); + return 0 + } + } + }, + + #[code(0x101)] + fn Debugtrap() { + todo!(); + }, + + #[code(0x102)] + fn Getmemsize() { + todo!(); + }, + + #[code(0x103)] + fn Setmemsize() { + todo!(); + }, + + #[code(0x104)] + fn Jumpabs() { + todo!(); + }, + + #[code(0x110)] + fn Random() { + todo!(); + }, + + #[code(0x111)] + fn Setrandom() { + todo!(); + }, + + #[code(0x120)] + fn Quit() { + println!("Story exited"); + std::process::exit(0); + }, + + #[code(0x121)] + fn Verify() { + todo!(); + }, + + #[code(0x122)] + fn Restart() { + todo!(); + }, + + #[code(0x123)] + fn Save() { + todo!(); + }, + + #[code(0x124)] + fn Restore() { + todo!(); + }, + + #[code(0x125)] + fn Saveundo() { + todo!(); + }, + + #[code(0x126)] + fn Restoreundo() { + todo!(); + }, + + #[code(0x127)] + fn Protect() { + todo!(); + }, + + #[code(0x128)] + fn Hasundo() { + todo!(); + }, + + #[code(0x129)] + fn Discardundo() { + todo!(); + }, + + #[code(0x130)] + fn Glk() { + todo!(); + }, + + #[code(0x140)] + fn Getstringtbl() { + todo!(); + }, + + #[code(0x141)] + fn Setstringtbl() { + todo!(); + }, + + #[code(0x148)] + fn Getiosys() { + todo!(); + }, + + #[code(0x149)] + fn Setiosys(&mut interpreter, mode: u32, rock: u32) { + match mode { + 0 => { + interpreter.output_mode = Output::Null; + }, + 1 => { + interpreter.output_mode = Output::Filter(rock); + }, + 2 => { + interpreter.output_mode = Output::Glk(Glk {}, rock); + }, + 20 => { + panic!("This interpreter does not support FyreVM"); + }, + _ => { + panic!("Unknown iosys mode {mode}"); + } } + }, + + #[code(0x150)] + fn Linearsearch() { + todo!(); + }, + + #[code(0x151)] + fn Binarysearch() { + todo!(); + }, + + #[code(0x152)] + fn Linkedsearch() { + todo!(); + }, + + #[code(0x160), no_store] + fn Callf(&mut interpreter, func_addr: u32) -> u32 { + interpreter.create_return_stub(); + interpreter.call_function(func_addr, Vec::new()); + + // This gets ignored because of gen_return_stub but it's here for type reasons + return 0; + }, + + #[code(0x161)] + fn Callfi() { + todo!(); + }, + + #[code(0x162)] + fn Callfii() { + todo!(); + }, + + #[code(0x163)] + fn Callfiii() { + todo!(); + }, + + #[code(0x170)] + fn Mzero() { + todo!(); + }, + + #[code(0x171)] + fn Mcopy() { + todo!(); + }, + + #[code(0x178)] + fn Malloc() { + todo!(); + }, + + #[code(0x179)] + fn Mfree() { + todo!(); + }, + + #[code(0x180)] + fn Accelfunc() { + todo!(); + }, + + #[code(0x181)] + fn Accelparam() { + todo!(); + }, + + #[code(0x190)] + fn Numtof() { + todo!(); + }, + + #[code(0x191)] + fn Ftonumz() { + todo!(); + }, + + #[code(0x192)] + fn Ftonumn() { + todo!(); + }, + + #[code(0x198)] + fn Ceil() { + todo!(); + }, + + #[code(0x199)] + fn Floor() { + todo!(); + }, + + #[code(0x1A0)] + fn Fadd() { + todo!(); + }, + + #[code(0x1A1)] + fn Fsub() { + todo!(); + }, + + #[code(0x1A2)] + fn Fmul() { + todo!(); + }, + + #[code(0x1A3)] + fn Fdiv() { + todo!(); + }, + + #[code(0x1A4)] + fn Fmod() { + todo!(); + }, + + #[code(0x1A8)] + fn Sqrt() { + todo!(); + }, + + #[code(0x1A9)] + fn Exp() { + todo!(); + }, + + #[code(0x1AA)] + fn Log() { + todo!(); + }, + + #[code(0x1AB)] + fn Pow() { + todo!(); + }, + + #[code(0x1B0)] + fn Sin() { + todo!(); + }, + + #[code(0x1B1)] + fn Cos() { + todo!(); + }, + + #[code(0x1B2)] + fn Tan() { + todo!(); + }, + + #[code(0x1B3)] + fn Asin() { + todo!(); + }, + + #[code(0x1B4)] + fn Acos() { + todo!(); + }, + + #[code(0x1B5)] + fn Atan() { + todo!(); + }, + + #[code(0x1B6)] + fn Atan2() { + todo!(); + }, + + #[code(0x1C0)] + fn Jfeq() { + todo!(); + }, + + #[code(0x1C1)] + fn Jfne() { + todo!(); + }, + + #[code(0x1C2)] + fn Jflt() { + todo!(); + }, + + #[code(0x1C3)] + fn Jfle() { + todo!(); + }, + + #[code(0x1C4)] + fn Jfgt() { + todo!(); + }, + + #[code(0x1C5)] + fn Jfge() { + todo!(); + }, + + #[code(0x1C8)] + fn Jisnan() { + todo!(); + }, + + #[code(0x1C9)] + fn Jisinf() { + todo!(); + }, + + #[code(0x200)] + fn Numtod() { + todo!(); + }, + + #[code(0x201)] + fn Dtonumz() { + todo!(); + }, + + #[code(0x202)] + fn Dtonumn() { + todo!(); + }, + + #[code(0x203)] + fn Ftod() { + todo!(); + }, + + #[code(0x204)] + fn Dtof() { + todo!(); + }, + + #[code(0x208)] + fn Dceil() { + todo!(); + }, + + #[code(0x209)] + fn Dfloor() { + todo!(); + }, + + #[code(0x210)] + fn Dadd() { + todo!(); + }, + + #[code(0x211)] + fn Dsub() { + todo!(); + }, + + #[code(0x212)] + fn Dmul() { + todo!(); + }, + + #[code(0x213)] + fn Ddiv() { + todo!(); + }, + + #[code(0x214)] + fn Dmodr() { + todo!(); + }, + + #[code(0x215)] + fn Dmodq() { + todo!(); + }, + + #[code(0x218)] + fn Dsqrt() { + todo!(); + }, + + #[code(0x219)] + fn Dexp() { + todo!(); + }, + + #[code(0x21A)] + fn Dlog() { + todo!(); + }, + + #[code(0x21B)] + fn Dpow() { + todo!(); + }, + + #[code(0x220)] + fn Dsin() { + todo!(); + }, + + #[code(0x221)] + fn Dcos() { + todo!(); + }, + + #[code(0x222)] + fn Dtan() { + todo!(); + }, + + #[code(0x223)] + fn Dasin() { + todo!(); + }, + + #[code(0x224)] + fn Dacos() { + todo!(); + }, + + #[code(0x225)] + fn Datan() { + todo!(); + }, + + #[code(0x226)] + fn Datan2() { + todo!(); + }, + + #[code(0x230)] + fn Jdeq() { + todo!(); + }, + + #[code(0x231)] + fn Jdne() { + todo!(); + }, + + #[code(0x232)] + fn Jdlt() { + todo!(); + }, + + #[code(0x233)] + fn Jdle() { + todo!(); + }, + + #[code(0x234)] + fn Jdgt() { + todo!(); + }, + + #[code(0x235)] + fn Jdge() { + todo!(); + }, + + #[code(0x238)] + fn Jdisnan() { + todo!(); + }, + + #[code(0x239)] + fn Jdisinf() { + todo!(); } } ); |