Skip to content

ppc: Extend VLE execution and add e200z4d - #48

Draft
iglooom wants to merge 10 commits into
antmicro:masterfrom
iglooom:ppc-vle-e200z4d
Draft

iglooom wants to merge 10 commits into
antmicro:masterfrom
iglooom:ppc-vle-e200z4d

Conversation

@iglooom

@iglooom iglooom commented Oct 10, 2026 •

Copy link
Copy Markdown

Summary

Companion peripheral proposal: renode/renode-infrastructure#272

This draft contributes reusable PowerPC CPU changes only. It adds an e200z4d core definition, implements many previously aborting compact and extended VLE instruction handlers, and registers selected classic opcode-31 instructions in the VLE decoder. It contains no board platform, application image, capture, or host display transport.

The series separates generally applicable fixes from core initialization and VLE work:

  • Restore MSR from saved register contents in rfci, rfdi, and rfmci, rather than from the SPR number.
  • Raise privilege-class program exceptions at the changed privileged instruction/register checks.
  • Correct the CR field produced by mcrxr and update derived CPU state when MSR is written through either register API.
  • Configure the existing e200 initialization path with MAS-format TLB storage and BookE206 instruction dispatch; add a separate e200z4d definition.
  • Preserve halfword-aligned VLE branch and exception-return destinations.
  • Implement VLE arithmetic, logical, compare, branch, register-transfer, load/store, multiple-register, and selected exception/system instructions. Separate rotate/mask helpers from classic Rc handling so VLE encodings do not spuriously modify CR0.
  • Reuse classic opcode-31 handlers through explicit VLE registrations, including selected integer, indexed load/store, SPR, cache-maintenance, synchronization, and TLB instructions. This is not an unrestricted fallback to the entire classic decoder.

Model boundaries and known limitations

  • The existing e200 initializer (also used by several existing core aliases) now declares a null TLB0 and a 32-entry fully associative TLB1. The separate e200z4d initializer declares a null TLB0 and a 16-entry fully associative TLB1. Both advertise variable pages from 4 KiB through 256 MiB and IPROT, and reuse existing BookE206 helpers. This does not establish complete MMU conformance or page-size validation.
  • The inherited mmubooke206_get_physical_address still has an identity-mapping fallback after unsuccessful translation/permission checks for portions of the address space. This series does not remove that fallback; therefore it does not provide strict translation-fault or access-protection enforcement across the address space.
  • MMUCSR0 is registered with generic read/write callbacks, not the available BookE206 invalidation-command callback. Do not infer working MMUCSR0 invalidation from register availability.
  • VLE mode is selected using the existing tlib_is_vle_enabled() callback, not a newly implemented per-page MAS2[VLE] mechanism. Per-page endian/cache attribute enforcement is not added.
  • e200 L1CSR0 and e200z4d L1CSR1 writes retain controls, clear the modeled command bits synchronously, and mask hardware-only status bits. These are register-level command semantics, not cache contents, cache timing, replacement, locking, or coherency simulation. The e200z4d definition does not add a data cache; its 32-byte line sizes support existing maintenance helpers.
  • Several implementation-specific SPRs remain generic storage. This is not a complete debug, branch-unit, SPE, or exception-conformance implementation.
  • VLE is not complete: se_rfmci still explicitly aborts, and gen_se_b retains an unsupported-encoding guard. Build success on ppc64.be is a compatibility/build check, not a claim of a 64-bit e200 core or comprehensive 64-bit VLE semantics.

Validation

  • All 10 commits built individually for both ppc.be and ppc64.be: 20 successful builds, no warnings recorded by the build checker.
  • git diff --check on the CPU series passed.
  • Fresh synthetic runtime checks passed: 152 assembled compare cases, 28 classic arithmetic/logical cases, reserved-field exception handling, e200z6/e200z4d cache-register contracts, PVR/TLB geometry, and re-execution of modified RAM code.
  • Additional synthetic checks passed for all 16 compact register encodings, four odd-following-halfword CR-preservation cases, and a taken branch to a halfword-aligned address.
  • A separate source audit found no collisions among 252 VLE decoder keys. This is not execution coverage of all 252 registrations.
  • Firmware-free reproduction sources prepared locally, with exact memory assertions, retained assembler/disassembler output and a selected-backend SHA-256.
  • Publish/link that reproduction in the maintainer-preferred repository or test layout.
  • Comprehensive MMU permission/fault, privilege and exception-return conformance and classic non-VLE runtime regression coverage.
  • Maintainer CI completed.

Runtime checks use the 32-bit big-endian backend. The broader unchecked conformance and CI items remain open; these tests do not turn the limitations above into supported features.

Contribution/process notes

Developed with AI assistance from ChatGPT (OpenAI Codex) and Claude (Anthropic). This disclosure does not substitute for human review or the validation above.

The checked-out Renode contribution guide requests an issue before a pull request, ticket-based branch naming, and a CLA. Please advise how to apply that process to this companion tlib series and the separate peripheral proposal. No issue number or signed-CLA status is asserted here. This is an early draft for maintainer feedback on scope, test placement and contribution process.

iglooom and others added 10 commits October 11, 2026 00:52
helper_rfci/rfdi/rfmci passed the SPR number (SPR_BOOKE_CSRR1 etc.)
instead of the register's value to do_rfi, so the restored MSR was a
constant unrelated to the interrupted context.

Co-authored-by: Claude Code <claude-code[bot]@users.noreply.github.com>
Privileged instructions executed in problem state raised a program
exception with the illegal-instruction reason (INVAL | PRIV_*), so
ESR[PIL] was set instead of ESR[PPR]. Add gen_priv_exception and use
it for the PRIV_OPC/PRIV_REG cases.

Co-authored-by: Claude Code <claude-code[bot]@users.noreply.github.com>
mcrxr must copy XER[SO,OV,CA] into bits 3..1 of the CR field
(LT,GT,EQ) and clear bit 0. The shift by XER_CA placed them one bit
too low.

Co-authored-by: Claude Code <claude-code[bot]@users.noreply.github.com>
Writing MSR through tlib_set_register_value stored the raw value and
left hflags and the MMU index stale until the next mtmsr. Route MSR
writes through ppc_store_msr.

Co-authored-by: Claude Code <claude-code[bot]@users.noreply.github.com>
e200 cores (e200z6 and family) implement a Book E 2.06 MAS-style MMU:
TLB0 is not present and TLB1 is a fully associative array with
variable page sizes and IPROT. The model used the 440-style embedded
TLB (TLB_EMB, 64 entries) and the classic Book E TLB instructions,
so tlbwe/tlbre/tlbsx through MAS registers did not work.

Configure TLB1 (32 entries) through TLBnCFG, use TLB_MAS and the
BOOKE206 instructions, and make L1CSR0 cache-invalidate and
lock-flash-clear commands complete immediately so polling loops
terminate.

Co-authored-by: Claude Code <claude-code[bot]@users.noreply.github.com>
e200z4d as used in NXP MPC56xx (e.g. MPC5645S/PXD20) and ST SPC56
microcontrollers: e200 instruction set with VLE, a 16-entry TLB1 and
an instruction cache controlled by L1CSR1.

Co-authored-by: Claude Code <claude-code[bot]@users.noreply.github.com>
VLE instructions are 2-byte aligned. Branch targets were masked with
~3 in gen_goto_tb and rfi masked SRR0 the same way, which corrupted
control flow to any halfword-aligned target. Mask with ~1 when VLE is
enabled.

Co-authored-by: Claude Code <claude-code[bot]@users.noreply.github.com>
Split gen_rlwimi/gen_rlwinm into helpers that take whether to honour
the Rc bit. The VLE e_rlwimi/e_rlwinm forms reuse the classic
translation but bit 0 selects the instruction, not Rc.

Co-authored-by: Claude Code <claude-code[bot]@users.noreply.github.com>
Implement the 16-bit (se_*) and 32-bit (e_*) VLE instructions that
were registered but aborted as unsupported:

- compact register fields map to r0-r7 and r24-r31 (RX/RY/RZ) or
  r8-r23 (ARX/ARY);
- SCI8, I16A, I16L, LI20, D8 and SD4 immediate/displacement forms;
- e_b/e_bc/se_b/se_bc/se_blr/se_bctr with halfword displacements
  and CTR forms;
- loads/stores including update forms and e_lmw/e_stmw;
- se_rfi/se_rfci/se_rfdi/se_illegal/se_sc, with SRR0 pointing at the
  16-bit instruction for program exceptions.

A 16-bit instruction must not decode fields from the low halfword of
the fetched word, which holds the next instruction; this is why
se_add no longer reuses gen_op_arith_add.

Co-authored-by: Claude Code <claude-code[bot]@users.noreply.github.com>
In VLE mode the classic X/XO-form opcode-31 instructions remain
available (integer arithmetic and logic, indexed loads/stores, isel,
mfcr/mtcrf, mfmsr/mtmsr, mfspr/mtspr, wrtee, cache and TLB
management, mbar/msync). Register them in the VLE decoder, which uses
a different split of the extended opcode.

Co-authored-by: Claude Code <claude-code[bot]@users.noreply.github.com>
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.

1 participant