Skip to content

Commit

Permalink
feat: parse PC offset arguments
Browse files Browse the repository at this point in the history
  • Loading branch information
dxrcy committed Dec 20, 2024
1 parent 26dfeea commit b4d0fbc
Show file tree
Hide file tree
Showing 3 changed files with 70 additions and 16 deletions.
2 changes: 1 addition & 1 deletion src/debugger/command.rs
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ pub enum Location {

#[derive(Debug)]
pub enum MemoryLocation {
PC,
PCOffset(i16),
Address(u16),
Label(Label),
}
Expand Down
31 changes: 25 additions & 6 deletions src/debugger/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -437,21 +437,30 @@ impl Debugger {
fn resolve_location_address(&self, state: &RunState, location: &MemoryLocation) -> Option<u16> {
match location {
MemoryLocation::Address(address) => Some(*address),
MemoryLocation::PC => Some(state.pc()),
MemoryLocation::PCOffset(offset) => self.resolve_pc_offset(state.pc(), *offset),
MemoryLocation::Label(label) => self.resolve_label_address(label),
}
}

fn resolve_pc_offset(&self, pc: u16, offset: i16) -> Option<u16> {
let Some(address) = self.add_address_offset(pc, offset) else {
dprintln!(
Always,
Error,
"Program counter + offset is out of bounds of memory."
);
return None;
};
Some(address)
}

fn resolve_label_address(&self, label: &Label) -> Option<u16> {
let Some(address) = get_label_address(&label.name) else {
dprintln!(Always, Error, "Label not found named `{}`.", label.name);
return None;
};

// Check address in user program area
let orig = self.orig() as i16;
let address = address as i16 + label.offset + orig;
if address < orig || (address as u16) >= 0xFE00 {
let Some(address) = self.add_address_offset(address + self.orig(), label.offset) else {
dprintln!(
Always,
Error,
Expand All @@ -467,7 +476,17 @@ impl Debugger {
label.name,
address
);
Some(address as u16)
Some(address)
}

fn add_address_offset(&self, address: u16, offset: i16) -> Option<u16> {
let address = address as i16 + offset;
// Check address in user program area
if address >= self.orig() as i16 && (address as u16) < 0xFE00 {
Some(address as u16)
} else {
None
}
}

fn orig(&self) -> u16 {
Expand Down
53 changes: 44 additions & 9 deletions src/debugger/parse.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ enum Argument {
Register(Register),
Integer(i32),
Label(Label),
PCOffset(i16),
}

#[derive(Clone, Copy, Debug)]
Expand Down Expand Up @@ -85,6 +86,7 @@ impl Argument {
Argument::Register(_) => "register",
Argument::Integer(_) => "integer",
Argument::Label(_) => "label",
Argument::PCOffset(_) => "program counter offset",
}
}
}
Expand Down Expand Up @@ -129,18 +131,18 @@ impl<'a> CommandIter<'a> {
#[rustfmt::skip]
let commands: &[(_, &[_])] = &[
(CommandName::Help, &["help", "--help", "h", "-h"]),
(CommandName::Continue, &["continue", "cont", "c"]),
(CommandName::Continue, &["continue", "cont", "c"]), // proceed
(CommandName::Finish, &["finish", "fin", "f"]),
(CommandName::Exit, &["exit"]),
(CommandName::Quit, &["quit", "q"]),
(CommandName::Registers, &["registers", "reg", "r"]),
(CommandName::Reset, &["reset"]),
(CommandName::Step, &["progress", "p"]),
(CommandName::Step, &["progress", "p"]), // advance
(CommandName::Next, &["next", "n"]),
(CommandName::Get, &["get", "g"]),
(CommandName::Set, &["set", "s"]),
(CommandName::Jump, &["jump", "j"]),
(CommandName::Source, &["assembly", "asm", "a"]),
(CommandName::Source, &["assembly", "asm", "a"]), // source
(CommandName::Eval, &["eval", "e"]),
(CommandName::BreakList, &["breaklist", "bl"]),
(CommandName::BreakAdd, &["breakadd", "ba"]),
Expand Down Expand Up @@ -223,15 +225,15 @@ impl<'a> CommandIter<'a> {
})
}

None => default,

Some(value) => Err(ArgumentError::InvalidValue {
argument_name,
error: ValueError::MismatchedType {
expected_type: "integer",
actual_type: value.kind(),
},
}),

None => default,
}
}

Expand All @@ -254,6 +256,14 @@ impl<'a> CommandIter<'a> {

Some(Argument::Label(label)) => Ok(Location::Memory(MemoryLocation::Label(label))),

Some(value) => Err(ArgumentError::InvalidValue {
argument_name,
error: ValueError::MismatchedType {
expected_type: "register, address, or label",
actual_type: value.kind(),
},
}),

None => Err(ArgumentError::MissingArgument {
argument_name,
expected_count,
Expand All @@ -280,12 +290,12 @@ impl<'a> CommandIter<'a> {
}

/// Parse and consume next [`MemoryLocation`] argument, defaulting to program counter
/// ([`MemoryLocation::PC`]).
/// ([`MemoryLocation::PCOffset`]).
pub fn next_memory_location_or_default(
&mut self,
argument_name: &'static str,
) -> Result<MemoryLocation, ArgumentError> {
self.next_memory_location_inner(argument_name, Ok(MemoryLocation::PC))
self.next_memory_location_inner(argument_name, Ok(MemoryLocation::PCOffset(0)))
}

/// Parse and consume next [`MemoryLocation`] argument. Use default result value if argument is `None`.
Expand All @@ -304,15 +314,15 @@ impl<'a> CommandIter<'a> {

Some(Argument::Label(label)) => Ok(MemoryLocation::Label(label)),

None => default,

Some(value) => Err(ArgumentError::InvalidValue {
argument_name,
error: ValueError::MismatchedType {
expected_type: "address or label",
actual_type: value.kind(),
},
}),

None => default,
}
}

Expand Down Expand Up @@ -440,6 +450,9 @@ impl<'a> CommandIter<'a> {
if self.is_end_of_argument() {
return Ok(None);
}
if let Some(offset) = self.next_pc_offset()? {
return Ok(Some(Argument::PCOffset(offset)));
}
if let Some(register) = self.next_register() {
return Ok(Some(Argument::Register(register)));
}
Expand Down Expand Up @@ -684,6 +697,28 @@ impl<'a> CommandIter<'a> {
offset,
}))
}

/// Parse and consume the next PC offset argument.
fn next_pc_offset(&mut self) -> Result<Option<i16>, ValueError> {
self.reset_head();
// Don't skip whitespace

if !self.next().is_some_and(|ch| ch == '^') {
return Ok(None);
}

self.set_base();
let offset = resize_int(self.next_integer_token(false)?.unwrap_or(0))?;

println!("{}", offset);

if !self.is_end_of_argument() {
// TODO(feat): Custom error
return Err(ValueError::MalformedLabel {});
}
self.set_base();
Ok(Some(offset))
}
}

#[cfg(test)]
Expand Down

0 comments on commit b4d0fbc

Please sign in to comment.