use core::convert::TryFrom;
use amplify::num::error::OverflowError;
use amplify::num::{u3, u4, u5};
use crate::reg::{RegAll, Register};
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Display)]
#[repr(u8)]
pub enum Reg32 {
#[display("[1]")]
Reg1 = 0,
#[display("[2]")]
Reg2 = 1,
#[display("[3]")]
Reg3 = 2,
#[display("[4]")]
Reg4 = 3,
#[display("[5]")]
Reg5 = 4,
#[display("[6]")]
Reg6 = 5,
#[display("[7]")]
Reg7 = 6,
#[display("[8]")]
Reg8 = 7,
#[display("[9]")]
Reg9 = 8,
#[display("[10]")]
Reg10 = 9,
#[display("[11]")]
Reg11 = 10,
#[display("[12]")]
Reg12 = 11,
#[display("[13]")]
Reg13 = 12,
#[display("[14]")]
Reg14 = 13,
#[display("[15]")]
Reg15 = 14,
#[display("[16]")]
Reg16 = 15,
#[display("[17]")]
Reg17 = 16,
#[display("[18]")]
Reg18 = 17,
#[display("[19]")]
Reg19 = 18,
#[display("[10]")]
Reg20 = 19,
#[display("[21]")]
Reg21 = 20,
#[display("[22]")]
Reg22 = 21,
#[display("[23]")]
Reg23 = 22,
#[display("[24]")]
Reg24 = 23,
#[display("[25]")]
Reg25 = 24,
#[display("[26]")]
Reg26 = 25,
#[display("[27]")]
Reg27 = 26,
#[display("[28]")]
Reg28 = 27,
#[display("[29]")]
Reg29 = 28,
#[display("[30]")]
Reg30 = 29,
#[display("[31]")]
Reg31 = 30,
#[display("[32]")]
Reg32 = 31,
}
impl Reg32 {
#[inline]
pub fn to_usize(self) -> usize { self as u8 as usize }
}
impl Register for Reg32 {
#[inline]
fn description() -> &'static str { "5-bit register index" }
}
impl Default for Reg32 {
#[inline]
fn default() -> Self { Reg32::Reg1 }
}
impl From<&Reg32> for u5 {
#[inline]
fn from(reg32: &Reg32) -> Self { u5::with(*reg32 as u8) }
}
impl From<Reg32> for u5 {
#[inline]
fn from(reg32: Reg32) -> Self { u5::with(reg32 as u8) }
}
impl From<&Reg32> for u8 {
#[inline]
fn from(reg32: &Reg32) -> Self { *reg32 as u8 }
}
impl From<Reg32> for u8 {
#[inline]
fn from(reg32: Reg32) -> Self { reg32 as u8 }
}
impl From<&Reg32> for Reg32 {
#[inline]
fn from(reg32: &Reg32) -> Self { *reg32 }
}
impl From<u5> for Reg32 {
fn from(val: u5) -> Self {
match val {
v if v == Reg32::Reg1.into() => Reg32::Reg1,
v if v == Reg32::Reg2.into() => Reg32::Reg2,
v if v == Reg32::Reg3.into() => Reg32::Reg3,
v if v == Reg32::Reg4.into() => Reg32::Reg4,
v if v == Reg32::Reg5.into() => Reg32::Reg5,
v if v == Reg32::Reg6.into() => Reg32::Reg6,
v if v == Reg32::Reg7.into() => Reg32::Reg7,
v if v == Reg32::Reg8.into() => Reg32::Reg8,
v if v == Reg32::Reg9.into() => Reg32::Reg9,
v if v == Reg32::Reg10.into() => Reg32::Reg10,
v if v == Reg32::Reg11.into() => Reg32::Reg11,
v if v == Reg32::Reg12.into() => Reg32::Reg12,
v if v == Reg32::Reg13.into() => Reg32::Reg13,
v if v == Reg32::Reg14.into() => Reg32::Reg14,
v if v == Reg32::Reg15.into() => Reg32::Reg15,
v if v == Reg32::Reg16.into() => Reg32::Reg16,
v if v == Reg32::Reg17.into() => Reg32::Reg17,
v if v == Reg32::Reg18.into() => Reg32::Reg18,
v if v == Reg32::Reg19.into() => Reg32::Reg19,
v if v == Reg32::Reg20.into() => Reg32::Reg20,
v if v == Reg32::Reg21.into() => Reg32::Reg21,
v if v == Reg32::Reg22.into() => Reg32::Reg22,
v if v == Reg32::Reg23.into() => Reg32::Reg23,
v if v == Reg32::Reg24.into() => Reg32::Reg24,
v if v == Reg32::Reg25.into() => Reg32::Reg25,
v if v == Reg32::Reg26.into() => Reg32::Reg26,
v if v == Reg32::Reg27.into() => Reg32::Reg27,
v if v == Reg32::Reg28.into() => Reg32::Reg28,
v if v == Reg32::Reg29.into() => Reg32::Reg29,
v if v == Reg32::Reg30.into() => Reg32::Reg30,
v if v == Reg32::Reg31.into() => Reg32::Reg31,
v if v == Reg32::Reg32.into() => Reg32::Reg32,
_ => unreachable!(),
}
}
}
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Display)]
#[repr(u8)]
pub enum Reg16 {
#[display("[1]")]
Reg1 = 0,
#[display("[2]")]
Reg2 = 1,
#[display("[3]")]
Reg3 = 2,
#[display("[4]")]
Reg4 = 3,
#[display("[5]")]
Reg5 = 4,
#[display("[6]")]
Reg6 = 5,
#[display("[7]")]
Reg7 = 6,
#[display("[8]")]
Reg8 = 7,
#[display("[9]")]
Reg9 = 8,
#[display("[10]")]
Reg10 = 9,
#[display("[11]")]
Reg11 = 10,
#[display("[12]")]
Reg12 = 11,
#[display("[13]")]
Reg13 = 12,
#[display("[14]")]
Reg14 = 13,
#[display("[15]")]
Reg15 = 14,
#[display("[16]")]
Reg16 = 15,
}
impl Default for Reg16 {
#[inline]
fn default() -> Self { Reg16::Reg1 }
}
impl Register for Reg16 {
#[inline]
fn description() -> &'static str { "4-bit register index" }
}
impl From<&Reg16> for u4 {
#[inline]
fn from(reg16: &Reg16) -> Self { u4::with(*reg16 as u8) }
}
impl From<Reg16> for u4 {
#[inline]
fn from(reg16: Reg16) -> Self { u4::with(reg16 as u8) }
}
impl From<u4> for Reg16 {
fn from(val: u4) -> Self {
match val {
v if v == Reg16::Reg1.into() => Reg16::Reg1,
v if v == Reg16::Reg2.into() => Reg16::Reg2,
v if v == Reg16::Reg3.into() => Reg16::Reg3,
v if v == Reg16::Reg4.into() => Reg16::Reg4,
v if v == Reg16::Reg5.into() => Reg16::Reg5,
v if v == Reg16::Reg6.into() => Reg16::Reg6,
v if v == Reg16::Reg7.into() => Reg16::Reg7,
v if v == Reg16::Reg8.into() => Reg16::Reg8,
v if v == Reg16::Reg9.into() => Reg16::Reg9,
v if v == Reg16::Reg10.into() => Reg16::Reg10,
v if v == Reg16::Reg11.into() => Reg16::Reg11,
v if v == Reg16::Reg12.into() => Reg16::Reg12,
v if v == Reg16::Reg13.into() => Reg16::Reg13,
v if v == Reg16::Reg14.into() => Reg16::Reg14,
v if v == Reg16::Reg15.into() => Reg16::Reg15,
v if v == Reg16::Reg16.into() => Reg16::Reg16,
_ => unreachable!(),
}
}
}
impl From<Reg16> for Reg32 {
#[inline]
fn from(reg16: Reg16) -> Self { u5::with(reg16 as u8).into() }
}
impl From<&Reg16> for Reg32 {
#[inline]
fn from(reg16: &Reg16) -> Self { u5::with(*reg16 as u8).into() }
}
impl TryFrom<Reg32> for Reg16 {
type Error = OverflowError;
fn try_from(value: Reg32) -> Result<Self, Self::Error> {
u4::try_from(value as u8).map(Reg16::from)
}
}
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Display)]
#[repr(u8)]
pub enum Reg8 {
#[display("[1]")]
Reg1 = 0,
#[display("[2]")]
Reg2 = 1,
#[display("[3]")]
Reg3 = 2,
#[display("[4]")]
Reg4 = 3,
#[display("[5]")]
Reg5 = 4,
#[display("[6]")]
Reg6 = 5,
#[display("[7]")]
Reg7 = 6,
#[display("[8]")]
Reg8 = 7,
}
impl Default for Reg8 {
#[inline]
fn default() -> Self { Reg8::Reg1 }
}
impl Register for Reg8 {
#[inline]
fn description() -> &'static str { "3-bit register index" }
}
impl From<&Reg8> for u3 {
#[inline]
fn from(reg8: &Reg8) -> Self { u3::with(*reg8 as u8) }
}
impl From<Reg8> for u3 {
#[inline]
fn from(reg8: Reg8) -> Self { u3::with(reg8 as u8) }
}
impl From<u3> for Reg8 {
fn from(val: u3) -> Self {
match val {
v if v == Reg8::Reg1.into() => Reg8::Reg1,
v if v == Reg8::Reg2.into() => Reg8::Reg2,
v if v == Reg8::Reg3.into() => Reg8::Reg3,
v if v == Reg8::Reg4.into() => Reg8::Reg4,
v if v == Reg8::Reg5.into() => Reg8::Reg5,
v if v == Reg8::Reg6.into() => Reg8::Reg6,
v if v == Reg8::Reg7.into() => Reg8::Reg7,
v if v == Reg8::Reg8.into() => Reg8::Reg8,
_ => unreachable!(),
}
}
}
impl From<Reg8> for Reg32 {
#[inline]
fn from(reg8: Reg8) -> Self { u5::with(reg8 as u8).into() }
}
impl From<&Reg8> for Reg32 {
#[inline]
fn from(reg8: &Reg8) -> Self { u5::with(*reg8 as u8).into() }
}
impl TryFrom<Reg32> for Reg8 {
type Error = OverflowError;
fn try_from(value: Reg32) -> Result<Self, Self::Error> {
u3::try_from(value as u8).map(Reg8::from)
}
}
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Display, From)]
#[display("s16[{0}]")]
pub struct RegS(#[from] u4);
impl RegS {
#[inline]
pub fn as_u8(self) -> u8 { self.0.as_u8() }
#[inline]
pub fn as_usize(self) -> usize { self.0.as_u8() as usize }
}
impl Register for RegS {
#[inline]
fn description() -> &'static str { "4-bit S register index" }
}
impl Default for RegS {
#[inline]
fn default() -> Self { RegS(u4::MIN) }
}
impl From<RegS> for u8 {
#[inline]
fn from(reg: RegS) -> Self { reg.0.as_u8() }
}
impl From<&RegS> for u8 {
#[inline]
fn from(reg: &RegS) -> Self { reg.0.as_u8() }
}
impl From<RegS> for usize {
#[inline]
fn from(reg: RegS) -> Self { reg.0.as_u8() as usize }
}
impl From<u8> for RegS {
#[inline]
fn from(val: u8) -> Self { RegS(u4::with(val % 16)) }
}
impl From<&u4> for RegS {
#[inline]
fn from(val: &u4) -> Self { RegS(*val) }
}
impl From<RegS> for u4 {
#[inline]
fn from(reg: RegS) -> Self { reg.0 }
}
impl From<&RegS> for u4 {
#[inline]
fn from(reg: &RegS) -> Self { reg.0 }
}
impl From<u5> for RegS {
#[inline]
fn from(val: u5) -> Self { RegS(u4::with(val.as_u8() % 16)) }
}
impl From<&u5> for RegS {
#[inline]
fn from(val: &u5) -> Self { RegS(u4::with(val.as_u8() % 16)) }
}
impl From<RegS> for u5 {
#[inline]
fn from(reg: RegS) -> Self { u5::with(reg.0.as_u8()) }
}
impl From<&RegS> for u5 {
#[inline]
fn from(reg: &RegS) -> Self { u5::with(reg.0.as_u8()) }
}
impl TryFrom<Reg32> for RegS {
type Error = OverflowError;
fn try_from(value: Reg32) -> Result<Self, Self::Error> {
u5::try_from(value as u8).map(RegS::from)
}
}
impl TryFrom<RegAll> for RegS {
type Error = ();
#[inline]
fn try_from(value: RegAll) -> Result<Self, Self::Error> {
match value {
RegAll::S => Ok(RegS(u4::with(0))),
_ => Err(()),
}
}
}