summary refs log tree commit diff
path: root/opcode_proc/src/lib.rs
diff options
context:
space:
mode:
Diffstat (limited to 'opcode_proc/src/lib.rs')
-rw-r--r--opcode_proc/src/lib.rs32
1 files changed, 29 insertions, 3 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>,