Commit Graph
725 Commits
Author SHA1 Message Date
joevt 0c05d4ff9f ppcopcodes: Add emulation of THRMn registers.
Required for booting Mac OS 9.2.2 on iMac.
2026-09-25 20:31:30 -07:00
joevt 529fff7d4d timermanager: Pre-allocate TimerInfo.
Remove std::shared_ptr allocation/deallocation of TimerInfo structs.
2026-09-25 20:12:05 -07:00
joevt 3d5e2442d3 timermanager: Return next_ns from process_timers.
The point of this change is that g_icycles might not always be the
current time. For example, when g_realtime is true.

process_timers now returns the next time a timer needs to be processed.
Don't subtract time_now, because for realtime mode, the time has changed
since time_now was captured, especially for timers that take a long time
to process.

When there's no timer pending, process_events will return a time of now
+ 0.5 ms for when process_timers should be called again.
2026-09-23 07:06:26 -07:00
joevt 14bae3d789 timermanager: Add time parameters to callback. 2026-09-23 07:04:04 -07:00
joevt ab874a0da9 ppcexceptions: Remove duplicate exception handling code. 2026-09-22 20:29:12 -07:00
joevt ba4a5c7c44 ppcemu: Define more PPC exceptions. 2026-09-22 20:26:38 -07:00
joevt e729b989bb ppcemu: Specify PPC exception values. 2026-09-22 20:26:10 -07:00
joevt 320688dee7 ppcmmu: Fix spelling. 2026-09-22 20:19:00 -07:00
Mihai Parparita 1a0439a871 ppcmmu: Flush all PAT-derived TLB entries for the tlbie instruction
This fixes booting Mac OS 8.6 hanging at the Happy Mac on the iMac G3.
During boot, as part of installing the nanokernel, the OS attempts to do
a full TLB flush via a series of `tlbie` instructions. We were trying to
respect the effective address that's specified in the instruction, but
the semantics of how it should be interpreted are different on the 750
CPU - the [user manual](https://www.nxp.com/docs/en/reference-manual/MPC750UM.pdf)
says:

> The `tlbie` instruction invalidates all TLB entries indexed by the EA,
> and operates on both the instruction and data TLBs simultaneously
> invalidating four TLB entries. The index corresponds to bits 14-19 of the EA.

We were not respecting the bits 14-19 part (`TLB_VPS_MASK` matched bits
4-19), and thus not matching all expected entries. The stale entries
would remain, leading to unexpected behavior.

Rather than trying to more precisely model the 750 behavior, we instead
flush all PAT-derived TLB entries. This matches QEMU's approach (see
qemu/qemu@3dcfb74fd4) and is allowed by
[the PowerPC specification](http://refspecs.linux-foundation.org/PPC_hrm.2005mar31.pdf):

> For example, the tlbie instruction may be implemented to purge all TLB
> entries in a congruence class (that is, all TLB entries indexed by the
> specified effective address which can include corresponding entries in
> data and instruction TLBs) **or the entire TLB**.

As of #219 a full flush is not that expensive, thus this does not
materially affect performance. The goal of the guest OS is a full TLB
flush anyway (hence the sweep of `tlbie` instructions), so we don't end
up doing too many extra lookups after they're done.

For #184
2026-09-16 18:33:16 -07:00
Mihai Parparita dced15e63d ppc: Ignore unchanged BAT register writes
Avoids unncessary TLB invalidations.
2026-08-20 22:54:26 -07:00
Mihai Parparita 13ccd42e16 ppcmmu: Track translated entries for invalidation
XNU frequently changes BAT and PAT mappings for physical-memory access.
Each  resulting context synchronization can walk tens of thousands of TLB
entries, which consumes a lot of time.

Record the instruction and data TLB slots populated by BAT or PAT and
invalidate only those slots. Pending invalidations are coalesced by source,
and BAT updates cover PAT-derived entries because a new BAT can shadow a page
mapping.

Saves another 0.7 secondss in the time it takes to boot Mac OS X 10.3 to
the WindowServer (compared to the generational PAT invalidation).
2026-08-20 22:54:26 -07:00
Mihai Parparita 855f43c2eb ppcmmu: Revert generational PAT invalidation
PAT generation counters make invalidation constant-time by adding a
generation check to every TLB lookup, but they added a per-access overhead
to compare generation counters. I am swithcing to an alternate approach
(explicitly tracking populated entries, which can also be used for
BAT-derived entries), and am removing this first to make that diff
easier to read.

This logically reverts the work from #199 (the TLB helper refactoring
from #203 prevents a mechanical revert).
2026-08-20 22:54:26 -07:00
Maxim Poliakovski 5f6f3624e1 ppcdechelpers.h: split operand decoding and value loading.
Also remove duplicated code wherever possible.
2026-08-18 16:25:03 +02:00
joevt f547057bb6 ppcdisasm: Fix rlwimi input register list.
The destination register is also an input since only some bits are
modified.
2026-08-18 06:55:11 -07:00
Maxim Poliakovski d5f16cf4b6 Rename ppcmacros.h to ppcdechelpers.h & cleanup formatting. 2026-08-17 14:11:55 +02:00
Mihai Parparita 253844cec5 ppcmmu: Add helpers for repeated TLB operations
Helps a bit with some of the code duplication introduced in #203.
2026-08-14 19:26:02 -07:00
Aliceandjoevt 26b7566179 hostevents_sdl: Add icnt_factor and g_realtime shortcuts.
Added controls to increment/decrement icnt_factor and toggle g_realtime
for testing and debugging purposes.
Control Alt Shift = -> increment_icnt_factor();
Control Alt Shift - -> decrement_icnt_factor();
Control Alt r -> toggle_g_realtime();

Co-Authored-By: joevt <joevt@shaw.ca>
2026-08-09 21:28:22 -07:00
joevt a3b248ea3d ppcemu: Use ppc_off_reason setter.
Makes things slightly cleaner and helps debugging. Changes to
ppc_off_reason can be logged.
2026-08-09 21:04:04 -07:00
Mihai Parparita 8f6274ed8a ppcmmu: Ignore dcbz for MMIO regions
The ATI drivers uses dcbz to simulate a write-combining buffer when
sending HOST_DATA payloads.

The intent is something like this (on real hardware):

```
dcbz:
    cache line = [0, 0, 0, 0, 0, 0, 0, 0]
    ATI sees nothing

following stores:
    cache line = [A, B, C, D, E, F, G, H]
    ATI still sees nothing

dcbf or eviction:
    write back [A, B, C, D, E, F, G, H]
    ATI receives one completed cache line
```

With our previous cacheless implementation, the behavior was more like this:
```
dcbz:
    ATI immediately receives [0, 0, 0, 0, 0, 0, 0, 0]

following stores:
    ATI then receives [A, B, C, D, E, F, G, H]

dcbf:
    no-op
```

The zero-ed out values have side effects (32 pixels of black being
written), so the intermediate state was visible.

The truly correct fix is to fully model the data cache, and do an
eventual write back of the modified cache lines with their final values,
but that is very invasive (and likely to be slow).

We instead just make `dcbz` a no-op for MMIO regions, which lets us
avoid that intermediate state and unintended side effects.
2026-08-08 06:46:01 -07:00
joevt eade7a0a30 ppcmmu: Fix indenting. 2026-08-07 06:47:41 -07:00
Mihai Parparita abf20ce712 Allow different levels of determinism (#201)
Add an "interactive" mode that allows user input, but still disables
hard drive and PRAM persistence.
2026-08-06 19:03:48 -07:00
Mihai Parparita 2c7a7c5c36 ppcmmu: Use generational flush for PAT entries
We end up flushing all entries very frequently (hundreds of thousands of times
during Mac OS X boot), and were spending a lot of time in `tlb_flush_entries`
walking through the array. We can instead store a generation counter and
make invalidation be a simple increment. This does make validity checks slightly
more expensive, but it appears to be a net win. On my machine it takes booting
the Mac OS X public meta to the Finder from ~58 seconds to ~35 seconds.
2026-08-06 07:33:54 -07:00
Mihai Parparita 1b0ac89674 ppcmmu: Move TLB internals into implementation
`TLBEntry` and its cache constants and flags are used exclusively by
ppcmmu.cpp. Keep them out of the public MMU header so future TLB changes
do not expand its interface.

This required a small fix in dbdma.cpp since it was implicitly relying on
an include that we removed.

Also declare `gTLBFlush*` variables as static to make it explicit that we
don't expect them to be accessed outside of ppcmmu.cpp.
2026-08-06 07:33:54 -07:00
Mihai Parparita 172efccd1b cpu: remove unused global variables (#197)
Last glob_bb_start_la use was removed in d83fdd8866.

Last last_read_area, last_write_area, and last_exec_area uses were removed
in c9d4cc3321.
2026-08-05 18:43:25 -07:00
dingusdev c916954187 Add missing VX and FEX updates 2026-08-01 11:32:07 -07:00
dingusdev 7658707bd3 Add missing return statements 2026-07-29 18:49:54 -07:00
dingusdev aef197841b Remove SNAN checks from FABS, FNABS, and FNEG
None of these checks are required
2026-07-05 18:47:37 -07:00
Mihai Parparita c5d24e98a3 ppcexec: Respect CPU-specific POW behavior (#188)
Followup to #186 - select `MSR[POW]` handling mode once during CPU
initialization instead of treating every processor as `HID0`-gated.

We match documented (and QEMU) behavior:
- 603/7xx CPUs require `HID0` doze, nap, or sleep bits before we enter
  the emulator sleep loop
- 604-family CPUs use just for `POW` directly
- 601 does not support `POW` at all
2026-07-03 18:13:10 -07:00
Mihai Parparita 79a06c55a4 ppcexec: Emulate PowerPC sleep on MSR POW (#186)
xnu-123.5 and similar vintage kernls enter the PowerPC 750 powersave mode
when the scheduler has no runnable work. `machine_idle_ppc` selects HID0
doze or nap, records a nap timestamp, then executes mtmsr with MSR[POW]
set. It stays in a loop there (in case the power saving had no effect
immediately) - it expects execution to resume at the `machine_idle_ret`
label (when an interrupt occurs), which ends up returning from the
function.

We model this state explicitly:
- When mtmsr sets MSR[POW] with the HID0 doze/nap/sleep flags, set a new
  EXEF_SLEEP flag.
- When EXEF_SLEEP is set, keep processing host events without advancing
  the guest PC.

Towards getting the 10.0 public beta to boot (#154) - before this we
would enter the DPPC debugger shortly after this instruction (due to a
bogus MSR LE flag eventually being set). Now we make more progress and
end up in a "Still waiting for root device" loop (presumably something
at the ATA layer)
2026-07-02 06:59:43 -07:00
dingusdev 8d1d22416a Further FPU fixes
Now only 472 floating point tests fail
2026-06-26 22:24:48 -07:00
dingusdev 103a06536c Small PPC Floating-Point fixes 2026-06-26 07:44:38 -07:00
Maxim Poliakovski 0e2ffa7863 Move endianswap.h to core/* 2026-06-07 21:10:51 +02:00
Maxim Poliakovski 0e03cac082 Move memaccess.h to core/* 2026-06-07 20:32:46 +02:00
joevt 54a1eb49f7 ppcmmu: Add a debug version of mmu_map_dma_mem.
This is for the DPPC debugger, not for debugging DPPC.
2026-06-02 20:34:26 -07:00
joevt b665629168 ppcemu: Remove unused timebase_counter global. 2026-06-02 20:33:55 -07:00
joevt fe80d14e8a ppcmmu: uintptr_t (not size_t) for host pointers. 2026-05-29 06:51:32 -07:00
Rairii 09c1248be7 CPU and memory controller endian changes.
===============
Rairii changes:

memctrlbase: The memory controller may have an endian swap mode.
mpc106: Only mmio regions need endian swap and only if PCIR_LE_MODE is
set.

videoctrl: Add framebuffer_in_main_memory flag. Use needs_swap_endian.

debugger: Fix disasm for little endian mode.

ppcmmu: little endian mode requires munging of the data and instruction
addresses, affecting the 3 least significant bits.

ppcexec: pc_real is always recalculated during little endian mode
because instructions are swapped every 8 bytes (due to the address
munging).

==============
joevt changes:

Add SUPPORTS_MEMORY_CTRL_ENDIAN_MODE for memory controller.
Use cmake -DDPPC_SUPPORT_PPC_LE=ON to enable.

Add SUPPORTS_PPC_LITTLE_ENDIAN_MODE for CPU.
Use cmake -DDPPC_SUPPORT_MEM_LE=ON to enable.

Add ppc_change_endian to handle endian switch for MPC601 (uses HID0
instead of MSR) and later PPC CPUs.

Add is_LE flag to ppc_state to indicate little endian mode for all
processor versions.

Create separate ppc_exec_inner template functions for little and big
endian.

Switch endian mode in the ppc_exec outer functions when power_off_reason
is po_endian_switch.

Since MPC601 doesn't have ILE and LE bits, remove that code for that
CPU.

videoctrl: Uses templated methods. See next commit for a fix that this
change introduces.
2026-04-12 10:06:32 -07:00
joevt 25860025b0 Add debug option LOG_INSTRUCTIONS.
Adds a log that remembers the last 16 million instructions.
2026-04-12 09:38:14 -07:00
joevt 7aacd5c703 ppcmmu: Initialize bat structs after bat regs.
Needed for machine restart.
2026-04-11 13:36:58 -07:00
joevt 688ec133c5 ppcexec: Initialize int_pin.
Problems happen if this is true after a restart.
2026-04-11 13:22:44 -07:00
joevt e689d62067 debugger: Parse BAT registers. 2026-04-11 10:26:06 -07:00
joevt 91f5ccc3f9 ppcmmu: Simplify pteg address calculation.
Maybe the optimizer can do it or maybe not.
2026-03-31 07:39:45 -07:00
joevt 4ca03953d7 ppcemu: Fix EAR spr exception. 2026-03-08 10:42:22 -07:00
Maxim Poliakovski 6092882a45 ppcopcodes: fix bit test in eciwx/ecowx. 2026-02-22 18:17:29 +01:00
Tim Jarzombek 398e0b025d Fix bugs caught by fuzzing 2026-02-12 21:11:11 -05:00
joevt 60d4750d54 ppcopcodes: Decrementer fixes.
- Always add a tick to the timeout calculation.
- Make sure value of decrementer is < 0 for timed decrementer exception.
- Don't recalculate decrementer write time stamp in the case of an
  immediate decrementer exception.
2026-01-31 13:17:22 +01:00
dingusdev 213dd4c16e Update copyright info further 2026-01-30 08:12:04 -07:00
Maxim Poliakovski 0d22d5cbd8 ppcopcodes: fix decrementer interrupts.
Enable decrementer interrupts for MPC601
required by  MkLinux DR3.
2026-01-30 15:40:15 +01:00
Maxim Poliakovski e75ee8d32a Update copyright year. 2026-01-30 12:15:00 +01:00
joevt 769ef49f67 ppcopcodes: Implement mfspr for tbl_u and tbu_u. 2026-01-29 07:53:37 -07:00