Skip to content

cpu: fix cycle count for conditional long branches - #14

Open
beardypig wants to merge 2 commits into
masterfrom
fix-cycle-count
Open

cpu: fix cycle count for conditional long branches#14
beardypig wants to merge 2 commits into
masterfrom
fix-cycle-count

Conversation

@beardypig

Copy link
Copy Markdown
Owner

No description provided.

@beardypig
beardypig requested a review from Copilot March 2, 2026 17:32

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

Adjusts M6809 emulation to correct cycle counting for conditional long branches and fixes RTI register restore behavior by reading the stacked CC first.

Changes:

  • Update RTI to pull CC first so the stacked E flag determines which registers get restored.
  • Refine long-branch cycle accounting to avoid adding the “taken” cycle for unconditional LBRA/LBRN.
  • Bump the vcpkg submodule reference.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 4 comments.

File Description
vcpkg Updates the vcpkg submodule commit pointer.
src/m6809.h Fixes RTI restore logic (E flag source) and adjusts long-branch cycle counting rules (LBRA/LBRN vs conditional).

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/m6809.h
Comment on lines +692 to 698
// First pull CC from the stack to get the E flag
cpu.registers.CC = cpu.Pull8(cpu.registers.SP);
cycles += 1;
// Now check E flag in the pulled CC to determine if we restore all registers
// 0xfe = all except CC (already pulled), 0x80 = just PC
uint8_t register_mask = (cpu.registers.flags.E) ? (uint8_t)0xfe : (uint8_t)0x80;
op_pull<reg_sp, reg_usp>()(cpu, register_mask, cycles);

Copilot AI Mar 2, 2026

Copy link

Choose a reason for hiding this comment

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

The new cycles += 1; is a hard-coded timing adjustment that isn’t explained relative to how op_pull(...) accounts for timing. To prevent future timing regressions, please document why this specific increment is correct (e.g., reference the RTI timing model used in this emulator) and how it composes with op_pull’s per-byte/per-register cycle accounting.

Copilot uses AI. Check for mistakes.
Comment thread src/m6809.h
Comment on lines +917 to +918
// Unconditional=true skips the extra cycle for LBRA/LBRN
template <typename Test, typename T, bool Negate=false, bool Unconditional=false>

Copilot AI Mar 2, 2026

Copy link

Choose a reason for hiding this comment

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

Introducing an additional boolean template parameter (Unconditional) makes call sites with multiple bools harder to read and easier to misuse (e.g., ..., false, true requires readers to remember the parameter order). Consider replacing the boolean with a small tag type/enum policy, or adding dedicated aliases/wrappers for LBRA/LBRN so the call site communicates intent without positional booleans.

Copilot uses AI. Check for mistakes.
Comment thread src/m6809.h
Comment on lines +939 to +940
template <typename Fn, bool negate=false, bool unconditional=false>
using op_bra_long = op_bra<Fn, int16_t, negate, unconditional>;

Copilot AI Mar 2, 2026

Copy link

Choose a reason for hiding this comment

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

Introducing an additional boolean template parameter (Unconditional) makes call sites with multiple bools harder to read and easier to misuse (e.g., ..., false, true requires readers to remember the parameter order). Consider replacing the boolean with a small tag type/enum policy, or adding dedicated aliases/wrappers for LBRA/LBRN so the call site communicates intent without positional booleans.

Copilot uses AI. Check for mistakes.
Comment thread src/m6809.h
Comment on lines +1416 to +1417
using op_lbra_inherent = opcode_count<op_bra_long<op_bra_always, false, true>, RegisterPC, inherent, NoFlags16, 5>;
using op_lbrn_inherent = opcode_count<op_bra_long<op_bra_always, true, true>, RegisterPC, inherent, NoFlags16, 5>;

Copilot AI Mar 2, 2026

Copy link

Choose a reason for hiding this comment

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

Introducing an additional boolean template parameter (Unconditional) makes call sites with multiple bools harder to read and easier to misuse (e.g., ..., false, true requires readers to remember the parameter order). Consider replacing the boolean with a small tag type/enum policy, or adding dedicated aliases/wrappers for LBRA/LBRN so the call site communicates intent without positional booleans.

Suggested change
using op_lbra_inherent = opcode_count<op_bra_long<op_bra_always, false, true>, RegisterPC, inherent, NoFlags16, 5>;
using op_lbrn_inherent = opcode_count<op_bra_long<op_bra_always, true, true>, RegisterPC, inherent, NoFlags16, 5>;
// Long branch operation aliases to avoid positional boolean template arguments.
using op_bra_long_always = op_bra_long<op_bra_always, false, true>; // LBRA: long branch always
using op_bra_long_never = op_bra_long<op_bra_always, true, true>; // LBRN: long branch never
using op_lbra_inherent = opcode_count<op_bra_long_always, RegisterPC, inherent, NoFlags16, 5>;
using op_lbrn_inherent = opcode_count<op_bra_long_never, RegisterPC, inherent, NoFlags16, 5>;

Copilot uses AI. Check for mistakes.
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