Skip to content

Add non-mutating single-instruction disassembler - #135

Open
mre wants to merge 1 commit into
masterfrom
disassemble-one
Open

Add non-mutating single-instruction disassembler#135
mre wants to merge 1 commit into
masterfrom
disassemble-one

Conversation

@mre

@mre mre commented Jun 21, 2026

Copy link
Copy Markdown
Owner

Adds a super simple instruction debugger.

Base automatically changed from huc6280-variant to master June 26, 2026 15:52
@mre
mre force-pushed the disassemble-one branch from 3a4e06f to 228f7d2 Compare June 26, 2026 22:01
Add `instruction::disassemble_one(pc, read)` and `DisasmInstr`: a
side-effect-free decoder that resolves one instruction at `pc` without
advancing the PC or dereferencing operands, so it can be driven from a
peek-style bus.

- Decodes the full HuC6280 superset via the existing `Huc6280::decode`
  table, so it can never drift from `fetch_next_and_decode` on which
  opcodes exist or how long they are (`length == 1 + mode.extra_bytes()`).
- Resolves branch targets to absolute addresses (`Relative` and the
  BBR/BBS `ZeroPageRelative` form); all other operands are static and
  as-encoded (no register offsets, no zero-page relocation, no pointer
  dereferencing).
- Never panics on unknown opcodes (defensive `.db $XX` fallback).

Supporting changes:
- `Instruction::mnemonic()` + `Display for Instruction`.
- Derive `PartialEq, Eq` for `AddressingMode`.
- Factor branch sign-extension into `sign_extend_offset`, now shared by
  the executing decoder and the disassembler.
- Add a default-on `alloc` feature (required by `DisasmInstr::text`),
  keeping the crate usable on bare-metal via `default-features = false`.

@omarandlorraine omarandlorraine left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great job, I only had a few nitpicks, sorry for the delay

Comment thread src/instruction.rs
/// Requires the `alloc` feature (enabled by default).
#[cfg(feature = "alloc")]
#[must_use]
pub fn disassemble_one(pc: u16, read: impl Fn(u16) -> u8) -> DisasmInstr {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Question: why is this one hardcoded to HuC6280? The way I see it, it could take a type parameter.

Comment thread src/instruction.rs
let text = if operand_text.is_empty() {
mnemonic.to_string()
} else {
format!("{mnemonic} {operand_text}")

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider if this could/should pad with spaces, now that some mnemonics are four characters long (for example, bbr0), so that the operand column will line up

Comment thread src/instruction.rs
pub const fn mnemonic(&self) -> &'static str {
match self {
Instruction::ADC | Instruction::ADCnd => "ADC",
Instruction::AND => "AND",

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nitpick: my preference would be for these to be lower case

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants