Many more operations (#5)
This commit is contained in:
16
Cargo.lock
generated
16
Cargo.lock
generated
@@ -111,6 +111,15 @@ dependencies = [
|
||||
"windows-sys 0.45.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "const_panic"
|
||||
version = "0.2.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "58baae561b85ca19b3122a9ddd35c8ec40c3bcd14fe89921824eae73f7baffbf"
|
||||
dependencies = [
|
||||
"konst_kernel",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "errno"
|
||||
version = "0.3.1"
|
||||
@@ -167,6 +176,12 @@ dependencies = [
|
||||
"windows-sys 0.48.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "konst_kernel"
|
||||
version = "0.3.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7771682454392dfe62a909aba2c6efc6674e2ad0b678fbc33b154e2e1bd59b89"
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.141"
|
||||
@@ -212,6 +227,7 @@ name = "performance_aware_programming"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"clap",
|
||||
"const_panic",
|
||||
"nom",
|
||||
]
|
||||
|
||||
|
@@ -7,4 +7,10 @@ edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
clap = { version = "4.2.1", features = [ "derive" ] }
|
||||
const_panic = "0.2.7"
|
||||
nom = "7.1.3"
|
||||
|
||||
[profile.release]
|
||||
lto = true
|
||||
strip = true
|
||||
panic = 'abort'
|
||||
|
349
src/assembly.rs
349
src/assembly.rs
@@ -1,7 +1,9 @@
|
||||
use nom::{
|
||||
branch::alt,
|
||||
bytes::complete::tag,
|
||||
character::complete::{char, digit1, line_ending, multispace0, not_line_ending, one_of},
|
||||
bytes::complete::{is_not, tag},
|
||||
character::complete::{
|
||||
alphanumeric1, char, digit1, line_ending, multispace0, not_line_ending, one_of,
|
||||
},
|
||||
combinator::map_res,
|
||||
multi::many0,
|
||||
sequence::{delimited, preceded, separated_pair, terminated, tuple},
|
||||
@@ -10,9 +12,10 @@ use nom::{
|
||||
|
||||
use crate::{
|
||||
register::{ByteRegisterSubset, GeneralRegister, Register, RegisterSubset, SpecialRegister},
|
||||
AccumulatorToMemory, Base, EffectiveAddress, ImmediateToRegister, ImmediateToRegisterOrMemory,
|
||||
Instruction, MemRegMove, MemoryToAccumulator, Program, RegMemMove, RegRegMove, SourceDest,
|
||||
WithOffset,
|
||||
AccumulatorToMemory, ArithmeticInstruction, ArithmeticInstructionSelect, ArithmeticOperation,
|
||||
Base, EffectiveAddress, ImmediateToRegister, ImmediateToRegisterOrMemory, Instruction, Jump,
|
||||
MemRegMove, MemoryToAccumulator, Program, RegMemMove, RegRegMove, SourceDest,
|
||||
TriviaInstruction, WithOffset,
|
||||
};
|
||||
|
||||
fn comment(input: &str) -> IResult<&str, &str> {
|
||||
@@ -138,17 +141,51 @@ fn source_dest(input: &str) -> IResult<&str, SourceDest> {
|
||||
}
|
||||
|
||||
fn absolute_u8(input: &str) -> IResult<&str, u8> {
|
||||
map_res(
|
||||
alt((digit1, preceded(tag("byte "), digit1))),
|
||||
str::parse::<u8>,
|
||||
)(input)
|
||||
alt((
|
||||
map_res(preceded(tag("0x"), alphanumeric1), |s: &str| {
|
||||
s.chars()
|
||||
.map(|x| {
|
||||
if x.is_ascii_digit() {
|
||||
Ok(x as u8 - b'0')
|
||||
} else if x.is_ascii_hexdigit() {
|
||||
Ok(x.to_ascii_lowercase() as u8 - b'a')
|
||||
} else {
|
||||
Err(())
|
||||
}
|
||||
})
|
||||
.fold(Ok(0u8), |acc, new| match (acc, new) {
|
||||
(Ok(acc), Ok(new)) => Ok(acc * 16 + new),
|
||||
(_, Err(())) => Err(()),
|
||||
(Err(()), _) => Err(()),
|
||||
})
|
||||
}),
|
||||
map_res(digit1, str::parse::<u8>),
|
||||
map_res(preceded(tag("byte "), digit1), str::parse::<u8>),
|
||||
))(input)
|
||||
}
|
||||
|
||||
fn absolute_u16(input: &str) -> IResult<&str, u16> {
|
||||
map_res(
|
||||
alt((digit1, preceded(tag("word "), digit1))),
|
||||
str::parse::<u16>,
|
||||
)(input)
|
||||
alt((
|
||||
map_res(preceded(tag("0x"), alphanumeric1), |s: &str| {
|
||||
s.chars()
|
||||
.map(|x| {
|
||||
if x.is_ascii_digit() {
|
||||
Ok(x as u16 - '0' as u16)
|
||||
} else if x.is_ascii_hexdigit() {
|
||||
Ok(x.to_ascii_lowercase() as u16 - 'a' as u16)
|
||||
} else {
|
||||
Err(())
|
||||
}
|
||||
})
|
||||
.fold(Ok(0u16), |acc, new| match (acc, new) {
|
||||
(Ok(acc), Ok(new)) => Ok(acc * 16 + new),
|
||||
(_, Err(())) => Err(()),
|
||||
(Err(()), _) => Err(()),
|
||||
})
|
||||
}),
|
||||
map_res(digit1, str::parse::<u16>),
|
||||
map_res(preceded(tag("word "), digit1), str::parse::<u16>),
|
||||
))(input)
|
||||
}
|
||||
|
||||
fn negative_u8(input: &str) -> IResult<&str, u8> {
|
||||
@@ -245,7 +282,7 @@ fn effective_address(input: &str) -> IResult<&str, EffectiveAddress> {
|
||||
},
|
||||
),
|
||||
// Offset from BX
|
||||
map_res(tag("bx"), |_| {
|
||||
map_res(bracketed(tag("bx")), |_| {
|
||||
Ok::<_, ()>(EffectiveAddress::Bx(WithOffset::Basic(())))
|
||||
}),
|
||||
map_res(
|
||||
@@ -324,19 +361,37 @@ fn mem_reg_move_instruction(input: &str) -> IResult<&str, MemRegMove> {
|
||||
)(input)
|
||||
}
|
||||
|
||||
fn immediate_wide(input: &str) -> IResult<&str, (Register, u16)> {
|
||||
tuple((
|
||||
terminated(wide_register, argument_sep),
|
||||
map_res(literal_u16, Ok::<_, ()>),
|
||||
))(input)
|
||||
}
|
||||
|
||||
fn immediate_byte(input: &str) -> IResult<&str, (Register, u8)> {
|
||||
tuple((
|
||||
terminated(byte_register, argument_sep),
|
||||
map_res(literal_u8, Ok::<_, ()>),
|
||||
))(input)
|
||||
}
|
||||
|
||||
fn immediate_to_register_instruction(input: &str) -> IResult<&str, ImmediateToRegister> {
|
||||
map_res(
|
||||
preceded(
|
||||
tag("mov "),
|
||||
alt((
|
||||
tuple((
|
||||
terminated(wide_register, argument_sep),
|
||||
terminated(map_res(literal_u16, |x| Ok::<_, ()>(Err(x))), line_ending),
|
||||
)),
|
||||
tuple((
|
||||
terminated(byte_register, argument_sep),
|
||||
terminated(map_res(literal_u8, |x| Ok::<_, ()>(Ok(x))), line_ending),
|
||||
)),
|
||||
terminated(
|
||||
map_res(immediate_wide, |(register, x)| {
|
||||
Ok::<_, ()>((register, Err(x)))
|
||||
}),
|
||||
line_ending,
|
||||
),
|
||||
terminated(
|
||||
map_res(immediate_byte, |(register, x)| {
|
||||
Ok::<_, ()>((register, Ok(x)))
|
||||
}),
|
||||
line_ending,
|
||||
),
|
||||
)),
|
||||
),
|
||||
|(register, contents)| {
|
||||
@@ -359,8 +414,8 @@ fn immediate_to_memory_instruction(input: &str) -> IResult<&str, ImmediateToRegi
|
||||
tuple((
|
||||
terminated(preceded(tag("mov "), effective_address), argument_sep),
|
||||
alt((
|
||||
map_res(literal_u8, |x| Ok::<_, ()>(Ok::<_, u16>(x))),
|
||||
map_res(literal_u16, |x| Ok::<_, ()>(Err::<u8, _>(x))),
|
||||
map_res(literal_u8, |x| Ok::<_, ()>(Ok(x))),
|
||||
map_res(literal_u16, |x| Ok::<_, ()>(Err(x))),
|
||||
)),
|
||||
)),
|
||||
|(addr, x)| {
|
||||
@@ -404,7 +459,241 @@ fn accumulator_to_memory_instruction(input: &str) -> IResult<&str, AccumulatorTo
|
||||
)(input)
|
||||
}
|
||||
|
||||
fn instruction(input: &str) -> IResult<&str, Instruction> {
|
||||
fn arithmetic_op(input: &str) -> IResult<&str, ArithmeticOperation> {
|
||||
alt((
|
||||
map_res(tag("add"), |_| Ok::<_, ()>(ArithmeticOperation::Add)),
|
||||
map_res(tag("sub"), |_| Ok::<_, ()>(ArithmeticOperation::Sub)),
|
||||
map_res(tag("cmp"), |_| Ok::<_, ()>(ArithmeticOperation::Cmp)),
|
||||
map_res(tag("acd"), |_| {
|
||||
Ok::<_, ()>(ArithmeticOperation::AddWithCarry)
|
||||
}),
|
||||
map_res(tag("sbb"), |_| {
|
||||
Ok::<_, ()>(ArithmeticOperation::SubWithBorrow)
|
||||
}),
|
||||
map_res(tag("and"), |_| Ok::<_, ()>(ArithmeticOperation::And)),
|
||||
map_res(tag("xor"), |_| Ok::<_, ()>(ArithmeticOperation::Xor)),
|
||||
map_res(tag("or"), |_| Ok::<_, ()>(ArithmeticOperation::Or)),
|
||||
))(input)
|
||||
}
|
||||
|
||||
fn arithmetic_select(input: &str) -> IResult<&str, ArithmeticInstructionSelect> {
|
||||
alt((
|
||||
map_res(
|
||||
preceded(
|
||||
char('a'),
|
||||
tuple((
|
||||
terminated(alt((char('l'), char('x'))), argument_sep),
|
||||
alt((
|
||||
// Order is important here.
|
||||
map_res(literal_u8, |x| Ok::<_, ()>(Err(x))),
|
||||
map_res(literal_u16, |x| Ok::<_, ()>(Ok(x))),
|
||||
)),
|
||||
)),
|
||||
),
|
||||
|(which_acc, data)| match (which_acc, data) {
|
||||
('x', Ok(wide)) => Ok(ArithmeticInstructionSelect::ImmediateToAccWord(wide)),
|
||||
('l', Ok(_)) => Err(()),
|
||||
('x', Err(byte)) => {
|
||||
Ok(ArithmeticInstructionSelect::ImmediateToAccWord(byte as u16))
|
||||
}
|
||||
('l', Err(byte)) => Ok(ArithmeticInstructionSelect::ImmediateToAccByte(byte)),
|
||||
(_, _) => panic!("can't hit, bad char {}", which_acc),
|
||||
},
|
||||
),
|
||||
map_res(
|
||||
tuple((terminated(register, argument_sep), register)),
|
||||
|(dest, source)| {
|
||||
Ok::<_, ()>(ArithmeticInstructionSelect::RegisterToRegister(
|
||||
crate::RegRegArithmetic { source, dest },
|
||||
))
|
||||
},
|
||||
),
|
||||
map_res(
|
||||
tuple((terminated(register, argument_sep), effective_address)),
|
||||
|(dest, source)| {
|
||||
Ok::<_, ()>(ArithmeticInstructionSelect::MemoryToRegister(
|
||||
crate::MemRegArithmetic { source, dest },
|
||||
))
|
||||
},
|
||||
),
|
||||
map_res(
|
||||
tuple((terminated(effective_address, argument_sep), register)),
|
||||
|(dest, source)| {
|
||||
Ok::<_, ()>(ArithmeticInstructionSelect::RegisterToMemory(
|
||||
crate::RegMemArithmetic { source, dest },
|
||||
))
|
||||
},
|
||||
),
|
||||
map_res(
|
||||
tuple((terminated(wide_register, argument_sep), literal_u8)),
|
||||
|(addr, literal)| {
|
||||
Ok::<_, ()>(ArithmeticInstructionSelect::ImmediateToRegisterByte(
|
||||
addr, literal, true,
|
||||
))
|
||||
},
|
||||
),
|
||||
map_res(
|
||||
tuple((terminated(wide_register, argument_sep), literal_u16)),
|
||||
|(addr, literal)| {
|
||||
Ok::<_, ()>(ArithmeticInstructionSelect::ImmediateToRegisterWord(
|
||||
addr, literal, false,
|
||||
))
|
||||
},
|
||||
),
|
||||
map_res(
|
||||
tuple((terminated(byte_register, argument_sep), literal_u8)),
|
||||
|(addr, literal)| {
|
||||
Ok::<_, ()>(ArithmeticInstructionSelect::ImmediateToRegisterByte(
|
||||
addr, literal, false,
|
||||
))
|
||||
},
|
||||
),
|
||||
map_res(
|
||||
tuple((
|
||||
terminated(preceded(tag("word "), effective_address), argument_sep),
|
||||
literal_u8,
|
||||
)),
|
||||
|(addr, literal)| {
|
||||
Ok::<_, ()>(
|
||||
ArithmeticInstructionSelect::ImmediateToRegisterOrMemoryByte(
|
||||
addr, literal, true,
|
||||
),
|
||||
)
|
||||
},
|
||||
),
|
||||
map_res(
|
||||
tuple((
|
||||
terminated(preceded(tag("word "), effective_address), argument_sep),
|
||||
literal_u16,
|
||||
)),
|
||||
|(addr, literal)| {
|
||||
Ok::<_, ()>(
|
||||
ArithmeticInstructionSelect::ImmediateToRegisterOrMemoryWord(addr, literal),
|
||||
)
|
||||
},
|
||||
),
|
||||
map_res(
|
||||
tuple((
|
||||
terminated(preceded(tag("byte "), effective_address), argument_sep),
|
||||
literal_u8,
|
||||
)),
|
||||
|(addr, literal)| {
|
||||
Ok::<_, ()>(
|
||||
ArithmeticInstructionSelect::ImmediateToRegisterOrMemoryByte(
|
||||
addr, literal, false,
|
||||
),
|
||||
)
|
||||
},
|
||||
),
|
||||
map_res(
|
||||
tuple((terminated(effective_address, argument_sep), literal_u16)),
|
||||
|(addr, literal)| {
|
||||
Ok::<_, ()>(
|
||||
ArithmeticInstructionSelect::ImmediateToRegisterOrMemoryWord(addr, literal),
|
||||
)
|
||||
},
|
||||
),
|
||||
map_res(
|
||||
tuple((terminated(effective_address, argument_sep), literal_u8)),
|
||||
|(addr, literal)| {
|
||||
Ok::<_, ()>(
|
||||
ArithmeticInstructionSelect::ImmediateToRegisterOrMemoryByte(
|
||||
addr, literal, false,
|
||||
),
|
||||
)
|
||||
},
|
||||
),
|
||||
))(input)
|
||||
}
|
||||
|
||||
fn arithmetic_instruction(input: &str) -> IResult<&str, ArithmeticInstruction> {
|
||||
map_res(
|
||||
tuple((
|
||||
terminated(arithmetic_op, char(' ')),
|
||||
terminated(arithmetic_select, line_ending),
|
||||
)),
|
||||
|(op, instruction)| Ok::<_, ()>(ArithmeticInstruction { op, instruction }),
|
||||
)(input)
|
||||
}
|
||||
|
||||
fn label(input: &str) -> IResult<&str, &str> {
|
||||
terminated(is_not(":\r\n \t"), terminated(char(':'), line_ending))(input)
|
||||
}
|
||||
|
||||
fn label_terminator(input: &str) -> IResult<&str, &str> {
|
||||
is_not("\r\n;")(input)
|
||||
}
|
||||
|
||||
fn jump(input: &str) -> IResult<&str, (Jump, &str)> {
|
||||
alt((
|
||||
map_res(preceded(tag("je "), label_terminator), |label| {
|
||||
Ok::<_, ()>((Jump::Je, label))
|
||||
}),
|
||||
map_res(preceded(tag("jnz "), label_terminator), |label| {
|
||||
Ok::<_, ()>((Jump::Jne, label))
|
||||
}),
|
||||
map_res(preceded(tag("jnl "), label_terminator), |label| {
|
||||
Ok::<_, ()>((Jump::Jnl, label))
|
||||
}),
|
||||
map_res(preceded(tag("jb "), label_terminator), |label| {
|
||||
Ok::<_, ()>((Jump::Jb, label))
|
||||
}),
|
||||
map_res(preceded(tag("jnb "), label_terminator), |label| {
|
||||
Ok::<_, ()>((Jump::Jnb, label))
|
||||
}),
|
||||
map_res(preceded(tag("jbe "), label_terminator), |label| {
|
||||
Ok::<_, ()>((Jump::Jbe, label))
|
||||
}),
|
||||
map_res(preceded(tag("jl "), label_terminator), |label| {
|
||||
Ok::<_, ()>((Jump::Jl, label))
|
||||
}),
|
||||
map_res(preceded(tag("jg "), label_terminator), |label| {
|
||||
Ok::<_, ()>((Jump::Jnle, label))
|
||||
}),
|
||||
map_res(preceded(tag("jle "), label_terminator), |label| {
|
||||
Ok::<_, ()>((Jump::Jle, label))
|
||||
}),
|
||||
map_res(preceded(tag("jo "), label_terminator), |label| {
|
||||
Ok::<_, ()>((Jump::Jo, label))
|
||||
}),
|
||||
map_res(preceded(tag("jp "), label_terminator), |label| {
|
||||
Ok::<_, ()>((Jump::Jp, label))
|
||||
}),
|
||||
map_res(preceded(tag("js "), label_terminator), |label| {
|
||||
Ok::<_, ()>((Jump::Js, label))
|
||||
}),
|
||||
map_res(preceded(tag("ja "), label_terminator), |label| {
|
||||
Ok::<_, ()>((Jump::Jnbe, label))
|
||||
}),
|
||||
map_res(preceded(tag("jnp "), label_terminator), |label| {
|
||||
Ok::<_, ()>((Jump::Jnp, label))
|
||||
}),
|
||||
map_res(preceded(tag("jno "), label_terminator), |label| {
|
||||
Ok::<_, ()>((Jump::Jno, label))
|
||||
}),
|
||||
map_res(preceded(tag("jns "), label_terminator), |label| {
|
||||
Ok::<_, ()>((Jump::Jns, label))
|
||||
}),
|
||||
map_res(preceded(tag("loop "), label_terminator), |label| {
|
||||
Ok::<_, ()>((Jump::Loop, label))
|
||||
}),
|
||||
map_res(preceded(tag("loopz "), label_terminator), |label| {
|
||||
Ok::<_, ()>((Jump::Loopz, label))
|
||||
}),
|
||||
map_res(preceded(tag("loopnz "), label_terminator), |label| {
|
||||
Ok::<_, ()>((Jump::Loopnz, label))
|
||||
}),
|
||||
map_res(preceded(tag("jcxz "), label_terminator), |label| {
|
||||
Ok::<_, ()>((Jump::Jcxz, label))
|
||||
}),
|
||||
// a duplicate! check this
|
||||
map_res(preceded(tag("jne "), is_not("\n")), |label| {
|
||||
Ok::<_, ()>((Jump::Jne, label))
|
||||
}),
|
||||
))(input)
|
||||
}
|
||||
|
||||
fn instruction(input: &str) -> IResult<&str, Instruction<&str>> {
|
||||
alt((
|
||||
// This must come before MemRegMove.
|
||||
map_res(memory_to_accumulator_instruction, |v| {
|
||||
@@ -429,6 +718,13 @@ fn instruction(input: &str) -> IResult<&str, Instruction> {
|
||||
map_res(immediate_to_memory_instruction, |v| {
|
||||
Ok::<_, ()>(Instruction::ImmediateToRegisterOrMemory(v))
|
||||
}),
|
||||
map_res(arithmetic_instruction, |v| {
|
||||
Ok::<_, ()>(Instruction::Arithmetic(v))
|
||||
}),
|
||||
map_res(jump, |(v, label)| Ok::<_, ()>(Instruction::Jump(v, label))),
|
||||
map_res(label, |v| {
|
||||
Ok::<_, ()>(Instruction::Trivia(TriviaInstruction::Label(v)))
|
||||
}),
|
||||
))(input)
|
||||
}
|
||||
|
||||
@@ -436,7 +732,7 @@ fn trivia(input: &str) -> IResult<&str, &str> {
|
||||
alt((comment, line_ending))(input)
|
||||
}
|
||||
|
||||
pub fn program(input: &str) -> IResult<&str, Program<Vec<Instruction>>> {
|
||||
pub fn program(input: &str) -> IResult<&str, Program<Vec<Instruction<&str>>, &str>> {
|
||||
map_res(
|
||||
preceded(
|
||||
many0(trivia),
|
||||
@@ -453,6 +749,7 @@ pub fn program(input: &str) -> IResult<&str, Program<Vec<Instruction>>> {
|
||||
Ok::<_, ()>(Program {
|
||||
bits,
|
||||
instructions: instructions.into_iter().flatten().collect(),
|
||||
offset: std::marker::PhantomData,
|
||||
})
|
||||
},
|
||||
)(input)
|
||||
|
1701
src/main.rs
1701
src/main.rs
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,7 @@
|
||||
use const_panic::concat_panic;
|
||||
use std::fmt::{Display, Write};
|
||||
|
||||
#[derive(Eq, PartialEq, Debug)]
|
||||
#[derive(Eq, PartialEq, Debug, Hash, Clone)]
|
||||
pub enum GeneralRegister {
|
||||
A,
|
||||
B,
|
||||
@@ -9,7 +10,7 @@ pub enum GeneralRegister {
|
||||
}
|
||||
|
||||
impl GeneralRegister {
|
||||
pub fn to_id(&self) -> u8 {
|
||||
pub const fn to_id(&self) -> u8 {
|
||||
match self {
|
||||
GeneralRegister::A => 0b00,
|
||||
GeneralRegister::B => 0b11,
|
||||
@@ -18,13 +19,13 @@ impl GeneralRegister {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn of_id(id: u8) -> GeneralRegister {
|
||||
pub const fn of_id(id: u8) -> GeneralRegister {
|
||||
match id {
|
||||
0 => GeneralRegister::A,
|
||||
1 => GeneralRegister::C,
|
||||
2 => GeneralRegister::D,
|
||||
3 => GeneralRegister::B,
|
||||
_ => panic!("Not a register: {}", id),
|
||||
_ => concat_panic!("Not a register: {}", id),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -40,7 +41,7 @@ impl Display for GeneralRegister {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Eq, PartialEq, Debug)]
|
||||
#[derive(Eq, PartialEq, Debug, Hash, Clone)]
|
||||
pub enum SpecialRegister {
|
||||
StackPointer,
|
||||
BasePointer,
|
||||
@@ -49,7 +50,7 @@ pub enum SpecialRegister {
|
||||
}
|
||||
|
||||
impl SpecialRegister {
|
||||
pub fn to_id(&self) -> u8 {
|
||||
pub const fn to_id(&self) -> u8 {
|
||||
// These are all wide.
|
||||
4 + match self {
|
||||
SpecialRegister::StackPointer => 0,
|
||||
@@ -59,13 +60,13 @@ impl SpecialRegister {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn of_id(id: u8) -> SpecialRegister {
|
||||
pub const fn of_id(id: u8) -> SpecialRegister {
|
||||
match id {
|
||||
4 => SpecialRegister::StackPointer,
|
||||
5 => SpecialRegister::BasePointer,
|
||||
6 => SpecialRegister::SourceIndex,
|
||||
7 => SpecialRegister::DestIndex,
|
||||
_ => panic!("Not a special register ID: {}", id),
|
||||
_ => concat_panic!("bad special register ID {}", id),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -81,13 +82,13 @@ impl Display for SpecialRegister {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Eq, PartialEq, Debug)]
|
||||
#[derive(Eq, PartialEq, Debug, Hash, Clone)]
|
||||
pub enum ByteRegisterSubset {
|
||||
High,
|
||||
Low,
|
||||
}
|
||||
|
||||
#[derive(Eq, PartialEq, Debug)]
|
||||
#[derive(Eq, PartialEq, Debug, Hash, Clone)]
|
||||
pub enum RegisterSubset {
|
||||
All,
|
||||
Subset(ByteRegisterSubset),
|
||||
@@ -103,7 +104,7 @@ impl Display for RegisterSubset {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Eq, PartialEq, Debug)]
|
||||
#[derive(Eq, PartialEq, Debug, Hash, Clone)]
|
||||
pub enum Register {
|
||||
General(GeneralRegister, RegisterSubset),
|
||||
Special(SpecialRegister),
|
||||
@@ -119,7 +120,7 @@ impl Display for Register {
|
||||
}
|
||||
|
||||
impl Register {
|
||||
pub fn of_id(id: u8, is_wide: bool) -> Register {
|
||||
pub const fn of_id(id: u8, is_wide: bool) -> Register {
|
||||
if is_wide {
|
||||
if id >= 4 {
|
||||
Register::Special(SpecialRegister::of_id(id))
|
||||
@@ -140,7 +141,7 @@ impl Register {
|
||||
}
|
||||
|
||||
// Returns true if the result is wide.
|
||||
pub fn to_id(self: &Register) -> (u8, bool) {
|
||||
pub const fn to_id(self: &Register) -> (u8, bool) {
|
||||
match self {
|
||||
Register::Special(s) => (s.to_id(), true),
|
||||
Register::General(reg, sub) => match sub {
|
||||
@@ -151,7 +152,7 @@ impl Register {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_wide(self: &Register) -> bool {
|
||||
pub const fn is_wide(self: &Register) -> bool {
|
||||
match self {
|
||||
Register::Special(_) => true,
|
||||
Register::General(_, RegisterSubset::All) => true,
|
||||
|
Reference in New Issue
Block a user