looklook 0.6.0

Descriptive signal synthesiser.
// Copyright 2026 Gabriel Bjørnager Jensen.
//
// This file is part of LOOKLOOK.
//
// LOOKLOOK is free software: you can redistribute
// it and/or modify it under the terms of the GNU
// Affero General Public License as published by
// the Free Software Foundation, either version 3
// of the License, or (at your option) any later
// version.
//
// LOOKLOOK is distributed in the hope that it will
// be useful, but WITHOUT ANY WARRANTY; without
// even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Affero General Public License for more details.
//
// You should have received a copy of the GNU Af-
// fero General Public License along with LOOKLOOK.
// If not, see <https://www.gnu.org/licenses/>.

//! The [`Stack`] type.

use crate::emu::{Address, Data, TraceMode};

/// A register stack.
#[derive(Debug)]
pub struct Stack {
	/// The data registers `D0` through `D7`.
	data: [u32; 8],

	/// The address registers `A0` through `A7`.
	address: [u32; 8],

	/// The `PC` programme counter.
	pc: u32,

	/// The `SR` status register.
	sr: u16,
}

impl Stack {
	/// Constructs a new, default stack.
	#[inline]
	#[must_use]
	pub const fn new() -> Self {
		Self {
			sr:      Default::default(),
			pc:      Default::default(),
			data:    [0; _],
			address: [0; _],
		}
	}

	/// Loads a data register.
	#[inline]
	#[must_use]
	pub const fn load_data(&self, index: Data) -> u32 {
		self.data[index.as_usize()]
	}

	/// Stores a data register.
	#[inline]
	pub const fn store_data(&mut self, index: Data, value: u32) {
		self.data[index.as_usize()] = value;
	}

	/// Loads an address register.
	#[inline]
	#[must_use]
	pub const fn load_address(&self, index: Address) -> u32 {
		self.address[index.as_usize()]
	}

	/// Stores an address register.
	#[inline]
	pub const fn store_address(&mut self, index: Address, value: u32) {
		self.address[index.as_usize()] = value;
	}

	/// Loads the programme counter.
	#[inline(always)]
	#[must_use]
	pub const fn load_pc(&self) -> u32 {
		self.pc
	}

	/// Stores the programme counter.
	#[inline(always)]
	pub const fn store_pc(&mut self, value: u32) {
		self.pc = value;
	}

	/// Reads the tracing mode.
	#[inline]
	#[must_use]
	pub const fn trace_mode(&self) -> TraceMode {
		TraceMode::from_u16(self.sr)
	}

	/// Specifies the tracing mode.
	#[inline]
	pub const fn set_trace_mode(&mut self, mode: TraceMode) {
		self.sr &= 0b0011_1111_1111_1111;
		self.sr |= mode.as_u16();
	}

	/// Clears the entire stack.
	#[inline]
	pub const fn clear(&mut self) {
		*self = Self::new();
	}
}

const impl Default for Stack {
	#[inline(always)]
	fn default() -> Self {
		const { Self::new() }
	}
}