1use monistode_binutils::{Architecture, Executable};
2
3use crate::tightly_packed_array;
4
5use super::{
6 arithmetic,
7 common::{Processor, ProcessorContinue},
8 flag_register::{implement_flag_register, FlagRegister, ProcessorFlags},
9 memory::Memory,
10 memory::{two_byte_memory, TwoByteMemory},
11 stack::{two_byte_stack, Stack, TwoByteStack},
12 system,
13};
14use num_derive::FromPrimitive;
15use num_traits::FromPrimitive;
16use std::{fs::File, io::Read};
17use ux::u6;
18
19#[derive(Debug, FromPrimitive)]
20enum Opcode {
21 Halt = 0b000000,
22 Load = 0b000001,
23 LoadFr = 0b000010,
24 LoadMem = 0b100000,
25 Store = 0b000100,
26 StoreImm = 0b100001,
27 StoreFr = 0b000101,
28 Swap = 0b000110,
29 Dup = 0b000111,
30 Dup2 = 0b001000,
31 Mov = 0b100010,
32 Push = 0b001001,
33 PushFr = 0b001010,
34 Pop = 0b001100,
35 PopFr = 0b001101,
36 Add = 0b001110,
37 Sub = 0b001111,
38 Mul = 0b010000,
39 Div = 0b10001,
40 And = 0b010010,
41 Or = 0b010011,
42 Xor = 0b010100,
43 Not = 0b010101,
44 LshImm = 0b100011,
45 RshImm = 0b100100,
46 CallImm = 0b100101,
47 Call = 0b010110,
48 Ret = 0b010111,
49 Cmpe = 0b011000,
50 CmpeImm = 0b100110,
51 Cmpb = 0b011001,
52 CmpbImm = 0b100111,
53 Jmp = 0b011010,
54 JmpImm = 0b101000,
55 Jc = 0b011011,
56 JcImm = 0b101001,
57 In = 0b101010,
58 Out = 0b101011,
59 Nop = 0b011100,
60}
61
62macro_rules! to_bool {
63 ($value:expr) => {{
64 if $value {
65 0b1111111111111111
66 } else {
67 0b0000000000000000
68 }
69 }};
70}
71
72macro_rules! with_immediate {
73 ($processor:ident, $op:expr) => {{
74 let immediate = $processor.load_immediate();
75 $op(immediate);
76 ProcessorContinue::KeepRunning
77 }};
78}
79
80macro_rules! arithmetic {
81 ($processor:ident, $op:expr) => {{
82 let a = $processor.register_stack().pop();
83 let b = $processor.register_stack().pop();
84 let result = $op(&mut $processor.registers.fr, a, b);
85 $processor.register_stack().push(result);
86 ProcessorContinue::KeepRunning
87 }};
88}
89
90macro_rules! arithmetic_imm {
91 ($processor:ident, $op:expr) => {
92 with_immediate!($processor, |immediate| {
93 let stack_value = $processor.register_stack().pop();
94 let result = $op(&mut $processor.registers.fr, immediate, stack_value);
95 $processor.register_stack().push(result);
96 ProcessorContinue::KeepRunning
97 })
98 };
99}
100
101implement_flag_register!(StackProcessorFlagRegister(u16));
102
103pub struct StackProcessorRegisters {
104 pub pc: u16,
105 pub fr: StackProcessorFlagRegister,
106 pub tos: u16,
107 pub sp: u16,
108}
109
110pub struct StackProcessor {
111 pub text_memory: Memory<u6>,
112 pub data_memory: Memory<u8>,
113 pub registers: StackProcessorRegisters,
114}
115
116impl StackProcessor {
117 pub fn new() -> StackProcessor {
118 StackProcessor {
119 text_memory: Memory::new(u6::new(0), 65536),
120 data_memory: Memory::new(0, 65536),
121 registers: StackProcessorRegisters {
122 pc: 0,
123 fr: StackProcessorFlagRegister::new(),
124 tos: 256,
125 sp: 1024,
126 },
127 }
128 }
129
130 pub fn load_from_bytes(&mut self, bytes: &[u8]) {
131 self.text_memory
132 .load_binary(&bytes.iter().map(|x| u6::new(*x)).collect::<Vec<_>>());
133 }
134
135 pub fn load_text_binary_file(&mut self, binary: &str) {
136 let mut file = File::open(binary).expect("File not found");
137 let mut buffer = Vec::new();
138 file.read_to_end(&mut buffer).expect("Could not read file");
139 self.text_memory
140 .load_binary(&buffer.iter().map(|x| u6::new(*x)).collect::<Vec<_>>());
141 }
142
143 two_byte_stack!(register_stack[tos: u16] -> u8, based on data_memory, growing downward);
144 two_byte_stack!(memory_stack[sp: u16] -> u8, based on data_memory);
145 two_byte_memory!(two_byte_data_memory: data_memory[u16] -> 2 * u8);
146
147 #[inline]
148 fn load_immediate(&mut self) -> u16 {
149 let low = self.text_memory[(self.registers.pc.wrapping_add(2)) as usize];
150 let middle = self.text_memory[(self.registers.pc.wrapping_add(1)) as usize];
151 let high = self.text_memory[self.registers.pc as usize];
152 self.registers.pc = self.registers.pc.wrapping_add(3);
153 (u16::from(high)) << 12 | (u16::from(middle)) << 6 | u16::from(low)
154 }
155}
156
157impl Processor<u6, u16, u16, u16> for StackProcessor {
158 fn next(&mut self) -> u6 {
159 let instruction = self.text_memory[self.registers.pc as usize];
160 self.registers.pc = self.registers.pc.wrapping_add(1);
161 instruction
162 }
163 fn at_pc_plus(&self, offset: u16) -> u6 {
164 self.text_memory[self.registers.pc.wrapping_add(offset) as usize]
165 }
166 fn pc(&self) -> u16 {
167 self.registers.pc
168 }
169
170 fn peek_stack(&mut self, n: u8) -> u16 {
171 self.register_stack().peek_down_by(n * 2)
172 }
173
174 fn run_command<T, U>(&mut self, output: T, input: U) -> ProcessorContinue
175 where
176 T: Fn(u16, u16),
177 U: Fn(u16) -> u16,
178 {
179 let next_instruction = self.next();
180 let next_instruction_as_enum = match Opcode::from_u8(next_instruction.into()) {
181 Some(opcode) => opcode,
182 None => {
183 return ProcessorContinue::Error;
184 }
185 };
186
187 match next_instruction_as_enum {
188 Opcode::Halt => system::halt(),
189 Opcode::Load => {
190 let address = self.register_stack().pop();
191 let result = self.two_byte_data_memory().read(address);
192 self.register_stack().push(result);
193 ProcessorContinue::KeepRunning
194 }
195 Opcode::LoadFr => {
196 let result = self.registers.fr.0;
197 self.register_stack().push(result);
198 ProcessorContinue::KeepRunning
199 }
200 Opcode::LoadMem => with_immediate!(self, |address| {
201 let source = self.two_byte_data_memory().read(address);
202 self.register_stack().push(source);
203 }),
204 Opcode::Store => {
205 let source = self.register_stack().pop();
206 let address = self.register_stack().pop();
207 self.two_byte_data_memory().write(address, source);
208 ProcessorContinue::KeepRunning
209 }
210 Opcode::StoreFr => {
211 let source = self.registers.fr.0;
212 let address = self.register_stack().pop();
213 self.two_byte_data_memory().write(address, source);
214 ProcessorContinue::KeepRunning
215 }
216 Opcode::StoreImm => with_immediate!(self, |source| {
217 let address = self.register_stack().pop();
218 self.two_byte_data_memory().write(address, source);
219 }),
220 Opcode::Mov => with_immediate!(self, |immediate| self.register_stack().push(immediate)),
221 Opcode::Push => {
222 let source = self.register_stack().pop();
223 self.memory_stack().push(source);
224 ProcessorContinue::KeepRunning
225 }
226 Opcode::PushFr => {
227 let source = self.registers.fr.0;
228 self.memory_stack().push(source);
229 ProcessorContinue::KeepRunning
230 }
231 Opcode::Pop => {
232 let source = self.memory_stack().pop();
233 self.register_stack().push(source);
234 ProcessorContinue::KeepRunning
235 }
236 Opcode::PopFr => {
237 let source = self.memory_stack().pop();
238 self.registers.fr.0 = source;
239 ProcessorContinue::KeepRunning
240 }
241 Opcode::Dup => {
242 let source = self.register_stack().pop();
243 self.register_stack().push(source);
244 self.register_stack().push(source);
245 ProcessorContinue::KeepRunning
246 }
247 Opcode::Dup2 => {
248 let source1 = self.register_stack().pop();
249 let source2 = self.register_stack().pop();
250 self.register_stack().push(source2);
251 self.register_stack().push(source1);
252 self.register_stack().push(source2);
253 ProcessorContinue::KeepRunning
254 }
255 Opcode::Add => arithmetic!(self, arithmetic::add),
257 Opcode::Sub => arithmetic!(self, arithmetic::sub),
258 Opcode::Mul => arithmetic!(self, arithmetic::mul),
259 Opcode::Div => arithmetic!(self, arithmetic::div),
260 Opcode::And => arithmetic!(self, arithmetic::and),
261 Opcode::Or => arithmetic!(self, arithmetic::or),
262 Opcode::Xor => arithmetic!(self, arithmetic::xor),
263 Opcode::Not => {
264 let source = self.register_stack().pop();
265 let result = arithmetic::not(&mut self.registers.fr, source);
266 self.register_stack().push(result);
267 ProcessorContinue::KeepRunning
268 }
269 Opcode::LshImm => arithmetic_imm!(self, |fr, a, b| arithmetic::shl(fr, b, a)),
270 Opcode::RshImm => arithmetic_imm!(self, |fr, a, b| arithmetic::shr(fr, b, a)),
271 Opcode::Swap => {
272 let source1 = self.register_stack().pop();
273 let source2 = self.register_stack().pop();
274 self.register_stack().push(source1);
275 self.register_stack().push(source2);
276 ProcessorContinue::KeepRunning
277 }
278 Opcode::Cmpe => arithmetic!(self, |_, a, b| to_bool!(a == b)),
279 Opcode::CmpeImm => arithmetic_imm!(self, |_, immediate, stack_value| to_bool!(
280 immediate == stack_value
281 )),
282 Opcode::Cmpb => arithmetic!(self, |_, a, b| to_bool!(a > b)),
283 Opcode::CmpbImm => arithmetic_imm!(self, |_, immediate, stack_value| to_bool!(
284 immediate > stack_value
285 )),
286 Opcode::Jmp => {
287 self.registers.pc = self.register_stack().pop().wrapping_add(self.registers.pc);
288 ProcessorContinue::KeepRunning
289 }
290 Opcode::JmpImm => with_immediate!(self, |target: u16| self.registers.pc =
291 target.wrapping_add(self.registers.pc)),
292 Opcode::Jc => {
293 if self.register_stack().pop() == 0b1111111111111111 {
294 self.registers.pc = self.register_stack().pop().wrapping_add(self.registers.pc);
295 }
296 ProcessorContinue::KeepRunning
297 }
298 Opcode::JcImm => with_immediate!(self, |destination: u16| {
299 if self.register_stack().pop() == 0b1111111111111111 {
300 self.registers.pc = destination.wrapping_add(self.registers.pc);
301 }
302 ProcessorContinue::KeepRunning
303 }),
304 Opcode::Call => {
305 let current_pc = self.registers.pc;
306 self.memory_stack().push(current_pc);
307 self.registers.pc = self.register_stack().pop().wrapping_add(self.registers.pc);
308 ProcessorContinue::KeepRunning
309 }
310 Opcode::CallImm => with_immediate!(self, |target: u16| {
311 let current_pc = self.registers.pc;
312 self.memory_stack().push(current_pc);
313 self.registers.pc = target.wrapping_add(self.registers.pc);
314 }),
315 Opcode::Ret => {
316 self.registers.pc = self.memory_stack().pop();
317 ProcessorContinue::KeepRunning
318 }
319 Opcode::Nop => ProcessorContinue::KeepRunning,
320 Opcode::Out => with_immediate!(self, |port| output(port, self.register_stack().pop())),
321 Opcode::In => with_immediate!(self, |port| {
322 self.register_stack().push(input(port));
323 }),
324 }
325 }
326
327 fn load_executable(&mut self, executable: &Executable) -> Result<(), String> {
328 if !matches!(executable.architecture(), Architecture::Stack) {
332 return Err("Executable is not stack architecture".to_string());
333 }
334 for segment in executable.segments() {
335 if segment.flags.executable {
336 let array = tightly_packed_array::TightlyPackedArray::new(segment.data.clone(), 6);
337 for i in 0..segment.address_space_size {
339 self.text_memory[(segment.address_space_start + i) as usize] =
340 u6::new(array.at(i as usize));
341 }
342 } else if segment.flags.readable {
343 for i in 0..segment.address_space_size {
344 self.data_memory[(segment.address_space_start + i) as usize] =
345 segment.serialize().1[i as usize];
346 }
347 }
348 }
349 self.registers.pc = executable.entry_point() as u16;
350 Ok(())
351 }
352}