looklook 0.9.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 ver-
// sion.
//
// LOOKLOOK is distributed in the hope that it will be useful, but WITHOUT ANY WAR-
// RANTY; 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 Affero General Public License along
// with LOOKLOOK. If not, see <https://www.gnu.org/licenses/>.

//! The [`Exception`] type.

use crate::isa::Long;

use std::error::Error;
use std::fmt::{self, Display, Formatter};
use std::hint::select_unpredictable;

/// A processor exception (a.k.a interrupt.)
#[repr(transparent)]
#[derive(Copy, Debug)]
#[derive_const(
	Clone,
	Eq,
	Ord,
	PartialEq,
	PartialOrd,
)]
pub struct Exception(u8);

impl Exception {
	/// An access fault.
	pub const ACCESS_FAULT: Self = Self::from_u8(2);

	/// An address error.
	pub const ADDRESS_ERROR: Self = Self::from_u8(3);

	/// An illegal instruction.
	pub const ILLEGAL_INSTRUCTION: Self = Self::from_u8(4);

	/// Integral division by zero.
	pub const INTEGER_DIVIDE_BY_ZERO: Self = Self::from_u8(5);

	/// Constructs an exception from a [`u8`] scalar.
	#[inline(always)]
	#[must_use]
	pub const fn from_u8(value: u8) -> Self {
		Self(value)
	}

	/// Selects an exception from an address.
	///
	/// This method returns [`None`] if the address is not within the vector.
	#[inline]
	#[must_use]
	pub const fn from_addr(addr: Long) -> Option<Self> {
		let value = addr.as_u32() >> 2;
		let exception = Self::from_u8(value.truncate::<u8>());

		select_unpredictable(
			addr.as_usize() < 0x400,
			Some(exception),
			None,
		)
	}

	/// Constructs a trap exception.
	///
	/// # Panics
	///
	/// This function panics if the trap number is greater than `15`.
	#[inline]
	#[must_use]
	pub const fn trap(index: u8) -> Self {
		const TRAP_BASE: u8 = 32;

		assert!(
			index <= 15,
			"cannot construct trap exception with index greater than `15`",
		);

		Self::from_u8(TRAP_BASE + index)
	}

	/// Computes the address of the exception's vector.
	#[inline]
	#[must_use]
	pub const fn addr(self) -> Long {
		Long::from(u32::from(self.as_u8()) << 2)
	}

	/// Retrieves the vector index (measured in long-words.)
	#[inline(always)]
	#[must_use]
	pub const fn as_u8(self) -> u8 {
		self.0
	}

	/// Retrieves the exception name.
	#[inline]
	#[must_use]
	pub const fn as_str(self) -> &'static str {
		match self.0 {
			000 => "reset initial stack pointer",
			001 => "reset initial programme counter",
			002 => "access fault",
			003 => "address error",
			004 => "illegal instruction",
			005 => "integer divide by zero",
			006 => "`chk` or `chk2` instruction",
			007 => "`ftrapcc` or `trapcc` or `trapv` instruction",
			008 => "privilege violation",
			009 => "trace",
			010 => "line `1010` emulator",
			011 => "line `1111` emulator",
			012 => "unknown exception `12`",
			013 => "coprocessor protocol violation",
			014 => "format error",
			015 => "uninitialised interrupt",
			016 => "unknown exception `16`",
			017 => "unknown exception `17`",
			018 => "unknown exception `18`",
			019 => "unknown exception `19`",
			020 => "unknown exception `20`",
			021 => "unknown exception `21`",
			022 => "unknown exception `22`",
			023 => "unknown exception `23`",
			024 => "spurious interrupt",
			025 => "level `1` interrupt autovector",
			026 => "level `2` interrupt autovector",
			027 => "level `3` interrupt autovector",
			028 => "level `4` interrupt autovector",
			029 => "level `5` interrupt autovector",
			030 => "level `6` interrupt autovector",
			031 => "level `7` interrupt autovector",
			032 => "`trap #0` instruction",
			033 => "`trap #1` instruction",
			034 => "`trap #2` instruction",
			035 => "`trap #3` instruction",
			036 => "`trap #4` instruction",
			037 => "`trap #5` instruction",
			038 => "`trap #6` instruction",
			039 => "`trap #7` instruction",
			040 => "`trap #8` instruction",
			041 => "`trap #9` instruction",
			042 => "`trap #10` instruction",
			043 => "`trap #11` instruction",
			044 => "`trap #12` instruction",
			045 => "`trap #13` instruction",
			046 => "`trap #14` instruction",
			047 => "`trap #15` instruction",
			048 => "fp branch or set on unordered condition",
			049 => "fp inexact result",
			050 => "fp divide by zero",
			051 => "fp underflow",
			052 => "fp operand error",
			053 => "fp overflow",
			054 => "fp signaling nan",
			055 => "fp unimplemented data type",
			056 => "mmu configuration error",
			057 => "mmu illeagl operation error",
			058 => "mmu access level violation error",
			059 => "unknown exception `59`",
			060 => "unknown exception `60`",
			061 => "unknown exception `61`",
			062 => "unknown exception `62`",
			063 => "unknown exception `63`",
			064 => "user defined vector `1`",
			065 => "user defined vector `2`",
			066 => "user defined vector `3`",
			067 => "user defined vector `4`",
			068 => "user defined vector `5`",
			069 => "user defined vector `6`",
			070 => "user defined vector `7`",
			071 => "user defined vector `8`",
			072 => "user defined vector `9`",
			073 => "user defined vector `10`",
			074 => "user defined vector `11`",
			075 => "user defined vector `12`",
			076 => "user defined vector `13`",
			077 => "user defined vector `14`",
			078 => "user defined vector `15`",
			079 => "user defined vector `16`",
			080 => "user defined vector `17`",
			081 => "user defined vector `18`",
			082 => "user defined vector `19`",
			083 => "user defined vector `20`",
			084 => "user defined vector `21`",
			085 => "user defined vector `22`",
			086 => "user defined vector `23`",
			087 => "user defined vector `24`",
			088 => "user defined vector `25`",
			089 => "user defined vector `26`",
			090 => "user defined vector `27`",
			091 => "user defined vector `28`",
			092 => "user defined vector `29`",
			093 => "user defined vector `30`",
			094 => "user defined vector `31`",
			095 => "user defined vector `32`",
			096 => "user defined vector `33`",
			097 => "user defined vector `34`",
			098 => "user defined vector `35`",
			099 => "user defined vector `36`",
			100 => "user defined vector `37`",
			101 => "user defined vector `38`",
			102 => "user defined vector `39`",
			103 => "user defined vector `40`",
			104 => "user defined vector `41`",
			105 => "user defined vector `42`",
			106 => "user defined vector `43`",
			107 => "user defined vector `44`",
			108 => "user defined vector `45`",
			109 => "user defined vector `46`",
			110 => "user defined vector `47`",
			111 => "user defined vector `48`",
			112 => "user defined vector `49`",
			113 => "user defined vector `50`",
			114 => "user defined vector `51`",
			115 => "user defined vector `52`",
			116 => "user defined vector `53`",
			117 => "user defined vector `54`",
			118 => "user defined vector `55`",
			119 => "user defined vector `56`",
			120 => "user defined vector `57`",
			121 => "user defined vector `58`",
			122 => "user defined vector `59`",
			123 => "user defined vector `60`",
			124 => "user defined vector `61`",
			125 => "user defined vector `62`",
			126 => "user defined vector `63`",
			127 => "user defined vector `64`",
			128 => "user defined vector `65`",
			129 => "user defined vector `66`",
			130 => "user defined vector `67`",
			131 => "user defined vector `68`",
			132 => "user defined vector `69`",
			133 => "user defined vector `70`",
			134 => "user defined vector `71`",
			135 => "user defined vector `72`",
			136 => "user defined vector `73`",
			137 => "user defined vector `74`",
			138 => "user defined vector `75`",
			139 => "user defined vector `76`",
			140 => "user defined vector `77`",
			141 => "user defined vector `78`",
			142 => "user defined vector `79`",
			143 => "user defined vector `80`",
			144 => "user defined vector `81`",
			145 => "user defined vector `82`",
			146 => "user defined vector `83`",
			147 => "user defined vector `84`",
			148 => "user defined vector `85`",
			149 => "user defined vector `86`",
			150 => "user defined vector `87`",
			151 => "user defined vector `88`",
			152 => "user defined vector `89`",
			153 => "user defined vector `90`",
			154 => "user defined vector `91`",
			155 => "user defined vector `92`",
			156 => "user defined vector `93`",
			157 => "user defined vector `94`",
			158 => "user defined vector `95`",
			159 => "user defined vector `96`",
			160 => "user defined vector `97`",
			161 => "user defined vector `98`",
			162 => "user defined vector `99`",
			163 => "user defined vector `100`",
			164 => "user defined vector `101`",
			165 => "user defined vector `102`",
			166 => "user defined vector `103`",
			167 => "user defined vector `104`",
			168 => "user defined vector `105`",
			169 => "user defined vector `106`",
			170 => "user defined vector `107`",
			171 => "user defined vector `108`",
			172 => "user defined vector `109`",
			173 => "user defined vector `110`",
			174 => "user defined vector `111`",
			175 => "user defined vector `112`",
			176 => "user defined vector `113`",
			177 => "user defined vector `114`",
			178 => "user defined vector `115`",
			179 => "user defined vector `116`",
			180 => "user defined vector `117`",
			181 => "user defined vector `118`",
			182 => "user defined vector `119`",
			183 => "user defined vector `120`",
			184 => "user defined vector `121`",
			185 => "user defined vector `122`",
			186 => "user defined vector `123`",
			187 => "user defined vector `124`",
			188 => "user defined vector `125`",
			189 => "user defined vector `126`",
			190 => "user defined vector `127`",
			191 => "user defined vector `128`",
			192 => "user defined vector `129`",
			193 => "user defined vector `130`",
			194 => "user defined vector `131`",
			195 => "user defined vector `132`",
			196 => "user defined vector `133`",
			197 => "user defined vector `134`",
			198 => "user defined vector `135`",
			199 => "user defined vector `136`",
			200 => "user defined vector `137`",
			201 => "user defined vector `138`",
			202 => "user defined vector `139`",
			203 => "user defined vector `140`",
			204 => "user defined vector `141`",
			205 => "user defined vector `142`",
			206 => "user defined vector `143`",
			207 => "user defined vector `144`",
			208 => "user defined vector `145`",
			209 => "user defined vector `146`",
			210 => "user defined vector `147`",
			211 => "user defined vector `148`",
			212 => "user defined vector `149`",
			213 => "user defined vector `150`",
			214 => "user defined vector `151`",
			215 => "user defined vector `152`",
			216 => "user defined vector `153`",
			217 => "user defined vector `154`",
			218 => "user defined vector `155`",
			219 => "user defined vector `156`",
			220 => "user defined vector `157`",
			221 => "user defined vector `158`",
			222 => "user defined vector `159`",
			223 => "user defined vector `160`",
			224 => "user defined vector `161`",
			225 => "user defined vector `162`",
			226 => "user defined vector `163`",
			227 => "user defined vector `164`",
			228 => "user defined vector `165`",
			229 => "user defined vector `166`",
			230 => "user defined vector `167`",
			231 => "user defined vector `168`",
			232 => "user defined vector `169`",
			233 => "user defined vector `170`",
			234 => "user defined vector `171`",
			235 => "user defined vector `172`",
			236 => "user defined vector `173`",
			237 => "user defined vector `174`",
			238 => "user defined vector `175`",
			239 => "user defined vector `176`",
			240 => "user defined vector `177`",
			241 => "user defined vector `178`",
			242 => "user defined vector `179`",
			243 => "user defined vector `180`",
			244 => "user defined vector `181`",
			245 => "user defined vector `182`",
			246 => "user defined vector `183`",
			247 => "user defined vector `184`",
			248 => "user defined vector `185`",
			249 => "user defined vector `186`",
			250 => "user defined vector `187`",
			251 => "user defined vector `188`",
			252 => "user defined vector `189`",
			253 => "user defined vector `190`",
			254 => "user defined vector `191`",
			255 => "user defined vector `192`",
		}
	}
}

impl Display for Exception {
	fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
		f.write_str(self.as_str())
	}
}

impl Error for Exception {}