add inline assembly module
[power-instruction-analyzer.git] / power-instruction-analyzer-proc-macro / src / lib.rs
index 30f208a5119710784de5ec170d649a9b4f1f2f78..b5eb2058f584d7ddfdf00eb5d37e4d79c3df820f 100644 (file)
@@ -12,6 +12,8 @@ use syn::{
     Attribute, Error, ItemFn, LitStr, Token,
 };
 
+mod inline_assembly;
+
 macro_rules! valid_enumerants_as_string {
     ($enumerant:ident) => {
         concat!("`", stringify!($enumerant), "`")
@@ -139,16 +141,9 @@ ident_enum! {
     }
 }
 
-#[derive(Debug, Clone)]
-enum AssemblyTextFragment {
-    Text(String),
-    InputIndex(usize),
-    OutputIndex(usize),
-}
-
 struct InlineAssembly {
     text: Vec<AssemblyTextFragment>,
-    text_span: Span,
+    text_span: Option<Span>,
     inputs: Vec<TokenStream>,
     outputs: Vec<TokenStream>,
     clobbers: Vec<TokenStream>,
@@ -165,6 +160,24 @@ impl fmt::Write for InlineAssembly {
     }
 }
 
+impl From<String> for InlineAssembly {
+    fn from(s: String) -> Self {
+        InlineAssembly {
+            text: vec![AssemblyTextFragment::Text(s)],
+            text_span: None,
+            inputs: Vec::new(),
+            outputs: Vec::new(),
+            clobbers: Vec::new(),
+        }
+    }
+}
+
+impl From<&'_ str> for InlineAssembly {
+    fn from(s: &'_ str) -> Self {
+        String::from(s).into()
+    }
+}
+
 impl InlineAssembly {
     fn new(text_span: Span) -> Self {
         Self {
@@ -196,6 +209,16 @@ impl InlineAssembly {
         self.text.push(AssemblyTextFragment::OutputIndex(index));
         Ok(())
     }
+    fn add_input(&mut self, input: TokenStream) -> usize {
+        let retval = self.inputs.len();
+        self.inputs.push(input);
+        retval
+    }
+    fn add_output(&mut self, output: TokenStream) -> usize {
+        let retval = self.outputs.len();
+        self.outputs.push(output);
+        retval
+    }
 }
 
 impl ToTokens for InlineAssembly {
@@ -284,25 +307,11 @@ impl Instruction {
         let mut asm = InlineAssembly::new(instruction_name.span());
         let mut before_asm = Vec::<TokenStream>::new();
         let mut after_asm = Vec::<TokenStream>::new();
-        for output in &self.outputs {
-            match output {
-                InstructionOutput::Rt(span) => {
-                    unimplemented!("InstructionOutput::Rt");
-                }
-                InstructionOutput::Carry(span) => {
-                    unimplemented!("InstructionOutput::Carry");
-                }
-                InstructionOutput::Overflow(span) => {
-                    unimplemented!("InstructionOutput::Overflow");
-                }
-                InstructionOutput::CR0(span) => {
-                    unimplemented!("InstructionOutput::CR0");
-                }
-            }
-        }
         for input in &self.inputs {
             match input {
                 InstructionInput::Ra(span) => {
+                    before_asm.push(quote! {let ra = inputs.ra;});
+                    let input_index = asm.add_input(quote! {"b"(ra)});
                     unimplemented!("InstructionInput::Ra");
                 }
                 InstructionInput::Rb(span) => {
@@ -316,18 +325,25 @@ impl Instruction {
                 }
             }
         }
+        for output in &self.outputs {
+            match output {
+                InstructionOutput::Rt(span) => {
+                    unimplemented!("InstructionOutput::Rt");
+                }
+                InstructionOutput::Carry(span) => {
+                    unimplemented!("InstructionOutput::Carry");
+                }
+                InstructionOutput::Overflow(span) => {
+                    unimplemented!("InstructionOutput::Overflow");
+                }
+                InstructionOutput::CR0(span) => {
+                    unimplemented!("InstructionOutput::CR0");
+                }
+            }
+        }
         Ok(quote! {
             pub fn #fn_name(inputs: InstructionInput) -> InstructionResult {
                 #![allow(unused_variables, unused_assignments)]
-                let InstructionInput {
-                    ra,
-                    rb,
-                    rc,
-                    carry,
-                } = inputs;
-                let rt: u64;
-                let xer: u64;
-                let cr: u32;
                 #(#before_asm)*
                 unsafe {
                     #asm;