osiris_process/
operation.rs1use std::collections::HashMap;
9use std::fmt::{Debug, Formatter};
10
11use osiris_data::data::atomic::Word;
12
13use crate::operation::error::OperationResult;
14use crate::operation::scheme::{ArgumentScheme, ArgumentType, InstructionScheme, OperationId};
15use crate::register::RegisterId;
16use crate::processor::Cpu;
17
18pub mod scheme;
19pub mod error;
20
21pub type OperationFn<T> = fn(&mut Cpu, InstructionScheme) -> OperationResult<T>;
22
23#[derive(Clone, Debug)]
25pub struct Operation<T> {
26 id: OperationId,
27 name: String,
28 has_target: bool,
29 argument: ArgumentType,
30 function: OperationFn<T>,
31}
32
33impl<T> Operation<T> {
34 pub fn new(id: OperationId, name: String, has_target: bool, argument: ArgumentType, function: OperationFn<T>) -> Self {
35 Operation { id, name, has_target, argument, function }
36 }
37 pub fn id(&self) -> OperationId {
38 self.id
39 }
40 pub fn name(&self) -> String { self.name.clone() }
41 pub fn argument_type(&self) -> ArgumentType { self.argument }
42 pub fn has_target(&self) -> bool { self.has_target }
43
44 pub fn to_asm_template(&self) -> String {
46 let mut target_asm = "".to_string();
47 if self.has_target {
48 target_asm = ":$target".to_string();
49 }
50 let mut argument_asm = self.argument.to_asm_template();
51 if !argument_asm.is_empty() {
52 argument_asm = " ".to_string();
53 argument_asm.push_str(self.argument.to_asm_template().as_str());
54 }
55 format!("{}{}{}", self.name, target_asm, argument_asm).trim().to_string()
56 }
57
58 pub fn call(&self, cpu: &mut Cpu, scheme: InstructionScheme) -> OperationResult<T> {
62 (self.function)(cpu, scheme)
63 }
64
65 pub fn call_debug(&self, cpu: &mut Cpu, scheme: InstructionScheme) -> OperationResult<T> {
67 let instr = scheme.identifier.to_u16();
68 let target = scheme.target.to_u16();
69 let arg = scheme.argument.to_u32();
70 println!("[\x1b[34m{:04x}\x1b[31m{:04x}\x1b[33m{:08x}\x1b[0m] {}", instr, target, arg, self.to_debug_asm(scheme));
71 (self.function)(cpu, scheme)
72 }
73
74 pub fn to_debug_asm(&self, scheme: InstructionScheme) -> String {
76 let mut target_asm = "".to_string();
77 if self.has_target {
78 target_asm = format!("\x1b[0m:\x1b[31m{:04x}", scheme.target.to_u16());
79 }
80 let mut argument_asm = "".to_string();
81 if self.argument != ArgumentType::NoArgument {
82 argument_asm = format!(" \x1b[33m{}", scheme.argument.to_asm());
83 }
84 format!("\x1b[34m{}{}{}\x1b[0m", self.name, target_asm, argument_asm).trim().to_string()
85 }
86}
87
88#[derive(Copy, Clone, Eq, PartialEq)]
89pub struct Instruction {
90 raw: u64,
91}
92
93impl Debug for Instruction {
94 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
95 write!(f, "Instruction({:016x})", self.raw)
96 }
97}
98
99impl Instruction {
100 pub fn new(raw: u64) -> Self { Self { raw } }
101 pub fn to_u64(&self) -> u64 { self.raw }
102 pub fn from_word(word: Word) -> Self { Self::new(word.to_u64()) }
103 pub fn to_word(&self) -> Word { Word::new(self.to_u64()) }
104 pub fn operation_to_instruction<T>(&self, operation: &Operation<T>) -> InstructionScheme { self.scheme(operation.argument_type()) }
105
106 pub fn identifier(&self) -> OperationId { OperationId::new((self.raw >> 48) as u16) }
107 pub fn target(&self) -> RegisterId { RegisterId::new((self.raw >> 32) as u16) }
108 pub fn argument(&self, arg_type: ArgumentType) -> ArgumentScheme { ArgumentScheme::from_type(arg_type, self.raw as u32) }
109 pub fn scheme(&self, argument: ArgumentType) -> InstructionScheme {
110 InstructionScheme { identifier: self.identifier(), target: self.target(), argument: self.argument(argument) }
111 }
112 pub fn matches<T>(&self, operation: &Operation<T>) -> bool {
113 self.identifier() == operation.id()
114 }
115}
116
117pub type OperationSet = HashMap<OperationId, Operation<()>>;
118
119pub fn match_operation(set: &OperationSet, instruction: Instruction) -> Option<Operation<()>> {
120 if set.contains_key(&instruction.identifier()) {
121 Some(set[&instruction.identifier()].clone())
122 } else {
123 None
124 }
125}
126
127pub fn merge(sets: &[OperationSet]) -> OperationSet {
128 let mut merged_set = OperationSet::default();
129 for set in sets {
130 for sub in set {
131 merged_set.insert(*sub.0, sub.1.clone());
132 }
133 }
134 merged_set
135}