TFR/EXG to/from internal TMP2/TMP3 silently ignored #6

Open
opened 2026-08-24 11:43:57 +02:00 by sid · 0 comments
Owner

Summary

The TFR/EXG/SEX decoder (ExecuteTransfer, M68HC12.cs:1112-1142)
silently drops any transfer that involves the internal TMP2/TMP3
registers:

if(sourceCode == 3 || destCode == 3)
{
    return; // TMP2/TMP3 are internal registers - not wired up
}

In the B7 post-byte, source/dest register codes 0-2,4-7 map to
A, B, CCR, D, X, Y, SP; code 3 selects the internal temp register
(TMP2 for a 16-bit transfer, TMP3 when the operation implies it).

Impact

  • Any TFR/EXG/SEX naming TMP2/TMP3 completes without doing
    anything
    — registers are not modified and no warning is logged, so the
    program silently computes wrong results.
  • The hardware extends the opcode page with EMULM/EDIVM (and related)
    forms that use the TMP registers; those are unusable while TMP is not
    modeled.

Current behavior

The post-byte is fetched, sourceCode/destCode extracted, and a bare
return occurs for code 3 — the rest of the transfer (including the SEX
sign-extension path) is skipped.

Affected files

  • src/Infrastructure/src/Emulator/Peripherals/Peripherals/CPU/M68HC12/M68HC12.cs:1112-1142

Desired behavior

  • Model TMP2/TMP3 as internal 16-bit registers (visible to the monitor for
    debugging, but not part of the GDB register set unless GDB expects them).
  • Complete the TFR/EXG/SEX post-byte table so code 3 transfers
    to/from the temp register work, including the SEX 8-bit→16-bit
    sign-extension rule.

Acceptance criteria

  • TFR A,TMP2 / EXG D,TMP3 and similar post-byte combos update the temp
    registers and the paired register exactly once (correct swap for EXG).
  • Behavior matches the CPU12RG TFR/EXG row and the binutils
    M6812_OP_TFR_MARKER/M6812_OP_EXG_MARKER decode
    (docs/m68hc12/reference/binutils-m68hc11-opc.c,
    docs/m68hc12/reference/binutils-opcode-m68hc11.h).
  • Unit tests cover a representative set of TFR/EXG/SEX post-bytes including
    code 3.
  • No silent no-op remains: every legal post-byte either executes or is caught
    by the unimplemented-opcode trap with a warning.

Suggested approach

  • Add two ushort fields (or reuse the register array) for TMP2/TMP3.
  • Extend TransferRegister (M68HC12.cs:1144) to map code 3 to the temp
    register instead of falling into the default (SP) case.
  • Verify SEX semantics: a transfer from an 8-bit source to a 16-bit dest
    sign-extends; the same rule already exists for A/B/CCR sources and should
    apply uniformly to the temp register.
## Summary The `TFR`/`EXG`/`SEX` decoder (`ExecuteTransfer`, `M68HC12.cs:1112-1142`) silently drops any transfer that involves the internal `TMP2`/`TMP3` registers: ```csharp if(sourceCode == 3 || destCode == 3) { return; // TMP2/TMP3 are internal registers - not wired up } ``` In the `B7` post-byte, source/dest register codes `0-2,4-7` map to A, B, CCR, D, X, Y, SP; code `3` selects the internal temp register (`TMP2` for a 16-bit transfer, `TMP3` when the operation implies it). ## Impact - Any `TFR`/`EXG`/`SEX` naming `TMP2`/`TMP3` completes **without doing anything** — registers are not modified and no warning is logged, so the program silently computes wrong results. - The hardware extends the opcode page with `EMULM`/`EDIVM` (and related) forms that use the TMP registers; those are unusable while TMP is not modeled. ## Current behavior The post-byte is fetched, `sourceCode`/`destCode` extracted, and a bare `return` occurs for code 3 — the rest of the transfer (including the SEX sign-extension path) is skipped. ## Affected files - `src/Infrastructure/src/Emulator/Peripherals/Peripherals/CPU/M68HC12/M68HC12.cs:1112-1142` ## Desired behavior - Model `TMP2`/`TMP3` as internal 16-bit registers (visible to the monitor for debugging, but not part of the GDB register set unless GDB expects them). - Complete the `TFR`/`EXG`/`SEX` post-byte table so code `3` transfers to/from the temp register work, including the SEX 8-bit→16-bit sign-extension rule. ## Acceptance criteria - `TFR` A,TMP2 / EXG D,TMP3 and similar post-byte combos update the temp registers and the paired register exactly once (correct swap for EXG). - Behavior matches the CPU12RG `TFR`/`EXG` row and the binutils `M6812_OP_TFR_MARKER`/`M6812_OP_EXG_MARKER` decode (`docs/m68hc12/reference/binutils-m68hc11-opc.c`, `docs/m68hc12/reference/binutils-opcode-m68hc11.h`). - Unit tests cover a representative set of TFR/EXG/SEX post-bytes including code `3`. - No silent no-op remains: every legal post-byte either executes or is caught by the unimplemented-opcode trap with a warning. ## Suggested approach - Add two `ushort` fields (or reuse the register array) for TMP2/TMP3. - Extend `TransferRegister` (`M68HC12.cs:1144`) to map code `3` to the temp register instead of falling into the `default` (SP) case. - Verify SEX semantics: a transfer from an 8-bit source to a 16-bit dest sign-extends; the same rule already exists for A/B/CCR sources and should apply uniformly to the temp register.
Sign in to join this conversation.
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
sid/renode-m68hc12#6
No description provided.