Skip to content

Commit 979bc77

Browse files
committed
feat(branch) Implemented basic operand formats.
1 parent ebdf4df commit 979bc77

File tree

9 files changed

+246
-15
lines changed

9 files changed

+246
-15
lines changed

src/instruction.rs

+41-1
Original file line numberDiff line numberDiff line change
@@ -1 +1,41 @@
1-
pub mod discriminator;
1+
use crate::num;
2+
use crate::operation::branch;
3+
use crate::state::flag::Flag;
4+
use crate::state::register::Register;
5+
6+
#[derive(Debug, Clone, Copy, PartialEq)]
7+
pub enum RegisterOperation {
8+
ReleaseMemory
9+
}
10+
11+
#[derive(Debug, Clone, Copy, PartialEq)]
12+
pub enum SizedRegisterOperation {
13+
14+
}
15+
16+
#[derive(Debug, Clone, Copy, PartialEq)]
17+
pub enum DualSizedRegisterOperation {
18+
19+
}
20+
21+
#[derive(Debug, Clone, Copy, PartialEq)]
22+
pub enum ConditionalBranchOperation {
23+
24+
}
25+
26+
#[derive(Debug, Clone, Copy, PartialEq)]
27+
pub enum Instruction {
28+
Nothing,
29+
WaitForInterrupt,
30+
Register { operation: RegisterOperation, register: Register },
31+
SizedRegister {
32+
operation: SizedRegisterOperation,
33+
size: num::Size, register: Register },
34+
DualSizedRegister {
35+
operation: DualSizedRegisterOperation,
36+
size: num::Size, registers: [Register; 2] },
37+
ConditionalBranch {
38+
operation: ConditionalBranchOperation,
39+
condition: Option<Flag>, hint: branch::Hint,
40+
address: branch::Address }
41+
}

src/instruction/discriminator.rs

-13
This file was deleted.

src/lib.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -14,4 +14,7 @@
1414
#![allow(clippy::unused_io_amount)]
1515
#![allow(soft_unstable)]
1616

17-
pub mod instruction;
17+
pub mod instruction;
18+
pub mod num;
19+
pub mod operation;
20+
pub mod state;

src/num.rs

+123
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
/// # Power
2+
/// The power is a representation of this primitive data type which when set to the power of 2 gives the size in bytes.
3+
/// The power only has its 2 least significant bits used and the rest are discarded.
4+
#[derive(Debug, Clone, Copy, PartialEq)]
5+
pub enum Size {
6+
X8,
7+
X16,
8+
X32,
9+
X64
10+
}
11+
12+
impl Size {
13+
/// Construct this enum from an exponent of the power of 2.
14+
pub fn from_power(size: u8) -> Self {
15+
match size & 0b000000_11 {
16+
0 => Self::X8,
17+
1 => Self::X16,
18+
2 => Self::X32,
19+
3 => Self::X64,
20+
_ => unreachable!()
21+
}
22+
}
23+
24+
/// Convert this enum representation to a power of 2.
25+
pub const fn power(self) -> u8 {
26+
match self {
27+
Self::X8 => 0,
28+
Self::X16 => 1,
29+
Self::X32 => 2,
30+
Self::X64 => 3
31+
}
32+
}
33+
34+
/// Get the number of bytes it would take to represent a value of this size.
35+
pub const fn size(self) -> u8 {
36+
let size = match self {
37+
Self::X8 => u8::BITS / 8,
38+
Self::X16 => u16::BITS / 8,
39+
Self::X32 => u32::BITS / 8,
40+
Self::X64 => u64::BITS / 8
41+
};
42+
43+
size as u8
44+
}
45+
46+
/// Attempt to increase the size to the next quantization.
47+
pub fn upsize(&mut self) {
48+
*self = match self {
49+
Self::X8 => Self::X16,
50+
Self::X16 => Self::X32,
51+
Self::X32 => Self::X64,
52+
Self::X64 => Self::X64
53+
}
54+
}
55+
56+
/// Whether if upsizing will return a different value.
57+
pub const fn can_upsize(self) -> bool {
58+
!matches!(self, Self::X64)
59+
}
60+
61+
/// Attempt to decrease the size to the next quantization.
62+
///
63+
/// # Result
64+
/// If this cannot be downsized anymore, then self is returned.
65+
pub fn downsize(&mut self) {
66+
*self = match self {
67+
Self::X64 => Self::X32,
68+
Self::X32 => Self::X16,
69+
Self::X16 => Self::X8,
70+
Self::X8 => Self::X8
71+
}
72+
}
73+
74+
/// Whether if downsizing will return a different value.
75+
pub const fn can_downsize(self) -> bool {
76+
!matches!(self, Self::X8)
77+
}
78+
79+
pub const fn mask(self) -> u64 {
80+
match self {
81+
Self::X8 => u8::MAX as u64,
82+
Self::X16 => u16::MAX as u64,
83+
Self::X32 => u32::MAX as u64,
84+
Self::X64 => u64::MAX
85+
}
86+
}
87+
88+
pub const fn minimum(value: u64) -> Self {
89+
if value > u32::MAX as u64 { Self::X64 }
90+
else if value > u16::MAX as u64 { Self::X32 }
91+
else if value > u8::MAX as u64 { Self::X16 }
92+
else { Self::X8 }
93+
}
94+
95+
pub const fn minimum_signed(value: i64) -> Self {
96+
if value > i32::MAX as i64 || value < i32::MIN as i64 { Self::X64 }
97+
else if value > i16::MAX as i64 || value < i16::MIN as i64 { Self::X32 }
98+
else if value > i8::MAX as i64 || value < i8::MIN as i64 { Self::X16 }
99+
else { Self::X8 }
100+
}
101+
}
102+
103+
macro_rules! impl_mask {
104+
($ty: ty, $name: tt) => {
105+
#[derive(Debug, Clone, Copy, PartialEq)]
106+
pub struct $name<const MASK: $ty>($ty);
107+
108+
impl<const MASK: $ty> $name<MASK> {
109+
pub const fn new(value: $ty) -> Self { Self(value & MASK) }
110+
pub const fn get(self) -> $ty { self.0 }
111+
pub fn set(&mut self, value: $ty) { self.0 = value & MASK }
112+
}
113+
};
114+
}
115+
116+
impl_mask!(u8, MaskedU8);
117+
impl_mask!(u16, MaskedU16);
118+
impl_mask!(u32, MaskedU32);
119+
impl_mask!(u64, MaskedU64);
120+
impl_mask!(i8, MaskedI8);
121+
impl_mask!(i16, MaskedI16);
122+
impl_mask!(i32, MaskedI32);
123+
impl_mask!(i64, MaskedI64);

src/operation.rs

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
pub mod branch;

src/operation/branch.rs

+62
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
use crate::num;
2+
use crate::state::flag::Flag;
3+
use crate::state::register::Register;
4+
5+
/// Hint to suggest whether the branch might be taken.
6+
pub type Hint = Option<bool>;
7+
8+
pub const IMMEDIATE_MASK: u32 = 0x3FFFF;
9+
pub type Immediate = num::MaskedU32<IMMEDIATE_MASK>;
10+
11+
#[derive(Debug, Clone, Copy, PartialEq)]
12+
pub enum Mode {
13+
Absolute,
14+
Relative
15+
}
16+
17+
#[derive(Debug, Clone, Copy, PartialEq)]
18+
pub enum Address {
19+
Immediate {
20+
mode: Mode,
21+
immediate: Immediate },
22+
Register {
23+
mode: Mode,
24+
register: Register }
25+
}
26+
27+
#[derive(Debug, Clone, Copy, PartialEq)]
28+
pub struct Condition(pub Option<Flag>);
29+
30+
pub const CONDITION_MASK: u8 = 0x07;
31+
pub type ConditionCode = num::MaskedU8<CONDITION_MASK>;
32+
33+
#[derive(Debug, Clone, Copy, PartialEq)]
34+
pub struct ConditionMapping {
35+
pub code: ConditionCode,
36+
pub variant: Condition
37+
}
38+
39+
impl Condition {
40+
pub const MAPPINGS: [Condition; 7] = [
41+
Condition(None ),
42+
Condition(Some(Flag::Negative )),
43+
Condition(Some(Flag::Zero )),
44+
Condition(Some(Flag::Overflow )),
45+
Condition(Some(Flag::Regrouping)),
46+
Condition(Some(Flag::Parity )),
47+
Condition(Some(Flag::Auxiliary ))
48+
];
49+
50+
pub fn from_code(code: ConditionCode) -> Option<Self> {
51+
Self::MAPPINGS.get(code.get() as usize).copied()
52+
}
53+
54+
pub fn to_code(self) -> ConditionCode {
55+
ConditionCode::new(
56+
Self::MAPPINGS
57+
.iter()
58+
.position(|&mapping| mapping == self)
59+
.unwrap() as u8,
60+
)
61+
}
62+
}

src/state.rs

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
pub mod flag;
2+
pub mod register;

src/state/flag.rs

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
#[derive(Debug, Clone, Copy, PartialEq)]
2+
pub enum Flag {
3+
Negative,
4+
Zero,
5+
Overflow,
6+
Regrouping,
7+
Parity,
8+
Auxiliary
9+
}

src/state/register.rs

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
use crate::num;
2+
3+
pub const REGISTER_MASK: u8 = 0x03;
4+
pub type Register = num::MaskedU8<REGISTER_MASK>;

0 commit comments

Comments
 (0)